Repository navigation
fix(config): keep git flake subdirectory refs as distinct inputs (#2704) - #2877
Conversation
Two git flake references pointing at the same repository but different subdirectories (via the `dir` query parameter) are distinct inputs, yet devbox deduplicated them and only installed one. The root cause was `parseVersionedName`: it split package strings on `@` to separate name from version. Git flake URLs legitimately contain `@` in their `git@host` authority, so e.g. git+ssh://git@gitlab.com/org/repo.git?dir=betteralign&ref=...&rev=... git+ssh://git@gitlab.com/org/repo.git?dir=recovergoroutine&ref=...&rev=... both parsed to the name "git+ssh://git", with the rest dumped into the "version". Config.Packages() then deduplicates by name (lo.UniqBy), so one of the two inputs was silently dropped. Fix: treat flake references as unversioned in parseVersionedName, so the whole reference is used as the name. This keeps refs that differ only by query parameters distinct while leaving versioned devbox packages (and flake refs without an `@`) unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013x2JTaq6GPt4kX5bubQC2D
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where Devbox incorrectly deduplicated distinct git flake inputs that point to the same repo but different subdirectories (via ?dir=...), caused by @ in git@host being misinterpreted as the name@version delimiter during package parsing.
Changes:
- Update
parseVersionedNameto treat flake references as unversioned, preserving the full flake ref as the package name. - Extend
TestParseVersionedNamecoverage forgit+ssh://git@...flake URLs (with and without query params). - Add a regression test ensuring
Config.Packages()does not deduplicate distinct git flake refs that differ only bydir.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| internal/devconfig/configfile/packages.go | Detect flake references early and avoid splitting on @, preventing incorrect deduplication. |
| internal/devconfig/configfile/packages_test.go | Adds test cases proving parseVersionedName preserves full git+ssh flake refs containing @. |
| internal/devconfig/config_test.go | Adds regression test asserting Config.Packages() preserves distinct git flake inputs differing by dir. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@claude please review this PR for correctness, and flag anything that would block merging. |
|
Claude finished @mikeland73's task in 2m 58s —— View job Reviewing PR #2877
Note: I was unable to run SummaryThis is a well-targeted, low-risk fix. I traced the root cause and confirmed it independently:
I checked a few things that could have made this risky, and they all check out:
TestsThe new test cases are appropriate and directly exercise the bug:
Nits (non-blocking)
VerdictI don't see anything that should block merging. The fix is correct, narrowly scoped, backed by tests that reproduce the actual bug (not just the parsing symptom), and I couldn't construct a case where it regresses existing behavior. |
Summary
Fixes #2704.
Two git flake references that point at the same repository but different subdirectories (via the
dirquery parameter) are distinct inputs, but devbox deduplicated them and silently installed only one. For example:Only
dir=recovergoroutineended up indevbox.lockand got installed.Root cause
parseVersionedName(ininternal/devconfig/configfile/packages.go) split every package string on@to separate the name from the version. Git flake URLs legitimately contain an@in theirgit@hostauthority, so both of the refs above parsed to the namegit+ssh://git, with the rest of the URL (including the differentiatingdir) dumped into the "version".Config.Packages()then deduplicates packages by name (lo.UniqBy(p.Name)— used so that a version override wins over an included/plugin package). Because both refs shared the same parsed name, one of the two distinct inputs was dropped.Fix
Treat flake references as unversioned in
parseVersionedName, so the whole reference is used as the name. Flake refs aren't Devboxname@versionpackages, so this is also conceptually correct. This:dir) distinct, andpython@3.10,emacsPackages.@@latest, …) and flake refs without an@unchanged.The flake-detection reuses the existing
pkgtype.IsFlakehelper (no import cycle —pkgtypedoes not depend onconfigfile). The package'sVersionedName()output is unchanged for these refs, so no lockfile migration is needed.Tests
TestParseVersionedName: addedgit-ssh-flake-with-dirandgit-ssh-flake-without-querycases.TestPackagesDoesNotDedupDistinctGitFlakes: new regression test asserting thatConfig.Packages()preserves both git flakes that differ only bydir.(The two pre-existing
TestFindErrorpermission sub-tests fail only when the suite runs as root and are unrelated to this change.)cc @maxiem-ota-insight (issue author)
🤖 Generated with Claude Code
https://claude.ai/code/session_013x2JTaq6GPt4kX5bubQC2D
Generated by Claude Code