Connecting GitHub and Cloudflare Workers makes it possible to review website changes on a Preview deployment from a working branch.
However, merging work into main does not guarantee that the old Preview disappears. A previous deployment can remain available at a separate address.
This article documents how I explored cleaning up only the matching Preview after the corresponding production deployment has succeeded, using GitHub Actions and Cloudflare APIs.
1. How the cleanup workflow is supposed to work
The intended sequence is:
- A GitHub Pull Request is merged into
main. - GitHub Actions begins the cleanup workflow.
- The workflow checks whether Cloudflare successfully completed a Production Build for the merged commit.
- It identifies the Preview matching the PR branch and commit.
- It deletes only the identified Workers Preview.
If production deployment failed or the Preview cannot be identified conclusively, the workflow should delete nothing. Older Previews created before this automation may require separate investigation.
2. Create a Cloudflare API token
GitHub Actions needs an API token to call Cloudflare.
Open the Cloudflare API Tokens page, choose Create Token → Create Custom Token, and provide a descriptive name such as Preview-Cleanup-Automation.
Permissions to examine
For a workflow that queries Workers Builds and deletes a Workers Preview, consider these permission scopes:
| Scope | Permission | Access |
|---|---|---|
| Account | Workers Builds Configuration | Edit |
| Account | Workers Scripts | Edit |
The Workers Builds API requires a user-scoped API token. Verify the actual permission names and requirements against Cloudflare's current documentation and the specific API calls you plan to make. Grant no more access than needed.
Additional token settings
- Account Resources: Prefer the one account used by this automation rather than
All accounts. - Client IP Address Filtering: GitHub-hosted runners can change IP addresses. Leave this filter unset if you do not use a predictable source IP.
- TTL: Choose expiration according to your security policy. If you set an expiration date, remember to refresh the GitHub Secret before then.
Proceed through Continue to summary → Create Token and store the token securely. Its plaintext may not be displayed again after creation.
Distinguish a token used by Cloudflare's own build/deployment service from a token GitHub Actions uses to call the Cloudflare API.
3. Find the Cloudflare Account ID
In the Cloudflare dashboard, open Workers & Pages for the intended account and locate the Account ID under account details. Cloudflare also maintains instructions for finding account and zone IDs.
An Account ID is not your sign-in email address or a Zone ID.
| Value | Meaning |
|---|---|
| Account ID | Identifier for the Cloudflare account |
| Zone ID | Identifier for a particular domain zone |
| Address used to sign in to Cloudflare | |
| API Token | Secret authentication string for API calls |
Verify that the identifier belongs to the account hosting the relevant Worker.
4. Register GitHub Actions Secrets
Open the relevant repository on GitHub and navigate to:
Settings → Secrets and variables → Actions → New repository secret
You can also use a URL in this form:
https://github.com/OWNER/REPOSITORY/settings/secrets/actions
Replace OWNER and REPOSITORY with the actual owner and repository name.
| Secret name | Value to enter |
|---|---|
CLOUDFLARE_API_TOKEN | The API token issued by Cloudflare |
CLOUDFLARE_ACCOUNT_ID | The Cloudflare Account ID |
The names on the left are the names that the workflow references. The values on the right must be taken from your own account. Never paste secrets into source code or a published blog article.
Existing GitHub Secret values cannot be read back through the interface. If a value is incorrect, update it.
5. Connect safe cleanup to GitHub Actions
Place a workflow YAML file under .github/workflows/ in the repository.
It should enforce the following conditions:
- Handle the
pull_requestclosedevent. - Confirm the PR was actually merged into
main. - Exclude pull requests from external forks.
- Verify that the Production Build succeeded for the corresponding merge commit SHA.
- Compare PR branch, commit, and Preview URL using Cloudflare Builds API metadata.
- Delete only the matching Workers Preview.
You can use supported Wrangler Preview-deletion functionality if appropriate. Do not guess a Preview identifier merely from a branch name, and do not treat every deployment-specific URL as a branch Preview.
Legacy Version Previews and Workers Previews need to be distinguished. If the evidence is insufficient to identify a deletion target, skip deletion.
This workflow can be triggered by a PR merge instead of running repeatedly on a timer.
6. The Account ID mistake I actually made
While setting this up, I accidentally entered my Cloudflare sign-in email address as CLOUDFLARE_ACCOUNT_ID.
GitHub Actions started, but Worker lookup failed with:
Cloudflare Worker lookup failed with HTTP 404 (Cloudflare errors: 7003)
That initially looked like it could be a token permission problem. In the actual incident, though, the confirmed mistake was entering an email address where an Account ID was expected.
If you see a similar error, check:
- Is this the correct Cloudflare Account ID?
- Did you accidentally enter an email address or a Zone ID?
- Does the API token apply to the intended account?
- Does the token have the permissions needed to inspect builds and delete the Preview?
After fixing the Secret, you can rerun the GitHub Actions workflow.
7. Verify that the Preview really disappeared
Open the repository's Actions tab and inspect the workflow run.
A workflow running does not by itself mean the Preview was deleted. Confirm:
- Did the corresponding Production deployment finish successfully?
- Was only this PR's Preview selected?
- Did the deletion operation complete successfully?
- Does the old Preview URL no longer serve the deleted Preview?
If the target cannot be identified, cleanup must be skipped. Neither the production Worker nor another branch's Preview should be affected.
Automation reduces repetitive tasks, but only when its authentication, permissions, target identification, and failure behavior have been verified.
Why I started thinking about cleanup
I did not begin by wanting to automate Preview deletion.
I started by finding it frustrating to exchange HTML files every time I wanted to review a blog draft. That led to a broader investigation of GitHub branches, Cloudflare Preview, and a simpler editorial workflow.
During that process I realized that a Preview might remain after a merge, and I started exploring GitHub Actions to clean it up.
I described how the initial inconvenience gradually led me to think about this automation in a separate Story.
Related readingFrom Exchanging HTML Files to Rethinking How I Publish My BlogStarting with the inconvenience of reviewing HTML files, I considered private GitHub branches and Cloudflare Zero Trust before choosing separate editorial and visual review stages.