This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / .github / lazy-store.sh
4.4 kB 105 lines
1#!/usr/bin/env bash 2# Mounts a lazy /nix/store for building a machine (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# `closure FETCH` collects the closure of the paths in FETCH, those the 11# build would substitute (from the eval job's dry-run, .github/ci-shared.sh), 12# from the caches' narinfos; it needs no drvs and can run while they are 13# fetched. `mount` mounts it on /nix/store and registers the paths, after 14# `closure` and once the drvs are in the store. 15# 16# Needs sudo, /dev/fuse and LAZY_STORE, the lazy-store package's out path 17# (substitutable). If anything fails before the paths are registered, the 18# mount is undone and the build substitutes eagerly: this script always 19# exits 0. The FUSE log ends up in $RUNNER_TEMP/lazy-store/fuse.log. 20# Usage: lazy-store.sh closure FETCH 21# lazy-store.sh mount 22set -euo pipefail 23L=$RUNNER_TEMP/lazy-store 24mkdir -p "$L" 25 26fallback() { 27 set +e 28 echo "::error::lazy store: $1; the build substitutes eagerly instead" 29 rm -f "$L/ready" 30 if [ -s "$L/fuse.log" ]; then 31 tail -n 50 "$L/fuse.log" 32 fi 33 if mountpoint -q /nix/store; then 34 sudo umount /nix/store || sudo umount -l /nix/store 35 fi 36 if mountpoint -q /lazy/nix; then 37 sudo umount -l /lazy/nix 38 fi 39 exit 0 40} 41trap 'fallback "line $LINENO failed"' ERR 42 43lazy=$LAZY_STORE/bin/lazy-store 44 45if [ "$1" = closure ]; then 46 if [ ! -s "$2" ]; then 47 echo "lazy store: nothing to substitute" 48 exit 0 49 fi 50 nix-store --realise "$LAZY_STORE" >/dev/null || fallback "cannot get $LAZY_STORE" 51 "$lazy" closure "$L" <"$2" >/dev/null || fallback "closure failed" 52 jq -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"' \ 53 "$L/closure.json" 54 if [ "$(jq length "$L/paths.json")" != 0 ]; then 55 touch "$L/ready" 56 fi 57 exit 0 58fi 59 60if [ ! -e "$L/ready" ]; then 61 exit 0 62fi 63nixbin=$(dirname "$(readlink -f "$(command -v nix-store)")") 64 65sudo modprobe fuse || true 66# The upper layer is the real store dir, reached through a private bind 67# mount of /nix, so that the mount on /nix/store doesn't show up there. 68sudo mkdir -p /lazy/nix 69sudo mount --bind /nix /lazy/nix || fallback "bind mount of /nix failed" 70sudo mount --make-private /lazy/nix || fallback "making /lazy/nix private failed" 71# shellcheck disable=SC2024 # the log is ours, only the mount needs root 72sudo "$lazy" mount "$L" /lazy/nix/store /nix/store >"$L/fuse.log" 2>&1 & 73fuse=$! 74# sudo runs as root (no kill -0) and stays a zombie until waited for 75fuse_alive() { 76 local s 77 s=$(ps -o stat= -p "$fuse") && [[ $s != Z* ]] 78} 79# it fetches all .ls listings before mounting; paths without one, and those 80# referring to them, it leaves out of paths.json and db.dump, so that the 81# build substitutes them 82until mountpoint -q /nix/store; do 83 fuse_alive || fallback "lazy-store exited before mounting /nix/store" 84 sleep 1 85done 86grep -m1 '^init: ' "$L/fuse.log" || true 87 88n=$(jq length "$L/paths.json") 89some=$(jq -r 'keys[0]' "$L/paths.json") 90[ -e "/nix/store/$some" ] || fallback "/nix/store/$some is not served" 91# shellcheck disable=SC2024 # db.dump is ours, only nix-store needs root 92sudo "$nixbin/nix-store" --load-db <"$L/db.dump" || fallback "registering the paths failed" 93# registered: the mount has to stay 94trap - ERR 95set +e 96grep '^no listing for ' "$L/fuse.log" 97jq -r --arg n "$n" '"lazy store: mounted on /nix/store, \($n) paths registered; \(.failed | length) without a listing, \(.incomplete) referring to those"' \ 98 "$L/no-listing.json" 99# niks3 and hestia leave out what cache.nixos.org signed by the signatures 100# in nix's database; without them they would upload (and so download) 101# those paths 102jq -r 'keys[] | "/nix/store/" + .' "$L/paths.json" | 103 sudo "$nixbin/nix" --extra-experimental-features nix-command \ 104 store copy-sigs -s "file://$L/narinfo" --stdin || 105 echo "::warning::lazy store: copying the signatures failed, uploads may download paths of cache.nixos.org"