ci: auto-label PRs "Work in progress" from review state - #10294
ci: auto-label PRs "Work in progress" from review state#10294igorpecovnik wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe pull request adds review-event and scheduled workflows that synchronize the “Work in progress” label using review decisions and unresolved threads. Approval cleanup no longer removes that label, and the shared script supports both single-PR and all-open-PR synchronization. ChangesWork-in-progress label synchronization
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant PullRequestReview
participant ReviewListener
participant WipWorkflow
participant WipLabelScript
participant GitHubGraphQL
participant PullRequestLabels
PullRequestReview->>ReviewListener: Submit, edit, or dismiss review
ReviewListener->>WipWorkflow: Upload PR number artifact
WipWorkflow->>WipLabelScript: Call syncOne for the reviewed PR
WipLabelScript->>GitHubGraphQL: Query review decision and unresolved threads
GitHubGraphQL-->>WipLabelScript: Return review state and thread count
WipLabelScript->>PullRequestLabels: Add or remove Work in progress label
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/maintenance-label-wip.yml:
- Around line 17-18: Replace the unsupported pull_request_review_thread trigger
in the workflow’s on configuration with a supported GitHub Actions trigger, or
remove the workflow if no suitable trigger is needed. If synchronization for
resolved and unresolved review threads must remain, use a cron/polling trigger
or external dispatch mechanism.
- Line 38: Update the workflow’s pull_request_review handling to address
fork-origin PRs: either authenticate label operations with a trusted
write-capable identity instead of the read-only fork-event GITHUB_TOKEN, or add
an explicit repository/branch condition that excludes fork PRs before label
add/remove steps run.
- Around line 25-30: Update the wip-label job to define a concurrency group
scoped to the pull request number and enable cancellation of superseded runs,
ensuring only the latest workflow run for each PR performs WIP label
synchronization.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 9d737439-5eab-400a-8057-afdda66cf24e
📒 Files selected for processing (2)
.github/workflows/maintenance-label-on-approval.yml.github/workflows/maintenance-label-wip.yml
34a447d to
2581851
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
.github/workflows/maintenance-label-wip-sweep.yml (3)
25-28: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winReduce pull-request permission to read-only.
The helper reads review state and manages PR labels through Issues endpoints; it does not modify pull requests. Use
pull-requests: readand verify thereviewThreadsquery still succeeds. GitHub exposes label management through Issues endpoints and review APIs with read-level pull-request access. (docs.github.com)Proposed fix
issues: write - pull-requests: write + pull-requests: read🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/maintenance-label-wip-sweep.yml around lines 25 - 28, Update the permissions block in the maintenance-label WIP sweep workflow to change pull-requests access from write to read, while retaining contents read and issues write. Verify the existing reviewThreads query continues to succeed with the reduced permission.
31-31: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winDisable checkout credential persistence.
The token is persisted for Git commands by default, but this job already passes it explicitly to
github-script. Prevent checked-out code from accessing unnecessary Git credentials:Proposed fix
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/maintenance-label-wip-sweep.yml at line 31, Update the actions/checkout step in the maintenance-label workflow to disable credential persistence by setting persist-credentials to false; leave the existing checkout reference and github-script token handling unchanged.Source: Linters/SAST tools
33-39: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSurface per-PR synchronization failures.
syncAllOpencurrently warns and continues when an individual PR fails, so this step can be green while labels remain stale. Configure retries and have the helper aggregate failed PRs, then callcore.setFailedafter the sweep completes.github-scriptotherwise performs no request retries by default. (github.com)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/maintenance-label-wip-sweep.yml around lines 33 - 39, Update the “Sync Work in progress” step invoking syncAllOpen to configure github-script request retries. Modify syncAllOpen to aggregate individual PR synchronization failures while completing the sweep, then have the workflow call core.setFailed with the aggregated failure details after syncAllOpen returns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/maintenance-label-wip-sweep.yml:
- Around line 3-8: Update the workflow’s actions/checkout configuration to
explicitly use the repository’s default branch ref for manual workflow_dispatch
runs, ensuring the sweep always executes the default-branch version of
.github/scripts/wip-label.js. Leave the scheduled trigger behavior and remaining
workflow logic unchanged.
In @.github/workflows/maintenance-label-wip.yml:
- Around line 34-54: Change the artifact handling before the “Sync "Work in
progress" for the PR” step to download into $RUNNER_TEMP rather than the trusted
workspace. Update the pr step to read only the expected $RUNNER_TEMP/pr.txt
artifact, validating the PR number before exporting it, so the checkout’s
.github/scripts/wip-label.js cannot be overwritten by PR-origin content.
---
Nitpick comments:
In @.github/workflows/maintenance-label-wip-sweep.yml:
- Around line 25-28: Update the permissions block in the maintenance-label WIP
sweep workflow to change pull-requests access from write to read, while
retaining contents read and issues write. Verify the existing reviewThreads
query continues to succeed with the reduced permission.
- Line 31: Update the actions/checkout step in the maintenance-label workflow to
disable credential persistence by setting persist-credentials to false; leave
the existing checkout reference and github-script token handling unchanged.
- Around line 33-39: Update the “Sync Work in progress” step invoking
syncAllOpen to configure github-script request retries. Modify syncAllOpen to
aggregate individual PR synchronization failures while completing the sweep,
then have the workflow call core.setFailed with the aggregated failure details
after syncAllOpen returns.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 672f8d88-e913-4727-95d2-56ccb0ed63f3
📒 Files selected for processing (5)
.github/scripts/wip-label.js.github/workflows/maintenance-label-on-approval.yml.github/workflows/maintenance-label-wip-sweep.yml.github/workflows/maintenance-label-wip.yml.github/workflows/maintenance-listen-review-wip.yml
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/maintenance-label-on-approval.yml
Adds automation that keeps the "Work in progress" label in sync with a PR's review state: present while a review requests changes or any conversation is unresolved, cleared once neither holds. GitHub Actions has no trigger for a review conversation being resolved, and pull_request_review from a fork gets a read-only GITHUB_TOKEN, so a single pull_request_review-triggered workflow cannot do this. Use a hybrid instead: - .github/scripts/wip-label.js -- shared logic (reviewDecision + paginated unresolved reviewThreads -> add/remove the label), so the event and cron paths can never drift. - maintenance-listen-review-wip.yml -- listens on pull_request_review with a read-only token (fork-safe) and just records the PR number as an artifact. - maintenance-label-wip.yml -- workflow_run worker fired by the listener; runs in the default-branch context with a write token, checks out the trusted script and syncs the one PR. Per-PR concurrency, newer reviews supersede. - maintenance-label-wip-sweep.yml -- scheduled backstop that recomputes the label for every open PR, catching conversation resolution (which has no event) and any missed events. Hardening: the listener artifact is fork-controlled, so the worker downloads it into RUNNER_TEMP (never the checkout) so it cannot overwrite the trusted script before github-script runs it; the sweep pins checkout to the default branch so a workflow_dispatch on another branch cannot run that branch's script; both set persist-credentials: false. Also drop "Work in progress" from the blanket removal list in maintenance-label-on-approval.yml (now owned by this automation) and quote $GITHUB_OUTPUT there (shellcheck SC2086). Signed-off-by: Igor Pecovnik <igor@armbian.com>
2581851 to
0b00307
Compare
Keeps the
Work in progresslabel in sync with a PR's review state: present while a review requests changes or any conversation is unresolved, cleared once neither holds.Why hybrid
Two hard GitHub constraints rule out a single
pull_request_review-triggered workflow (thanks @coderabbitai for catching both):pull_request_review_threadis a webhook event but not a valid Actions trigger — actionlint rejects it. So nothing fires when a thread is resolved/unresolved.GITHUB_TOKENonpull_request_review, so directaddLabels/removeLabelwould silently fail on any fork PR.So this uses an event path (fast, for the common cases) plus a cron backstop (for the case that has no event):
.github/scripts/wip-label.jsreviewDecision+ paginated unresolvedreviewThreads→ add/remove label. Single source of truth so the two paths can't drift.maintenance-listen-review-wip.ymlpull_request_reviewwith a read-only token (fork-safe); only records the PR number as an artifact.maintenance-label-wip.ymlworkflow_runworker fired by the listener — runs in the default-branch context with a write token, checks out the trusted script, syncs that one PR.maintenance-label-wip-sweep.yml*/30), recomputes the label for every open PR — catches conversation resolution and any missed events.How this addresses the review
pull_request_review_threadtrigger → removed entirely; conversation-resolution is handled by the cron sweep instead.workflow_run/schedulecontext, which has a write token even for fork PRs. The worker checks out the default branch, so the label logic is never PR-authored code.cancel-in-progress; the sweep serialises with its own group.Also
Work in progressfrom the blanket removal list inmaintenance-label-on-approval.yml(now owned by this automation, so an approved-but-unresolved PR keeps the label until resolved), and quoted$GITHUB_OUTPUTthere (shellcheck SC2086).Work in progresslabel already exists in.github/labels.yml.actionlint— clean.Trade-off / tunables
The event path is instant for "changes requested" and re-reviews. The one case with no event — resolving the last conversation without submitting a review — is picked up by the sweep within its cron interval (
*/30, tunable). Set it looser to reduce Actions runs, tighter for faster resolution latency.