Skip to content

Check_pr_body

FieldValue
TypeSkill Resource
Source~/.copilot/skills/quality/scripts/check_pr_body.py
DescriptionNot specified

Source Content

#!/usr/bin/env python3
"""Check a drafted PR body matches the real diff and has a test plan.
Usage: check_pr_body.py <pr-body.md> [base-ref]
Cross-checks every file path mentioned in the PR body against
`git diff <base-ref>...HEAD --name-only` (default base: origin/main), and
requires a "Test plan" (or "Testing") section to be present and non-empty.
"""
import re
import subprocess
import sys
def git_changed_files(base_ref: str):
try:
out = subprocess.run(
["git", "diff", f"{base_ref}...HEAD", "--name-only"],
capture_output=True, text=True, check=True,
).stdout
return set(line.strip() for line in out.splitlines() if line.strip())
except subprocess.CalledProcessError as e:
print(f"⚠️ git diff failed ({e}) — skipped diff cross-check", file=sys.stderr)
return None
def main() -> int:
if len(sys.argv) not in (2, 3):
print("Usage: check_pr_body.py <pr-body.md> [base-ref]", file=sys.stderr)
return 2
body = open(sys.argv[1], encoding="utf-8").read()
base_ref = sys.argv[2] if len(sys.argv) == 3 else "origin/main"
fail = 0
changed = git_changed_files(base_ref)
if changed is not None:
mentioned = set(re.findall(r"`([\w./-]+\.\w+)`", body))
stale = mentioned - changed
if stale:
print(f"❌ PR body mentions file(s) not in the actual diff: {sorted(stale)}")
fail = 1
else:
print(f"✅ every file path mentioned in the body appears in the diff ({len(changed)} files changed)")
if re.search(r"#+\s*(Test [Pp]lan|Testing)\b", body):
section = re.split(r"#+\s*(?:Test [Pp]lan|Testing)\b", body, maxsplit=1)[-1]
next_heading = re.search(r"\n#+\s", section)
section_body = section[:next_heading.start()] if next_heading else section
if section_body.strip():
print("✅ Test plan / Testing section present and non-empty")
else:
print("❌ Test plan / Testing section header found but body is empty")
fail = 1
else:
print("❌ no 'Test plan' or 'Testing' section found")
fail = 1
return fail
if __name__ == "__main__":
raise SystemExit(main())