feat: add version-file input#542
Conversation
You can now use .tool-versions file to specify GoReleaser version to download
caarlos0
left a comment
There was a problem hiding this comment.
looks good - could you add tests as well? there's a bunch in there, you can follow their lead
|
@caarlos0 just added a test file! |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #542 +/- ##
==========================================
+ Coverage 66.92% 68.78% +1.86%
==========================================
Files 3 4 +1
Lines 130 157 +27
Branches 23 43 +20
==========================================
+ Hits 87 108 +21
- Misses 27 49 +22
+ Partials 16 0 -16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Hey sorry about the missing unused imports, I will clean it up |
|
@caarlos0 I've updated the test file to remove the unused imports, tell me if that |
| if (requestedVersion && versionFilePath) { | ||
| core.warning( | ||
| `Both version (${requestedVersion}) and version-file (${versionFilePath}) inputs are specified, only version will be used` | ||
| ); | ||
| } |
There was a problem hiding this comment.
i wonder if it would be better to simplify all this making version-file having precedence
so, if version-file is given, use it, or error
otherwise, use version, which would also mean we don't need to manually default to ~> v2
wdyt?
There was a problem hiding this comment.
I think it is a better solution indeed because then I can revert all the changes about how the default version is computed.
I've taken much inspiration from the current implementation in the goreleaser action, so I've essentially implemented the same behavior.
Let me change it with your suggestion.
There was a problem hiding this comment.
Pull request overview
Adds support for selecting the GoReleaser version via a version-file input (currently .tool-versions), with parsing logic and tests.
Changes:
- Introduced
getRequestedVersion()to resolve version fromversionorversion-file. - Wired resolved version into the installation flow in
src/main.ts. - Documented the new input and added Jest coverage for version resolution.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/version.ts | Adds logic to resolve GoReleaser version from .tool-versions (or fall back to version). |
| src/main.ts | Uses resolved version when installing GoReleaser. |
| src/context.ts | Adds versionFile input wiring. |
| action.yml | Declares new version-file input. |
| tests/version.test.ts | Adds Jest tests for version resolution behavior. |
| README.md | Documents version-file and updates TOC / inputs list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const workingDirectory = inputs.workdir; | ||
| if (workingDirectory) { | ||
| versionFilePath = path.join(workingDirectory, versionFilePath); | ||
| } | ||
|
|
||
| if (!fs.existsSync(versionFilePath)) { | ||
| throw new Error(`The specified GoReleaser version file at: ${versionFilePath} does not exist`); | ||
| } |
There was a problem hiding this comment.
This always resolves version-file relative to workdir when workdir is set (including common monorepo setups where workdir is a subdirectory). That makes it impossible to reference a version file in the repo root while also using a non-root workdir, despite the docs saying the path can be relative to the root or workdir. Consider resolving relative paths by checking both candidates (repo root path first, then path.join(workdir, versionFile)), or updating the docs to state that version-file is interpreted relative to workdir when provided.
| if (path.basename(versionFilePath) === '.tool-versions') { | ||
| // asdf/mise file. | ||
| const match = content.match(/^goreleaser\s+([^\n#]+)/m); | ||
| requestedVersion = match ? 'v' + match[1].trim().replace(/^v/gi, '') : ''; |
There was a problem hiding this comment.
If .tool-versions doesn’t contain a goreleaser ... entry, this sets requestedVersion to an empty string, which will likely cause a confusing failure later during install. Prefer throwing a clear error when no matching entry is found (e.g., file exists but no goreleaser line), so users get an actionable message.
| requestedVersion = match ? 'v' + match[1].trim().replace(/^v/gi, '') : ''; | |
| if (!match) { | |
| throw new Error( | |
| `No 'goreleaser' entry found in ${versionFilePath}. ` + | |
| "Please add a line like 'goreleaser <version>' or specify the version input directly." | |
| ); | |
| } | |
| requestedVersion = 'v' + match[1].trim().replace(/^v/gi, ''); |
|
|
||
| if (path.basename(versionFilePath) === '.tool-versions') { | ||
| // asdf/mise file. | ||
| const match = content.match(/^goreleaser\s+([^\n#]+)/m); |
There was a problem hiding this comment.
The parser requires goreleaser to start at column 0. .tool-versions files sometimes contain leading whitespace; allowing optional leading spaces (e.g., ^\\s*goreleaser\\s+... with the m flag) would make the parsing more robust without changing intended behavior.
| const match = content.match(/^goreleaser\s+([^\n#]+)/m); | |
| const match = content.match(/^\s*goreleaser\s+([^\n#]+)/m); |
| expect(v).toBe('v1.2.3'); | ||
| }); | ||
|
|
||
| it('parses .tool-versions and returns v-prefixed version', () => { |
There was a problem hiding this comment.
There isn’t a test covering the case where .tool-versions exists but has no goreleaser entry (or has a malformed one). If getRequestedVersion() is updated to throw a specific error for that scenario (recommended), please add a Jest test asserting that behavior (ideally also asserting the error message).
| expect(v).toBe('v1.2.3'); | ||
| }); | ||
|
|
||
| it('when both version and version-file are provided, version-file takes precedence', () => { |
There was a problem hiding this comment.
There isn’t a test covering the case where .tool-versions exists but has no goreleaser entry (or has a malformed one). If getRequestedVersion() is updated to throw a specific error for that scenario (recommended), please add a Jest test asserting that behavior (ideally also asserting the error message).
| const v = getRequestedVersion(inputs); | ||
| expect(v).toBe('v1.2.3'); | ||
| }); | ||
|
|
There was a problem hiding this comment.
There isn’t a test covering the case where .tool-versions exists but has no goreleaser entry (or has a malformed one). If getRequestedVersion() is updated to throw a specific error for that scenario (recommended), please add a Jest test asserting that behavior (ideally also asserting the error message).
| it('throws when .tool-versions exists but has no goreleaser entry', () => { | |
| const toolVersionsPath = path.join(tmpDir, '.tool-versions'); | |
| fs.writeFileSync(toolVersionsPath, 'nodejs 20.0.0\n'); | |
| const inputs: Inputs = { | |
| distribution: 'goreleaser', | |
| version: '', | |
| versionFile: '.tool-versions', | |
| args: '', | |
| workdir: tmpDir, | |
| installOnly: false | |
| }; | |
| expect(() => getRequestedVersion(inputs)).toThrow(/goreleaser/i); | |
| }); | |
| it('throws when .tool-versions has a malformed goreleaser entry', () => { | |
| const toolVersionsPath = path.join(tmpDir, '.tool-versions'); | |
| fs.writeFileSync(toolVersionsPath, 'goreleaser not-a-version\n'); | |
| const inputs: Inputs = { | |
| distribution: 'goreleaser', | |
| version: '', | |
| versionFile: '.tool-versions', | |
| args: '', | |
| workdir: tmpDir, | |
| installOnly: false | |
| }; | |
| expect(() => getRequestedVersion(inputs)).toThrow(/goreleaser/i); | |
| }); |
| expect(() => getRequestedVersion(inputs)).toThrow(); | ||
| }); | ||
|
|
||
| it('throws when version-file is an unsupported type', () => { |
There was a problem hiding this comment.
There isn’t a test covering the case where .tool-versions exists but has no goreleaser entry (or has a malformed one). If getRequestedVersion() is updated to throw a specific error for that scenario (recommended), please add a Jest test asserting that behavior (ideally also asserting the error message).
Resolves the GoReleaser version from a file. Currently supports the
asdf/mise `.tool-versions` format; resolved value takes precedence
over the `version` input.
# .tool-versions
goreleaser 2.13.0
- uses: goreleaser/goreleaser-action@v7
with:
version-file: .tool-versions
args: release --clean
Path is resolved relative to `workdir` unless absolute. Bare semvers
are auto-prefixed with `v`; constraint expressions and `latest` are
returned as-is. Multiple fallback versions per asdf convention are
accepted but only the first is used.
Refs #541
Closes #542
Co-authored-by: Anthony Couvreur <22034450+acouvreur@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Hi @acouvreur — thanks a lot for this contribution! I'm taking the work over in #556 to add more test coverage and tighten parsing edge cases (inline comments, asdf fallback lists, error messages). The original feature design is preserved. Crediting you as co-author on the commit. |
|
merged in #556 - thanks! |
Resolves the GoReleaser version from a file. Currently supports the
asdf/mise `.tool-versions` format; resolved value takes precedence
over the `version` input.
# .tool-versions
goreleaser 2.13.0
- uses: goreleaser/goreleaser-action@v7
with:
version-file: .tool-versions
args: release --clean
Path is resolved relative to `workdir` unless absolute. Bare semvers
are auto-prefixed with `v`; constraint expressions and `latest` are
returned as-is. Multiple fallback versions per asdf convention are
accepted but only the first is used.
Refs goreleaser#541
Closes goreleaser#542
Co-authored-by: Anthony Couvreur <22034450+acouvreur@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
You can now use .tool-versions file to specify GoReleaser version to download
Closes #541
Testing
With
version-filereferencing a non-existing fileTypo
.tools-versioninstead of.tool-versionssablierapp/sablier@0700179
With
version-filereferencing.tool-versionsfilesablierapp/sablier@94739c4
No version specified
sablierapp/sablier@d5d4432