forked from
lass.pds.lassul.us/superconfig
This repository has no description
3.9 kB
91 lines
1#!/usr/bin/env bash
2# Mounts a lazy /nix/store for building INSTALLABLE... (the machine jobs of
3# ci.yml): every store path the build would substitute from cache.nixos.org
4# or cache.lassul.us is registered as valid from its narinfo and served by
5# lazy-store (tools/lazy-store), which downloads a path's NAR only when a
6# file in it is opened first. What nix builds, and what neither cache has,
7# is built or substituted (also from hestia) as usual; writes go to the
8# real store dir below the mount.
9#
10# Needs sudo, /dev/fuse and LAZY_STORE, the lazy-store package's out path
11# (substitutable). If anything fails before the paths are registered, the
12# mount is undone and the build substitutes eagerly: this script always
13# exits 0. The FUSE log ends up in $RUNNER_TEMP/lazy-store/fuse.log.
14# Usage: lazy-store.sh INSTALLABLE...
15set -euo pipefail
16L=$RUNNER_TEMP/lazy-store
17mkdir -p "$L"
18
19fallback() {
20 set +e
21 echo "::error::lazy store: $1; the build substitutes eagerly instead"
22 if [ -s "$L/fuse.log" ]; then
23 tail -n 50 "$L/fuse.log"
24 fi
25 if mountpoint -q /nix/store; then
26 sudo umount /nix/store || sudo umount -l /nix/store
27 fi
28 if mountpoint -q /lazy/nix; then
29 sudo umount -l /lazy/nix
30 fi
31 exit 0
32}
33trap 'fallback "line $LINENO failed"' ERR
34
35nix-store --realise "$LAZY_STORE" >/dev/null || fallback "cannot get $LAZY_STORE"
36lazy=$LAZY_STORE/bin/lazy-store
37nixbin=$(dirname "$(readlink -f "$(command -v nix-store)")")
38
39nix build --dry-run "$@" 2>"$L/plan" || fallback "nix build --dry-run failed: $(cat "$L/plan")"
40# the path lines below the "will be fetched" header, up to the next header
41awk '/^[^ ]/ { f = /will be fetched/; next } f && $1 ~ /^\/nix\/store\// { print $1 }' \
42 "$L/plan" >"$L/fetch"
43if [ ! -s "$L/fetch" ]; then
44 echo "lazy store: nothing to substitute"
45 exit 0
46fi
47
48"$lazy" closure "$L" <"$L/fetch" >/dev/null || fallback "closure failed"
49jq -r '"lazy store: \(.paths) of the \(.roots) paths to substitute and their closure (\(.file_size / 1048576 | floor) MiB to download eagerly); \(.missing | length) not in the caches, \(.incomplete) referring to those"' \
50 "$L/closure.json"
51n=$(jq length "$L/paths.json")
52if [ "$n" = 0 ]; then
53 exit 0
54fi
55
56sudo modprobe fuse || true
57# The upper layer is the real store dir, reached through a private bind
58# mount of /nix, so that the mount on /nix/store doesn't show up there.
59sudo mkdir -p /lazy/nix
60sudo mount --bind /nix /lazy/nix || fallback "bind mount of /nix failed"
61sudo mount --make-private /lazy/nix || fallback "making /lazy/nix private failed"
62# shellcheck disable=SC2024 # the log is ours, only the mount needs root
63sudo "$lazy" mount "$L" /lazy/nix/store /nix/store >"$L/fuse.log" 2>&1 &
64fuse=$!
65# sudo runs as root (no kill -0) and stays a zombie until waited for
66fuse_alive() {
67 local s
68 s=$(ps -o stat= -p "$fuse") && [[ $s != Z* ]]
69}
70# it fetches all .ls listings before mounting
71until mountpoint -q /nix/store; do
72 fuse_alive || fallback "lazy-store exited before mounting /nix/store"
73 sleep 1
74done
75grep -m1 '^init: ' "$L/fuse.log" || true
76
77some=$(jq -r 'keys[0]' "$L/paths.json")
78[ -e "/nix/store/$some" ] || fallback "/nix/store/$some is not served"
79# shellcheck disable=SC2024 # db.dump is ours, only nix-store needs root
80sudo "$nixbin/nix-store" --load-db <"$L/db.dump" || fallback "registering the paths failed"
81# registered: the mount has to stay
82trap - ERR
83set +e
84echo "lazy store: mounted on /nix/store, $n paths registered"
85# niks3 and hestia leave out what cache.nixos.org signed by the signatures
86# in nix's database; without them they would upload (and so download)
87# those paths
88jq -r 'keys[] | "/nix/store/" + .' "$L/paths.json" |
89 sudo "$nixbin/nix" --extra-experimental-features nix-command \
90 store copy-sigs -s "file://$L/narinfo" --stdin ||
91 echo "::warning::lazy store: copying the signatures failed, uploads may download paths of cache.nixos.org"