From c620c5cb0cc50ccebfbed743de8f68552cb7c477 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Tue, 3 Mar 2026 10:42:10 +0700 Subject: [PATCH 1/2] fix(nix): update tauri-runtime and bunDeps hashes for v0.7.9 tauri-runtime upgraded from 2.9.1 to 2.10.0 (branch handy-2.10.2) and bun.lock changed, but flake.nix hashes were not updated. --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 0a064a0c6..a52b021e9 100644 --- a/flake.nix +++ b/flake.nix @@ -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="; }; }; From e7038c7fdb7bdde912f4bfe98bd28c6f80698205 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Tue, 3 Mar 2026 10:42:35 +0700 Subject: [PATCH 2/2] chore(nix): add hash update script and CI evaluation check - scripts/update-nix-hashes.sh: automatically detects outputHashes version mismatches against Cargo.lock and fixes hashes via iterative nix build. Works on NixOS, Ubuntu, macOS. - .github/workflows/nix-check.yml: non-blocking PR check that catches flake.nix evaluation failures and hints at the script. - .gitignore: add nix build result symlink. --- .github/workflows/nix-check.yml | 39 ++++++ .gitignore | 3 + scripts/update-nix-hashes.sh | 203 ++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 .github/workflows/nix-check.yml create mode 100755 scripts/update-nix-hashes.sh diff --git a/.github/workflows/nix-check.yml b/.github/workflows/nix-check.yml new file mode 100644 index 000000000..ea9746644 --- /dev/null +++ b/.github/workflows/nix-check.yml @@ -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 diff --git a/.gitignore b/.gitignore index 813005fb4..c3ee81c14 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ blob-report/ .direnv .envrc + +# Nix build output +result diff --git a/scripts/update-nix-hashes.sh b/scripts/update-nix-hashes.sh new file mode 100755 index 000000000..a5f35fea2 --- /dev/null +++ b/scripts/update-nix-hashes.sh @@ -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