squash! Prefer installing version from `toolchain` directive

Avoid installing from `toolchain` if `GOTOOLCHAIN` is `local`, also
better regex for matching toolchain directive
This commit is contained in:
Matthew Hughes 2025-08-25 20:08:21 +01:00
parent 277ab1eb0e
commit b967a467e1
3 changed files with 82 additions and 33 deletions

View File

@ -129,6 +129,9 @@ describe('setup-go', () => {
}); });
afterEach(() => { afterEach(() => {
// clear out env var set during 'run'
delete process.env[im.GOTOOLCHAIN_ENV_VAR];
//jest.resetAllMocks(); //jest.resetAllMocks();
jest.clearAllMocks(); jest.clearAllMocks();
//jest.restoreAllMocks(); //jest.restoreAllMocks();
@ -989,11 +992,16 @@ use .
}); });
describe('go-version-file-toolchain', () => { describe('go-version-file-toolchain', () => {
const goModContents = `module example.com/mymodule const goVersions = ['1.22.0', '1.21rc2', '1.18'];
const placeholderVersion = '1.19';
const buildGoMod = (
goVersion: string,
toolchainVersion: string
) => `module example.com/mymodule
go 1.14 go ${goVersion}
toolchain go1.21.0 toolchain go${toolchainVersion}
require ( require (
example.com/othermodule v1.2.3 example.com/othermodule v1.2.3
@ -1005,36 +1013,67 @@ replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0 exclude example.com/thismodule v1.3.0
`; `;
const goWorkContents = `go 1.19 const buildGoWork = (
goVersion: string,
toolchainVersion: string
) => `go 1.19
toolchain go1.21.0 toolchain go${toolchainVersion}
use . use .
`; `;
it('reads version from toolchain directive in go.mod', async () => { goVersions.forEach(version => {
inputs['go-version-file'] = 'go.mod'; [
existsSpy.mockImplementation(() => true); {
readFileSpy.mockImplementation(() => Buffer.from(goModContents)); goVersionfile: 'go.mod',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
expected_version: version,
desc: 'from toolchain directive'
},
{
goVersionfile: 'go.work',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
expected_version: version,
desc: 'from toolchain directive'
},
{
goVersionfile: 'go.mod',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
gotoolchain_env: 'local',
expected_version: placeholderVersion,
desc: 'from go directive when GOTOOLCHAIN is local'
},
{
goVersionfile: 'go.work',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
gotoolchain_env: 'local',
expected_version: placeholderVersion,
desc: 'from go directive when GOTOOLCHAIN is local'
}
].forEach(test => {
it(`reads version (${version}) in ${test.goVersionfile} ${test.desc}`, async () => {
inputs['go-version-file'] = test.goVersionfile;
if (test.gotoolchain_env !== undefined) {
process.env[im.GOTOOLCHAIN_ENV_VAR] = test.gotoolchain_env;
}
existsSpy.mockImplementation(() => true);
readFileSpy.mockImplementation(() => Buffer.from(test.fileContents));
await main.run(); await main.run();
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.21.0'); expect(logSpy).toHaveBeenCalledWith(
expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.21.0...'); `Setup go version spec ${test.expected_version}`
expect(logSpy).toHaveBeenCalledWith('matching 1.21.0...'); );
}); expect(logSpy).toHaveBeenCalledWith(
`Attempting to download ${test.expected_version}...`
it('reads version from toolchain directive in go.work', async () => { );
inputs['go-version-file'] = 'go.work'; expect(logSpy).toHaveBeenCalledWith(
existsSpy.mockImplementation(() => true); `matching ${test.expected_version}...`
readFileSpy.mockImplementation(() => Buffer.from(goWorkContents)); );
});
await main.run(); });
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.21.0');
expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.21.0...');
expect(logSpy).toHaveBeenCalledWith('matching 1.21.0...');
}); });
}); });

12
dist/setup/index.js vendored
View File

@ -94666,10 +94666,14 @@ function parseGoVersionFile(versionFilePath) {
const contents = fs_1.default.readFileSync(versionFilePath).toString(); const contents = fs_1.default.readFileSync(versionFilePath).toString();
if (path.basename(versionFilePath) === 'go.mod' || if (path.basename(versionFilePath) === 'go.mod' ||
path.basename(versionFilePath) === 'go.work') { path.basename(versionFilePath) === 'go.work') {
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain // for backwards compatibility: use version from go directive if
const matchToolchain = contents.match(/^toolchain go(\d+(\.\d+)*)/m); // 'GOTOOLCHAIN' has been explicitly set
if (matchToolchain) { if (process.env[exports.GOTOOLCHAIN_ENV_VAR] !== exports.GOTOOLCHAIN_LOCAL_VAL) {
return matchToolchain[1]; // toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
const matchToolchain = contents.match(/^toolchain go(1\.\d+(?:\.\d+|rc\d+)?)/m);
if (matchToolchain) {
return matchToolchain[1];
}
} }
// go directive: https://go.dev/ref/mod#go-mod-file-go // go directive: https://go.dev/ref/mod#go-mod-file-go
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m); const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);

View File

@ -497,10 +497,16 @@ export function parseGoVersionFile(versionFilePath: string): string {
path.basename(versionFilePath) === 'go.mod' || path.basename(versionFilePath) === 'go.mod' ||
path.basename(versionFilePath) === 'go.work' path.basename(versionFilePath) === 'go.work'
) { ) {
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain // for backwards compatibility: use version from go directive if
const matchToolchain = contents.match(/^toolchain go(\d+(\.\d+)*)/m); // 'GOTOOLCHAIN' has been explicitly set
if (matchToolchain) { if (process.env[GOTOOLCHAIN_ENV_VAR] !== GOTOOLCHAIN_LOCAL_VAL) {
return matchToolchain[1]; // toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
const matchToolchain = contents.match(
/^toolchain go(1\.\d+(?:\.\d+|rc\d+)?)/m
);
if (matchToolchain) {
return matchToolchain[1];
}
} }
// go directive: https://go.dev/ref/mod#go-mod-file-go // go directive: https://go.dev/ref/mod#go-mod-file-go