4.6 KiB
PR Review Agent — Design Spec
Date: 2026-03-22 Status: Approved
Overview
An automated GitHub Actions workflow that evaluates every new pull request against the rules in CONTRIBUTING.md. Compliant PRs are auto-merged to main. Non-compliant PRs are left untouched for manual review.
Goals
- Auto-merge PRs that fully comply with all contributing rules
- Zero false positives — only merge when every check passes
- No action on non-compliant PRs (no comments, no closing, no labels)
- Notifications via GitHub's built-in notification system
New Files
| File | Purpose |
|---|---|
.github/workflows/pr-review.yml |
Workflow triggered on PR open/update |
scripts/review_pr.py |
Validation script implementing all CONTRIBUTING.md rules |
Component 1: GitHub Actions Workflow (pr-review.yml)
Trigger: pull_request events (types: opened, synchronize) targeting main.
Steps:
- Checkout the repo (with the PR merge ref)
- Set up Python + uv
- Run the validation script:
uv run python scripts/review_pr.py - On exit 0: approve the PR via GitHub API and squash-merge it
- On exit 0: the merge comment thanks the contributor
- On non-zero exit: do nothing
Permissions: contents: write, pull-requests: write.
Concurrency: No special concurrency controls needed — each PR runs independently.
Component 2: Validation Script (scripts/review_pr.py)
A single Python script using PyGithub (already a project dependency) and the standard library.
Input
Environment variables set by the workflow:
GITHUB_TOKEN— GitHub Actions tokenPR_NUMBER— the pull request numberGITHUB_REPOSITORY—owner/repostring
Validation Pipeline
All checks must pass for auto-merge. The script exits 0 only if every check passes, non-zero otherwise.
1. PR Description Check
- Reject if the PR body is empty or whitespace-only.
2. Files Changed Check
- Only
README.mdshould be modified. - Any other file changed → skip (exit non-zero).
3. Extract Added Lines
- From the PR diff, extract only lines added to
README.md. - Ignore blank lines, section headers (
##,###), and other non-entry lines.
4. Single Entry Check
- Exactly one new entry line must be added.
- Zero or more than one → skip.
5. Format Validation
The entry must match the regex used by parse.py:
^\s*- \[(.*)\]\((.*)\) - (.*)$
Additional checks:
- Description ends with a period (
.) before the optional[GitHub]link. - All URLs use
https://. [GitHub](url)link, if present, uses the exact format[GitHub](https://github.com/owner/repo).
6. Duplicate Check
- Search the current
README.mdfor the project name (case-insensitive). - Search for all URLs found in the entry.
- If any match is found → skip.
7. Section Placement Check
- Verify the entry is placed under a valid
##(language) and###(category) heading. - The entry must not be floating outside a recognized section.
8. Activity Check
For any GitHub URL found in the entry (primary URL or [GitHub](url) link):
- Fetch the repo via GitHub API.
archived == true→ skip.- Last push date older than 12 months → skip.
- No README file in the repo → skip.
9. URL Reachability
- Verify the primary URL returns a non-error HTTP status (2xx or 3xx).
Output
- Prints a structured summary to stdout (pass/fail per check) for workflow logs.
- Exit code 0 = all passed, non-zero = at least one check failed.
Component 3: Merge & Notification Flow
On All Checks Pass (exit 0)
- The workflow submits an approving review via
GITHUB_TOKENwith message: "All checks passed. Auto-merging. Thanks for the contribution!" - Squash-merges the PR to
main. - This triggers the existing
build.ymlworkflow (push tomainwithREADME.mdchange), so the site auto-updates.
On Any Check Fails (non-zero exit)
- The workflow does nothing.
- The PR remains open for manual review.
Notifications
GitHub's built-in notifications cover all cases:
- New PR opened → notified as repo owner.
- PR auto-merged → notified via merge event.
- PR left open → visible in open PR list.
No additional notification infrastructure required.
Dependencies
PyGithub— already inpyproject.toml- No new dependencies needed
Security Considerations
- The
GITHUB_TOKENprovided by GitHub Actions has scoped permissions (onlycontents: writeandpull-requests: write). - The script never executes code from the PR — it only reads the diff and queries the GitHub API.
- URL reachability checks use HEAD/GET requests only.