Skip to content

Commit b126a86

Browse files
committed
feat(sw): stamp CACHE_NAME with git hash on Release publish
Source carries a hand-bumped 'ona-plotter-vNNN' literal that has to be incremented for every shell-asset change or the browser keeps serving the previous version's cache. A new StampPublishedServiceWorker MSBuild target rewrites the published copy of service-worker.js with the commit hash already computed by StampBuildInfo, so every build is automatically cache-unique and the source line just stays as a sane default. The stamp script anchors its regex on the CACHE_NAME assignment so TILE_CACHE_NAME (different lifecycle) isn't touched. Source file is untouched; only the publish output changes.
1 parent 54a09b3 commit b126a86

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

OnaPlotter/OnaPlotter.csproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,28 @@
188188
Condition="'@(_JsToMinify)' != ''" />
189189
</Target>
190190

191+
<!-- Stamp the published service-worker.js CACHE_NAME with the git
192+
hash so a new build invalidates the browser's installed SW
193+
cache. Source carries a hand-bumped placeholder
194+
(const CACHE_NAME = 'ona-plotter-vNNN'); this target rewrites
195+
it in the publish output only, leaving the source clean. Runs
196+
after MinifyPublishedJs so the stamped name lives in the
197+
version the helm actually downloads.
198+
199+
OnaGitHash is computed by the StampBuildInfo target earlier
200+
in the build; on git-less environments it falls back to
201+
"unknown", in which case every cacheless deploy lands on the
202+
same key. That's a deliberate trade-off vs failing the build
203+
in environments that have no .git directory (tarball builds,
204+
certain CI containers). -->
205+
<Target Name="StampPublishedServiceWorker"
206+
AfterTargets="MinifyPublishedJs"
207+
Condition="'$(Configuration)' == 'Release'">
208+
<PropertyGroup>
209+
<_SwPath>$(PublishDir)wwwroot\service-worker.js</_SwPath>
210+
</PropertyGroup>
211+
<Exec Command="node &quot;$(MSBuildThisFileDirectory)..\scripts\stamp-cache-name.mjs&quot; &quot;$(_SwPath)&quot; &quot;$(OnaGitHash)&quot;"
212+
Condition="Exists('$(_SwPath)')" />
213+
</Target>
214+
191215
</Project>

scripts/stamp-cache-name.mjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env node
2+
//
3+
// Stamps the service worker's CACHE_NAME with a deploy-unique identifier
4+
// so a new build invalidates the browser's installed cache. Without this,
5+
// the SW reuses the cache keyed by the hand-bumped 'ona-plotter-vNNN'
6+
// literal, and stale .wasm / .js / .css get served from cache until the
7+
// helm hard-refreshes.
8+
//
9+
// Invoked from OnaPlotter.csproj's StampPublishedServiceWorker target on
10+
// Release publish. Two args:
11+
//
12+
// node stamp-cache-name.mjs <path-to-service-worker.js> <git-hash>
13+
//
14+
// Patches in place. Idempotent: matches /ona-plotter-[\w-]+/ at the
15+
// CACHE_NAME assignment line so re-running with a different hash works.
16+
// Fails non-zero (and explains) if no match is found - a future rename
17+
// of CACHE_NAME would otherwise silently skip the stamp and let stale
18+
// caches leak through.
19+
//
20+
21+
import { readFileSync, writeFileSync } from 'node:fs';
22+
23+
const [, , swPath, hash] = process.argv;
24+
if (!swPath || !hash) {
25+
console.error('usage: stamp-cache-name.mjs <path> <hash>');
26+
process.exit(2);
27+
}
28+
29+
const src = readFileSync(swPath, 'utf8');
30+
31+
// Anchor the regex on the CACHE_NAME assignment to avoid catching the
32+
// TILE_CACHE_NAME (which has its own lifecycle) or any incidental
33+
// "ona-plotter-..." substring elsewhere in the file.
34+
const pattern = /(const CACHE_NAME = ')ona-plotter-[\w-]+(')/;
35+
if (!pattern.test(src)) {
36+
console.error(
37+
`stamp-cache-name: no 'const CACHE_NAME = "ona-plotter-..."' line ` +
38+
`found in ${swPath}. Did the assignment shape change?`,
39+
);
40+
process.exit(1);
41+
}
42+
43+
const patched = src.replace(pattern, `$1ona-plotter-${hash}$2`);
44+
writeFileSync(swPath, patched);
45+
console.log(`stamp-cache-name: CACHE_NAME = ona-plotter-${hash} in ${swPath}`);

0 commit comments

Comments
 (0)