Skip to content

Commit 5dbe99b

Browse files
authored
fix(nix): Fixed nix hash for dependencies, added CI job and script for updating dependencies versions (cjpais#948)
1 parent aebd432 commit 5dbe99b

File tree

4 files changed

+247
-2
lines changed

4 files changed

+247
-2
lines changed

.github/workflows/nix-check.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: "nix build check"
2+
on: [pull_request]
3+
4+
jobs:
5+
nix-build:
6+
runs-on: ubuntu-24.04
7+
continue-on-error: true
8+
steps:
9+
- uses: actions/checkout@v4
10+
11+
- uses: cachix/install-nix-action@v30
12+
with:
13+
nix_path: nixpkgs=channel:nixos-unstable
14+
15+
- name: Check flake evaluation
16+
id: eval
17+
run: |
18+
if ! nix eval .#packages.x86_64-linux.handy.drvPath 2>eval_err.log; then
19+
echo "failed=true" >> "$GITHUB_OUTPUT"
20+
cat eval_err.log
21+
fi
22+
23+
- name: Hint on evaluation failure
24+
if: steps.eval.outputs.failed == 'true'
25+
run: |
26+
echo ""
27+
echo "::warning::flake.nix evaluation failed — likely outdated outputHashes or bunDeps hash."
28+
echo ""
29+
echo "┌─────────────────────────────────────────────────────────────────┐"
30+
echo "│ To fix, run on NixOS, Ubuntu/Debian, macOS with nix installed: │"
31+
echo "│ │"
32+
echo "│ ./scripts/update-nix-hashes.sh │"
33+
echo "│ │"
34+
echo "│ The script will update version keys and hashes in flake.nix │"
35+
echo "│ automatically. Commit the resulting changes. │"
36+
echo "└─────────────────────────────────────────────────────────────────┘"
37+
echo ""
38+
cat eval_err.log
39+
exit 1

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ blob-report/
3737

3838
.direnv
3939
.envrc
40+
41+
# Nix build output
42+
result

flake.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
outputHashAlgo = "sha256";
5353
outputHashMode = "recursive";
54-
outputHash = "sha256-+hUANv0w3qnK5d2+4JW3XMazLRDhWCbOxUXQyTGta/0=";
54+
outputHash = "sha256-84Aw9E2+fEZT+lIb9k1bodessoex+YFr0im2GMVAPnw=";
5555
};
5656
in
5757
{
@@ -68,7 +68,7 @@
6868
"rdev-0.5.0-2" = "sha256-0F7EaPF8Oa1nnSCAjzEAkitWVpMldL3nCp3c5DVFMe0=";
6969
"rodio-0.20.1" = "sha256-wq72awTvN4fXZ9qZc5KLYS9oMxtNDZ4YGxfqz8msofs=";
7070
"tauri-nspanel-2.1.0" = "sha256-gotQQ1DOhavdXU8lTEux0vdY880LLetk7VLvSm6/8TI=";
71-
"tauri-runtime-2.9.1" = "sha256-sdneSI2kfRMgTkuqQoFPgtYvkqMPSuoyrffFwOph+ZM=";
71+
"tauri-runtime-2.10.0" = "sha256-s1IBM9hOY+HRdl/E5r7BsRTE7aLaFCCMK/DdS+bvZRc=";
7272
"vad-rs-0.1.5" = "sha256-Q9Dxq31npyUPY9wwi6OxqSJrEvFvG8/n0dbyT7XNcyI=";
7373
};
7474
};

scripts/update-nix-hashes.sh

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#!/usr/bin/env bash
2+
# Updates outputHashes and bunDeps hash in flake.nix
3+
# when Cargo or JS dependencies change.
4+
#
5+
# Usage: ./scripts/update-nix-hashes.sh
6+
#
7+
# Handles:
8+
# - Version changes in git dependencies (Cargo.lock → outputHashes)
9+
# - bun.lock changes (→ bunDeps outputHash)
10+
#
11+
# Requires: nix, awk, sed
12+
# Works on: NixOS, Ubuntu/Debian, macOS
13+
14+
set -euo pipefail
15+
16+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
18+
19+
FLAKE_NIX="$PROJECT_DIR/flake.nix"
20+
CARGO_LOCK="$PROJECT_DIR/src-tauri/Cargo.lock"
21+
22+
FAKE_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
23+
24+
# Portable sed -i (macOS requires -i '', GNU sed requires just -i)
25+
sedi() {
26+
if sed --version >/dev/null 2>&1; then
27+
sed -i "$@"
28+
else
29+
sed -i '' "$@"
30+
fi
31+
}
32+
33+
if ! command -v nix >/dev/null 2>&1; then
34+
echo "error: nix is not installed. Install it from https://nixos.org/download/" >&2
35+
exit 1
36+
fi
37+
if [ ! -f "$FLAKE_NIX" ]; then
38+
echo "error: flake.nix not found at $FLAKE_NIX" >&2
39+
exit 1
40+
fi
41+
if [ ! -f "$CARGO_LOCK" ]; then
42+
echo "error: Cargo.lock not found at $CARGO_LOCK" >&2
43+
exit 1
44+
fi
45+
46+
# ---------------------------------------------------------------------------
47+
# Step 1: Extract git dependency representative keys from Cargo.lock
48+
#
49+
# Cargo.lock format (consecutive lines per package):
50+
# [[package]]
51+
# name = "foo"
52+
# version = "1.2.3"
53+
# source = "git+https://...#commit"
54+
#
55+
# Multiple packages from the same git URL share one outputHash entry keyed
56+
# by the alphabetically first "name-version" from that URL.
57+
# ---------------------------------------------------------------------------
58+
59+
extract_cargo_git_keys() {
60+
awk '
61+
/^name = / { name = substr($3, 2, length($3) - 2) }
62+
/^version = / { version = substr($3, 2, length($3) - 2) }
63+
/^source = "git\+/ {
64+
src = $3
65+
gsub(/^"git\+/, "", src)
66+
sub(/#.*/, "", src)
67+
key = name "-" version
68+
if (!(src in best) || key < best[src])
69+
best[src] = key
70+
}
71+
END { for (s in best) print best[s] }
72+
' "$CARGO_LOCK" | sort
73+
}
74+
75+
# ---------------------------------------------------------------------------
76+
# Step 2: Extract current outputHashes keys from flake.nix
77+
# ---------------------------------------------------------------------------
78+
79+
extract_flake_keys() {
80+
# Portable: no grep -P, use awk instead
81+
sed -n '/outputHashes/,/};/p' "$FLAKE_NIX" \
82+
| awk -F'"' '/sha256-/ { print $2 }' \
83+
| sort
84+
}
85+
86+
# ---------------------------------------------------------------------------
87+
# Step 3: Compare keys and update flake.nix where needed
88+
# ---------------------------------------------------------------------------
89+
90+
update_output_hash_keys() {
91+
local cargo_keys flake_keys
92+
cargo_keys=$(extract_cargo_git_keys)
93+
flake_keys=$(extract_flake_keys)
94+
95+
local changed=0
96+
97+
# For each flake key, check if it still matches a Cargo.lock git dep.
98+
# If the package name matches but version differs -> update.
99+
echo "$flake_keys" | while IFS= read -r fk; do
100+
[ -z "$fk" ] && continue
101+
102+
# Extract the package name prefix (everything before the version)
103+
fname=$(echo "$fk" | sed 's/-[0-9][0-9.]*[-0-9]*$//')
104+
105+
if echo "$cargo_keys" | grep -qxF "$fk"; then
106+
continue
107+
fi
108+
109+
# Key not found in Cargo.lock — look for a replacement with the same name
110+
replacement=$(echo "$cargo_keys" | while IFS= read -r ck; do
111+
cname=$(echo "$ck" | sed 's/-[0-9][0-9.]*[-0-9]*$//')
112+
if [ "$cname" = "$fname" ]; then
113+
echo "$ck"
114+
break
115+
fi
116+
done)
117+
118+
if [ -n "$replacement" ]; then
119+
echo "outputHashes: $fk -> $replacement"
120+
sedi "s|\"$fk\" = \"sha256-[^\"]*\"|\"$replacement\" = \"$FAKE_HASH\"|" "$FLAKE_NIX"
121+
changed=1
122+
else
123+
echo "warning: $fk not found in Cargo.lock git deps and no replacement detected" >&2
124+
echo " This entry may need to be removed or added manually." >&2
125+
fi
126+
done
127+
128+
# Check for new git deps not yet in flake.nix
129+
echo "$cargo_keys" | while IFS= read -r ck; do
130+
[ -z "$ck" ] && continue
131+
if ! echo "$flake_keys" | grep -qxF "$ck" && ! grep -q "\"$ck\"" "$FLAKE_NIX"; then
132+
echo "warning: git dep $ck exists in Cargo.lock but not in flake.nix outputHashes" >&2
133+
echo " You may need to add it manually." >&2
134+
fi
135+
done
136+
137+
return $changed
138+
}
139+
140+
# ---------------------------------------------------------------------------
141+
# Step 4: Iteratively fix hashes by running nix build and parsing errors
142+
# ---------------------------------------------------------------------------
143+
144+
fix_hashes() {
145+
local max_attempts=10
146+
local attempt=0
147+
148+
while [ "$attempt" -lt "$max_attempts" ]; do
149+
attempt=$((attempt + 1))
150+
echo ""
151+
echo "=== nix build attempt $attempt/$max_attempts ==="
152+
153+
local output
154+
if output=$(nix build .#handy 2>&1); then
155+
echo "Build successful!"
156+
return 0
157+
fi
158+
159+
# Check for hash mismatch
160+
if echo "$output" | grep -q "hash mismatch in fixed-output derivation"; then
161+
local specified got
162+
specified=$(echo "$output" | grep "specified:" | awk '{print $2}')
163+
got=$(echo "$output" | grep "got:" | awk '{print $2}')
164+
165+
if [ -n "$specified" ] && [ -n "$got" ]; then
166+
echo "Hash mismatch: $specified -> $got"
167+
sedi "s|$specified|$got|" "$FLAKE_NIX"
168+
continue
169+
fi
170+
fi
171+
172+
# If we can't parse the error, show it and bail out
173+
echo ""
174+
echo "Build failed with an error that cannot be fixed automatically:" >&2
175+
echo "$output" | tail -20 >&2
176+
return 1
177+
done
178+
179+
echo "error: exceeded max attempts ($max_attempts)" >&2
180+
return 1
181+
}
182+
183+
# ---------------------------------------------------------------------------
184+
# Main
185+
# ---------------------------------------------------------------------------
186+
187+
cd "$PROJECT_DIR"
188+
189+
echo "=== Nix flake hash updater ==="
190+
echo ""
191+
echo "Checking outputHashes keys against Cargo.lock..."
192+
193+
if update_output_hash_keys; then
194+
echo "All outputHashes keys are up to date."
195+
fi
196+
197+
echo ""
198+
echo "Running nix build to verify/fix hashes..."
199+
fix_hashes
200+
201+
echo ""
202+
echo "Done. Changes in flake.nix:"
203+
git diff --stat -- flake.nix 2>/dev/null || true

0 commit comments

Comments
 (0)