feat: new action review-post-release-pr - #227
Conversation
more general beyond just pre-commit
_commit message is ai-generated_
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #227 +/- ##
==========================================
+ Coverage 98.18% 98.70% +0.52%
==========================================
Files 13 14 +1
Lines 881 1239 +358
==========================================
+ Hits 865 1223 +358
Misses 16 16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
_commit message is ai-generated_
…workflow _commit message is ai-generated_
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The validator has multiple paths that can approve unvalidated changes, and the example references a release without the new action.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 6
Open (7)
Post-formatting commits bypass revalidation · New Numeric changes are not validated by field · New Overly broad pure-insertion auto-approval · New Prefix filtering skips additions and deletions · New Unpaginated file listing misses disallowed changes · New Approval is not bound to the validated commit · New Example references an action tag released too early · New
What changed in this PR
Adds automated review and approval for post-release cleanup PRs.
Changes:
- Adds validation, reviewer resolution, workflow approval, and auto-merge logic.
- Adds the composite action, documentation, workflow example, and changelog entry.
- Adds comprehensive Python unit tests.
| File | Description |
|---|---|
src/ccbr_actions/post_release_pr.py |
Implements review policy and automation. |
src/ccbr_actions/pr_review.py |
Adds shared workflow-run helpers. |
review-post-release-pr/action.yml |
Defines the composite action. |
review-post-release-pr/README.qmd |
Adds source documentation. |
review-post-release-pr/README.md |
Adds rendered documentation. |
review-pre-commit-pr/README.qmd |
Simplifies the existing example. |
review-pre-commit-pr/README.md |
Updates rendered documentation. |
examples/pre-review-pr.yml |
Integrates post-release PR review. |
tests/test_post_release_pr.py |
Tests the new review policy. |
tests/test_pr_review.py |
Tests shared helper additions. |
tests/test_action_test_coverage.py |
Registers the API-only action exemption. |
README.md |
Lists the new action. |
CHANGELOG.md |
Records the user-facing feature. |
.gitignore |
Ignores uv.lock. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…#227 - Audit that the version file was actually bumped, not just that changed files are allowed. - Replace generic per-token diff validation with field-specific validators (version, R DESCRIPTION, CITATION.cff, codemeta.json, changelog heading insertion, readme) using full file content instead of GitHub's patch field. - Paginate get_pr_files and fail closed on a pagination/changed_files count mismatch. - Pin approvals to the validated head commit, recheck it immediately before approving, and abort if it changed concurrently. - Track approvals per-commit (is_pr_approved_for_commit) so a stale approval left before an auto-format push no longer short-circuits re-validation. - Add synchronize to the pull_request trigger so auto-format pushes are re-reviewed. - Fix the example workflow's action ref: review-post-release-pr isn't in any release yet, so use @main until the next release. _commit message is ai-generated_
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The auto-approval gate currently permits unrelated metadata changes, mishandles outstanding reviews and R packages, and can approve workflow runs outside the validated commit.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 4
Open (7)
Validator approves arbitrary JSON without comparing metadata changes · New Pending runs are approved before validating the current head SHA · New Changes-requested reviews are incorrectly treated as unapproved · New Branch-only run filtering can approve runs from another fork · New Date validation accepts dates that do not match the release · New R-package DESCRIPTION version bumps are not recognized · New Post-release action exception never expires · New
Resolved since last review (7)
Approval is not bound to the validated commit Unpaginated file listing misses disallowed changes Prefix filtering skips additions and deletions Overly broad pure-insertion auto-approval Numeric changes are not validated by field Post-formatting commits bypass revalidation Example references an action tag released too early
…quests Track a per-commit marker in the human-review comment so a synchronize-triggered re-run doesn't spam duplicate comments and reviewer requests for a PR that still fails the same commit's validation. force-review still overrides the skip. _commit message is ai-generated_
…eedback - Tighten readme validation to only accept version/date token bumps within a recognized citation context (version mention or bibtex month/year), not any line whose token coincidentally matches. - Rewrite the codemeta.json validator to compare old vs new content and only permit version/date fields to change, matching the release. - Require CITATION.cff/codemeta.json date fields to exactly match the release's published/created date instead of only checking the date shape. - Filter approved workflow runs to the validated commit's exact head SHA, not just branch name, and approve them only after the head-SHA concurrency recheck (previously runs could be approved before an aborted approval was detected). - Route PRs with an active human CHANGES_REQUESTED review to human review instead of treating 'not yet approved' as permission to auto-approve. - Fix the version-bump audit for R packages where the version and description files are the same DESCRIPTION file (a validated description role no longer gets silently ignored). - Make the examples test's @main exception for unreleased actions self-expiring, tied to the release it was written against. _commit message is ai-generated_
The review-post-release-pr job's synchronize branch had no sender check, so anyone able to push to a PR titled "chore: post-release cleanup for ..." could trigger the elevated CCBR-bot review token. Require sender.type == 'Bot' for opened/synchronize, matching the existing review_requested check. Also restores the bot-sender check in the README "Example" snippets for review-pre-commit-pr and review-post-release-pr, which had been simplified away. _AI-assisted: Claude Sonnet 5 via Copilot_
…thon
review-post-release-pr and review-pre-commit-pr spliced `${{ inputs.* }}`
directly into the literal text of an embedded `shell: python {0}` script.
Any value expanded there is exploitable as a template-injection vector
(GitHub expands the template before Python ever sees the source). Move
each value into a step-level `env:` and read it via `os.environ[...]`
instead.
_AI-assisted: Claude Sonnet 5 via Copilot_
_validate_codemeta_file treated a previously-present dateModified/ datePublished/dateCreated field going missing as an unchanged field, silently accepting the removal as a valid bump. Require the field to either stay unchanged or be present and match a release date. _AI-assisted: Claude Sonnet 5 via Copilot_
Note that it returns the actor for the most recent run of the given workflow file repo-wide, not necessarily the run tied to the specific release/PR under review. _AI-assisted: Claude Sonnet 5 via Copilot_
_AI-assisted: Claude Sonnet 5 via Copilot_



Changes
review-post-release-pr: automatically reviews post-release cleanup PRs opened by thepost-releaseaction.CITATION.cff,codemeta.json, changelog/news file, and/or readme files) that correspond to an actual GitHub release tag. A readme's re-rendered citation snippet (fromauto-format) is accepted the same way.reviewerinput, the actor that triggered the most recentdraft-release.ymlrun, or the repo's default (catch-all*)CODEOWNERSentry.review-post-release-pras a job in thepre-review-pr.ymlexample workflow, including aworkflow_dispatchre-scan job mirroring the existingreview-pre-commit-prjob.ccbr_actions.post_release_prmodule with the review/validation logic, plus new generic helpers inccbr_actions.pr_review(approve_pending_workflow_runs,get_last_workflow_run_actor).Issues
Resolves #209
PR Checklist
CHANGELOG.mdwith a short description of any user-facing changes and reference the PR number. Guidelines: https://keepachangelog.com/en/1.1.0/AI-assisted: Claude Sonnet 5 via Copilot