|
1 | 1 | #!/usr/bin/env node |
2 | | -// Cheap proxy for the Nix fetchPnpmDeps hash going stale. |
3 | | -// |
4 | | -// flake.nix pins a `hash = "sha256-..."` for pkgs.fetchPnpmDeps, computed |
5 | | -// from pnpm-lock.yaml. If the lockfile changes and nobody refreshes that |
6 | | -// hash, `nix build` fails in CI with a hash mismatch. Recomputing the real |
7 | | -// hash requires `nix`, which may not be installed locally, so this checks a |
8 | | -// proxy instead: did pnpm-lock.yaml change on this branch without flake.nix |
9 | | -// also changing? That's not proof the hash is stale (a flake.nix edit could |
10 | | -// be unrelated), but it's the cheap signal that catches the common case. |
11 | | -// |
12 | | -// ponytail: proxy check, not a real hash recompute — upgrade to `nix build |
13 | | -// --dry-run` locally if false positives/negatives become a problem. |
| 2 | +// Use the branch diff as a fast path, then verify inconclusive lock-only changes |
| 3 | +// against the committed dependency derivation. Rebuild fixed-output dependencies |
| 4 | +// so a cached store path cannot hide a stale hash. |
14 | 5 | import { execFileSync } from 'node:child_process'; |
| 6 | +import { pathToFileURL } from 'node:url'; |
15 | 7 |
|
16 | 8 | function git(args) { |
17 | 9 | return execFileSync('git', args, { encoding: 'utf8' }).trim(); |
@@ -60,10 +52,20 @@ if (!lockChanged || flakeChanged) { |
60 | 52 | process.exit(0); |
61 | 53 | } |
62 | 54 |
|
63 | | -console.error( |
64 | | - '❌ pnpm-lock.yaml changed on this branch but flake.nix did not.\n' + |
65 | | - ' flake.nix pins a fetchPnpmDeps hash of pnpm-lock.yaml, so its hash may be stale.\n' + |
66 | | - ' Refresh it: run a nix build (e.g. `nix build .#pythinker-code`), take the sha256-... hash\n' + |
67 | | - ' from the mismatch error, paste it into the `hash = "sha256-...";` line in flake.nix, commit, and re-push.', |
68 | | -); |
69 | | -process.exit(1); |
| 55 | +console.log('[nix-hash-freshness] lockfile changed without flake.nix; verifying the committed dependency hash.'); |
| 56 | +try { |
| 57 | + const source = pathToFileURL(git(['rev-parse', '--show-toplevel'])); |
| 58 | + source.searchParams.set('rev', git(['rev-parse', 'HEAD'])); |
| 59 | + source.hash = 'pythinker-code.pnpmDeps'; |
| 60 | + execFileSync('nix', ['build', `git+${source.href}`, '--rebuild', '--no-link'], { |
| 61 | + stdio: 'inherit', |
| 62 | + timeout: 600_000, |
| 63 | + }); |
| 64 | +} catch (error) { |
| 65 | + console.error( |
| 66 | + '[nix-hash-freshness] could not verify the committed dependency hash. ' + |
| 67 | + 'Install Nix if unavailable, resolve build errors, or refresh flake.nix with the reported hash.', |
| 68 | + ); |
| 69 | + console.error(error.message); |
| 70 | + process.exit(1); |
| 71 | +} |
0 commit comments