#!/usr/bin/env python3 """Validate that a PR description follows the repository template. The GitHub workflow passes the PR body in PR_BODY. The script is also unit-tested directly so changes to the template gate are reviewed like normal code. """ from __future__ import annotations import os import re import sys from pathlib import Path # Share the Markdown-section + changelog parsing with the release-time harvester # (.github/scripts/changelog/generate.py) so the gate and the harvester can # never disagree on what the "## Changelog" section means. sys.path.insert(0, str(Path(__file__).resolve().parent)) from _md import changelog_description from _md import checked_labels as _checked_labels from _md import heading_spans as _heading_spans from _md import section as _section from _md import strip_html_comments as _strip_html_comments REQUIRED_HEADINGS = ( "Summary", "Test Plan", "Type of change", "Test coverage", ) TYPE_LABELS = ( "Bug fix", "Feature", "UI / frontend change", "Refactor / chore", "Docs", "Test / CI", "Breaking change", ) TEST_LABELS = ( "Unit tests added / updated", "Integration tests added / updated", "E2E tests added / updated", "Manual verification completed", "Existing tests cover this change", "Not applicable", ) PLACEHOLDER_FRAGMENTS = ( "what changed and why", "check all that apply", "describe below", "how was this change tested", ) class ValidationResult: def __init__(self, ok: bool, errors: list[str]) -> None: self.ok = ok self.errors = errors _CHECKBOX_RE = re.compile(r"(?im)^\s*-\s*\[(?P[ xX])\]\s*(?P