From a02a504511e6e71447a6a5018e343069b2231838 Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Sun, 24 May 2026 14:03:26 -0500 Subject: [PATCH] fix(ci): scoped permissions for preview-smoke + visual-diff workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Playwright-on-Vercel workflows fail at the very first action (`patrickedqvist/wait-for-vercel-preview@v1.3.2`) with 403 "Resource not accessible by integration". The cause is the repo-default workflow token being read-only-by-default with no scopes declared by the workflow. Add minimal scoped permission blocks per the GitHub Actions least-privilege guidance: preview-smoke.yml: contents: read deployments: read # wait-for-vercel-preview queries GitHub Deployments pull-requests: read # correlate deployment with this PR statuses: read # some Vercel deployments use commit statuses visual-diff.yml: contents: read deployments: read pull-requests: write # final step posts "Visual Diff" comment via Issues API statuses: read Verified against the failure on PR #15: - Playwright smoke: "Resource not accessible by integration" on wait-for-vercel-preview → fixed by deployments+statuses+pull-requests:read - Screenshot diff: 403 from POST /repos/.../issues/15/comments with `x-accepted-github-permissions: issues=write; pull_requests=write` in the response → fixed by pull-requests:write (covers Issues API for PR comments; issues:write would also work but pull-requests:write is the idiomatic scope) Unblocks visual-regression signal on every future PR. No code changes, no test changes — workflow YAML only. Co-authored-by: Cursor --- .github/workflows/preview-smoke.yml | 12 ++++++++++++ .github/workflows/visual-diff.yml | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/.github/workflows/preview-smoke.yml b/.github/workflows/preview-smoke.yml index ffd5c8b..a4f7a73 100644 --- a/.github/workflows/preview-smoke.yml +++ b/.github/workflows/preview-smoke.yml @@ -19,6 +19,18 @@ concurrency: group: preview-smoke-${{ github.event.pull_request.number }} cancel-in-progress: true +# Default workflow token is read-only on this repo. The `wait-for-vercel-preview` +# action needs `deployments: read` to query Vercel's GitHub Deployment status, +# plus `statuses: read` because some Vercel deployments use commit statuses +# instead of the Deployments API. `pull-requests: read` lets it correlate the +# deployment back to this PR. Without these, the action 403s on the Checks API +# and the smoke job fails before Playwright even starts. +permissions: + contents: read + deployments: read + pull-requests: read + statuses: read + jobs: gate: name: Should run? diff --git a/.github/workflows/visual-diff.yml b/.github/workflows/visual-diff.yml index 5c34b87..eec3606 100644 --- a/.github/workflows/visual-diff.yml +++ b/.github/workflows/visual-diff.yml @@ -18,6 +18,16 @@ concurrency: group: visual-diff-${{ github.event.pull_request.number }} cancel-in-progress: true +# `deployments: read` + `statuses: read` are required by wait-for-vercel-preview +# (see preview-smoke.yml for context). `pull-requests: write` is required by the +# final github-script step that posts the "Visual Diff" comment back to the PR; +# without it the API returns 403 even though the screenshots upload fine. +permissions: + contents: read + deployments: read + pull-requests: write + statuses: read + jobs: gate: name: Should run?