From f89625afe7449588aa5211e6db2cdf2abcc0af66 Mon Sep 17 00:00:00 2001 From: Stefan Kapferer Date: Fri, 23 Oct 2026 10:42:30 +0200 Subject: [PATCH] Clean up outdated preview deployments Cloudflare Pages keeps all deployments. Delete the preview deployments of deleted branches and all but the latest one of each existing branch when a branch is deleted, weekly, and on demand. --- .github/workflows/preview-cleanup.yml | 54 +++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 55 insertions(+) create mode 100644 .github/workflows/preview-cleanup.yml diff --git a/.github/workflows/preview-cleanup.yml b/.github/workflows/preview-cleanup.yml new file mode 100644 index 0000000..16319fb --- /dev/null +++ b/.github/workflows/preview-cleanup.yml @@ -0,0 +1,54 @@ +name: Clean up Previews + +# Cloudflare Pages keeps all deployments forever. This workflow deletes the preview deployments +# of deleted branches and all but the latest preview deployment of each existing branch. +on: + delete: + schedule: + - cron: '0 3 * * 1' + workflow_dispatch: + +permissions: + contents: read + +env: + CLOUDFLARE_PROJECT: contextmapper-preview + +jobs: + cleanup: + name: Delete outdated Preview Deployments + runs-on: ubuntu-latest + + steps: + - name: Delete outdated preview deployments + run: | + API="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PROJECT/deployments" + gh api "repos/$GITHUB_REPOSITORY/branches" --paginate --jq '.[].name' | jq -R . | jq -s . > branches.json + + # collect all preview deployments first (deleting while paging would shift the pages) + echo '[]' > deployments.json + page=1 + while :; do + result=$(curl -sSf -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" "$API?env=preview&per_page=25&page=$page" | jq '.result') + [ "$(jq length <<< "$result")" -eq 0 ] && break + jq -s 'add' deployments.json <(echo "$result") > tmp.json && mv tmp.json deployments.json + page=$((page + 1)) + done + echo "Found $(jq length deployments.json) preview deployments" + + # outdated: the branch does not exist anymore, or it is not the latest deployment of the branch + jq -r --slurpfile branches branches.json ' + group_by(.deployment_trigger.metadata.branch) + | map(sort_by(.created_on) | reverse + | if (.[0].deployment_trigger.metadata.branch | IN($branches[0][])) then .[1:] else . end) + | flatten | .[] | "\(.id) \(.deployment_trigger.metadata.branch)"' deployments.json > outdated.txt + + while read -r id branch; do + echo "Deleting deployment $id (branch: $branch)" + curl -sSf -X DELETE -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" "$API/$id?force=true" > /dev/null + done < outdated.txt + echo "Deleted $(wc -l < outdated.txt) outdated preview deployments" + env: + GH_TOKEN: ${{ github.token }} + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} diff --git a/README.md b/README.md index 21a7787..d21223e 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ To preview the website locally, follow these steps: ## Deployment and Previews * **Production:** every push to `master` is built with Jekyll and deployed to [https://contextmapper.org/](https://contextmapper.org/) (GitHub Pages) by the [Build & Deploy Website](.github/workflows/deploy.yml) workflow. Pull requests are built (but not deployed) by the same workflow. * **Previews:** to review changes in the browser before merging them, run the [Deploy Preview (manual)](.github/workflows/preview.yml) workflow on your branch (_Actions_ > _Deploy Preview (manual)_ > _Run workflow_ > select the branch). The branch is deployed to Cloudflare Pages and the URL is shown in the workflow run summary (`https://.contextmapper-preview.pages.dev`). The previews are protected by Cloudflare Access; ask a maintainer to get access. + * **Preview cleanup:** the [Clean up Previews](.github/workflows/preview-cleanup.yml) workflow deletes the preview deployments of deleted branches and keeps only the latest deployment of each existing branch (runs when a branch is deleted, weekly, and manually). ## Contribution If you think something is missing on our documentation website and you still have unanswered questions, we are happy if you create an issue [here](https://github.com/ContextMapper/contextmapper.github.io/issues) allowing us to improve the docs. PRs are always welcome as well!