Skip to content

Latest commit

 

History

History
120 lines (88 loc) · 4.61 KB

File metadata and controls

120 lines (88 loc) · 4.61 KB

Lockfile Format

go2nix uses TOML lockfiles to pin module hashes. Both builder modes share the same lockfile format, generated by go2nix generate.

Format

# go2nix lockfile v2. Generated by go2nix. Do not edit.

[mod]
"github.com/foo/[email protected]" = "sha256-abc..."
"golang.org/x/[email protected]" = "sha256-def..."

[replace]
"github.com/foo/[email protected]" = "github.com/fork/bar"

Versioning

The header comment carries a format version (go2nix lockfile vN). The current version is v2. go2nix generate always writes the current version; older lockfiles should be regenerated.

Sections

[mod] — Module hashes. Each key is a composite "path@version" string, each value is a sha256-... SRI NAR hash of the module as laid out by go mod download under $GOMODCACHE (the same tree the FOD fetcher produces).

[replace] — Module replacements (from go.mod replace directives). Maps the original composite key to the replacement module path. Only remote replacements are recorded; local replace directives (filesystem paths) are not included.

Composite keys

Module keys use "path@version" format (e.g., "golang.org/x/[email protected]"). This keeps each module uniquely identified and avoids collisions across versions.

Package graph resolution

The lockfile stores only module NAR hashes; the package graph is discovered separately (eval-time plugin in default mode, build-time go list in experimental mode — see Builder Modes).

Monorepo support

When go2nix generate is given multiple directories, all modules are merged into a single lockfile. Modules from different go.mod files coexist without conflict since each is uniquely keyed by "path@version".

When to regenerate

Regenerate the lockfile when — and only when — the module set changes:

  • you add, remove, or bump a require line in go.mod
  • a replace directive changes which remote module a path resolves to
  • go.sum gains or loses entries

You do not need to regenerate after changing which packages import which other packages, adding a new local package, or editing .go files. The lockfile pins module hashes; the package graph is rediscovered on every evaluation (see Package graph resolution).

go2nix generate .   # rewrite go2nix.toml
go2nix check .      # verify go2nix.toml still matches go.mod, no rewrite

Lockfile-free builds

Default mode can build without a lockfile by setting goLock = null:

goEnv.buildGoApplication {
  src = ./.;
  goLock = null;
  pname = "my-app";
  version = "0.1.0";
}

When no lockfile is present, the Nix plugin is invoked with resolveHashes = true and computes a NAR hash for each module from go.sum + GOMODCACHE, returning a moduleHashes attrset that fills the role of the [mod] section. Module FODs are then keyed on those hashes.

This trades a checked-in pin file for zero lockfile maintenance. The build is still reproducible as long as go.sum is unchanged, but you lose the explicit, reviewable hash list.

Note: the build-time staleness check (mvscheck, see below) is skipped when goLock = null — there is no lockfile for go.mod to drift from. Module versions are read live from go.sum via the plugin on every evaluation, so a go get is reflected on the next nix build with nothing to regenerate. The standalone go2nix check subcommand still requires a lockfile path and is not applicable in this mode.

Prefer a committed lockfile for anything you ship; lockfile-free is useful for ad-hoc builds and during early development.

Staleness detection

When What Applies to How
Generation MVS (Minimal Version Selection) consistency All modes go list -json -deps resolves actual versions
Nix eval Package graph Default only builtins.resolveGoPackages runs go list at eval time
Build time Lockfile consistency Default, with lockfile link-binary re-reads go.mod and checks every required module is present in the lockfile at the right version; skipped when goLock = null

In default mode, missing or mismatched modules are caught at build time when link-binary validates the lockfile. Stale package graph information is caught at eval time when builtins.resolveGoPackages runs go list. In experimental mode, module mismatches surface at build time when go list or module fetching fails inside the recursive-nix sandbox.

Run go2nix check <dir> or go2nix check --lockfile <path> <dir> to verify a lockfile without building.