diff --git a/.github/workflows/pr-auto-review.yml b/.github/workflows/pr-auto-review.yml index 49bd1eb9f..420c83440 100644 --- a/.github/workflows/pr-auto-review.yml +++ b/.github/workflows/pr-auto-review.yml @@ -8,7 +8,7 @@ # reusable workflow above. # • You MAY change: the workflow name(s) in `workflow_run.workflows` to match # your repository's CI workflow name(s). -# • You MUST NOT change: the `@pr-auto-review/v1-next` channel in the `uses:` +# • You MUST NOT change: the `@pr-auto-review/v1-stable` channel in the `uses:` # line — this reusable is on the org-wide moving-channel model (rollout and # rollback are a single central tag move; a frozen `@vN`/`@` pin is # rejected by the compliance audit). Nor the trigger event types or the @@ -44,25 +44,37 @@ on: permissions: {} +# Deduplicate ONLY the default-branch-context triggers (issue #1126). On GitHub +# Free (20 concurrent jobs, org-wide) this stub fanned out per trigger. Its runs +# split by context: +# • check_suite / workflow_run — head_branch=main, the check does NOT attach to +# the PR head, so superseding an in-flight run is SAFE. Both events collapse +# onto one group per PR (`…-pr-`) with cancel-in-progress: true. +# • pull_request / pull_request_review — run on the PR head; a cancelled run +# would leave a cancelled `pr-auto-review / check-and-dispatch` check on the +# head. They get a unique-per-run group and never cancel, so they behave +# exactly as before. +# A default-branch trigger with no associated PR (fork / no PR) also falls back to +# the unique-per-run group so unrelated PRs never collapse into one group. +concurrency: + group: >- + ${{ + (github.event_name == 'check_suite' && github.event.check_suite.pull_requests[0].number) + && format('pr-auto-review-ready-check-pr-{0}', github.event.check_suite.pull_requests[0].number) + || (github.event_name == 'workflow_run' && github.event.workflow_run.pull_requests[0].number) + && format('pr-auto-review-ready-check-pr-{0}', github.event.workflow_run.pull_requests[0].number) + || format('pr-auto-review-ready-check-unique-{0}', github.run_id) + }} + cancel-in-progress: ${{ github.event_name == 'check_suite' || github.event_name == 'workflow_run' }} + jobs: pr-auto-review: - # Skip Dependabot-authored events (#1390, mirrors the #864 guard in - # dev-lead-reusable.yml): a Dependabot `pull_request` run has no access to - # GH_PAT_WORKFLOWS, so the secrets expression below resolves empty and the - # reusable's ready-check checkout fails at startup with - # "Input required and not supplied: token". Dependabot PRs are handled by - # dependabot-automerge.yml and never need the review-agent dispatch, so - # skipping cleanly here removes the false failure without touching the - # channel, trigger event types, or permissions block. - # Two conditions: actor covers Dependabot-triggered events (pull_request, - # workflow_run); PR-author login covers pull_request_review events where the - # actor is the human reviewer, not Dependabot. if: github.actor != 'dependabot[bot]' && github.event.pull_request.user.login != 'dependabot[bot]' permissions: pull-requests: read checks: read actions: read - uses: petry-projects/.github/.github/workflows/pr-auto-review-reusable.yml@pr-auto-review/v1-next # NOSONAR(githubactions:S7637) first-party channel ref + uses: petry-projects/.github/.github/workflows/pr-auto-review-reusable.yml@pr-auto-review/v1-stable # NOSONAR(githubactions:S7637) first-party channel ref secrets: # Canonical-first fallback (.github-private#1326). The reusable resolves this # secret BY NAME, so only the VALUE changes — the passed key stays named diff --git a/.github/workflows/test-dev-lead.yml b/.github/workflows/test-dev-lead.yml index 802f28ca7..5922fdc51 100644 --- a/.github/workflows/test-dev-lead.yml +++ b/.github/workflows/test-dev-lead.yml @@ -268,5 +268,5 @@ jobs: persist-credentials: false - name: Install PyYAML run: python3 -m pip install --quiet --only-binary ":all:" pyyaml==6.0.3 - - name: Validate pr-auto-review.yml skips Dependabot and pins @pr-auto-review/v1-next + - name: Validate pr-auto-review.yml skips Dependabot and pins @pr-auto-review/v1-stable run: python3 tests/dev-lead/integration/test_pr_auto_review_stub.py diff --git a/tests/dev-lead/integration/test_pr_auto_review_stub.py b/tests/dev-lead/integration/test_pr_auto_review_stub.py index 534afab8c..8427ec9c8 100644 --- a/tests/dev-lead/integration/test_pr_auto_review_stub.py +++ b/tests/dev-lead/integration/test_pr_auto_review_stub.py @@ -10,7 +10,7 @@ reusable's checkout. Dependabot PRs are handled by dependabot-automerge.yml and never need the review-agent dispatch. -Regression guard: dropping the Dependabot guard (or repinning off the @pr-auto-review/v1-next +Regression guard: dropping the Dependabot guard (or repinning off the @pr-auto-review/v1-stable channel) reintroduces the failure class. """ from __future__ import annotations @@ -24,7 +24,7 @@ WORKFLOW = ".github/workflows/pr-auto-review.yml" REUSABLE = "petry-projects/.github/.github/workflows/pr-auto-review-reusable.yml" -EXPECTED_REF = "@pr-auto-review/v1-next" +EXPECTED_REF = "@pr-auto-review/v1-stable" DEPENDABOT_ACTOR = "dependabot[bot]" @@ -69,7 +69,7 @@ def main() -> int: failures.append( f" Wrong ref: {ref!r}\n" f" Expected: '{REUSABLE}{EXPECTED_REF}'\n" - " Reason: first-party reusable must stay on the @pr-auto-review/v1-next\n" + " Reason: first-party reusable must stay on the @pr-auto-review/v1-stable\n" " moving channel (AGENTS.md §Release channel tags)." )