Skip to content

Commit a35b4ce

Browse files
committed
[CELL-293] cache-publish now runs even when an earlier build step failed, so a partial /nix volume hydrates the next run instead of starting from zero — cache-bust available via the skip_nix_cache workflow input
- feat(infra): `Stream-publish /nix volume to GHCR cache image` in both `build.dev.yml` and `build.release.yml` now uses `if: !cancelled() && inputs.skip_nix_cache != true`. A flaky cache.nixos.org download or any other transient build failure no longer throws away the derivations that *did* land in the volume — retry runs hydrate the partial cache and finish faster - feat(infra): add an inline `du -s /nix` guard before each publish — if the volume is under 1 GB, the step exits early. Protects the healthy cache from being overwritten by an empty-volume publish when the hydrate step itself failed - feat(infra): expose `skip_nix_cache` as a `workflow_dispatch` input on `build.release.yml` (it already existed on `build.dev.yml`). Setting it to `true` skips both hydrate AND publish — operators can manually flush a poisoned cache by re-running with that flag, then re-running normally to publish a fresh one
1 parent 9c3294b commit a35b4ce

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

‎.github/workflows/build.dev.yml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,28 @@ jobs:
190190
# `-C / nix`: archive entries land under `nix/...` natively
191191
# (BusyBox tar doesn't implement --transform).
192192
# `--exclude=nix/var/nix/daemon-socket`: Unix sockets can't tar.
193+
# Publish even on prior-step failure — a partially-populated
194+
# /nix volume still speeds up the next run's hydrate. Skip when:
195+
# - the job was cancelled (intentional, don't write garbage)
196+
# - skip_nix_cache=true (cache-bust mode, deliberately fresh)
197+
# - the volume is under 1 GB (hydrate-step failure → empty
198+
# volume, don't overwrite a healthy cache with nothing)
193199
- name: Stream-publish /nix volume to GHCR cache image
200+
if: ${{ !cancelled() && inputs.skip_nix_cache != true }}
194201
timeout-minutes: 80
195202
run: |
196203
set -eo pipefail
197204
HASH=${{ hashFiles('nixhome/**') }}
198205
EXACT="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:nix-cache-${{ matrix.arch }}-${HASH}"
199206
LATEST="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:nix-cache-${{ matrix.arch }}-latest"
200207
208+
SIZE_KB=$(docker run --rm -v devcell-nix-store-${{ matrix.arch }}:/nix:ro alpine du -s /nix 2>/dev/null | awk '{print $1}')
209+
if [ "${SIZE_KB:-0}" -lt 1000000 ]; then
210+
echo "skipping publish: /nix is only ${SIZE_KB}KB — won't overwrite cache with empty volume"
211+
exit 0
212+
fi
213+
echo "publishing /nix (${SIZE_KB}KB) — job status: ${{ job.status }}"
214+
201215
docker run --rm -v devcell-nix-store-${{ matrix.arch }}:/nix:ro alpine \
202216
tar -cf - \
203217
--exclude='nix/var/nix/daemon-socket' \

‎.github/workflows/build.release.yml‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ on:
99
types:
1010
- created
1111
workflow_dispatch:
12+
inputs:
13+
skip_nix_cache:
14+
description: 'Skip nix cache (genesis mode — full rebuild, no pre-seeding, no post-build publish)'
15+
type: boolean
16+
default: false
1217

1318
permissions:
1419
contents: write
@@ -85,6 +90,7 @@ jobs:
8590
# builds reuse the same nixhome closure as dev builds for any
8691
# given `hashFiles('nixhome/**')`, so the cache is interchangeable.
8792
- name: Stream-hydrate /nix volume from prior GHCR cache (if available)
93+
if: inputs.skip_nix_cache != true
8894
run: |
8995
set -eo pipefail
9096
HASH=${{ hashFiles('nixhome/**') }}
@@ -126,14 +132,25 @@ jobs:
126132
run: docker push ${{ steps.build.outputs.tag }}
127133

128134
# Publish the populated /nix volume back to the GHCR cache so
129-
# subsequent dev + release builds can reuse it.
135+
# subsequent dev + release builds can reuse it. Runs even on
136+
# prior-step failure (partial volume is still useful), but skips
137+
# under cancellation, cache-bust mode, or near-empty volume.
130138
- name: Stream-publish /nix volume to GHCR cache image
139+
if: ${{ !cancelled() && inputs.skip_nix_cache != true }}
131140
timeout-minutes: 80
132141
run: |
133142
set -eo pipefail
134143
HASH=${{ hashFiles('nixhome/**') }}
135144
LATEST="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:nix-cache-${{ matrix.arch }}-latest"
136145
EXACT="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:nix-cache-${{ matrix.arch }}-${HASH}"
146+
147+
SIZE_KB=$(docker run --rm -v devcell-nix-store-${{ matrix.arch }}:/nix:ro alpine du -s /nix 2>/dev/null | awk '{print $1}')
148+
if [ "${SIZE_KB:-0}" -lt 1000000 ]; then
149+
echo "skipping publish: /nix is only ${SIZE_KB}KB — won't overwrite cache with empty volume"
150+
exit 0
151+
fi
152+
echo "publishing /nix (${SIZE_KB}KB) — job status: ${{ job.status }}"
153+
137154
docker run --rm -v devcell-nix-store-${{ matrix.arch }}:/nix:ro alpine \
138155
tar -cf - \
139156
--exclude='nix/var/nix/daemon-socket' \

0 commit comments

Comments
 (0)