fix(nix): Fixed nix hash for dependencies, added CI job and script for updating dependencies versions (#948)

This commit is contained in:
Evgeny Khudoba 2026-03-12 17:39:39 +07:00 committed by GitHub
parent aebd432390
commit 5dbe99bf00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 247 additions and 2 deletions

39
.github/workflows/nix-check.yml vendored Normal file
View 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
View file

@ -37,3 +37,6 @@ blob-report/
.direnv
.envrc
# Nix build output
result

View file

@ -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
View 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