From f589b1c07802e0e4615b920a691e69d6cca87e1d Mon Sep 17 00:00:00 2001 From: Padreug Date: Mon, 25 May 2026 13:16:23 +0200 Subject: [PATCH] fix(deploy/push-cache): push build-time deps too, not just runtime closure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cachix push by default only walks the RUNTIME closure of the paths it gets on stdin. Build-time inputs like fetchPnpmDeps tarballs are consumed during a build and then thrown away — never referenced from the final output — so they never make it into the cache. This bites when an ATM has the cached runtime output for an older version of bitspire-atm-app but then needs to rebuild it (e.g. because a flake.nix change shifts the toplevel hash, cascading through to a new app derivation). Sintra OOM-killed itself today (2026-05-25) doing exactly this: 1.4 GB of pnpm install + node-headers on 1 GB of RAM. Fix: query the .drv that produced each output path, then walk `nix-store -qR --include-outputs ` — that gives the full build-time closure (every path needed to realize the build, including fixed-output fetchers like fetchPnpmDeps). cachix push then uploads all of them. Cost: somewhat larger pushes, but the dev box has the headroom. Benefit: ATM nixos-upgrade never falls into the rebuild-from-source trap. Co-Authored-By: Claude Opus 4.7 (1M context) --- deploy/push-cache.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/deploy/push-cache.sh b/deploy/push-cache.sh index 6eb1832..0604204 100755 --- a/deploy/push-cache.sh +++ b/deploy/push-cache.sh @@ -29,8 +29,22 @@ build_and_push() { local attr="$2" echo "==> Building $name ($attr)..." - nix build ".#$attr" --no-link --print-out-paths | cachix push "$CACHE" - echo "==> Pushed $name to $CACHE.cachix.org" + local out_paths + out_paths=$(nix build ".#$attr" --no-link --print-out-paths) + + # Walk the BUILD-TIME closure (not just runtime) so derivations like + # `bitspire-atm-app-pnpm-deps` (fetchPnpmDeps tarball, consumed only + # during the app's build and discarded) land in the cache. Without + # this, ATMs that need to rebuild the app from source — i.e. any time + # `cachix push` already-cached the runtime output but a downstream + # eval needs a new toplevel that re-derives the app — would OOM-kill + # themselves trying to run `pnpm install` locally on 1 GB of RAM. + # OOM caught on Sintra 2026-05-25 with the 1.4 GB pnpm-deps build. + local drvs + drvs=$(echo "$out_paths" | xargs -r -n1 nix-store -q --deriver) + echo "$drvs" | xargs -r nix-store -qR --include-outputs | cachix push "$CACHE" + + echo "==> Pushed $name (runtime + build-time closure) to $CACHE.cachix.org" } case "$target" in