mirror of
https://github.com/ansible/ansible-documentation.git
synced 2026-03-26 13:18:58 +07:00
pr_labeler: add nag comment for issues and PRs without description (#353)
* pr_labeler: add issue member to IssueLabelerCtx Pull requests also support the Github issue API. This allows more easily writing code that works with both issues and pull requests without extra conditionals. * pr_labeler: add dependency on jinja2 * pr_labeler: comment on PRs/issues w/o descriptions This change adds a job to pr_labeler to leave a comment on PRs and issues without body text. It also includes necessary plumbing for rendering jinja2 templates and idempotently leaving comments on issues. Fixes: https://github.com/ansible/ansible-documentation/issues/333 * pr_labeler: improve nag comment wording Co-authored-by: Don Naro <dnaro@redhat.com> --------- Co-authored-by: Don Naro <dnaro@redhat.com>
This commit is contained in:
7
hacking/pr_labeler/data/no_body_nag.md
Normal file
7
hacking/pr_labeler/data/no_body_nag.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Thanks for your contribution, @{{ ctx.member.user.login }}! Please make sure that your {{ ctx.TYPE }} includes sufficient and meaningful details in the description.
|
||||
{% if ctx.TYPE == "pull request" %}
|
||||
PR descriptions provide important context and allow other developers and our future selves to understand a change's rationale and what it actually fixes or accomplishes.
|
||||
{% else %}
|
||||
Issue descriptions are important so others can fully understand and reproduce the issue.
|
||||
{% endif %}
|
||||
<!--- boilerplate: no_body_nag --->
|
||||
@@ -10,7 +10,7 @@ from collections.abc import Collection
|
||||
from contextlib import suppress
|
||||
from functools import cached_property
|
||||
from pathlib import Path
|
||||
from typing import Any, Union
|
||||
from typing import Any, ClassVar, Union
|
||||
|
||||
import github
|
||||
import github.Auth
|
||||
@@ -19,6 +19,7 @@ import github.PullRequest
|
||||
import github.Repository
|
||||
import typer
|
||||
from codeowners import CodeOwners, OwnerTuple
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined, select_autoescape
|
||||
|
||||
OWNER = "ansible"
|
||||
REPO = "ansible-documentation"
|
||||
@@ -28,6 +29,12 @@ LABELS_BY_CODEOWNER: dict[OwnerTuple, list[str]] = {
|
||||
HERE = Path(__file__).resolve().parent
|
||||
ROOT = HERE.parent.parent
|
||||
CODEOWNERS = (ROOT / ".github/CODEOWNERS").read_text("utf-8")
|
||||
JINJA2_ENV = Environment(
|
||||
loader=FileSystemLoader(HERE / "data"),
|
||||
autoescape=select_autoescape(),
|
||||
trim_blocks=True,
|
||||
undefined=StrictUndefined,
|
||||
)
|
||||
|
||||
IssueOrPrCtx = Union["IssueLabelerCtx", "PRLabelerCtx"]
|
||||
IssueOrPr = Union["github.Issue.Issue", "github.PullRequest.PullRequest"]
|
||||
@@ -62,6 +69,9 @@ class LabelerCtx:
|
||||
repo: github.Repository.Repository
|
||||
dry_run: bool
|
||||
event_info: dict[str, Any]
|
||||
issue: github.Issue.Issue
|
||||
|
||||
TYPE: ClassVar[str]
|
||||
|
||||
@property
|
||||
def member(self) -> IssueOrPr:
|
||||
@@ -90,6 +100,8 @@ class LabelerCtx:
|
||||
class IssueLabelerCtx(LabelerCtx):
|
||||
issue: github.Issue.Issue
|
||||
|
||||
TYPE = "issue"
|
||||
|
||||
@property
|
||||
def member(self) -> IssueOrPr:
|
||||
return self.issue
|
||||
@@ -103,6 +115,8 @@ class IssueLabelerCtx(LabelerCtx):
|
||||
class PRLabelerCtx(LabelerCtx):
|
||||
pr: github.PullRequest.PullRequest
|
||||
|
||||
TYPE = "pull request"
|
||||
|
||||
@property
|
||||
def member(self) -> IssueOrPr:
|
||||
return self.pr
|
||||
@@ -121,11 +135,31 @@ def create_comment(ctx: IssueOrPrCtx, body: str) -> None:
|
||||
ctx.pr.create_issue_comment(body)
|
||||
|
||||
|
||||
def get_data_file(name: str) -> str:
|
||||
def get_data_file(name: str, **kwargs: Any) -> str:
|
||||
"""
|
||||
Get a data file
|
||||
Template a data file
|
||||
"""
|
||||
return (HERE / "data" / name).read_text("utf-8")
|
||||
return JINJA2_ENV.get_template(name).render(**kwargs).rstrip("\n")
|
||||
|
||||
|
||||
def create_boilerplate_comment(ctx: IssueOrPrCtx, name: str, **kwargs) -> None:
|
||||
"""
|
||||
Add a boilerplate comment if it hasn't already been added
|
||||
"""
|
||||
tmpl = get_data_file(name, ctx=ctx, **kwargs)
|
||||
tmpl_lines = tmpl.splitlines()
|
||||
last = tmpl_lines[-1]
|
||||
if not (last.startswith("<!--- boilerplate: ") and last.endswith(" --->")):
|
||||
raise ValueError(
|
||||
"Last line must of the template"
|
||||
" must have an identifying boilerplate comment"
|
||||
)
|
||||
for comment in ctx.issue.get_comments():
|
||||
if comment.body.splitlines()[-1] == last:
|
||||
log(ctx, name, "boilerplate was already commented")
|
||||
return
|
||||
log(ctx, "Templating", name, "boilerplate")
|
||||
create_comment(ctx, tmpl)
|
||||
|
||||
|
||||
def handle_codeowner_labels(ctx: PRLabelerCtx) -> None:
|
||||
@@ -174,6 +208,15 @@ def new_contributor_welcome(ctx: IssueOrPrCtx) -> None:
|
||||
create_comment(ctx, get_data_file("docs_team_info.md"))
|
||||
|
||||
|
||||
def no_body_nag(ctx: IssueOrPrCtx) -> None:
|
||||
"""
|
||||
Complain if a non-bot user creates a PR or issue without body text
|
||||
"""
|
||||
if ctx.member.user.login.endswith("[bot]") or (ctx.member.body or "").strip():
|
||||
return
|
||||
create_boilerplate_comment(ctx, "no_body_nag.md")
|
||||
|
||||
|
||||
APP = typer.Typer()
|
||||
|
||||
|
||||
@@ -200,6 +243,7 @@ def process_pr(
|
||||
pr=pr,
|
||||
dry_run=dry_run,
|
||||
event_info=get_event_info(),
|
||||
issue=pr.as_issue(),
|
||||
)
|
||||
if pr.state != "open":
|
||||
log(ctx, "Refusing to process closed ticket")
|
||||
@@ -208,6 +252,7 @@ def process_pr(
|
||||
handle_codeowner_labels(ctx)
|
||||
add_label_if_new(ctx, "needs_triage")
|
||||
new_contributor_welcome(ctx)
|
||||
no_body_nag(ctx)
|
||||
|
||||
|
||||
@APP.command(name="issue")
|
||||
@@ -233,6 +278,7 @@ def process_issue(
|
||||
|
||||
add_label_if_new(ctx, "needs_triage")
|
||||
new_contributor_welcome(ctx)
|
||||
no_body_nag(ctx)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
codeowners
|
||||
jinja2
|
||||
pygithub
|
||||
typer
|
||||
|
||||
Reference in New Issue
Block a user