Skip to content

Commit f85cb00

Browse files
authored
Merge pull request #3 from flexion/fix/deployment-hygiene
fix: deployment hygiene — concurrency, CNAME, per-branch previews
2 parents 574b64f + de532c2 commit f85cb00

6 files changed

Lines changed: 752 additions & 10 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ permissions:
1111
deployments: write
1212

1313
concurrency:
14-
group: deploy-${{ github.ref }}
14+
group: deploy-${{ github.event_name == 'delete' && github.event.ref || github.ref_name }}
1515
cancel-in-progress: true
1616

1717
jobs:
@@ -66,11 +66,11 @@ jobs:
6666
retention-days: 3
6767

6868
publish:
69-
if: github.event_name == 'push'
69+
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
7070
needs: build-and-test
7171
runs-on: ubuntu-latest
7272
environment:
73-
name: ${{ needs.build-and-test.outputs.is_production == 'true' && 'production' || 'preview' }}
73+
name: ${{ needs.build-and-test.outputs.is_production == 'true' && 'production' || format('preview/{0}', needs.build-and-test.outputs.branch) }}
7474
url: ${{ needs.build-and-test.outputs.is_production == 'true' && 'https://labs.flexion.us/' || format('https://labs.flexion.us/preview/{0}/', needs.build-and-test.outputs.branch) }}
7575
steps:
7676
- name: Check out or bootstrap gh-pages
@@ -112,9 +112,6 @@ jobs:
112112
mkdir -p "$(dirname "$rel")"
113113
cp -r ../dist "$rel"
114114
fi
115-
if [ ! -f CNAME ]; then
116-
cp ../CNAME . 2>/dev/null || true
117-
fi
118115
119116
- name: Commit and push gh-pages
120117
working-directory: gh-pages-work
@@ -133,6 +130,7 @@ jobs:
133130
runs-on: ubuntu-latest
134131
permissions:
135132
contents: write
133+
deployments: write
136134
steps:
137135
- name: Check out gh-pages (skip if absent)
138136
id: checkout
@@ -165,3 +163,35 @@ jobs:
165163
git commit -m "Remove preview for deleted branch $SANITIZED"
166164
git push origin gh-pages
167165
fi
166+
167+
- name: Deactivate preview deployments for the deleted branch
168+
env:
169+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
170+
run: |
171+
set -euo pipefail
172+
SANITIZED="$(echo "${{ github.event.ref }}" | tr '/' '-' | tr -cd 'a-zA-Z0-9._-')"
173+
ENV_NAME="preview/$SANITIZED"
174+
# List all deployments for this environment. Paginate to be safe.
175+
deployment_ids="$(gh api \
176+
--method GET \
177+
-H 'Accept: application/vnd.github+json' \
178+
"/repos/${GITHUB_REPOSITORY}/deployments?environment=${ENV_NAME}&per_page=100" \
179+
--paginate \
180+
--jq '.[].id' || true)"
181+
if [ -z "$deployment_ids" ]; then
182+
echo "No deployments found for environment $ENV_NAME."
183+
exit 0
184+
fi
185+
echo "$deployment_ids" | while read -r id; do
186+
[ -z "$id" ] && continue
187+
echo "Marking deployment $id inactive."
188+
if ! output=$(gh api \
189+
--method POST \
190+
-H 'Accept: application/vnd.github+json' \
191+
"/repos/${GITHUB_REPOSITORY}/deployments/${id}/statuses" \
192+
-f state=inactive \
193+
-f description='Branch deleted; preview removed.' 2>&1); then
194+
echo "::warning::Failed to mark deployment $id inactive: $output"
195+
fi
196+
done
197+

docs/deployment.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ The site is hosted on GitHub Pages with a custom domain.
1717

1818
## Workflow
1919

20-
`.github/workflows/deploy.yml` runs on every push:
20+
`.github/workflows/deploy.yml` runs on every push, on branch delete, and on manual `workflow_dispatch`:
2121

2222
1. Installs Bun, runs the test suite, builds the site with `SITE_BASE_URL` set to `/` for `main` or `/preview/<branch>/` for other branches.
2323
2. Runs the axe-core a11y scan against the built output.
2424
3. Checks out `gh-pages`, syncs the build output into the right directory, commits, and pushes.
25-
4. Registers a GitHub Deployment against the `production` or `preview` environment so the URL appears in the PR "Deployments" panel.
25+
4. Registers a GitHub Deployment against the `production` environment (for main) or a per-branch `preview/<sanitized-branch>` environment, so every branch's URL appears in the PR "Deployments" panel and the repo's Deployments page can be used to navigate per-branch preview state.
2626

27-
When a branch is deleted, a cleanup job removes `preview/<sanitized-branch>/` from `gh-pages`.
27+
Concurrency is keyed on the acted-on branch name, not `github.ref`. A `delete` event against `feat/foo` and a `push` to `main` run in different concurrency groups, so a branch cleanup cannot cancel a production deploy.
28+
29+
When a branch is deleted, the `cleanup-preview` job runs and does two things:
30+
- Removes `preview/<sanitized-branch>/` from `gh-pages`.
31+
- Marks every deployment in the `preview/<sanitized-branch>` environment as `inactive` so the GitHub UI stops showing them as live.
32+
33+
The environment entry itself persists in the Deployments sidebar. Deleting environments requires repo-admin rights that `GITHUB_TOKEN` cannot be granted via `permissions:`; that step would need a PAT-backed secret and has been deferred.
2834

2935
## Custom domain
3036

31-
`CNAME` at the source repo root contains `labs.flexion.us`. The workflow copies it to `gh-pages` if absent.
37+
`CNAME` at the source repo root contains `labs.flexion.us`. The build driver (`src/build/entry.tsx`) copies it into `dist/` on production builds only — preview subdirectories must not carry a CNAME.
3238

3339
## Base path
3440

0 commit comments

Comments
 (0)