Add support for native Go version syntax in go-version input

pull/804/head
Jitender Pal Singh 5 hours ago
parent 90ad2b35f6
commit 04c4297c04

@ -94,10 +94,13 @@ the [check-latest input](docs/advanced-usage.md#check-latest-version).
The `go-version` input supports the following syntax:
- Specific versions: `1.25`, `1.24.11`, `1.24.0-rc.1`, `1.23.0-beta.1`
- Native Go versions: `go1.21`, `go1.21.5`, `go1.18beta2`, `go1.21rc2`. `go1.21` resolves to exactly `1.21.0`, unlike `1.21`, which matches patch releases.
- SemVer version range syntax: `^1.25.1`, `~1.24.1`, `>=1.25.0-rc.1`, `<1.25.0`, `>=1.22.0 <1.24.0`
- Aliases: `stable`, `oldstable`
- Wildcards: `1.25.x`, `1.x`
> **Note:** Native Go version validation and normalization apply only when no custom download base URL is configured. When `go-download-base-url` or `GO_DOWNLOAD_BASE_URL` is set, the `go-version` input is passed through unchanged.
For details on Semantic Versioning, see [the semver package documentation](https://github.com/npm/node-semver).
> **Note**: Due to the peculiarities of YAML parsing, it is recommended to wrap the version in single quotation marks:

@ -874,6 +874,121 @@ describe('setup-go', () => {
expect(im.makeSemver('1.13.1')).toBe('1.13.1');
});
it('isGoNativeVersion accepts supported Go-native version formats', () => {
expect(im.isGoNativeVersion('go1.21')).toBe(true);
expect(im.isGoNativeVersion('go1.21.5')).toBe(true);
expect(im.isGoNativeVersion('go1.18beta2')).toBe(true);
expect(im.isGoNativeVersion('go1.21rc2')).toBe(true);
expect(im.isGoNativeVersion('go1.21.x')).toBe(false);
expect(im.isGoNativeVersion('go^1.21')).toBe(false);
expect(im.isGoNativeVersion('1.21')).toBe(false);
expect(im.isGoNativeVersion('go1')).toBe(false);
expect(im.isGoNativeVersion('go1.21.5beta1')).toBe(false);
expect(im.isGoNativeVersion('go1.21.0rc1')).toBe(false);
});
it('accepts a Go-native go-version input and normalizes it', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = 'go1.21';
findSpy.mockImplementation(() => path.normalize('/cache/go/1.21.0/x64'));
await main.run();
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.21.0');
expect(findSpy).toHaveBeenCalledWith('go', '1.21.0', 'x64');
expect(logSpy).toHaveBeenCalledWith(
'Successfully set up Go version 1.21.0'
);
});
it('rejects a malformed Go-native go-version input', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = 'go1.21.x';
await main.run();
expect(cnSpy).toHaveBeenCalledWith(
expect.stringContaining('Invalid Go version "go1.21.x"')
);
});
it('accepts a Go-native go-version input with beta suffix and normalizes it', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = 'go1.18beta2';
findSpy.mockImplementation(() =>
path.normalize('/cache/go/1.18.0-beta.2/x64')
);
await main.run();
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.18.0-beta.2');
expect(findSpy).toHaveBeenCalledWith('go', '1.18.0-beta.2', 'x64');
expect(logSpy).toHaveBeenCalledWith(
'Successfully set up Go version 1.18.0-beta.2'
);
});
it('accepts a Go-native go-version input with rc suffix and normalizes it', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = 'go1.21rc2';
findSpy.mockImplementation(() =>
path.normalize('/cache/go/1.21.0-rc.2/x64')
);
await main.run();
expect(logSpy).toHaveBeenCalledWith('Setup go version spec 1.21.0-rc.2');
expect(findSpy).toHaveBeenCalledWith('go', '1.21.0-rc.2', 'x64');
expect(logSpy).toHaveBeenCalledWith(
'Successfully set up Go version 1.21.0-rc.2'
);
});
it('downloads a normalized Go-native version on cache miss', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = 'go1.13';
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
extractTarSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () =>
path.normalize('/cache/go/1.13.0/x64')
);
await main.run();
expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.13.0...');
expect(dlSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
'Successfully set up Go version 1.13.0'
);
});
it('keeps go-prefixed version unchanged when a custom download URL is set', async () => {
os.platform = 'linux';
os.arch = 'x64';
const customBaseUrl = 'https://example.com/golang';
inputs['go-version'] = 'go1.25.1';
inputs['go-download-base-url'] = customBaseUrl;
const toolName = im.customToolCacheName(customBaseUrl);
findSpy.mockImplementation(() =>
path.normalize(`/cache/${toolName}/1.25.1/x64`)
);
await main.run();
expect(logSpy).toHaveBeenCalledWith('Setup go version spec go1.25.1');
expect(findSpy).toHaveBeenCalledWith(toolName, 'go1.25.1', 'x64');
});
describe('check-latest flag', () => {
it("use local version and don't check manifest if check-latest is not specified", async () => {
os.platform = 'linux';

@ -3,7 +3,7 @@ description: 'Setup a Go environment and add it to the PATH'
author: 'GitHub'
inputs:
go-version:
description: 'The Go version to download (if necessary) and use. Supports semver spec and ranges. Be sure to enclose this option in single quotation marks.'
description: 'The Go version to download (if necessary) and use. Supports native Go versions (e.g. go1.21.5), semver specs and ranges. Be sure to enclose this option in single quotation marks.'
go-version-file:
description: 'Path to the go.mod, go.work, .go-version, or .tool-versions file.'
check-latest:

@ -42335,6 +42335,10 @@ async function findMatch(versionSpec, arch = external_os_default().arch(), dlUrl
}
return result;
}
function isGoNativeVersion(version) {
const expression = /^go[1-9]\d*\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*)|(?:beta|rc)[1-9]\d*)?$/;
return expression.test(version);
}
//
// Convert the go version syntax into semver for semver matching
// 1.13.1 => 1.13.1
@ -97835,6 +97839,15 @@ function resolveVersionInput() {
warning('Both go-version and go-version-file inputs are specified, only go-version will be used');
}
if (version) {
// With a custom download URL leave the version unchanged.
const customBaseUrl = getInput('go-download-base-url') ||
process.env['GO_DOWNLOAD_BASE_URL'];
if (version.startsWith('go') && !customBaseUrl) {
if (!isGoNativeVersion(version)) {
throw new Error(`Invalid Go version "${version}". Go-native versions must look like go1.21, go1.21.5, go1.18beta2, or go1.21rc2. For version ranges, use semver syntax (e.g. ~1.21, ^1.21).`);
}
version = makeSemver(version);
}
return version;
}
if (versionFilePath) {

@ -53,6 +53,8 @@ steps:
To try a **pre-release**:
Download and use beta or RC Go versions as needed.
When no custom download base URL is configured, the `go-version` input also accepts native Go version strings: `go1.21.5`, `go1.18beta2`, and `go1.21rc2` normalize to `1.21.5`, `1.18.0-beta.2`, and `1.21.0-rc.2`, respectively. `go1.21` resolves to exactly `1.21.0`; use `1.21` for matching patch releases. For ranges and wildcards, use SemVer syntax such as `~1.21` or `1.21.x`, not `go1.21.x`.
```yaml
# RC version
steps:

@ -610,6 +610,12 @@ export async function findMatch(
return result;
}
export function isGoNativeVersion(version: string): boolean {
const expression =
/^go[1-9]\d*\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*)|(?:beta|rc)[1-9]\d*)?$/;
return expression.test(version);
}
//
// Convert the go version syntax into semver for semver matching
// 1.13.1 => 1.13.1

@ -215,6 +215,18 @@ function resolveVersionInput(): string {
}
if (version) {
// With a custom download URL leave the version unchanged.
const customBaseUrl =
core.getInput('go-download-base-url') ||
process.env['GO_DOWNLOAD_BASE_URL'];
if (version.startsWith('go') && !customBaseUrl) {
if (!installer.isGoNativeVersion(version)) {
throw new Error(
`Invalid Go version "${version}". Go-native versions must look like go1.21, go1.21.5, go1.18beta2, or go1.21rc2. For version ranges, use semver syntax (e.g. ~1.21, ^1.21).`
);
}
version = installer.makeSemver(version);
}
return version;
}

Loading…
Cancel
Save