fix(nix): Fixed nix hash for dependencies, added CI job and script for updating dependencies versions (#948)
This commit is contained in:
parent
aebd432390
commit
5dbe99bf00
4 changed files with 247 additions and 2 deletions
39
.github/workflows/nix-check.yml
vendored
Normal file
39
.github/workflows/nix-check.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: "nix build check"
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
nix-build:
|
||||
runs-on: ubuntu-24.04
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: cachix/install-nix-action@v30
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: Check flake evaluation
|
||||
id: eval
|
||||
run: |
|
||||
if ! nix eval .#packages.x86_64-linux.handy.drvPath 2>eval_err.log; then
|
||||
echo "failed=true" >> "$GITHUB_OUTPUT"
|
||||
cat eval_err.log
|
||||
fi
|
||||
|
||||
- name: Hint on evaluation failure
|
||||
if: steps.eval.outputs.failed == 'true'
|
||||
run: |
|
||||
echo ""
|
||||
echo "::warning::flake.nix evaluation failed — likely outdated outputHashes or bunDeps hash."
|
||||
echo ""
|
||||
echo "┌─────────────────────────────────────────────────────────────────┐"
|
||||
echo "│ To fix, run on NixOS, Ubuntu/Debian, macOS with nix installed: │"
|
||||
echo "│ │"
|
||||
echo "│ ./scripts/update-nix-hashes.sh │"
|
||||
echo "│ │"
|
||||
echo "│ The script will update version keys and hashes in flake.nix │"
|
||||
echo "│ automatically. Commit the resulting changes. │"
|
||||
echo "└─────────────────────────────────────────────────────────────────┘"
|
||||
echo ""
|
||||
cat eval_err.log
|
||||
exit 1
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -37,3 +37,6 @@ blob-report/
|
|||
|
||||
.direnv
|
||||
.envrc
|
||||
|
||||
# Nix build output
|
||||
result
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-+hUANv0w3qnK5d2+4JW3XMazLRDhWCbOxUXQyTGta/0=";
|
||||
outputHash = "sha256-84Aw9E2+fEZT+lIb9k1bodessoex+YFr0im2GMVAPnw=";
|
||||
};
|
||||
in
|
||||
{
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
"rdev-0.5.0-2" = "sha256-0F7EaPF8Oa1nnSCAjzEAkitWVpMldL3nCp3c5DVFMe0=";
|
||||
"rodio-0.20.1" = "sha256-wq72awTvN4fXZ9qZc5KLYS9oMxtNDZ4YGxfqz8msofs=";
|
||||
"tauri-nspanel-2.1.0" = "sha256-gotQQ1DOhavdXU8lTEux0vdY880LLetk7VLvSm6/8TI=";
|
||||
"tauri-runtime-2.9.1" = "sha256-sdneSI2kfRMgTkuqQoFPgtYvkqMPSuoyrffFwOph+ZM=";
|
||||
"tauri-runtime-2.10.0" = "sha256-s1IBM9hOY+HRdl/E5r7BsRTE7aLaFCCMK/DdS+bvZRc=";
|
||||
"vad-rs-0.1.5" = "sha256-Q9Dxq31npyUPY9wwi6OxqSJrEvFvG8/n0dbyT7XNcyI=";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
203
scripts/update-nix-hashes.sh
Executable file
203
scripts/update-nix-hashes.sh
Executable file
|
|
@ -0,0 +1,203 @@
|
|||
#!/usr/bin/env bash
|
||||
# Updates outputHashes and bunDeps hash in flake.nix
|
||||
# when Cargo or JS dependencies change.
|
||||
#
|
||||
# Usage: ./scripts/update-nix-hashes.sh
|
||||
#
|
||||
# Handles:
|
||||
# - Version changes in git dependencies (Cargo.lock → outputHashes)
|
||||
# - bun.lock changes (→ bunDeps outputHash)
|
||||
#
|
||||
# Requires: nix, awk, sed
|
||||
# Works on: NixOS, Ubuntu/Debian, macOS
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
FLAKE_NIX="$PROJECT_DIR/flake.nix"
|
||||
CARGO_LOCK="$PROJECT_DIR/src-tauri/Cargo.lock"
|
||||
|
||||
FAKE_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
||||
|
||||
# Portable sed -i (macOS requires -i '', GNU sed requires just -i)
|
||||
sedi() {
|
||||
if sed --version >/dev/null 2>&1; then
|
||||
sed -i "$@"
|
||||
else
|
||||
sed -i '' "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if ! command -v nix >/dev/null 2>&1; then
|
||||
echo "error: nix is not installed. Install it from https://nixos.org/download/" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$FLAKE_NIX" ]; then
|
||||
echo "error: flake.nix not found at $FLAKE_NIX" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$CARGO_LOCK" ]; then
|
||||
echo "error: Cargo.lock not found at $CARGO_LOCK" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Step 1: Extract git dependency representative keys from Cargo.lock
|
||||
#
|
||||
# Cargo.lock format (consecutive lines per package):
|
||||
# [[package]]
|
||||
# name = "foo"
|
||||
# version = "1.2.3"
|
||||
# source = "git+https://...#commit"
|
||||
#
|
||||
# Multiple packages from the same git URL share one outputHash entry keyed
|
||||
# by the alphabetically first "name-version" from that URL.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
extract_cargo_git_keys() {
|
||||
awk '
|
||||
/^name = / { name = substr($3, 2, length($3) - 2) }
|
||||
/^version = / { version = substr($3, 2, length($3) - 2) }
|
||||
/^source = "git\+/ {
|
||||
src = $3
|
||||
gsub(/^"git\+/, "", src)
|
||||
sub(/#.*/, "", src)
|
||||
key = name "-" version
|
||||
if (!(src in best) || key < best[src])
|
||||
best[src] = key
|
||||
}
|
||||
END { for (s in best) print best[s] }
|
||||
' "$CARGO_LOCK" | sort
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Step 2: Extract current outputHashes keys from flake.nix
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
extract_flake_keys() {
|
||||
# Portable: no grep -P, use awk instead
|
||||
sed -n '/outputHashes/,/};/p' "$FLAKE_NIX" \
|
||||
| awk -F'"' '/sha256-/ { print $2 }' \
|
||||
| sort
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Step 3: Compare keys and update flake.nix where needed
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
update_output_hash_keys() {
|
||||
local cargo_keys flake_keys
|
||||
cargo_keys=$(extract_cargo_git_keys)
|
||||
flake_keys=$(extract_flake_keys)
|
||||
|
||||
local changed=0
|
||||
|
||||
# For each flake key, check if it still matches a Cargo.lock git dep.
|
||||
# If the package name matches but version differs -> update.
|
||||
echo "$flake_keys" | while IFS= read -r fk; do
|
||||
[ -z "$fk" ] && continue
|
||||
|
||||
# Extract the package name prefix (everything before the version)
|
||||
fname=$(echo "$fk" | sed 's/-[0-9][0-9.]*[-0-9]*$//')
|
||||
|
||||
if echo "$cargo_keys" | grep -qxF "$fk"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Key not found in Cargo.lock — look for a replacement with the same name
|
||||
replacement=$(echo "$cargo_keys" | while IFS= read -r ck; do
|
||||
cname=$(echo "$ck" | sed 's/-[0-9][0-9.]*[-0-9]*$//')
|
||||
if [ "$cname" = "$fname" ]; then
|
||||
echo "$ck"
|
||||
break
|
||||
fi
|
||||
done)
|
||||
|
||||
if [ -n "$replacement" ]; then
|
||||
echo "outputHashes: $fk -> $replacement"
|
||||
sedi "s|\"$fk\" = \"sha256-[^\"]*\"|\"$replacement\" = \"$FAKE_HASH\"|" "$FLAKE_NIX"
|
||||
changed=1
|
||||
else
|
||||
echo "warning: $fk not found in Cargo.lock git deps and no replacement detected" >&2
|
||||
echo " This entry may need to be removed or added manually." >&2
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for new git deps not yet in flake.nix
|
||||
echo "$cargo_keys" | while IFS= read -r ck; do
|
||||
[ -z "$ck" ] && continue
|
||||
if ! echo "$flake_keys" | grep -qxF "$ck" && ! grep -q "\"$ck\"" "$FLAKE_NIX"; then
|
||||
echo "warning: git dep $ck exists in Cargo.lock but not in flake.nix outputHashes" >&2
|
||||
echo " You may need to add it manually." >&2
|
||||
fi
|
||||
done
|
||||
|
||||
return $changed
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Step 4: Iteratively fix hashes by running nix build and parsing errors
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
fix_hashes() {
|
||||
local max_attempts=10
|
||||
local attempt=0
|
||||
|
||||
while [ "$attempt" -lt "$max_attempts" ]; do
|
||||
attempt=$((attempt + 1))
|
||||
echo ""
|
||||
echo "=== nix build attempt $attempt/$max_attempts ==="
|
||||
|
||||
local output
|
||||
if output=$(nix build .#handy 2>&1); then
|
||||
echo "Build successful!"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for hash mismatch
|
||||
if echo "$output" | grep -q "hash mismatch in fixed-output derivation"; then
|
||||
local specified got
|
||||
specified=$(echo "$output" | grep "specified:" | awk '{print $2}')
|
||||
got=$(echo "$output" | grep "got:" | awk '{print $2}')
|
||||
|
||||
if [ -n "$specified" ] && [ -n "$got" ]; then
|
||||
echo "Hash mismatch: $specified -> $got"
|
||||
sedi "s|$specified|$got|" "$FLAKE_NIX"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we can't parse the error, show it and bail out
|
||||
echo ""
|
||||
echo "Build failed with an error that cannot be fixed automatically:" >&2
|
||||
echo "$output" | tail -20 >&2
|
||||
return 1
|
||||
done
|
||||
|
||||
echo "error: exceeded max attempts ($max_attempts)" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
echo "=== Nix flake hash updater ==="
|
||||
echo ""
|
||||
echo "Checking outputHashes keys against Cargo.lock..."
|
||||
|
||||
if update_output_hash_keys; then
|
||||
echo "All outputHashes keys are up to date."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Running nix build to verify/fix hashes..."
|
||||
fix_hashes
|
||||
|
||||
echo ""
|
||||
echo "Done. Changes in flake.nix:"
|
||||
git diff --stat -- flake.nix 2>/dev/null || true
|
||||
Loading…
Reference in a new issue