Skip to content

fix(ci): preview cleanup no longer fails on GitHub environment delete#71

Merged
kentcdodds merged 2 commits intomainfrom
cursor/fix-preview-env-cleanup-token-67ec
Apr 12, 2026
Merged

fix(ci): preview cleanup no longer fails on GitHub environment delete#71
kentcdodds merged 2 commits intomainfrom
cursor/fix-preview-env-cleanup-token-67ec

Conversation

@kentcdodds
Copy link
Copy Markdown
Member

Summary

Run 24308663446 failed on Cleanup Preview Resources with HttpError: Resource not accessible by integration at the Delete GitHub preview environment step.

Root cause

  • #69 added a step that calls DELETE /repos/{owner}/{repo}/environments/{environment_name}.
  • The default GITHUB_TOKEN is not allowed to delete deployment environments (GitHub returns 403 for this API).
  • #70 removed environments: write from workflow permissions because that key is invalid for workflow YAML validation — but that permission was never a real fix for this API limitation anyway.

So the failure is not transient; it will recur on every PR close until the step stops throwing on 403.

Changes

  • Treat 403 like 404 for this step: log a warning and continue so Cloudflare cleanup still completes and the job is green.
  • Support optional repo secret PREVIEW_ENV_CLEANUP_TOKEN (PAT with repo admin for this repository) passed to actions/github-script as github-token when maintainers want automatic GitHub environment removal.
  • Document the behavior and secret in docs/agents/setup.md.

Verification

  • bun run lint and bun run typecheck pass.
  • bun run validate still fails on prettier --check for several pre-existing files in the workspace (unchanged by this PR); formatted only the touched docs file.
Open in Web Open in Cursor 

The cleanup job calls DELETE /repos/.../environments/... which returns 403 for
the default GITHUB_TOKEN. PR #70 removed invalid workflow permission
environments: write, which did not fix token scope anyway.

Catch 403 so PR-close cleanup succeeds after Cloudflare teardown. Use optional
secret PREVIEW_ENV_CLEANUP_TOKEN when a repo wants automatic environment
removal, and document it in the setup guide.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 12, 2026

🔎 Preview deployed: https://epicflare-pr-71.kentcdodds.workers.dev

Worker: epicflare-pr-71
D1: epicflare-pr-71-db
KV: epicflare-pr-71-oauth-kv

Mocks:

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Misleading 403 warning when custom PAT is used
    • Updated the 403 warning to describe missing permissions for the current token and distinguish between default token usage and PAT scope issues.
Preview (95db2843fb)
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -561,6 +561,10 @@
           INPUT_TARGET: ${{ inputs.target }}
           INPUT_PR_NUMBER: ${{ inputs.pr_number }}
         with:
+          # The default GITHUB_TOKEN cannot delete deployment environments (403).
+          # Optional: set repo secret PREVIEW_ENV_CLEANUP_TOKEN to a PAT with repo
+          # scope (classic) or Administration: write (fine-grained) for this repo.
+          github-token: ${{ secrets.PREVIEW_ENV_CLEANUP_TOKEN || github.token }}
           script: |
             const eventName = process.env.EVENT_NAME;
             let envName;
@@ -606,6 +610,14 @@
                 core.info(
                   `GitHub environment not found (already deleted): ${envName}`,
                 );
+              } else if (e.status === 403) {
+                core.warning(
+                  [
+                    `Cannot delete GitHub environment "${envName}" with the current token (403).`,
+                    "The current token may not have permission to delete environments.",
+                    "If you're using the default workflow token, add repository secret PREVIEW_ENV_CLEANUP_TOKEN (PAT: classic `repo`, or fine-grained with Administration read/write on this repository). If you're already using a PAT, ensure it has the required permissions.",
+                  ].join(" "),
+                );
               } else {
                 throw e;
               }

diff --git a/docs/agents/setup.md b/docs/agents/setup.md
--- a/docs/agents/setup.md
+++ b/docs/agents/setup.md
@@ -121,6 +121,16 @@
 When a PR is closed, the cleanup job deletes the preview Worker(s) and these
 resources as well.
 
+The same cleanup job removes the matching GitHub deployment environment
+(`preview-<pr>`). GitHub’s default `GITHUB_TOKEN` cannot call the delete
+environment API (you would see HTTP 403). That step is non-fatal: the workflow
+still succeeds and Cloudflare resources are still removed. To delete the GitHub
+environment automatically, add an Actions secret named
+`PREVIEW_ENV_CLEANUP_TOKEN` whose value is a personal access token with
+permission to administer this repository (for example a classic PAT with the
+`repo` scope, or a fine-grained PAT with **Administration** read and write on
+this repo only).
+
 Cloudflare Workers supports version `preview_urls`, but those preview URLs are
 not currently available for Workers that use Durable Objects. The main app
 Worker binds `MCP_OBJECT`, so app previews continue to use per-PR Worker names.

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 392c571. Configure here.

Comment thread .github/workflows/preview.yml
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds kentcdodds merged commit a6bf373 into main Apr 12, 2026
8 checks passed
@kentcdodds kentcdodds deleted the cursor/fix-preview-env-cleanup-token-67ec branch April 12, 2026 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants