1
0
Fork 0
mirror of https://github.com/NixOS/nix.dev.git synced 2024-10-18 14:32:43 -04:00
nix.dev/nix/update-nix-releases.nix
2024-04-05 17:17:53 +02:00

87 lines
3.4 KiB
Nix

{ writeShellApplication
, git
, nix
, ripgrep
, coreutils
, jq
}:
# Custom update mechanism for Nix releases in ./nix-versions.json
writeShellApplication {
name = "update-nix-releases";
runtimeInputs = [ git nix ripgrep coreutils jq ];
text = ''
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
echo >&2 "Fetching the Nix git history"
# We only need the Git history of the repo, the contents we download directly into the Nix store.
# --filter=tree:0 prevents downloading any contents and --bare prevents creating a working tree
git clone --quiet --filter=tree:0 --bare https://github.com/nixos/nix "$tmp/nix"
echo >&2 "Going through all *-maintenance branches"
git -C "$tmp/nix" branch --list '*-maintenance' --format '%(refname)' \
| rg 'refs/heads/(.*)-maintenance' -or '$1' \
| sort --reverse --version-sort \
| while read -r version; do
rev=$(git -C "$tmp/nix" rev-parse "$version-maintenance")
echo >&2 "Version $version on branch $version-maintenance is at $rev"
# Try to find a cached build by iterating back through the Git history
# This is necessary because the maintenance branches are pushed to directly and Hydra will take a while to build it
cached=false
steps=0
while true; do
# We fetch Nix the same as `fetchTarball { name = "source"; ... }`, such that we should definitely get the same hashes and co.
# Though older versions of Nix didn't pin flake-compat, but this doesn't appear to be a problem in this case
# See https://github.com/NixOS/nix.dev/pull/830#issuecomment-1922672937
url=https://github.com/nixos/nix/tarball/"$rev"
readarray -t sha256Source < <(nix-prefetch-url --unpack --name source --print-path "$url")
sha256=''${sha256Source[0]}
source=''${sha256Source[1]}
if [[ ! -f "$source"/.version ]]; then
# Not having a .version indicates that we're not in the release anymore
break
fi
fullVersion="$(<"$source"/.version)"
# Only try versions recent enough to have the same structure, this filter out versions before 2.4
if ! drvPath=$(nix-instantiate "$source" --argstr system "x86_64-linux" -A default 2> /dev/null); then
echo >&2 "No default.nix supporting -A default"
break
fi
# We need a doc output, this is always the case for >= 2.4
if ! docOutput=$(nix-store --query --binding doc "$drvPath"); then
echo >&2 "No doc output"
break
fi
# Check if the path is cached; `--size` is needed because without it, no query to the cache would be made
if nix-store --query --size "$docOutput" --store https://cache.nixos.org > /dev/null 2>&1; then
cached=true
break
fi
# If it's not cached, try the parent commit, usually only a couple steps are required at most
rev=$(git -C "$tmp/nix" rev-parse "$rev~")
steps=$(( steps + 1 ))
done
if [ "$cached" = false ]; then
echo >&2 "Could not find a cached version for release $version"
continue
fi
echo >&2 "Found a cached version, $steps steps away from the latest commit"
jq -n \
--arg key "$version" \
--arg url "$url" \
--arg version "$fullVersion" \
--arg sha256 "$sha256" \
'$ARGS.named'
done \
| jq -s 'map({ key: .key, value: del(.key) }) | from_entries' \
> nix/nix-versions.json
'';
}