Skip to content

Commit

Permalink
Add version-resolver input
Browse files Browse the repository at this point in the history
Tool cache can be stale in GitHub and self-hosted runners. If supplied
`go-version` is a semver range--instead of an explicit version--it will
be tried through the version inventory in cache, first. Even though
the GitHub local copy or origin distribution may have newer versions
matching the passed range, as long as the cache can satisfy the range,
the latest version from cache will be used.

Introduce an optional input, `version-resolver`. If defined, it tries to
resolve the version spec against either GitHub local copy or Go's
canonical source of version manifest.
If the value of `version-resolver` is:
  - "manifest": the manifest file under @actions/go-version get used.
  - "dist": the manifest at https://golang.org/dl/?mode=json&include=all
  gets used.  It can take values

Example:
--------
- Latest Go Version: 1.15.2
- tool-cache has go1.15 (1.15.0), latest.

build.yml:
```
[...]
  - uses: actions/setup-go@v2
    with:
      go-version: '>=1.5 <2'
[...]
```

Although the intention of the user might be to get latest
version between "oldest Go 1.15.0, newest--not inclusive--Go 2.0", the
cache will match this range with Go 1.15.0.

build.yml (v2):
```
[...]
  - uses: actions/setup-go@v2
    with:
      go-version: '>=1.5 <2'
      version-resolver: 'manifest'
[...]
```

With supplied version resolver, the semver range will be checked against
the local GitHub version manifest from @actions/go-versions[1], and
match 1.15.2. Cache will be queried with the resolved version, instead
of the range. When the cache gets updated globally, next runs will use
the tool from the cache, instead of downloading locally or in case of
resolver 'dist', directly from Google.

[1]: https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json

Closes #73
  • Loading branch information
bdd committed Sep 14, 2020
1 parent 7ff6287 commit 9333ae6
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 13 deletions.
4 changes: 3 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: 'Setup Go environment'
description: 'Setup a Go environment and add it to the PATH'
author: 'GitHub'
inputs:
inputs:
go-version:
description: 'The Go version to download (if necessary) and use. Supports semver spec and ranges.'
version-resolver:
description: 'Version inventory for resolving semver ranges before checking tool cache. Use "manifest" for @actions/go-versions, or "dist" for golang.org/dl'
stable:
description: 'Whether to download only stable versions'
default: 'true'
Expand Down
41 changes: 35 additions & 6 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1440,7 +1440,21 @@ function run() {
if (versionSpec) {
let token = core.getInput('token');
let auth = !token || isGhes() ? undefined : `token ${token}`;
const installDir = yield installer.getGo(versionSpec, stable, auth);
// Tool cache can be stale in GitHub and self-hosted runners. If supplied
// `go-version` is a semver range--instead of an explicit version--it will
// be tried through the version inventory in cache, first. Even though
// the GitHub local copy or origin distribution may have newer versions
// matching the passed range, as long as the cache can satisfy the range,
// the latest version from cache will be used.
//
// Allow passing a prefered version inventory for resolving versionSpec.
// - "manifest": GitHub hosted (@actions/go-versions)
// - "dist": Origin (https://golang.org/dl/?mode=json&include=all)
let resolver = core.getInput('version-resolver');
if (resolver && resolver != 'manifest' && resolver != 'dist') {
throw new Error(`Unknown version-resolver: '${resolver}'`);
}
const installDir = yield installer.getGo(versionSpec, resolver, stable, auth);
core.exportVariable('GOROOT', installDir);
core.addPath(path_1.default.join(installDir, 'bin'));
core.info('Added go to the path');
Expand Down Expand Up @@ -4943,10 +4957,23 @@ const semver = __importStar(__webpack_require__(280));
const httpm = __importStar(__webpack_require__(539));
const sys = __importStar(__webpack_require__(737));
const os_1 = __importDefault(__webpack_require__(87));
function getGo(versionSpec, stable, auth) {
function getGo(versionSpec, versionSpecResolver, stable, auth) {
return __awaiter(this, void 0, void 0, function* () {
let osPlat = os_1.default.platform();
let osArch = os_1.default.arch();
let versionInfo = null;
if (versionSpecResolver) {
core.info(`Resolving versionSpec '${versionSpec}' from '${versionSpecResolver}'`);
switch (versionSpecResolver) {
case 'manifest':
versionInfo = yield getInfoFromManifest(versionSpec, stable, auth);
break;
case 'dist':
versionInfo = yield getInfoFromDist(versionSpec, stable);
break;
}
}
if (versionInfo && versionInfo.resolvedVersion.length > 0) {
versionSpec = versionInfo.resolvedVersion;
}
// check cache
let toolPath;
toolPath = tc.find('go', versionSpec);
Expand All @@ -4962,7 +4989,7 @@ function getGo(versionSpec, stable, auth) {
// Try download from internal distribution (popular versions only)
//
try {
info = yield getInfoFromManifest(versionSpec, stable, auth);
info = versionInfo !== null && versionInfo !== void 0 ? versionInfo : (yield getInfoFromManifest(versionSpec, stable, auth));
if (info) {
downloadPath = yield installGoVersion(info, auth);
}
Expand All @@ -4985,8 +5012,10 @@ function getGo(versionSpec, stable, auth) {
// Download from storage.googleapis.com
//
if (!downloadPath) {
info = yield getInfoFromDist(versionSpec, stable);
info = versionInfo !== null && versionInfo !== void 0 ? versionInfo : (yield getInfoFromDist(versionSpec, stable));
if (!info) {
let osPlat = os_1.default.platform();
let osArch = os_1.default.arch();
throw new Error(`Unable to find Go version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`);
}
try {
Expand Down
32 changes: 27 additions & 5 deletions src/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as semver from 'semver';
import * as httpm from '@actions/http-client';
import * as sys from './system';
import os from 'os';
import {version} from 'process';

type InstallationType = 'dist' | 'manifest';

Expand All @@ -30,11 +31,29 @@ export interface IGoVersionInfo {

export async function getGo(
versionSpec: string,
versionSpecResolver: string | undefined,
stable: boolean,
auth: string | undefined
) {
let osPlat: string = os.platform();
let osArch: string = os.arch();
): Promise<string> {
let versionInfo: IGoVersionInfo | null = null;

if (versionSpecResolver) {
core.info(
`Resolving versionSpec '${versionSpec}' from '${versionSpecResolver}'`
);
switch (versionSpecResolver) {
case 'manifest':
versionInfo = await getInfoFromManifest(versionSpec, stable, auth);
break;
case 'dist':
versionInfo = await getInfoFromDist(versionSpec, stable);
break;
}
}

if (versionInfo && versionInfo.resolvedVersion.length > 0) {
versionSpec = versionInfo.resolvedVersion;
}

// check cache
let toolPath: string;
Expand All @@ -52,7 +71,8 @@ export async function getGo(
// Try download from internal distribution (popular versions only)
//
try {
info = await getInfoFromManifest(versionSpec, stable, auth);
info =
versionInfo ?? (await getInfoFromManifest(versionSpec, stable, auth));
if (info) {
downloadPath = await installGoVersion(info, auth);
} else {
Expand All @@ -79,8 +99,10 @@ export async function getGo(
// Download from storage.googleapis.com
//
if (!downloadPath) {
info = await getInfoFromDist(versionSpec, stable);
info = versionInfo ?? (await getInfoFromDist(versionSpec, stable));
if (!info) {
let osPlat: string = os.platform();
let osArch: string = os.arch();
throw new Error(
`Unable to find Go version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
);
Expand Down
22 changes: 21 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,27 @@ export async function run() {
let token = core.getInput('token');
let auth = !token || isGhes() ? undefined : `token ${token}`;

const installDir = await installer.getGo(versionSpec, stable, auth);
// Tool cache can be stale in GitHub and self-hosted runners. If supplied
// `go-version` is a semver range--instead of an explicit version--it will
// be tried through the version inventory in cache, first. Even though
// the GitHub local copy or origin distribution may have newer versions
// matching the passed range, as long as the cache can satisfy the range,
// the latest version from cache will be used.
//
// Allow passing a prefered version inventory for resolving versionSpec.
// - "manifest": GitHub hosted (@actions/go-versions)
// - "dist": Origin (https://golang.org/dl/?mode=json&include=all)
let resolver = core.getInput('version-resolver');
if (resolver && resolver != 'manifest' && resolver != 'dist') {
throw new Error(`Unknown version-resolver: '${resolver}'`);
}

const installDir = await installer.getGo(
versionSpec,
resolver,
stable,
auth
);

core.exportVariable('GOROOT', installDir);
core.addPath(path.join(installDir, 'bin'));
Expand Down

0 comments on commit 9333ae6

Please sign in to comment.