From 121d6a72c0bc62c8a0699db87fb4f11b1bb73a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sat, 31 Jan 2026 19:32:11 +0100 Subject: [PATCH] fix(nix): restore native runners for darwin hash computation (#11495) --- .github/workflows/nix-hashes.yml | 167 +++++++++++++++++-------------- flake.nix | 23 +---- nix/node_modules.nix | 11 +- 3 files changed, 99 insertions(+), 102 deletions(-) diff --git a/.github/workflows/nix-hashes.yml b/.github/workflows/nix-hashes.yml index 061b4ada8d..bb4db70882 100644 --- a/.github/workflows/nix-hashes.yml +++ b/.github/workflows/nix-hashes.yml @@ -21,11 +21,68 @@ on: - ".github/workflows/nix-hashes.yml" jobs: - nix-hashes: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + # Native runners required: bun install cross-compilation flags (--os/--cpu) + # do not produce byte-identical node_modules as native installs. + compute-hash: + strategy: + fail-fast: false + matrix: + include: + - system: x86_64-linux + runner: blacksmith-4vcpu-ubuntu-2404 + - system: aarch64-linux + runner: blacksmith-4vcpu-ubuntu-2404-arm + - system: x86_64-darwin + runner: macos-15-intel + - system: aarch64-darwin + runner: macos-latest + runs-on: ${{ matrix.runner }} + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Nix + uses: nixbuild/nix-quick-install-action@v34 + + - name: Compute node_modules hash + id: hash + env: + SYSTEM: ${{ matrix.system }} + run: | + set -euo pipefail + + BUILD_LOG=$(mktemp) + trap 'rm -f "$BUILD_LOG"' EXIT + + # Build with fakeHash to trigger hash mismatch and reveal correct hash + nix build ".#packages.${SYSTEM}.node_modules_updater" --no-link 2>&1 | tee "$BUILD_LOG" || true + + HASH="$(grep -E 'got:\s+sha256-' "$BUILD_LOG" | sed -E 's/.*got:\s+(sha256-[A-Za-z0-9+/=]+).*/\1/' | head -n1 || true)" + if [ -z "$HASH" ]; then + HASH="$(grep -A2 'hash mismatch' "$BUILD_LOG" | grep 'got:' | sed -E 's/.*got:\s+(sha256-[A-Za-z0-9+/=]+).*/\1/' | head -n1 || true)" + fi + + if [ -z "$HASH" ]; then + echo "::error::Failed to compute hash for ${SYSTEM}" + cat "$BUILD_LOG" + exit 1 + fi + + echo "$HASH" > hash.txt + echo "Computed hash for ${SYSTEM}: $HASH" + + - name: Upload hash + uses: actions/upload-artifact@v4 + with: + name: hash-${{ matrix.system }} + path: hash.txt + retention-days: 1 + + update-hashes: + needs: compute-hash + if: github.event_name != 'pull_request' runs-on: blacksmith-4vcpu-ubuntu-2404 - env: - TITLE: node_modules hashes steps: - name: Checkout repository @@ -33,108 +90,64 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - ref: ${{ github.head_ref || github.ref_name }} - repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + ref: ${{ github.ref_name }} - name: Setup git committer - id: committer uses: ./.github/actions/setup-git-committer with: opencode-app-id: ${{ vars.OPENCODE_APP_ID }} opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - name: Setup Nix - uses: nixbuild/nix-quick-install-action@v34 - - name: Pull latest changes - env: - TARGET_BRANCH: ${{ github.head_ref || github.ref_name }} run: | - BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}" - git pull --rebase --autostash origin "$BRANCH" + git pull --rebase --autostash origin "$GITHUB_REF_NAME" - - name: Compute all node_modules hashes + - name: Download hash artifacts + uses: actions/download-artifact@v4 + with: + path: hashes + pattern: hash-* + + - name: Update hashes.json run: | set -euo pipefail HASH_FILE="nix/hashes.json" - SYSTEMS="x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin" - if [ ! -f "$HASH_FILE" ]; then - mkdir -p "$(dirname "$HASH_FILE")" - echo '{"nodeModules":{}}' > "$HASH_FILE" - fi + [ -f "$HASH_FILE" ] || echo '{"nodeModules":{}}' > "$HASH_FILE" - for SYSTEM in $SYSTEMS; do - echo "Computing hash for ${SYSTEM}..." - BUILD_LOG=$(mktemp) - trap 'rm -f "$BUILD_LOG"' EXIT - - # The updater derivations use fakeHash, so they will fail and reveal the correct hash - UPDATER_ATTR=".#packages.x86_64-linux.${SYSTEM}_node_modules" - - nix build "$UPDATER_ATTR" --no-link 2>&1 | tee "$BUILD_LOG" || true - - CORRECT_HASH="$(grep -E 'got:\s+sha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | awk '{print $2}' | head -n1 || true)" - - if [ -z "$CORRECT_HASH" ]; then - CORRECT_HASH="$(grep -A2 'hash mismatch' "$BUILD_LOG" | grep 'got:' | awk '{print $2}' | sed 's/sha256:/sha256-/' || true)" + for SYSTEM in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do + FILE="hashes/hash-${SYSTEM}/hash.txt" + if [ -f "$FILE" ]; then + HASH="$(tr -d '[:space:]' < "$FILE")" + echo "${SYSTEM}: ${HASH}" + jq --arg sys "$SYSTEM" --arg h "$HASH" '.nodeModules[$sys] = $h' "$HASH_FILE" > tmp.json + mv tmp.json "$HASH_FILE" + else + echo "::warning::Missing hash for ${SYSTEM}" fi - - if [ -z "$CORRECT_HASH" ]; then - echo "Failed to determine correct node_modules hash for ${SYSTEM}." - cat "$BUILD_LOG" - exit 1 - fi - - echo " ${SYSTEM}: ${CORRECT_HASH}" - jq --arg sys "$SYSTEM" --arg h "$CORRECT_HASH" \ - '.nodeModules[$sys] = $h' "$HASH_FILE" > "${HASH_FILE}.tmp" - mv "${HASH_FILE}.tmp" "$HASH_FILE" done - echo "All hashes computed:" cat "$HASH_FILE" - - name: Commit ${{ env.TITLE }} changes - env: - TARGET_BRANCH: ${{ github.head_ref || github.ref_name }} + - name: Commit changes run: | set -euo pipefail HASH_FILE="nix/hashes.json" - echo "Checking for changes..." - summarize() { - local status="$1" - { - echo "### Nix $TITLE" - echo "" - echo "- ref: ${GITHUB_REF_NAME}" - echo "- status: ${status}" - } >> "$GITHUB_STEP_SUMMARY" - if [ -n "${GITHUB_SERVER_URL:-}" ] && [ -n "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_RUN_ID:-}" ]; then - echo "- run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> "$GITHUB_STEP_SUMMARY" - fi - echo "" >> "$GITHUB_STEP_SUMMARY" - } - - FILES=("$HASH_FILE") - STATUS="$(git status --short -- "${FILES[@]}" || true)" - if [ -z "$STATUS" ]; then - echo "No changes detected." - summarize "no changes" + if [ -z "$(git status --short -- "$HASH_FILE")" ]; then + echo "No changes to commit" + echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" + echo "Status: no changes" >> "$GITHUB_STEP_SUMMARY" exit 0 fi - echo "Changes detected:" - echo "$STATUS" - git add "${FILES[@]}" + git add "$HASH_FILE" git commit -m "chore: update nix node_modules hashes" - BRANCH="${TARGET_BRANCH:-${GITHUB_REF_NAME}}" - git pull --rebase --autostash origin "$BRANCH" - git push origin HEAD:"$BRANCH" - echo "Changes pushed successfully" + git pull --rebase --autostash origin "$GITHUB_REF_NAME" + git push origin HEAD:"$GITHUB_REF_NAME" - summarize "committed $(git rev-parse --short HEAD)" + echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" + echo "Status: committed $(git rev-parse --short HEAD)" >> "$GITHUB_STEP_SUMMARY" diff --git a/flake.nix b/flake.nix index e4d214a0b9..ea78b1a434 100644 --- a/flake.nix +++ b/flake.nix @@ -42,28 +42,15 @@ desktop = pkgs.callPackage ./nix/desktop.nix { inherit opencode; }; - # nixpkgs cpu naming to bun cpu naming - cpuMap = { x86_64 = "x64"; aarch64 = "arm64"; }; - # matrix of node_modules builds - these will always fail due to fakeHash usage - # but allow computation of the correct hash from any build machine for any cpu/os - # see the update-nix-hashes workflow for usage - moduleUpdaters = pkgs.lib.listToAttrs ( - pkgs.lib.concatMap (cpu: - map (os: { - name = "${cpu}-${os}_node_modules"; - value = node_modules.override { - bunCpu = cpuMap.${cpu}; - bunOs = os; - hash = pkgs.lib.fakeHash; - }; - }) [ "linux" "darwin" ] - ) [ "x86_64" "aarch64" ] - ); in { default = opencode; inherit opencode desktop; - } // moduleUpdaters + # Updater derivation with fakeHash - build fails and reveals correct hash + node_modules_updater = node_modules.override { + hash = pkgs.lib.fakeHash; + }; + } ); }; } diff --git a/nix/node_modules.nix b/nix/node_modules.nix index 981a60ef9b..6d75b9e750 100644 --- a/nix/node_modules.nix +++ b/nix/node_modules.nix @@ -2,8 +2,6 @@ lib, stdenvNoCC, bun, - bunCpu ? if stdenvNoCC.hostPlatform.isAarch64 then "arm64" else "x64", - bunOs ? if stdenvNoCC.hostPlatform.isLinux then "linux" else "darwin", rev ? "dirty", hash ? (lib.pipe ./hashes.json [ @@ -16,6 +14,9 @@ let builtins.readFile builtins.fromJSON ]; + platform = stdenvNoCC.hostPlatform; + bunCpu = if platform.isAarch64 then "arm64" else "x64"; + bunOs = if platform.isLinux then "linux" else "darwin"; in stdenvNoCC.mkDerivation { pname = "opencode-node_modules"; @@ -39,9 +40,7 @@ stdenvNoCC.mkDerivation { "SOCKS_SERVER" ]; - nativeBuildInputs = [ - bun - ]; + nativeBuildInputs = [ bun ]; dontConfigure = true; @@ -63,10 +62,8 @@ stdenvNoCC.mkDerivation { installPhase = '' runHook preInstall - mkdir -p $out find . -type d -name node_modules -exec cp -R --parents {} $out \; - runHook postInstall '';