Skip to content

Commit 998fd5a

Browse files
authored
fix(ci): scope the Next.js build cache sticky disk per branch (#6072)
* fix(ci): scope the Next.js build cache sticky disk per branch The Turbopack persistent build cache disk was keyed on github.event_name alone, so every open PR shared one mutable volume. A sticky disk mount clones the last committed snapshot and commits back last-write-wins, so each PR build restored a cache produced by a different branch. Measured on the same staging commit, two runs minutes apart: the single-writer push disk compiled in 9.3 min, the shared pull_request disk in 14.0 min. Across 22 recent runs, push builds land at 3.5-11 min and PR builds at 13.5-17.8 min. Correctness matters more than the minutes here. turbopackFileSystemCacheForBuild is beta and cross-commit restore is not a documented-supported mode - vercel/next.js#87283 reports stale HTML from a cache built at another commit, with no maintainer answer. Every other cache layer in this repo already isolates by branch: GitHub's cache cannot read sibling branches, and Blacksmith's cache product branch-scopes by default. Only this key didn't. Adds pre/post-build cache size reporting, because whether the cache was warm is otherwise invisible - the disk mounts either way and turbo buffers the build log. Adds ci-cache-cleanup.yml to delete a branch's disk when its PR closes, so per-branch disks track open PRs instead of accumulating at ~5 GB each. Also corrects the 105s-cold/22s-warm comment: those were local numbers and have never reproduced in CI. * refactor(ci): trim the cache-key comments to the load-bearing facts Keeps the mechanism (one mutable volume per key, clone-on-mount, last-write-wins) and the two numbers, drops the restated reasoning. Both report steps collapse to a single du, dropping a second full walk of a ~5 GB tree. Cleanup workflow loses a concurrency group a once-per-PR delete never needed.
1 parent 161b21f commit 998fd5a

2 files changed

Lines changed: 58 additions & 6 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CI Cache Cleanup
2+
3+
# test-build.yml keys the Next.js build cache sticky disk per branch, so every PR
4+
# leaves a ~5 GB volume behind. Branches are short-lived; the disks aren't. Only
5+
# the pull_request disks are reclaimed — the push disks belong to main/staging/dev
6+
# and must stay warm.
7+
8+
on:
9+
pull_request:
10+
types: [closed]
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
delete-nextjs-cache:
17+
name: Delete Next.js build cache disk
18+
# Sticky disks only exist on Blacksmith; the GitHub break-glass path uses
19+
# actions/cache, which expires on its own.
20+
if: vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith'
21+
runs-on: blacksmith-2vcpu-ubuntu-2404
22+
timeout-minutes: 5
23+
24+
steps:
25+
# Must stay byte-identical to the Mount Next.js build cache key in
26+
# test-build.yml, or this deletes nothing and the disks accumulate.
27+
# Non-blocking: PRs skipped by ci.yml's paths-ignore never made a disk.
28+
- name: Delete sticky disk
29+
uses: useblacksmith/stickydisk-delete@b41313d28b8647d72114c9ba3c96bb04061562b6 # v1
30+
continue-on-error: true
31+
with:
32+
delete-key: ${{ github.repository }}-nextjs-cache-pull_request${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ github.head_ref }}

.github/workflows/test-build.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,21 @@ jobs:
265265

266266
# Turbopack's persistent build cache (NEXT_TURBOPACK_BUILD_CACHE below)
267267
# writes ~5 GB into .next/cache — a sticky disk mounts it in ~1s where an
268-
# actions/cache round-trip would eat the warm-build win. Same event/fork
269-
# namespacing as the other mounts; the GitHub fallback inside cache-mount
270-
# still uses actions/cache with a run_id-suffixed key.
268+
# actions/cache round-trip would eat the warm-build win.
269+
#
270+
# Keyed per branch, not just per event. A sticky disk is one mutable volume
271+
# per key: mounting clones the last committed snapshot, job end commits back
272+
# last-write-wins. An event-only key had every open PR restoring a cache
273+
# built from a different branch — 14.0 min vs 9.3 min for the single-writer
274+
# push disk on the same commit. Branch scoping also keeps us off
275+
# cross-commit restore, which turbopackFileSystemCacheForBuild (beta) does
276+
# not document as supported (vercel/next.js#87283: stale HTML from a cache
277+
# built at another commit). ci-cache-cleanup.yml reclaims the disks.
271278
- name: Mount Next.js build cache
272279
uses: ./.github/actions/cache-mount
273280
with:
274281
provider: ${{ vars.CI_PROVIDER }}
275-
key: ${{ github.repository }}-nextjs-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}
282+
key: ${{ github.repository }}-nextjs-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ github.head_ref || github.ref_name }}
276283
path: ./apps/sim/.next/cache
277284

278285
# Running out of RAM kills the whole VM and surfaces only as "the runner
@@ -293,6 +300,13 @@ jobs:
293300
- name: Install dependencies
294301
run: bun install --frozen-lockfile --ignore-scripts
295302

303+
# The disk mounts successfully whether or not it carried anything and turbo
304+
# buffers the build log, so cache warmth is otherwise unobservable — #5859
305+
# shipped a cache that carried almost nothing and it took a PR to notice.
306+
# Reported, never gated.
307+
- name: Report Next.js cache size (pre-build)
308+
run: du -sh apps/sim/.next/cache 2>/dev/null || echo 'cold — no cache restored'
309+
296310
- name: Build application
297311
env:
298312
NODE_OPTIONS: '--no-warnings --max-old-space-size=8192'
@@ -304,7 +318,13 @@ jobs:
304318
AWS_REGION: 'us-west-2'
305319
ENCRYPTION_KEY: '7cf672e460e430c1fba707575c2b0e2ad5a99dddf9b7b7e3b5646e630861db1c' # dummy key for CI only
306320
TURBO_CACHE_DIR: .turbo
307-
# Opt into Turbopack's persistent build cache (beta) for this CI
308-
# check build only — measured 105s cold vs 22s warm locally.
321+
# Opt into Turbopack's persistent build cache (beta) for this CI check
322+
# build only. #5869's 105s-cold/22s-warm was measured locally and has
323+
# never reproduced in CI (compile has ranged 3.5-17.8 min) — local
324+
# numbers, not a CI target.
309325
NEXT_TURBOPACK_BUILD_CACHE: '1'
310326
run: bunx turbo run build --filter=sim
327+
328+
- name: Report Next.js cache size (post-build)
329+
if: always()
330+
run: du -sh apps/sim/.next/cache 2>/dev/null || echo 'no cache written'

0 commit comments

Comments
 (0)