Skip to content

Commit 5e84965

Browse files
ci: add Surface Tag release+purge (Step 2) and drop the stale bundle-guard
surface-forms (packages/surface-scripts) now owns the tag source and pushes the built surface_tag.js / surface_embed_v1.js to this repo. Add the release-and-purge workflow: on a push to main that changes those files, cut the next semver release (so jsDelivr @latest advances) and purge the CDN (raw + .min.js) fail-loud. Remove the ci.yml 'Bundle is up to date' step — it rebuilds from this repo's now non-authoritative src/ and would diff against the pushed bytes and red main.
1 parent 0dfbb41 commit 5e84965

2 files changed

Lines changed: 79 additions & 7 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ jobs:
2727

2828
- name: Unit tests
2929
run: pnpm test
30-
31-
# surface_tag.js / surface_embed_v1.js are committed CDN artifacts.
32-
# Fail if src/ was edited without rebuilding them.
33-
- name: Bundle is up to date
34-
run: |
35-
pnpm run build
36-
git diff --exit-code surface_tag.js surface_embed_v1.js
30+
# NOTE: the "Bundle is up to date" build-guard was removed — surface-forms
31+
# (packages/surface-scripts) now owns the tag source and pushes the built
32+
# surface_tag.js / surface_embed_v1.js here, so rebuilding from this repo's
33+
# (now non-authoritative) src/ would diff against the pushed bytes and fail main.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# STEP 2 of the two-step Surface Tag publish pipeline.
2+
#
3+
# Step 1 (surface-forms/.github/workflows/push-scripts-to-cdn.yml): builds the two bundles and pushes
4+
# them to this repo's main in one commit (via the "Scripts Repo Deploy" GitHub App).
5+
# Step 2 (this file): that push triggers this workflow, which cuts a release (advancing jsDelivr
6+
# @latest) and purges the CDN so customers get the new bytes immediately.
7+
#
8+
# No provisioned token needed — this Action acts on its OWN repo, so the built-in GITHUB_TOKEN (granted
9+
# contents:write below) is enough. surface-forms is now the source of truth; this repo only serves the
10+
# built artifacts it pushes (the ci.yml "Bundle is up to date" build-guard is removed in this same PR).
11+
12+
name: Release Surface Tag + purge CDN
13+
14+
on:
15+
push:
16+
branches: [main]
17+
# Only react to a real tag-bundle change, not docs/readme commits.
18+
paths:
19+
- surface_tag.js
20+
- surface_embed_v1.js
21+
22+
permissions:
23+
contents: write
24+
25+
# Never let two releases race (e.g. two quick pushes); run them one at a time.
26+
concurrency:
27+
group: release-surface-tag
28+
cancel-in-progress: false
29+
30+
jobs:
31+
release-and-purge:
32+
runs-on: ubuntu-latest
33+
steps:
34+
# jsDelivr @latest resolves to the highest SEMVER release, and this repo already uses v1.1.x — so
35+
# bump the PATCH of the latest release (v1.1.8 -> v1.1.9). Date-based tags would break @latest:
36+
# leading zeros (2026.09.02) are not valid semver, so jsDelivr would ignore them. target = the exact
37+
# pushed commit, so @latest serves precisely these bytes.
38+
- name: Cut a release for the pushed commit
39+
env:
40+
GH_TOKEN: ${{ github.token }}
41+
run: |
42+
set -euo pipefail
43+
latest=$(gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq '.tag_name' 2>/dev/null || echo "v1.1.0")
44+
ver=${latest#v} # strip an optional leading v
45+
IFS=. read -r MAJOR MINOR PATCH <<< "${ver}"
46+
RELEASE_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
47+
echo "Latest release ${latest}; cutting ${RELEASE_TAG} at ${GITHUB_SHA}"
48+
gh api -X POST "repos/${GITHUB_REPOSITORY}/releases" \
49+
-f tag_name="${RELEASE_TAG}" \
50+
-f target_commitish="${GITHUB_SHA}" \
51+
-f name="${RELEASE_TAG}" \
52+
-f body="Surface Tag synced from surface-forms (packages/surface-scripts)."
53+
echo "Released ${RELEASE_TAG}; jsDelivr @latest now resolves to this commit."
54+
55+
# jsDelivr caches aggressively; purge so @latest / @main serve the new bytes immediately instead of
56+
# up to 7 days later. A swallowed purge failure would show a green release while customers keep stale
57+
# bytes, so fail loudly.
58+
- name: Purge jsDelivr cache
59+
run: |
60+
set -euo pipefail
61+
purge_failed=0
62+
for f in surface_tag.js surface_tag.min.js surface_embed_v1.js surface_embed_v1.min.js; do
63+
for ref in latest main; do
64+
url="https://purge.jsdelivr.net/gh/${GITHUB_REPOSITORY}@${ref}/${f}"
65+
echo "Purging ${url}"
66+
if ! curl -sfS "${url}"; then
67+
echo "::warning::purge failed for ${url}"
68+
purge_failed=1
69+
fi
70+
done
71+
done
72+
if [ "${purge_failed}" -ne 0 ]; then
73+
echo "::error::One or more jsDelivr purges failed; @latest/@main may serve stale bytes. Re-run the purge."
74+
exit 1
75+
fi

0 commit comments

Comments
 (0)