Skip to content

Commit 7d12308

Browse files
Configure environment to avoid toolchain installs
Force `go` to always use the local toolchain (i.e. the one the one that shipped with the go command being run) via setting the `GOTOOLCHAIN` environment variable to `local`[1]: > When GOTOOLCHAIN is set to local, the go command always runs the bundled Go toolchain. This is how things are setup in the official Docker images (e.g.[2], see also the discussion around that change[3]). The motivation behind this is to: * Reduce duplicate work: if the `toolchain` version in `go.mod` was greated than the `go` version, the version from the `go` directive would be installed, then Go would detect the `toolchain` version and additionally install that * Avoid Unexpected behaviour: if you specify this action runs with some Go version (e.g. `1.21.0`) but your go.mod contains a `toolchain` or `go` directive for a newer version (e.g. `1.22.0`) then, without any other configuration/environment setup, any go commands will be run using go `1.22.0` This will be a **breaking change** for some workflows. Given a `go.mod` like: module proj go 1.22.0 Then running any `go` command, e.g. `go mod tidy`, in an environment where only go versions before `1.22.0` were installed would previously trigger a toolchain download of Go `1.22.0` and that version being used to execute the command. With this change the above would error out with something like: > go: go.mod requires go >= 1.22.0 (running go 1.21.7; GOTOOLCHAIN=local) [1] https://go.dev/doc/toolchain#select [2] https://github.com/docker-library/golang/blob/dae3405a325073e8ad7c8c378ebdf2540d8565c4/Dockerfile-linux.template#L163 [3] docker-library/golang#472
1 parent 8e57b58 commit 7d12308

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

__tests__/setup-go.test.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ describe('setup-go', () => {
285285
expect(logSpy).toHaveBeenCalledWith(`Setup go version spec 1.13.0`);
286286
});
287287

288-
it('does not export any variables for Go versions >=1.9', async () => {
288+
it('does not export GOROOT for Go versions >=1.9', async () => {
289289
inputs['go-version'] = '1.13.0';
290290
inSpy.mockImplementation(name => inputs[name]);
291291

@@ -298,7 +298,7 @@ describe('setup-go', () => {
298298
});
299299

300300
await main.run();
301-
expect(vars).toStrictEqual({});
301+
expect(vars).not.toHaveProperty('GOROOT');
302302
});
303303

304304
it('exports GOROOT for Go versions <1.9', async () => {
@@ -314,9 +314,7 @@ describe('setup-go', () => {
314314
});
315315

316316
await main.run();
317-
expect(vars).toStrictEqual({
318-
GOROOT: toolPath
319-
});
317+
expect(vars).toHaveProperty('GOROOT', toolPath);
320318
});
321319

322320
it('finds a version of go already in the cache', async () => {
@@ -989,4 +987,18 @@ use .
989987
}
990988
);
991989
});
990+
991+
it('exports GOTOOLCHAIN and sets it in current process env', async () => {
992+
inputs['go-version'] = '1.21.0';
993+
inSpy.mockImplementation(name => inputs[name]);
994+
995+
const vars: {[key: string]: string} = {};
996+
exportVarSpy.mockImplementation((name: string, val: string) => {
997+
vars[name] = val;
998+
});
999+
1000+
await main.run();
1001+
expect(vars).toStrictEqual({GOTOOLCHAIN: 'local'});
1002+
expect(process.env).toHaveProperty('GOTOOLCHAIN', 'local');
1003+
});
9921004
});

dist/setup/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93707,6 +93707,7 @@ const os_1 = __importDefault(__nccwpck_require__(2037));
9370793707
function run() {
9370893708
return __awaiter(this, void 0, void 0, function* () {
9370993709
try {
93710+
setToolchain();
9371093711
//
9371193712
// versionSpec is optional. If supplied, install / use from the tool cache
9371293713
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
@@ -93820,6 +93821,21 @@ function resolveVersionInput() {
9382093821
}
9382193822
return version;
9382293823
}
93824+
function setToolchain() {
93825+
// docs: https://go.dev/doc/toolchain
93826+
// "local indicates the bundled Go toolchain (the one that shipped with the go command being run)"
93827+
// this is so any 'go' command is run with the selected Go version
93828+
// and doesn't trigger a toolchain download and run commands with that
93829+
// see e.g. issue #424
93830+
// and a similar discussion: https://github.com/docker-library/golang/issues/472
93831+
const toolchain = 'local';
93832+
const toolchainVar = 'GOTOOLCHAIN';
93833+
// set the value in process env so any `go` commands run as child-process
93834+
// don't cause toolchain downloads
93835+
process.env[toolchainVar] = toolchain;
93836+
// and in the runner env so e.g. a user running `go mod tidy` won't cause it
93837+
core.exportVariable(toolchainVar, toolchain);
93838+
}
9382393839

9382493840

9382593841
/***/ }),

src/main.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import os from 'os';
1111

1212
export async function run() {
1313
try {
14+
setToolchain();
1415
//
1516
// versionSpec is optional. If supplied, install / use from the tool cache
1617
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
@@ -160,3 +161,20 @@ function resolveVersionInput(): string {
160161

161162
return version;
162163
}
164+
165+
function setToolchain() {
166+
// docs: https://go.dev/doc/toolchain
167+
// "local indicates the bundled Go toolchain (the one that shipped with the go command being run)"
168+
// this is so any 'go' command is run with the selected Go version
169+
// and doesn't trigger a toolchain download and run commands with that
170+
// see e.g. issue #424
171+
// and a similar discussion: https://github.com/docker-library/golang/issues/472
172+
const toolchain = 'local';
173+
const toolchainVar = 'GOTOOLCHAIN';
174+
175+
// set the value in process env so any `go` commands run as child-process
176+
// don't cause toolchain downloads
177+
process.env[toolchainVar] = toolchain;
178+
// and in the runner env so e.g. a user running `go mod tidy` won't cause it
179+
core.exportVariable(toolchainVar, toolchain);
180+
}

0 commit comments

Comments
 (0)