Repository navigation
feat(config): read .tool-versions when resolving versions - #291
Merged
Merged
Conversation
Version resolution now reads .tool-versions, the file asdf writes and mise reads to pin several tools at once, and which actions/setup-node, actions/setup-python and ruby/setup-ruby can read in CI. It applies to Node.js, Python and Ruby alike. - It is read in the same upward walk as the other version files. Within one directory the order is .dtvem/runtimes.json, then .tool-versions, then the runtime's own files (.node-version/.nvmrc, .python-version, .ruby-version), which is asdf's order when it reads those files too. - The runtime's line is found by tool name: nodejs (asdf) or node (mise), python, ruby. Lines for other tools are ignored, and a file with no line for the runtime is passed over, so it never hides a pin in the same directory's own file or further up. - The first version on the line is used (asdf treats the rest as fallbacks), under the runtime's usual rules: exact or partial, optional prefix, Ruby pre-releases. Inline # comments are skipped. - system, ref:, path:, anything else the runtime's rules reject, and a tool listed without a version are reported, naming the tool, instead of falling back to the global version.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
dtvem now reads
.tool-versions, the multi-tool file asdf writes and mise reads.actions/setup-node,actions/setup-pythonandruby/setup-rubycan all read it in CI. A repository whose versions live there gets the same Node.js, Python and Ruby on a dtvem machine as in CI and on its asdf/mise users' machines, with no extra file.It builds on the version-file mechanism from #286, #288 and #290.
Type of Change
Related Issues
Resolves #287
Relates to #283, #284, #285, #289
Changes Made
Where and precedence: the same upward walk as the other version files; the nearest directory wins. Within one directory:
.dtvem/runtimes.json.tool-versions.node-version/.nvmrc,.python-version,.ruby-version)This is asdf's order when it reads those files too.
ruby/setup-rubyuses the opposite order. The global version stays the fallback.Finding the runtime's line: by tool name:
nodejs(asdf) ornode(mise) → Node.js,python→ Python,ruby→ Ruby. Names are case-sensitive and must match exactly. Lines for tools dtvem doesn't manage (golang,terraform, …) are ignored.A file without the runtime does not stop the walk. A
.tool-versionswith no line for the runtime is passed over. So aruby-only file in a subproject doesn't hide the same directory's.python-version, or anodejspin in a parent directory.Syntax:
<tool> <version> [<version>...].#comments (including after a version) and tabs or CRLF are fine.v/python-/ruby-prefix, and Ruby pre-releases.Unsupported forms are reported, not replaced by the global version, and the error names the tool, since one file pins several:
system,ref:…,path:…, aliases likeltsFor example:
…\.tool-versions asks for python "system": dtvem supports only version numbers (x, x.y or x.y.z)and…\.tool-versions lists nodejs without a version.VersionFileErrorgains aToolfield for this. An unsupported first version is not skipped in favour of a later one on the line.Not installed / visibility: as for the other files. The shim names
.tool-versionsand suggestsdtvem install <runtime> <version>, anddtvem currentshows it in the Source column.Home directory: the walk reaches
$HOME, so an asdf user's~/.tool-versions(written byasdf set --home) applies everywhere under the home directory, ahead of dtvem's global config. That's asdf's own behaviour, and feat(node): read .node-version and .nvmrc when resolving the version #283 already treats a~/.nvmrcthe same way. The issue asked for this to be documented; it's now in CLAUDE.md, and the dtvem.io docs live in a separate repo.Docs: README feature line,
dtvem current --help, and the CLAUDE.md "Version Resolution" section.Testing
Test Environment
Test Steps
./rnr check: gofmt, golangci-lint (0 issues), and all tests pass.src/internal/config/versionfile_test.go:nodejs/node,vprefix, a file mixing other tools, multiple versions on a line, inline comments, a Ruby preview, tabs/CRLF/comment lines, first matching line wins.system,ref:,path:, alias, a runtime-rule rejection, a missing version, an unsupported first version that isn't skipped. Plus the two new messages.runtimes.jsonover.tool-versions, and.tool-versionsover the runtime's own files in one directory.tool-versions.nvmrcbeating a parent.tool-versionsnode.exe,python.exeandruby.exe, and ran them against the real install from temp project directories.Test Results
v25.2.0/3.12.12/3.4.7(globals).tool-versions:nodejs 22,python 3.9,ruby 3.3.9 # CI,golang 1.22.0, run frompackages/appv22.12.0/3.9.9/3.3.9.tool-versionsnodejs 22.0.0+.node-version22.12.0v22.0.0.dtvem/runtimes.jsonpython3.8.9+.tool-versionspython 3.9.93.8.9.tool-versionsnodejs 22.0.0, child.tool-versionsruby 3.3.9v22.0.0/ (global) /3.3.9python systemnodejswith no version… lists nodejs without a version, exit 1python 3.11(not installed)Set by:.tool-versions,dtvem install python 3.11, exit 1dtvem currentshowed all three runtimes with.tool-versionsas their Source.Checklist
golangci-lint runand fixed all issues (includes gofmt, govet, and 40+ linters)go mod tidyto clean up dependencies (no dependency changes in this PR)go test ./...)Breaking Changes
None intended. A
~/.tool-versionsnow applies under the home directory, as described above. If it listssystemfor a runtime, which asdf users commonly do, that runtime's shims under the home directory stop with an error instead of running the global version.Additional Notes
.tool-versionsand a runtime's own file in the same directory disagree. I left it out. Resolution lives ininternal/config, which has no output path, so a warning needs plumbing through the shim andcurrent. It could be a follow-up.mise.toml, asdf'sASDF_<TOOL>_VERSIONenvironment variables, andASDF_TOOL_VERSIONS_FILENAME.