Merge pull request #10982 from MarcZX10/marc/feat-template-heading-messages

feat(tools): say which pull request template heading is missing, empty or misspelled
This commit is contained in:
Dean authored and GitHub committed 2026-10-27 05:34:54 +13:00
commit 60f36a2dfb
2 files changed
+30 -7

No files matched your search

+6 -2
View File
@@ -401,8 +401,12 @@ class Check:
body = re.sub(r"<!--.*?-->", "", body or "", flags=re.S)
sections = dict(zip(SECTION.findall(body), SECTION.split(body)[2::2]))
for name in ("What", "Tested", "Checklist"):
if not sections.get(name, "").strip():
self.report("pr-template", "", 0, f"section '{name}' is missing or empty")
if name not in sections:
found = re.search(rf"^[ \t]*#+[ \t]*{name}[ \t]*$", body, re.M | re.I)
hint = f"; found '{found.group(0).strip()}'" if found else ""
self.report("pr-template", "", 0, f"add the '### {name}' heading of the template{hint}")
elif not sections[name].strip():
self.report("pr-template", "", 0, f"fill the '### {name}' section")
checklist = sections.get("Checklist", "")
for item in re.findall(r"^\s*[-*+]\s*\[ \]\s*(.+)$", checklist, re.M):
self.report("pr-template", "", 0, f"unchecked: {item.strip()}")
@@ -71,8 +71,8 @@ class PullRequestTemplateTests(unittest.TestCase):
self.assertTrue(items)
result, findings = self.run_checker(template)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertIn("section 'What' is missing or empty", findings)
self.assertIn("section 'Tested' is missing or empty", findings)
self.assertIn("fill the '### What' section", findings)
self.assertIn("fill the '### Tested' section", findings)
for item in items:
self.assertIn(f"unchecked: {item.strip()}", findings)
self.assertIn("answer AI-assisted with yes or no", findings)
@@ -109,9 +109,28 @@ class PullRequestTemplateTests(unittest.TestCase):
def test_sections_must_have_content(self):
checklist = "- [x] Depends on: none\n- [x] AI-assisted: yes\n"
self.assert_findings(body(checklist, what="<!-- nothing -->"), ["section 'What' is missing or empty"])
self.assert_findings(body(checklist, tested=" \n"), ["section 'Tested' is missing or empty"])
self.assert_findings(body(checklist).replace("### What", "#### What"), ["section 'What' is missing or empty"])
self.assert_findings(body(checklist, what="<!-- nothing -->"), ["fill the '### What' section"])
self.assert_findings(body(checklist, tested=" \n"), ["fill the '### Tested' section"])
self.assert_findings(body(checklist).replace("### What", "#### What"),
["add the '### What' heading of the template; found '#### What'"])
def test_a_heading_at_another_level_or_case_is_named(self):
checklist = "- [x] Depends on: none\n- [x] AI-assisted: yes\n"
cases = {
"## What": "add the '### What' heading of the template; found '## What'",
" ### what ": "add the '### What' heading of the template; found '### what'",
"#WHAT": "add the '### What' heading of the template; found '#WHAT'",
}
for heading, finding in cases.items():
with self.subTest(heading=heading):
self.assert_findings(body(checklist).replace("### What", heading), [finding])
self.assert_findings(body(checklist).replace("### What", "### Whatever"), ["add the '### What' heading of the template"])
def test_a_body_without_template_headings_names_each_heading(self):
text = "What\nFix x.\n\nTested\nNot tested.\n\nChecklist\n- [x] Depends on: none\n- [x] AI-assisted: yes\n"
self.assert_findings(text, ["add the '### What' heading of the template",
"add the '### Tested' heading of the template",
"add the '### Checklist' heading of the template"])
def test_title_must_be_conventional(self):
text = body("- [x] Depends on: none\n- [x] AI-assisted: yes\n")