Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve toolchain handling #460

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 67 additions & 5 deletions __tests__/setup-go.test.ts
Expand Up @@ -265,7 +265,7 @@ describe('setup-go', () => {
expect(logSpy).toHaveBeenCalledWith(`Setup go version spec 1.13.0`);
});

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

Expand All @@ -278,7 +278,7 @@ describe('setup-go', () => {
});

await main.run();
expect(vars).toStrictEqual({});
expect(vars).not.toHaveProperty('GOROOT');
});

it('exports GOROOT for Go versions <1.9', async () => {
Expand All @@ -294,9 +294,7 @@ describe('setup-go', () => {
});

await main.run();
expect(vars).toStrictEqual({
GOROOT: toolPath
});
expect(vars).toHaveProperty('GOROOT', toolPath);
});

it('finds a version of go already in the cache', async () => {
Expand Down Expand Up @@ -966,4 +964,68 @@ use .
}
);
});

describe('go-version-file-toolchain', () => {
const goModContents = `module example.com/mymodule

go 1.14

toolchain go1.21.0

require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)

replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
`;

const goWorkContents = `go 1.19

toolchain go1.21.0

use .

`;

it('reads version from toolchain directive in go.mod', async () => {
inputs['go-version-file'] = 'go.mod';
existsSpy.mockImplementation(() => true);
readFileSpy.mockImplementation(() => Buffer.from(goModContents));

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...');
});

it('reads version from toolchain directive in go.work', async () => {
inputs['go-version-file'] = 'go.work';
existsSpy.mockImplementation(() => true);
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...');
});
});

it('exports GOTOOLCHAIN and sets it in current process env', async () => {
inputs['go-version'] = '1.21.0';
inSpy.mockImplementation(name => inputs[name]);

const vars: {[key: string]: string} = {};
exportVarSpy.mockImplementation((name: string, val: string) => {
vars[name] = val;
});

await main.run();
expect(vars).toStrictEqual({GOTOOLCHAIN: 'local'});
expect(process.env).toHaveProperty('GOTOOLCHAIN', 'local');
});
});
26 changes: 24 additions & 2 deletions dist/setup/index.js
Expand Up @@ -88318,8 +88318,14 @@ function parseGoVersionFile(versionFilePath) {
const contents = fs_1.default.readFileSync(versionFilePath).toString();
if (path.basename(versionFilePath) === 'go.mod' ||
path.basename(versionFilePath) === 'go.work') {
const match = contents.match(/^go (\d+(\.\d+)*)/m);
return match ? match[1] : '';
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
const matchToolchain = contents.match(/^toolchain go(\d+(\.\d+)*)/m);
if (matchToolchain) {
return matchToolchain[1];
}
// go directive: https://go.dev/ref/mod#go-mod-file-go
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);
return matchGo ? matchGo[1] : '';
}
return contents.trim();
}
Expand Down Expand Up @@ -88422,6 +88428,7 @@ const os_1 = __importDefault(__nccwpck_require__(2037));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
setToolchain();
//
// versionSpec is optional. If supplied, install / use from the tool cache
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
Expand Down Expand Up @@ -88538,6 +88545,21 @@ function resolveVersionInput() {
}
return version;
}
function setToolchain() {
// docs: https://go.dev/doc/toolchain
// "local indicates the bundled Go toolchain (the one that shipped with the go command being run)"
// this is so any 'go' command is run with the selected Go version
// and doesn't trigger a toolchain download and run commands with that
// see e.g. issue #424
// and a similar discussion: https://github.com/docker-library/golang/issues/472
const toolchain = 'local';
const toolchainVar = 'GOTOOLCHAIN';
// set the value in process env so any `go` commands run as child-process
// don't cause toolchain downloads
process.env[toolchainVar] = toolchain;
// and in the runner env so e.g. a user running `go mod tidy` won't cause it
core.exportVariable(toolchainVar, toolchain);
}


/***/ }),
Expand Down
11 changes: 9 additions & 2 deletions src/installer.ts
Expand Up @@ -424,8 +424,15 @@ export function parseGoVersionFile(versionFilePath: string): string {
path.basename(versionFilePath) === 'go.mod' ||
path.basename(versionFilePath) === 'go.work'
) {
const match = contents.match(/^go (\d+(\.\d+)*)/m);
return match ? match[1] : '';
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
const matchToolchain = contents.match(/^toolchain go(\d+(\.\d+)*)/m);
if (matchToolchain) {
return matchToolchain[1];
}

// go directive: https://go.dev/ref/mod#go-mod-file-go
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);
return matchGo ? matchGo[1] : '';
}

return contents.trim();
Expand Down
18 changes: 18 additions & 0 deletions src/main.ts
Expand Up @@ -11,6 +11,7 @@ import os from 'os';

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

return version;
}

function setToolchain() {
// docs: https://go.dev/doc/toolchain
// "local indicates the bundled Go toolchain (the one that shipped with the go command being run)"
// this is so any 'go' command is run with the selected Go version
// and doesn't trigger a toolchain download and run commands with that
// see e.g. issue #424
// and a similar discussion: https://github.com/docker-library/golang/issues/472
const toolchain = 'local';
const toolchainVar = 'GOTOOLCHAIN';

// set the value in process env so any `go` commands run as child-process
// don't cause toolchain downloads
process.env[toolchainVar] = toolchain;
// and in the runner env so e.g. a user running `go mod tidy` won't cause it
core.exportVariable(toolchainVar, toolchain);
}