diff --git a/.github/actions/nix-setup/action.yml b/.github/actions/nix-setup/action.yml new file mode 100644 index 0000000000..0fcd7784bc --- /dev/null +++ b/.github/actions/nix-setup/action.yml @@ -0,0 +1,8 @@ +name: 'Setup Nix' +description: 'Install Nix with DeterminateSystems and enable magic-nix-cache' + +runs: + using: composite + steps: + - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13 diff --git a/.github/workflows/nix-lockfile-check.yml b/.github/workflows/nix-lockfile-check.yml index 61c428021b..9c9bc734a6 100644 --- a/.github/workflows/nix-lockfile-check.yml +++ b/.github/workflows/nix-lockfile-check.yml @@ -2,14 +2,6 @@ name: Nix Lockfile Check on: pull_request: - paths: - - 'ui-tui/package.json' - - 'ui-tui/package-lock.json' - - 'web/package.json' - - 'web/package-lock.json' - - 'nix/tui.nix' - - 'nix/web.nix' - - 'nix/lib.nix' workflow_dispatch: permissions: @@ -27,7 +19,7 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: nixbuild/nix-quick-install-action@63ca48f939ee3b8d835f4126562537df0fee5b91 # v30 + - uses: ./.github/actions/nix-setup - name: Resolve head SHA id: sha diff --git a/.github/workflows/nix-lockfile-fix.yml b/.github/workflows/nix-lockfile-fix.yml index 5021e318fd..a1c7dd6e5c 100644 --- a/.github/workflows/nix-lockfile-fix.yml +++ b/.github/workflows/nix-lockfile-fix.yml @@ -98,7 +98,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - - uses: nixbuild/nix-quick-install-action@63ca48f939ee3b8d835f4126562537df0fee5b91 # v30 + - uses: ./.github/actions/nix-setup - name: Apply lockfile hashes id: apply diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 387c9e5d13..7cae6f8151 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -4,15 +4,6 @@ on: push: branches: [main] pull_request: - paths: - - 'flake.nix' - - 'flake.lock' - - 'nix/**' - - 'pyproject.toml' - - 'uv.lock' - - 'hermes_cli/**' - - 'run_agent.py' - - 'acp_adapter/**' permissions: contents: read @@ -29,9 +20,8 @@ jobs: runs-on: ${{ matrix.os }} timeout-minutes: 30 steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 - - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: ./.github/actions/nix-setup - name: Check flake if: runner.os == 'Linux' run: nix flake check --print-build-logs diff --git a/nix/lib.nix b/nix/lib.nix index f97f1539f6..ee28537a66 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -2,17 +2,23 @@ { pkgs, npm-lockfile-fix }: { # Returns a buildNpmPackage-compatible attrs set that provides: - # patchPhase — strips trailing NUL newline from lockfile + # patchPhase — ensures lockfile has exactly one trailing newline # nativeBuildInputs — [ updateLockfileScript ] (list, prepend with ++ for more) # passthru.devShellHook — stamp-checked npm install + hash auto-update # passthru.npmLockfile — metadata for mkFixLockfiles # + # NOTE: npmConfigHook runs `diff` between the source lockfile and the + # npm-deps cache lockfile. fetchNpmDeps preserves whatever trailing + # newlines the lockfile has. The patchPhase normalizes to exactly one + # trailing newline so both sides always match. + # # Usage: # npm = hermesNpmLib.mkNpmPassthru { folder = "ui-tui"; attr = "tui"; pname = "hermes-tui"; }; # pkgs.buildNpmPackage (npm // { ... } # or: # pkgs.buildNpmPackage ({ ... } // npm) mkNpmPassthru = - { folder, # repo-relative folder with package.json, e.g. "ui-tui" + { + folder, # repo-relative folder with package.json, e.g. "ui-tui" attr, # flake package attr, e.g. "tui" pname, # e.g. "hermes-tui" nixFile ? "nix/${attr}.nix", # defaults to nix/.nix @@ -20,7 +26,25 @@ { patchPhase = '' runHook prePatch - sed -i -z 's/\n$//' package-lock.json + # Normalize trailing newlines so source and npm-deps always match, + # regardless of what fetchNpmDeps preserves. + sed -i -z 's/\n*$/\n/' package-lock.json + + # Make npmConfigHook's byte-for-byte diff newline-agnostic by + # replacing its hardcoded /nix/store/.../diff with a wrapper that + # normalizes trailing newlines on both sides before comparing. + mkdir -p "$TMPDIR/bin" + cat > "$TMPDIR/bin/diff" << DIFFWRAP + #!/bin/sh + f1=\$(mktemp) && sed -z 's/\n*$/\n/' "\$1" > "\$f1" + f2=\$(mktemp) && sed -z 's/\n*$/\n/' "\$2" > "\$f2" + ${pkgs.diffutils}/bin/diff "\$f1" "\$f2" && rc=0 || rc=\$? + rm -f "\$f1" "\$f2" + exit \$rc + DIFFWRAP + chmod +x "$TMPDIR/bin/diff" + export PATH="$TMPDIR/bin:$PATH" + runHook postPatch '';