fix(nix): parse Nix versions without a patch component - #2864
mikeland73 wants to merge 6 commits into
Conversation
Newer Nix releases drop the patch component from their version string
(e.g. "2.33" and prereleases like "2.33pre20251107_479b6b73"). The
version regexp required major.minor.patch, so it failed to match these,
leaving the detected version empty. Devbox then reported:
Error: Devbox requires nix of version >= 2.12.0. Your version is .
Make the patch component optional in the regexp, and coerce two-component
prerelease versions into valid semver (inserting a ".0" patch) before
comparing in Info.AtLeast, since semver requires major.minor.patch for
prerelease versions.
Fixes #2766
There was a problem hiding this comment.
Pull request overview
Updates Devbox’s Nix version detection to handle newer Nix releases that omit the patch component (e.g. 2.33 / 2.33pre…), preventing startup failures caused by an unparsed/invalid version.
Changes:
- Relax
versionRegexpto make the patch component optional while continuing to support existing prerelease/build variants. - Refactor version comparison logic by introducing an
Info.semver()coercion helper and using it inInfo.AtLeast. - Add regression tests covering patchless versions and patchless prereleases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| nix/nix.go | Accepts patchless Nix versions in parsing and coerces Nix versions into valid semver for comparisons. |
| nix/nix_test.go | Adds regression tests for parsing and AtLeast behavior with patchless versions/prereleases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if strings.Count(base, ".") == 1 { | ||
| base += ".0" | ||
| } | ||
| return "v" + base + suffix |
There was a problem hiding this comment.
Good catch — fixed in fbf8f80. Info.semver() now validates the coerced value with semver.IsValid and returns "" on failure, matching the docstring and preventing invalid strings from reaching any future callers.
Generated by Claude Code
Match the documented contract by validating the coerced value before returning it, so semver() never propagates an invalid semver string.
|
Closing as a duplicate of #2924, which addresses the same issue with the same fix. |
Summary
Fixes #2766.
Newer Nix releases dropped the patch component from their version string. For example, Nix 2.33 reports:
(
2.33pre…, not2.33.0pre…). Devbox'sversionRegexprequired a fullmajor.minor.patch, so it failed to match these strings.parseInfothen returned an empty version, and startup failed with the confusing:This blocked
devbox shell/initentirely for anyone on a recent Nix.Fix
versionRegexp— make the patch component optional so it matches both2.33and2.33pre20251107_479b6b73as well as the existing2.21.2/2.23.0pre20240526_7de033d6forms.Info.AtLeast— extract a smallInfo.semver()helper that coerces a Nix version into a valid semver before comparing. A two-component prerelease such as2.33pre…coerces tov2.33.0-pre.20251107+479b6b73(inserting the.0patch), because the semver package requiresmajor.minor.patchfor prerelease versions. Without this, even after the regex matched, the version would still compare as invalid and the check would keep failing.How was it tested?
go test ./nix/passes.TestParseVersionInfoShort(2.33,2.33pre20251107_479b6b73) and toTestVersionInfoAtLeast(verifying2.33and2.33pre…satisfy>= MinVersionand compare correctly against neighboring versions).AtLeastassertions (including the#2128prerelease cases) still pass unchanged.cc @Electrenator (issue reporter)
Generated by Claude Code