NixOS hash verification #6

Merged
kmendell merged 4 commits from ci/nix-hash-verification into main 2026-08-21 12:18:32 -05:00
Owner

Hashes are falling out of sync and NixOS is particular about things matching.

Hashes are falling out of sync and NixOS is particular about things matching.
Both fixed-output hashes in nix/package.nix were stale, so every consumer of
the flake failed at deploy time:

  vendorHash  owH9KEYnBnzT2XpznOQjX4UfbJZEIgnlXaB4B3nTOUk= -> 4dDm3v+WPoFOJTXaptnhqB34gELkvno7JoNlLFCXcTk=
  pnpm hash   V9ktD9gW5yR9qZKyQ2Usr39+eppVOWyLV/GBj3XsdCc= -> GuvJ7r3C2Cy1YTtDFKtp8E1beZSZfy67TQ8848yav18=

The vendorHash mismatch is the one that broke overpass-node on deployed hosts.

Staging the web assets in `preBuild` also made the problem worse than it needed
to be. buildGoModule copies `preBuild` verbatim into the -go-modules derivation,
so vendoring the Go modules pulled in the entire pnpm/Next.js build, and a
change to the web lockfile could take the Go vendor step down with it. Moving
the copy to `postConfigure` -- which that derivation does not inherit -- leaves
the main build unchanged while giving go-modules no web dependency at all.

checks now realises every variant a consumer can select (full, cp, node, cli)
rather than only the full build, and the module check no longer hands the node
an explicit package, so it asserts the module default really resolves to the
noweb overpass-node variant.
Nothing in CI realised the flake, so a stale fixed-output hash reached main and
surfaced only on the machines that deployed it. The one workflow that did run
Nix used `nix flake check --no-build`, which cannot catch this by construction:
a fixed-output hash is only verifiable by building the derivation.

- ci.yaml gains a `nix` job on pull requests and pushes to main: verify both
  pinned hashes, check nix formatting, then `nix flake check --all-systems`
  with no --no-build.
- nix-flake-update.yaml no longer runs on every push to main (which churned the
  lock and made an unrelated nixpkgs change a deploy-time surprise). It is now
  weekly or on demand, regenerates the hashes after the bump -- a new Go
  toolchain or pnpm legitimately invalidates them -- proves the result builds,
  and only then commits the lock and the hashes together. It also no longer
  pulls in the release toolchain just to mint a token.
- release.yaml gates the tag on the same Nix build, since comin-managed hosts
  consume the flake rather than the GoReleaser artifacts.

nix/update-hashes.sh regenerates both hashes, or verifies them with --check,
and is exposed as `just nix-hashes` / `just nix-hashes-check`.
A flake input names one ref and Nix has no "newest tag" resolution, so a host
either follows main or names the release it wants. Both are gated by the same
Nix build in CI.
ci(nix): refresh the pinned hashes on push to main instead of only failing
Some checks failed
CI / lint (pull_request) Successful in 49s
CI / test (pull_request) Failing after 2m31s
CI / nix (pull_request) Successful in 3m10s
0b19dd794c
This repository lands work by pushing straight to main -- there are no merge
commits -- so a job that only verifies leaves main broken until somebody reads
the CI result. That is how v0.18.0, v0.18.1 and v0.19.0 all shipped unbuildable:
fb9352e moved web/pnpm-lock.yaml and 5b8f170 moved go.sum, and neither re-pinned
the hash that depends on it.

nix-hashes.yaml regenerates both pins on every push to main, proves the result
builds, and commits the fix only if something actually moved. It is a separate
workflow so that ci.yaml -- the one that runs on pull requests -- never needs the
OIDC token that pushing to main requires; pull requests and tags keep running
`update-hashes.sh --check`, which fails rather than pushing.

The refresh commit re-triggers the workflow once, finds the pins correct and
pushes nothing, so it terminates. Nightly skips that commit: it is a bot push
that cannot change what a nightly would contain.
kmendell approved these changes 2026-08-21 12:18:24 -05:00
kmendell deleted branch ci/nix-hash-verification 2026-08-21 12:18:32 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ofkm/overpass!6
No description provided.