ops(ci): sweep closed-PR preview environments daily#8620
Merged
Conversation
ui-preview.yml / ui-preview-deploy.yml (via the shared deploy-ui-preview composite) create a "preview/pr-<N>" GitHub Environment via createDeployment the first time a PR gets a preview build -- transient_environment: true is only a display hint, it never triggers deletion, and nothing else in the repo ever calls the delete-environment API. Confirmed live: 1254 of 1260 environments were preview/pr-* entries for already-closed PRs (spanning PR #4140-#8617), none carrying protection rules -- cleaned up directly via the API as a one-time sweep before adding this workflow. Mirrors cache-cleanup.yml's existing fix for the identical class of problem (GHA caches instead of environments): batched on a daily schedule, not a pull_request:[closed] trigger, so PR-close bursts never queue a runner per event and compete with real CI. No storage-budget urgency here unlike the 10GB cache cap, so daily is enough. Needs a new ENVIRONMENT_ADMIN_TOKEN secret -- deleting an environment requires repo scope (classic PAT) or Administration:write (fine-grained PAT); GITHUB_TOKEN can never be granted this via a permissions: block, confirmed against GitHub's own docs.
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8620 +/- ##
=======================================
Coverage 92.76% 92.76%
=======================================
Files 797 797
Lines 79355 79355
Branches 24034 24034
=======================================
Hits 73616 73616
Misses 4592 4592
Partials 1147 1147
Flags with carried forward coverage won't be shown. Click here to find out more. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Investigated why the repo had 1260 GitHub Environments — 1254 of them were
preview/pr-<N>entries (spanning PR #4140–#8617), all for already-closed PRs.Root cause:
ui-preview.yml/ui-preview-deploy.yml(via the shareddeploy-ui-previewcomposite action) callcreateDeployment({ environment: "preview/pr-<N>", transient_environment: true, ... })for every PR that gets a UI preview build. GitHub auto-creates the Environment object the first time a deployment targets a name that doesn't exist —transient_environment: trueis purely a display hint for the Deployments UI, it does not trigger any cleanup. Nothing in the repo ever called the delete-environment API. Confirmed none of the 1254 carry protection rules (pure disposable deploy-tracking metadata).Immediate fix: swept and deleted all 1254 directly via the API (using my own already-sufficiently-scoped session token) — 0 environments remain today besides
release,release-beta,preview, and two other pre-existing ones.Ongoing fix (this PR): a new scheduled workflow, mirroring
cache-cleanup.yml's existing fix for the identical class of problem (GHA caches instead of environments) — batched on a daily schedule (07:20 UTC, offset from the other daily cron cluster), not apull_request: [closed]trigger, so PR-close bursts never queue a runner per event and compete with real CI for the org's concurrent-runner cap. There's no storage-budget urgency here the way there was for the 10GB cache cap, so daily (vs. cache-cleanup's 6-hourly) is plenty.Required before this can actually run
ENVIRONMENT_ADMIN_TOKEN— a new repo secret. Deleting an environment requiresreposcope (classic PAT) or Administration: write (fine-grained PAT) — confirmed against GitHub's own docs that the defaultGITHUB_TOKENcan never be granted this via apermissions:block, unlike cache deletion (whichactions: writealready covers). Scope a fine-grained PAT to this repo only with Administration: write, add it as a repo secret (not environment-scoped — this workflow doesn't use a GitHub Environment itself).Test plan
python3 -c "import yaml; yaml.safe_load(...)"— valid YAMLnpm run actionlint— cleanGET /repos/JSONbored/loopover/environmentsnow returns 0preview/pr-*entries