Skip to content

Commit 493769a

Browse files
committed
fix: parse go-version-file by content
The `parseGoVersionFile` function used to only check for exact filenames like "go.{mod,work}". When `go-version-file` pointed to something like a tools modfile ("go.tool.mod"), it would just dump the whole file contents back, which then got mistaken for a version spec and broke the manifest/dist resolution. Now it looks at the file content to spot Go module or workspace files and pulls out the `toolchain` or `go` directives. Left ".tool-versions" handling alone. Fixes #746 Signed-off-by: Dwi Siswanto <git@dw1.io>
1 parent 4a36011 commit 493769a

File tree

4 files changed

+60
-20
lines changed

4 files changed

+60
-20
lines changed

__tests__/setup-go.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,18 @@ use .
901901
expect(logSpy).toHaveBeenCalledWith('matching 1.19...');
902902
});
903903

904+
it('reads version from go.mod-like file name', async () => {
905+
inputs['go-version-file'] = 'go.tool.mod';
906+
existsSpy.mockImplementation(() => true);
907+
readFileSpy.mockImplementation(() => Buffer.from(goModContents));
908+
909+
await main.run();
910+
911+
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.14');
912+
expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.14...');
913+
expect(logSpy).toHaveBeenCalledWith('matching 1.14...');
914+
});
915+
904916
it('reads version from .tool-versions', async () => {
905917
inputs['go-version-file'] = '.tool-versions';
906918
existsSpy.mockImplementation(() => true);
@@ -1066,6 +1078,19 @@ use .
10661078
expected_version: placeholderVersion,
10671079
desc: 'from go directive when GOTOOLCHAIN is local'
10681080
},
1081+
{
1082+
goVersionfile: 'go.tool.mod',
1083+
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
1084+
expected_version: version,
1085+
desc: 'from toolchain directive'
1086+
},
1087+
{
1088+
goVersionfile: 'go.tool.mod',
1089+
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
1090+
gotoolchain_env: 'local',
1091+
expected_version: placeholderVersion,
1092+
desc: 'from go directive when GOTOOLCHAIN is local'
1093+
},
10691094
{
10701095
goVersionfile: 'go.work',
10711096
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),

dist/setup/index.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77493,26 +77493,33 @@ function makeSemver(version) {
7749377493
return fullVersion;
7749477494
}
7749577495
function parseGoVersionFile(versionFilePath) {
77496+
const moduleOrWorkspaceDirective = /^\s*go\s+(\d+(?:\.\d+)*)/m;
77497+
const toolchainDirective = /^\s*toolchain\s+go(1\.\d+(?:\.\d+|rc\d+)?)/m;
77498+
const moduleDeclaration = /^\s*module\s+\S+/m;
77499+
const workspaceUseDirective = /^\s*use(?:\s+\S+|\s*\()/m;
7749677500
const contents = fs_1.default.readFileSync(versionFilePath).toString();
77497-
if (path.basename(versionFilePath) === 'go.mod' ||
77498-
path.basename(versionFilePath) === 'go.work') {
77501+
const fileName = path.basename(versionFilePath);
77502+
const isGoModOrWorkFileName = fileName === 'go.mod' || fileName === 'go.work';
77503+
const isGoModuleOrWorkspaceLike = moduleOrWorkspaceDirective.test(contents) &&
77504+
(moduleDeclaration.test(contents) || workspaceUseDirective.test(contents));
77505+
if (fileName === '.tool-versions') {
77506+
const match = contents.match(/^golang\s+([^\n#]+)/m);
77507+
return match ? match[1].trim() : '';
77508+
}
77509+
if (isGoModOrWorkFileName || isGoModuleOrWorkspaceLike) {
7749977510
// for backwards compatibility: use version from go directive if
7750077511
// 'GOTOOLCHAIN' has been explicitly set
7750177512
if (process.env[exports.GOTOOLCHAIN_ENV_VAR] !== exports.GOTOOLCHAIN_LOCAL_VAL) {
7750277513
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
77503-
const matchToolchain = contents.match(/^toolchain go(1\.\d+(?:\.\d+|rc\d+)?)/m);
77514+
const matchToolchain = contents.match(toolchainDirective);
7750477515
if (matchToolchain) {
7750577516
return matchToolchain[1];
7750677517
}
7750777518
}
7750877519
// go directive: https://go.dev/ref/mod#go-mod-file-go
77509-
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);
77520+
const matchGo = contents.match(moduleOrWorkspaceDirective);
7751077521
return matchGo ? matchGo[1] : '';
7751177522
}
77512-
else if (path.basename(versionFilePath) === '.tool-versions') {
77513-
const match = contents.match(/^golang\s+([^\n#]+)/m);
77514-
return match ? match[1].trim() : '';
77515-
}
7751677523
return contents.trim();
7751777524
}
7751877525
function resolveStableVersionDist(versionSpec, arch) {

docs/advanced-usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ jobs:
164164

165165
## Using the `go-version-file` input
166166

167-
`setup-go` action can read the Go version from a version file. `go-version-file` input is used for specifying the path to the version file. If the file supplied to the `go-version-file` input doesn't exist, the action will fail with an error. This input supports go.mod, go.work, .go-version, and .tool-versions files.
167+
`setup-go` action can read the Go version from a version file. `go-version-file` input is used for specifying the path to the version file. If the file supplied to the `go-version-file` input doesn't exist, the action will fail with an error. This input supports standard `go.mod` and `go.work` files, custom files that use the same `go.mod`/`go.work` format (for example, `go.tool.mod`), and `.go-version` and `.tool-versions` files.
168168

169169
If both the `go-version` and the `go-version-file` inputs are provided then the `go-version` input is used. The `.tool-versions` file supports version specifications in accordance with asdf standards, adhering to Semantic Versioning ([semver](https://semver.org)).
170170

src/installer.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -651,30 +651,38 @@ export function makeSemver(version: string): string {
651651
}
652652

653653
export function parseGoVersionFile(versionFilePath: string): string {
654+
const moduleOrWorkspaceDirective = /^\s*go\s+(\d+(?:\.\d+)*)/m;
655+
const toolchainDirective = /^\s*toolchain\s+go(1\.\d+(?:\.\d+|rc\d+)?)/m;
656+
const moduleDeclaration = /^\s*module\s+\S+/m;
657+
const workspaceUseDirective = /^\s*use(?:\s+\S+|\s*\()/m;
658+
654659
const contents = fs.readFileSync(versionFilePath).toString();
660+
const fileName = path.basename(versionFilePath);
655661

656-
if (
657-
path.basename(versionFilePath) === 'go.mod' ||
658-
path.basename(versionFilePath) === 'go.work'
659-
) {
662+
const isGoModOrWorkFileName = fileName === 'go.mod' || fileName === 'go.work';
663+
const isGoModuleOrWorkspaceLike =
664+
moduleOrWorkspaceDirective.test(contents) &&
665+
(moduleDeclaration.test(contents) || workspaceUseDirective.test(contents));
666+
667+
if (fileName === '.tool-versions') {
668+
const match = contents.match(/^golang\s+([^\n#]+)/m);
669+
return match ? match[1].trim() : '';
670+
}
671+
672+
if (isGoModOrWorkFileName || isGoModuleOrWorkspaceLike) {
660673
// for backwards compatibility: use version from go directive if
661674
// 'GOTOOLCHAIN' has been explicitly set
662675
if (process.env[GOTOOLCHAIN_ENV_VAR] !== GOTOOLCHAIN_LOCAL_VAL) {
663676
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
664-
const matchToolchain = contents.match(
665-
/^toolchain go(1\.\d+(?:\.\d+|rc\d+)?)/m
666-
);
677+
const matchToolchain = contents.match(toolchainDirective);
667678
if (matchToolchain) {
668679
return matchToolchain[1];
669680
}
670681
}
671682

672683
// go directive: https://go.dev/ref/mod#go-mod-file-go
673-
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);
684+
const matchGo = contents.match(moduleOrWorkspaceDirective);
674685
return matchGo ? matchGo[1] : '';
675-
} else if (path.basename(versionFilePath) === '.tool-versions') {
676-
const match = contents.match(/^golang\s+([^\n#]+)/m);
677-
return match ? match[1].trim() : '';
678686
}
679687

680688
return contents.trim();

0 commit comments

Comments
 (0)