Skip to content

Commit c717e3e

Browse files
committed
circleci: fix cache save by eliminating fan-in workspace collision
Problem: CircleCI throws 'Concurrent upstream jobs persisted the same file(s) into the workspace' when multiple jobs try to persist the same paths (packages/x86, build/x86, etc.) simultaneously. Previous approach: Used separate save_cache_x86/save_cache_ppc64 jobs that attached multiple upstream workspaces, but still hit the fan-in collision. Fix: Each seed job saves its cache immediately after building, before persisting to workspace. No fan-in jobs needed. New job types: - build_and_persist_save_cache_x86: x86-musl-cross-make only, saves musl cache - build_and_persist_save_cache_coreboot_x86: per-fork seeds, saves fork-specific coreboot+toolchain cache keyed with -<coreboot_dir> suffix - build_and_persist_save_cache_ppc64: talos-2 builds toolchain+board, saves all Cache restore: Added per-fork fallback keys in prep_env to match the new fork-specific cache key format (e.g., ...-coreboot-dasharo_msi_z790). Each coreboot fork now has its own cache: - coreboot-dasharo_nv4x (novacustom-nv4x_adl) - coreboot-dasharo_v56 (novacustom-v560tu) - coreboot-purism (librem_14) - coreboot-25.09 (EOL_t480-hotp-maximized) - coreboot-4.11 (EOL_librem_l1um) - coreboot-dasharo_msi_z690 (UNTESTED_msi_z690a_ddr4) - coreboot-dasharo_msi_z790 (UNTESTED_msi_z790p_ddr4) Last fork (UNTESTED_msi_z790p_ddr4) also saves full modules cache. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
1 parent dc5d23f commit c717e3e

1 file changed

Lines changed: 145 additions & 103 deletions

File tree

.circleci/config.yml

Lines changed: 145 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,19 @@ jobs:
7575
command: |
7676
find ./flake.lock modules/musl-cross-make* -type f | sort -h | xargs sha256sum > ./tmpDir/musl-cross-make.sha256sums
7777
- restore_cache:
78-
# First matched/found key wins and following keys are not tried
7978
keys:
80-
# Cache for matching modules digest, validated to be exactly the same as in GitHub current commit.
81-
# This cache was made on top of below caches, if previously existing.
82-
# If no module definition changed, we reuse this one
79+
# First matched/found key wins and following keys are not tried.
8380
# x86 caches
8481
- nix-docker-heads-modules-x86-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
85-
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
82+
# coreboot-musl cache: exact match + fork fallbacks
83+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-dasharo_msi_z790
84+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-dasharo_msi_z690
85+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-4.11
86+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-25.09
87+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-purism
88+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-dasharo_v56
89+
- nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-coreboot-dasharo_nv4x
8690
- nix-docker-heads-musl-cross-make-x86-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
87-
# Cache for coreboot module (and patches) and musl-cross-make digests (coreboot: triannual release)
8891
# ppc64 caches
8992
- nix-docker-heads-modules-ppc64-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
9093
- nix-docker-heads-coreboot-musl-cross-make-ppc64-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
@@ -175,78 +178,137 @@ jobs:
175178
target: <<parameters.target>>
176179
subcommand: <<parameters.subcommand>>
177180

178-
save_cache_x86:
181+
# build_and_persist_save_cache_x86: builds musl-cross-make for x86 and saves the
182+
# musl-cross-make cache immediately. Used only for x86-musl-cross-make.
183+
# Workspace chain: prep_env -> here (linear, no collision).
184+
build_and_persist_save_cache_x86:
179185
docker:
180-
# Docker image: tlaurion/heads-dev-env:v0.2.9
181186
- image: tlaurion/heads-dev-env@sha256:96f8f91c6464305c4a990d59f9ef93910c16c7fd0501a46b43b34a4600a368de
182187
resource_class: large
183188
working_directory: ~/heads
189+
parameters:
190+
target:
191+
type: string
192+
subcommand:
193+
type: string
184194
steps:
185195
- attach_workspace:
186196
at: ~/heads
187-
- save_cache:
188-
# Generate cache for the same musl-cross-make module definition if hash is not previously existing
189-
# CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
190-
key: nix-docker-heads-musl-cross-make-x86-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
197+
- build_board:
198+
arch: x86
199+
target: << parameters.target >>
200+
subcommand: << parameters.subcommand >>
201+
- persist_to_workspace:
202+
root: ~/heads
191203
paths:
192-
- build/x86/musl-cross-make-fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c
193-
- crossgcc/x86
194204
- packages/x86
205+
- build/x86
206+
- crossgcc/x86
207+
- install/x86
195208
- save_cache:
196-
# Generate cache for the same coreboot and musl-cross-make modules definition if hash is not previously existing
197-
# CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
198-
key: nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
209+
key: nix-docker-heads-musl-cross-make-x86-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
199210
paths:
200-
- build/x86/coreboot-4.11
201-
- build/x86/coreboot-24.02.01
202-
- build/x86/coreboot-25.09
203-
- build/x86/coreboot-dasharo_v56
204-
- build/x86/coreboot-dasharo_nv4x
205-
- build/x86/coreboot-dasharo_msi_z790
206-
- build/x86/coreboot-dasharo_msi_z690
207-
- build/x86/coreboot-purism
208211
- build/x86/musl-cross-make-fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c
209212
- crossgcc/x86
210213
- packages/x86
211-
- save_cache:
212-
# Generate cache for the exact same modules definitions if hash is not previously existing
213-
key: nix-docker-heads-modules-x86-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
214+
215+
# build_and_persist_save_cache_coreboot_x86: builds a coreboot fork seed board and
216+
# saves its fork-specific coreboot+toolchain cache immediately after building.
217+
# Used for each distinct coreboot fork (24.02.01, purism, 25.09, 4.11, dasharo_*).
218+
# Workspace chain at this point: prep_env -> x86-musl-cross-make -> here.
219+
# Still linear — no concurrent upstream collision.
220+
# Each fork saves only the coreboot dirs it built, keyed on coreboot+musl digest.
221+
# The full modules cache (nix-docker-heads-modules-x86) is saved by the last fork.
222+
build_and_persist_save_cache_coreboot_x86:
223+
docker:
224+
- image: tlaurion/heads-dev-env@sha256:96f8f91c6464305c4a990d59f9ef93910c16c7fd0501a46b43b34a4600a368de
225+
resource_class: large
226+
working_directory: ~/heads
227+
parameters:
228+
target:
229+
type: string
230+
subcommand:
231+
type: string
232+
coreboot_dir:
233+
type: string
234+
description: "The build/x86/coreboot-* directory built by this fork (e.g. coreboot-24.02.01)"
235+
save_full_modules_cache:
236+
type: boolean
237+
default: false
238+
description: "Set true only on the last coreboot fork in sequence to save the full modules cache"
239+
steps:
240+
- attach_workspace:
241+
at: ~/heads
242+
- build_board:
243+
arch: x86
244+
target: << parameters.target >>
245+
subcommand: << parameters.subcommand >>
246+
- persist_to_workspace:
247+
root: ~/heads
214248
paths:
249+
- packages/x86
215250
- build/x86
251+
- crossgcc/x86
216252
- install/x86
253+
- save_cache:
254+
key: nix-docker-heads-coreboot-musl-cross-make-x86-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}-<< parameters.coreboot_dir >>
255+
paths:
256+
- build/x86/<< parameters.coreboot_dir >>
257+
- build/x86/musl-cross-make-fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c
217258
- crossgcc/x86
218259
- packages/x86
219-
220-
221-
222-
save_cache_ppc64:
260+
- when:
261+
condition: << parameters.save_full_modules_cache >>
262+
steps:
263+
- save_cache:
264+
key: nix-docker-heads-modules-x86-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
265+
paths:
266+
- build/x86
267+
- install/x86
268+
- crossgcc/x86
269+
- packages/x86
270+
271+
# build_and_persist_save_cache_ppc64: builds ppc64 toolchain and talos-2 board,
272+
# saves all ppc64 caches immediately. ppc64 has only one coreboot fork, so no
273+
# fan-in and no workspace collision.
274+
build_and_persist_save_cache_ppc64:
223275
docker:
224-
# Docker image: tlaurion/heads-dev-env:v0.2.9
225276
- image: tlaurion/heads-dev-env@sha256:96f8f91c6464305c4a990d59f9ef93910c16c7fd0501a46b43b34a4600a368de
226277
resource_class: large
227278
working_directory: ~/heads
279+
parameters:
280+
target:
281+
type: string
282+
subcommand:
283+
type: string
228284
steps:
229285
- attach_workspace:
230286
at: ~/heads
287+
- build_board:
288+
arch: ppc64
289+
target: << parameters.target >>
290+
subcommand: << parameters.subcommand >>
291+
- persist_to_workspace:
292+
root: ~/heads
293+
paths:
294+
- packages/ppc64
295+
- build/ppc64
296+
- crossgcc/ppc64
297+
- install/ppc64
231298
- save_cache:
232-
# Generate cache for the same musl-cross-make module definition if hash is not previously existing
233-
# CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
234299
key: nix-docker-heads-musl-cross-make-ppc64-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
235300
paths:
236301
- build/ppc64/musl-cross-make-fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c
237302
- crossgcc/ppc64
238303
- packages/ppc64
239304
- save_cache:
240-
# Generate cache for the same coreboot and musl-cross-make modules definition if hash is not previously existing
241-
# CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
242305
key: nix-docker-heads-coreboot-musl-cross-make-ppc64-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
243306
paths:
244307
- build/ppc64/coreboot-talos_2
245308
- build/ppc64/musl-cross-make-fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c
246309
- crossgcc/ppc64
247310
- packages/ppc64
248311
- save_cache:
249-
# Generate cache for the exact same modules definitions if hash is not previously existing
250312
key: nix-docker-heads-modules-ppc64-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
251313
paths:
252314
- build/ppc64
@@ -261,98 +323,94 @@ workflows:
261323
jobs:
262324
- prep_env
263325

264-
# This step builds musl-cross-make for x86 architecture, which will be used by subsequent x86 board builds
265-
- build_and_persist:
326+
# ── x86 toolchain seed ────────────────────────────────────────────────
327+
# Builds musl-cross-make for x86. Saves musl-cross-make cache immediately.
328+
# Chain: prep_env -> here (linear, no collision).
329+
- build_and_persist_save_cache_x86:
266330
name: x86-musl-cross-make
267331
target: EOL_t480-hotp-maximized
268332
subcommand: "musl-cross-make"
269333
requires:
270334
- prep_env
271335

272-
# This step builds musl-cross-make for ppc64 architecture, which will be used by subsequent ppc64 board builds
273-
- build_and_persist:
274-
name: ppc64-musl-cross-make
275-
arch: ppc64
336+
# ── ppc64 toolchain + board ───────────────────────────────────────────
337+
# Builds musl-cross-make then talos-2 board. Saves all ppc64 caches.
338+
# Chain: prep_env -> ppc64-musl-cross-make -> UNTESTED_talos-2 (linear, no collision).
339+
- build_and_persist_save_cache_ppc64:
340+
name: UNTESTED_talos-2
276341
target: UNTESTED_talos-2
277-
subcommand: "musl-cross-make"
342+
subcommand: ""
278343
requires:
279344
- prep_env
280345

281-
# Below, sequentially build one board for each coreboot version.
282-
# The last board in the sequence is the dependency for the parallel boards built at the end, and also save_cache.
346+
# ── coreboot fork seeds (x86) ─────────────────────────────────────────
347+
# Each seed builds exactly one coreboot fork toolchain and saves its own
348+
# fork-specific cache keyed on coreboot_dir. No fan-in -> no workspace collision.
349+
# Chain for all: prep_env -> x86-musl-cross-make -> here (linear)
283350

284-
# coreboot 24.02.01
285-
- build_and_persist:
351+
# coreboot-dasharo_nv4x
352+
- build_and_persist_save_cache_coreboot_x86:
286353
name: novacustom-nv4x_adl
287354
target: novacustom-nv4x_adl
288355
subcommand: ""
356+
coreboot_dir: coreboot-dasharo_nv4x
289357
requires:
290358
- x86-musl-cross-make
291359

292-
# coreboot purism: builds 24.02.01 toolchain, all librem boards share it
293-
- build_and_persist:
360+
# coreboot-dasharo_v56
361+
- build_and_persist_save_cache_coreboot_x86:
362+
name: novacustom-v560tu
363+
target: novacustom-v560tu
364+
subcommand: ""
365+
coreboot_dir: coreboot-dasharo_v56
366+
requires:
367+
- x86-musl-cross-make
368+
369+
# coreboot-purism
370+
- build_and_persist_save_cache_coreboot_x86:
294371
name: librem_14
295372
target: librem_14
296373
subcommand: ""
374+
coreboot_dir: coreboot-purism
297375
requires:
298376
- x86-musl-cross-make
299377

300-
# t480 is based on 25.09 coreboot release, not sharing any buildstack from now, depend on muscl-cross cache
301-
- build_and_persist:
378+
# coreboot-25.09
379+
- build_and_persist_save_cache_coreboot_x86:
302380
name: EOL_t480-hotp-maximized
303381
target: EOL_t480-hotp-maximized
304382
subcommand: ""
383+
coreboot_dir: coreboot-25.09
305384
requires:
306385
- x86-musl-cross-make
307386

308-
# coreboot talos_2
309-
- build_and_persist:
310-
name: UNTESTED_talos-2
311-
arch: ppc64
312-
target: UNTESTED_talos-2
313-
subcommand: ""
314-
requires:
315-
- ppc64-musl-cross-make
316-
317-
# coreboot 4.11
318-
- build_and_persist:
387+
# coreboot-4.11
388+
- build_and_persist_save_cache_coreboot_x86:
319389
name: EOL_librem_l1um
320390
target: EOL_librem_l1um
321391
subcommand: ""
392+
coreboot_dir: coreboot-4.11
322393
requires:
323394
- x86-musl-cross-make
324395

325-
# dasharo_msi: builds its own toolchain, msi_z690a_ddr5 depends on it
326-
- build_and_persist:
396+
# coreboot-dasharo_msi_z690
397+
- build_and_persist_save_cache_coreboot_x86:
327398
name: UNTESTED_msi_z690a_ddr4
328399
target: UNTESTED_msi_z690a_ddr4
329400
subcommand: ""
401+
coreboot_dir: coreboot-dasharo_msi_z690
330402
requires:
331403
- x86-musl-cross-make
332404

333-
# Dasharo forks: each fork builds its own toolchain (FSP header incompatibilities)
334-
# - novacustom-nv4x_adl: builds dasharo_nv4x toolchain, nitropad-ns50 reuses it
335-
# - novacustom-v560tu: builds dasharo_v56 toolchain, v540tu reuses it
336-
# - UNTESTED_msi_z690a_ddr4: builds dasharo_msi_z690 toolchain, msi_z690a_ddr5 reuses it
337-
# - UNTESTED_msi_z790p_ddr4: builds dasharo_msi_z790 toolchain, msi_z790p_ddr5 reuses it
338-
339-
# x86: combines x86 workspaces and saves x86 cache
340-
# Workspaces combined: x86-musl-cross-make, novacustom-nv4x_adl, librem_14,
341-
# EOL_t480-hotp-maximized, EOL_librem_l1um, UNTESTED_msi_z690a_ddr4
342-
- save_cache_x86:
405+
# coreboot-dasharo_msi_z790 — last fork seed, also saves full modules cache
406+
- build_and_persist_save_cache_coreboot_x86:
407+
name: UNTESTED_msi_z790p_ddr4
408+
target: UNTESTED_msi_z790p_ddr4
409+
subcommand: ""
410+
coreboot_dir: coreboot-dasharo_msi_z790
411+
save_full_modules_cache: true
343412
requires:
344413
- x86-musl-cross-make
345-
- novacustom-nv4x_adl
346-
- librem_14
347-
- EOL_t480-hotp-maximized
348-
- EOL_librem_l1um
349-
- UNTESTED_msi_z690a_ddr4
350-
351-
# ppc64: combines ppc64 workspaces and saves ppc64 cache
352-
# Workspaces combined: ppc64-musl-cross-make, UNTESTED_talos-2
353-
- save_cache_ppc64:
354-
requires:
355-
- UNTESTED_talos-2
356414

357415
# Those onboarding new boards should add their entries below.
358416
# coreboot 25.09 boards
@@ -625,14 +683,6 @@ workflows:
625683
requires:
626684
- novacustom-nv4x_adl
627685

628-
# NovaCustom v56: builds dasharo_v56 toolchain
629-
- build:
630-
name: novacustom-v560tu
631-
target: novacustom-v560tu
632-
subcommand: ""
633-
requires:
634-
- x86-musl-cross-make
635-
636686
# NovaCustom v56: shares dasharo_v56 toolchain with novacustom-v560tu
637687
- build:
638688
name: novacustom-v540tu
@@ -649,14 +699,6 @@ workflows:
649699
requires:
650700
- UNTESTED_msi_z690a_ddr4
651701

652-
# Dasharo msi_z790: builds dasharo_msi_z790 toolchain
653-
- build:
654-
name: UNTESTED_msi_z790p_ddr4
655-
target: UNTESTED_msi_z790p_ddr4
656-
subcommand: ""
657-
requires:
658-
- x86-musl-cross-make
659-
660702
# Dasharo msi_z790: shares dasharo_msi_z790 toolchain with UNTESTED_msi_z790p_ddr4
661703
- build:
662704
name: msi_z790p_ddr5

0 commit comments

Comments
 (0)