From 5a651ab63596ff9223d4a9be753096989f7912bc Mon Sep 17 00:00:00 2001 From: "Deavon M. McCaffery" Date: Mon, 29 Jun 2026 22:11:24 +0100 Subject: [PATCH] fix(merge): grant checks:read so ff-merge can read the check-run rollup ff-merge verifies a PR's status rollup via the Checks API (checks.listForRef), which an App token can only call with checks:read. The least-privilege token mints granted contents/pull-requests/administration/ workflows/issues but not checks, so /merge failed with "Resource not accessible by integration" and the continue-on-error auto-merge paths silently never completed. Add permission-checks: read to every mint step that precedes an ff-merge call, in both merge.yaml and dependabot-merge.yaml. The v1.1.0 callers were unaffected because they minted an unrestricted token that inherited the App's checks grant; the regression landed when v3.0.0 switched to the explicit allow-list and omitted it. Signed-off-by: Deavon M. McCaffery --- .github/workflows/dependabot-merge.yaml | 8 ++++--- .github/workflows/merge.yaml | 32 ++++++++++++++++--------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/dependabot-merge.yaml b/.github/workflows/dependabot-merge.yaml index 61c21a7..4f9712f 100644 --- a/.github/workflows/dependabot-merge.yaml +++ b/.github/workflows/dependabot-merge.yaml @@ -84,12 +84,14 @@ jobs: client-id: ${{ inputs.app-client-id }} private-key: ${{ secrets.app-private-key }} # ff-merge moves the ref (contents) and reads/approves the PR (pull-requests), - # and needs workflows to move a ref whose commits touch .github/workflows/ - # files; the approval (minor/patch only) is the authorization gate, not - # maintainer-only, so no administration scope is needed. + # needs workflows to move a ref whose commits touch .github/workflows/ files, + # and reads the head commit's check-run rollup (checks); the approval + # (minor/patch only) is the authorization gate, not maintainer-only, so no + # administration scope is needed. permission-contents: write permission-pull-requests: write permission-workflows: write + permission-checks: read - name: Resolve the Dependabot PR and assess the update policy id: assess diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml index eec3d17..adfc279 100644 --- a/.github/workflows/merge.yaml +++ b/.github/workflows/merge.yaml @@ -119,14 +119,16 @@ jobs: # Least-privilege within the App's installation ceiling: ff-merge moves the # base ref (contents), reads/comments on the PR (pull-requests), resolves # the actor's access level for maintainer-only (administration), closes the - # PR's linked issues (issues), and moves a ref whose commits touch + # PR's linked issues (issues), moves a ref whose commits touch # .github/workflows/ files (workflows — GitHub rejects any ref update that - # adds or edits a workflow file without it). + # adds or edits a workflow file without it), and reads the head commit's + # check-run rollup to confirm every required check is green (checks). permission-contents: write permission-pull-requests: write permission-administration: read permission-workflows: write permission-issues: write + permission-checks: read - name: Fast-forward merge uses: bitwise-media-group/ff-merge@261714459a53c43ba032fe0e3a3e6f3ab8fd14de # v1.2.0 @@ -165,12 +167,14 @@ jobs: private-key: ${{ secrets.app-private-key }} # Labels and comments on the PR (pull-requests), closes the PR's linked # issues (issues), and moves the ref via the best-effort ff-merge (contents), - # which also needs workflows when the merge touches .github/workflows/ files; - # maintainer-only:false here, so no administration scope is needed. + # which also needs workflows when the merge touches .github/workflows/ files + # and checks to read the head commit's check-run rollup; maintainer-only:false + # here, so no administration scope is needed. permission-contents: write permission-pull-requests: write permission-workflows: write permission-issues: write + permission-checks: read - name: Ensure the auto-merge label is present env: @@ -241,13 +245,15 @@ jobs: client-id: ${{ inputs.app-client-id }} private-key: ${{ secrets.app-private-key }} # ff-merge moves the ref (contents), reads the PR (pull-requests), closes the - # PR's linked issues (issues), and needs workflows to move a ref whose commits - # touch .github/workflows/ files; maintainer-only:false here, so no - # administration scope is needed. + # PR's linked issues (issues), reads the head commit's check-run rollup + # (checks), and needs workflows to move a ref whose commits touch + # .github/workflows/ files; maintainer-only:false here, so no administration + # scope is needed. permission-contents: write permission-pull-requests: write permission-workflows: write permission-issues: write + permission-checks: read - name: Resolve the open PR for this branch id: pr @@ -311,13 +317,15 @@ jobs: client-id: ${{ inputs.app-client-id }} private-key: ${{ secrets.app-private-key }} # ff-merge moves the ref (contents), reads the PR (pull-requests), closes the - # PR's linked issues (issues), and needs workflows to move a ref whose commits - # touch .github/workflows/ files; maintainer-only:false here, so no - # administration scope is needed. + # PR's linked issues (issues), reads the head commit's check-run rollup + # (checks), and needs workflows to move a ref whose commits touch + # .github/workflows/ files; maintainer-only:false here, so no administration + # scope is needed. permission-contents: write permission-pull-requests: write permission-workflows: write permission-issues: write + permission-checks: read - name: Resolve the open PR for this branch id: pr @@ -416,11 +424,13 @@ jobs: client-id: ${{ inputs.app-client-id }} private-key: ${{ secrets.app-private-key }} # ff-merge closes the PR's linked issues (issues) on a successful sweep merge, - # alongside the ref move (contents) and the workflow-file allowance (workflows). + # alongside the ref move (contents), the workflow-file allowance (workflows), + # and reading the head commit's check-run rollup (checks). permission-contents: write permission-pull-requests: write permission-workflows: write permission-issues: write + permission-checks: read - name: Fast-forward merge # Best effort: ff-merge declines a PR that is not yet approved/green (expected