Skip to content

fix(nix): correctly qualify flake input refs as tags or branches - #45000

Draft
mglazer wants to merge 1 commit into
renovatebot:mainfrom
mglazer:fix/nix-flake-ref-qualification
Draft

fix(nix): correctly qualify flake input refs as tags or branches#45000
mglazer wants to merge 1 commit into
renovatebot:mainfrom
mglazer:fix/nix-flake-ref-qualification

Conversation

@mglazer

@mglazer mglazer commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Changes

When the nix manager rewrites a flake input's ref= query param (e.g. bumping ref=some-branch to a newer value), it substring-replaces the old ref value with the new one while keeping whatever refs/heads//refs/tags/ qualifier (or lack of one) the old ref happened to have.

This breaks when the new value resolves to a different ref namespace than the old one — for example, bumping an unqualified branch ref to a value that only exists as a tag upstream. Nix's git fetcher resolves a bare or mis-qualified ref via refs/heads/<ref> only, with no fallback to refs/tags/, so nix flake lock/nix flake update then fails with:

fatal: couldn't find remote ref refs/heads/<ref>

even though the ref exists as a tag (or vice versa).

This PR:

  • Adds gitRefType ('tags' | 'heads') to Release, populated by the git-refs datasource from the actual remote refs it already fetches (preferring 'tags' when a value is ambiguous, matching Nix's own resolution order).
  • Threads gitRefType through generateUpdateLookupUpdateUpgrade, so managers can see how a candidate new version actually resolves upstream.
  • Reintroduces a nix-specific updateDependency (it didn't previously exist; nix relied on the generic auto-replace fallback). Without it, auto-replace can't reliably locate and rewrite a flake input URL's ref=/rev= query params together and throws for the common case of an input pinning both a ref and a rev.
  • The new updateDependency uses gitRefType to decide the correct qualifier when rewriting a flake input URL, falling back to the old ref's own shape (qualified or bare) when that information isn't available, so behavior for datasources/managers that don't set gitRefType is unchanged.

Context / repro

Repro'd locally with real nix (Determinate Nix 2.33 / upstream 2.18+): a flake input pinned via ref=v20.0.0 where v20.0.0 exists only as a tag on the remote fails identically:

fatal: couldn't find remote ref refs/heads/v20.0.0

while ref=refs/tags/v20.0.0 resolves correctly. Also confirmed that without a nix-specific updateDependency, the generic auto-replace path throws WORKER_FILE_UPDATE_FAILED for a flake input pinning both ref= and rev= when bumping to a new value, since it can't locate a single replaceString/currentValue covering both.

Tests

  • Added lib/modules/manager/nix/update.spec.ts (12 cases): bare ref → tag, bare ref → branch, stale-qualifier correction, tag→tag preservation, no-gitRefType fallback, github: shorthand handling, digest-only updates, and not-found/unparseable-URL edge cases. 100% statement/line coverage on the new file.
  • Updated lib/modules/datasource/git-refs/index.spec.ts snapshot for the new gitRefType field.
  • Ran the full existing suites for lib/modules/manager/nix/, lib/modules/datasource/git-refs/, lib/workers/repository/process/lookup/, and lib/workers/repository/update/branch/ — all passing, no regressions.

When the nix manager rewrites a flake input's `ref=` query param
(e.g. bumping `ref=some-branch` to a newer value), it currently
substring-replaces the old ref value with the new one, keeping
whatever refs/heads//refs/tags/ qualifier (or lack of one) the old
ref happened to have.

This breaks when the new value resolves to a different ref namespace
than the old one, e.g. bumping an unqualified branch ref to a value
that only exists as a tag upstream. Nix's git fetcher resolves a bare
or mis-qualified ref via refs/heads/<ref> only, with no fallback to
refs/tags/, so `nix flake lock`/`nix flake update` then fails with
"fatal: couldn't find remote ref refs/heads/<ref>" even though the
ref exists as a tag.

Thread the git-refs datasource's own knowledge of each ref's actual
type (tag vs branch) through lookup generation into the nix manager,
and use it to decide the correct qualifier when rewriting a flake
input URL, falling back to the old ref's shape when that information
isn't available.

This also reintroduces a nix-specific updateDependency implementation:
without one, the generic auto-replace fallback cannot reliably locate
and rewrite a flake input's `ref=`/`rev=` query params together, and
throws for the common case of a flake input pinning both a ref and a
rev.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant