|
31 | 31 | # namespace on top: untrusted fork runs must never share a cache with |
32 | 32 | # push runs (whose caches feed production image builds) or with trusted |
33 | 33 | # internal-PR runs. |
| 34 | + # |
| 35 | + # node_modules ALSO keys on the lockfile hash, the other two deliberately |
| 36 | + # do not. A sticky disk is a persistent mutable volume, so every branch |
| 37 | + # sharing one key shares one node_modules tree, and `bun install |
| 38 | + # --frozen-lockfile` installs what the lockfile needs without pruning what |
| 39 | + # it no longer references. Branches cut before a dependency bump therefore |
| 40 | + # wrote their older copies onto the shared disk and every other branch |
| 41 | + # inherited them — that is how builds on next 16.2.11 ended up loading a |
| 42 | + # stale @next/swc 16.2.6 that appears nowhere in bun.lock. Hashing the |
| 43 | + # lockfile gives each distinct dependency set its own disk, so a tree can |
| 44 | + # never mix versions from two different lockfiles. |
| 45 | + # |
| 46 | + # The bun download cache is content-addressed by package+version and the |
| 47 | + # Turbo cache is keyed by task hash, so both are safe to share across |
| 48 | + # lockfiles — and sharing them is what keeps a fresh node_modules disk |
| 49 | + # cheap to populate. |
34 | 50 | - name: Mount Bun cache |
35 | 51 | uses: ./.github/actions/cache-mount |
36 | 52 | with: |
|
42 | 58 | uses: ./.github/actions/cache-mount |
43 | 59 | with: |
44 | 60 | provider: ${{ vars.CI_PROVIDER }} |
45 | | - key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }} |
| 61 | + key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }} |
46 | 62 | path: ./node_modules |
47 | 63 |
|
48 | 64 | - name: Mount Turbo cache |
@@ -193,8 +209,10 @@ jobs: |
193 | 209 | # Next.js production build, in parallel with lint + tests. Sticky disks are |
194 | 210 | # cloned from the last committed snapshot per job and committed last-writer- |
195 | 211 | # wins, so concurrent mounts are safe. The bun/node_modules disks are shared |
196 | | - # with test-build (identical content from the same lockfile — LWW loss is |
197 | | - # harmless), but the Turbo cache gets its own key: with a shared key, only |
| 212 | + # with test-build — and because the node_modules key now includes the lockfile |
| 213 | + # hash, the two jobs only ever share a disk when they really do resolve the |
| 214 | + # same dependency tree, so the LWW loss really is harmless. The Turbo cache |
| 215 | + # gets its own key: with a shared key, only |
198 | 216 | # the last committer's new entries survive each run, so the test and build |
199 | 217 | # Turbo entries would evict each other nondeterministically. |
200 | 218 | # Same next build as the app image, so it needs a large runner. Peak RSS |
@@ -236,7 +254,7 @@ jobs: |
236 | 254 | uses: ./.github/actions/cache-mount |
237 | 255 | with: |
238 | 256 | provider: ${{ vars.CI_PROVIDER }} |
239 | | - key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }} |
| 257 | + key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }} |
240 | 258 | path: ./node_modules |
241 | 259 |
|
242 | 260 | - name: Mount Turbo cache |
|
0 commit comments