fix(docs): retain prior builds' hashed assets across Pages deploys

Pages serves exactly the newest artifact, so every push-triggered deploy
deleted the previous build's content-hashed JS/CSS while edge caches
(max-age=300, stale-while-revalidate=3600) kept serving HTML that
referenced them. With deploys landing every ~15-30 min, docs pages spent
most of the day pointing at 404'd bundles — search (pure client JS) was
the loudest casualty.

Fix: keep a rolling 14-day pool of hashed assets (en + zh-Hans) in the
Actions cache and union-merge it into each deploy artifact, current
build authoritative on collision (cp --update=none). Stale HTML and
already-open tabs now keep resolving across any number of deploys.
This commit is contained in:
Teknium
2026-08-08 05:51:51 -07:00
parent d135f64b51
commit 3d7dda4cf4

View File

@@ -189,6 +189,61 @@ jobs:
cp website/build/llms-full.txt _site/llms-full.txt
fi
# Pages serves exactly the newest artifact, so each deploy used to delete
# the previous build's content-hashed JS/CSS while edge caches (Vercel →
# Fastly, max-age=300 + stale-while-revalidate=3600) kept serving HTML
# that referenced it — every asset request 404'd for up to ~65 minutes
# after each deploy. With push-triggered deploys landing every ~15-30
# minutes, the docs were in that broken window most of the day (search,
# being pure client JS, died first). Fix: keep a rolling pool of prior
# builds' hashed assets and union-merge it into every artifact so stale
# HTML keeps resolving. Hashed filenames are content-addressed, so a
# collision is by definition the identical file — the merge never
# overwrites current-build output (cp --update=none).
- name: Restore asset retention pool
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: _asset_retention
key: docs-asset-retention-${{ github.run_id }}
restore-keys: |
docs-asset-retention-
- name: Merge retained assets from previous deploys
run: |
set -euo pipefail
ASSET_DIRS="assets zh-Hans/assets"
mkdir -p _asset_retention
# 1) Add this build's hashed assets to the pool (fresh mtimes, so
# assets still shipped by current builds never age out).
for d in $ASSET_DIRS; do
if [ -d "_site/docs/$d" ]; then
mkdir -p "_asset_retention/$d"
cp -a "_site/docs/$d/." "_asset_retention/$d/"
fi
done
# 2) Drop pool entries no build has produced for 14 days — far
# beyond any edge-cache or open-tab horizon.
find _asset_retention -type f -mtime +14 -delete
find _asset_retention -type d -empty -delete
# 3) Union-merge the pool into the artifact; --update=none keeps the
# current build authoritative for any path it produced.
for d in $ASSET_DIRS; do
if [ -d "_asset_retention/$d" ]; then
mkdir -p "_site/docs/$d"
cp -R --update=none "_asset_retention/$d/." "_site/docs/$d/"
fi
done
echo "retention pool:" && du -sh _asset_retention
echo "deployed assets:" && du -sh _site/docs/assets
- name: Save asset retention pool
# Always save under a fresh key (caches are immutable); restore-keys
# prefix matching picks the newest on the next run.
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: _asset_retention
key: docs-asset-retention-${{ github.run_id }}
- name: Upload artifact
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with: