Use GitHub releases to download Go versions. (#58)

This commit is contained in:
Dmitry Shibanov 2020-06-29 18:41:13 +03:00 committed by GitHub
parent 0f551ac199
commit 1616116e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 4156 additions and 9837 deletions

View file

@ -1,4 +1,4 @@
name: go-versions name: Validate 'setup-go'
on: on:
push: push:
branches: branches:
@ -8,44 +8,67 @@ on:
pull_request: pull_request:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
schedule:
- cron: 0 0 * * *
jobs: jobs:
run: local-cache:
name: Go name: Setup local-cache version
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false
matrix: matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest] os: [macos-latest, windows-latest, ubuntu-latest]
go: [1.12, 1.13, 1.14]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: setup-go ^1.13.6 - name: setup-go ${{ matrix.go }}
uses: ./ uses: ./
with: with:
go-version: ^1.13.6 go-version: ${{ matrix.go }}
- name: validate version - name: verify go
run: go version | grep "go1." run: __tests__/verify-go.sh ${{ matrix.go }}
shell: bash
- name: setup-go 1.13
uses: ./ setup-versions-from-manifest:
with: name: Setup ${{ matrix.go }} ${{ matrix.os }}
go-version: 1.13 runs-on: ${{ matrix.os }}
strategy:
- name: validate version fail-fast: false
run: go version | grep "go1.13." matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
- name: setup-go 1.12.9 go: [1.12.16, 1.13.11, 1.14.3]
uses: ./ steps:
with: - name: Checkout
go-version: 1.12.9 uses: actions/checkout@v2
- name: validate version - name: setup-go ${{ matrix.go }}
run: go version | grep "go1.12.9" uses: ./
with:
- name: dump env go-version: ${{ matrix.go }}
- name: verify go
run: __tests__/verify-go.sh ${{ matrix.go }}
shell: bash
setup-versions-from-dist:
name: Setup ${{ matrix.go }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
go: [1.7, 1.8.6]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: setup-go ${{ matrix.go }}
uses: ./
with:
go-version: ${{ matrix.go }}
- name: verify go
run: __tests__/verify-go.sh ${{ matrix.go }}
shell: bash shell: bash
run: |
echo $PATH
echo go versions in tool cache:
echo $(ls $RUNNER_TOOL_CACHE/go)

View file

@ -0,0 +1,77 @@
[
{
"version": "1.12.17",
"stable": true,
"release_url": "https://github.com/actions/go-versions/releases/tag/1.12.17-20200616.21",
"files": [
{
"filename": "go-1.12.17-darwin-x64.tar.gz",
"arch": "x64",
"platform": "darwin",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.17-20200616.21/go-1.12.17-darwin-x64.tar.gz"
},
{
"filename": "go-1.12.17-linux-x64.tar.gz",
"arch": "x64",
"platform": "linux",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.17-20200616.21/go-1.12.17-linux-x64.tar.gz"
},
{
"filename": "go-1.12.17-win32-x64.zip",
"arch": "x64",
"platform": "win32",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.17-20200616.21/go-1.12.17-win32-x64.zip"
}
]
},
{
"version": "1.12.16",
"stable": true,
"release_url": "https://github.com/actions/go-versions/releases/tag/1.12.16-20200616.20",
"files": [
{
"filename": "go-1.12.16-darwin-x64.tar.gz",
"arch": "x64",
"platform": "darwin",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.16-20200616.20/go-1.12.16-darwin-x64.tar.gz"
},
{
"filename": "go-1.12.16-linux-x64.tar.gz",
"arch": "x64",
"platform": "linux",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.16-20200616.20/go-1.12.16-linux-x64.tar.gz"
},
{
"filename": "go-1.12.16-win32-x64.zip",
"arch": "x64",
"platform": "win32",
"download_url": "https://github.com/actions/go-versions/releases/download/1.12.16-20200616.20/go-1.12.16-win32-x64.zip"
}
]
},
{
"version": "1.9.7",
"stable": true,
"release_url": "https://github.com/actions/go-versions/releases/tag/1.9.7-20200616.1",
"files": [
{
"filename": "go-1.9.7-darwin-x64.tar.gz",
"arch": "x64",
"platform": "darwin",
"download_url": "https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-darwin-x64.tar.gz"
},
{
"filename": "go-1.9.7-linux-x64.tar.gz",
"arch": "x64",
"platform": "linux",
"download_url": "https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-linux-x64.tar.gz"
},
{
"filename": "go-1.9.7-win32-x64.zip",
"arch": "x64",
"platform": "win32",
"download_url": "https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-win32-x64.zip"
}
]
}
]

View file

@ -3,13 +3,14 @@ import * as io from '@actions/io';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import fs from 'fs'; import fs from 'fs';
import cp from 'child_process'; import cp from 'child_process';
import osm = require('os'); import osm from 'os';
import path from 'path'; import path from 'path';
import * as main from '../src/main'; import * as main from '../src/main';
import * as im from '../src/installer'; import * as im from '../src/installer';
let goJsonData = require('./data/golang-dl.json'); let goJsonData = require('./data/golang-dl.json');
let matchers = require('../matchers.json'); let matchers = require('../matchers.json');
let goTestManifest = require('./data/versions-manifest.json');
let matcherPattern = matchers.problemMatcher[0].pattern[0]; let matcherPattern = matchers.problemMatcher[0].pattern[0];
let matcherRegExp = new RegExp(matcherPattern.regexp); let matcherRegExp = new RegExp(matcherPattern.regexp);
@ -32,6 +33,7 @@ describe('setup-go', () => {
let existsSpy: jest.SpyInstance; let existsSpy: jest.SpyInstance;
let mkdirpSpy: jest.SpyInstance; let mkdirpSpy: jest.SpyInstance;
let execSpy: jest.SpyInstance; let execSpy: jest.SpyInstance;
let getManifestSpy: jest.SpyInstance;
beforeEach(() => { beforeEach(() => {
// @actions/core // @actions/core
@ -52,18 +54,22 @@ describe('setup-go', () => {
dlSpy = jest.spyOn(tc, 'downloadTool'); dlSpy = jest.spyOn(tc, 'downloadTool');
exSpy = jest.spyOn(tc, 'extractTar'); exSpy = jest.spyOn(tc, 'extractTar');
cacheSpy = jest.spyOn(tc, 'cacheDir'); cacheSpy = jest.spyOn(tc, 'cacheDir');
getSpy = jest.spyOn(im, 'getVersions'); getSpy = jest.spyOn(im, 'getVersionsDist');
getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo');
// io // io
whichSpy = jest.spyOn(io, 'which'); whichSpy = jest.spyOn(io, 'which');
existsSpy = jest.spyOn(fs, 'existsSync'); existsSpy = jest.spyOn(fs, 'existsSync');
mkdirpSpy = jest.spyOn(io, 'mkdirP'); mkdirpSpy = jest.spyOn(io, 'mkdirP');
// gets
getManifestSpy.mockImplementation(() => <tc.IToolRelease[]>goTestManifest);
// writes // writes
cnSpy = jest.spyOn(process.stdout, 'write'); cnSpy = jest.spyOn(process.stdout, 'write');
logSpy = jest.spyOn(console, 'log'); logSpy = jest.spyOn(core, 'info');
dbgSpy = jest.spyOn(main, '_debug'); dbgSpy = jest.spyOn(core, 'debug');
getSpy.mockImplementation(() => <im.IGoVersion[]>goJsonData); getSpy.mockImplementation(() => <im.IGoVersion[] | null>goJsonData);
cnSpy.mockImplementation(line => { cnSpy.mockImplementation(line => {
// uncomment to debug // uncomment to debug
// process.stderr.write('write:' + line + '\n'); // process.stderr.write('write:' + line + '\n');
@ -86,27 +92,43 @@ describe('setup-go', () => {
afterAll(async () => {}, 100000); afterAll(async () => {}, 100000);
it('can query versions', async () => { it('can find 1.9.7 from manifest on osx', async () => {
let versions: im.IGoVersion[] | null = await im.getVersions( os.platform = 'darwin';
'https://non.existant.com/path' os.arch = 'x64';
let match = await im.getInfoFromManifest('1.9.7', true, 'mocktoken');
expect(match).toBeDefined();
expect(match!.resolvedVersion).toBe('1.9.7');
expect(match!.type).toBe('manifest');
expect(match!.downloadUrl).toBe(
'https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-darwin-x64.tar.gz'
); );
expect(versions).toBeDefined();
let l: number = versions ? versions.length : 0;
expect(l).toBe(91);
}); });
it('finds stable match for exact version', async () => { it('can find 1.9 from manifest on linux', async () => {
os.platform = 'linux';
os.arch = 'x64';
let match = await im.getInfoFromManifest('1.9.7', true, 'mocktoken');
expect(match).toBeDefined();
expect(match!.resolvedVersion).toBe('1.9.7');
expect(match!.type).toBe('manifest');
expect(match!.downloadUrl).toBe(
'https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-linux-x64.tar.gz'
);
});
it('can find 1.9 from manifest on windows', async () => {
os.platform = 'win32'; os.platform = 'win32';
os.arch = 'x64'; os.arch = 'x64';
// get request is already mocked let match = await im.getInfoFromManifest('1.9.7', true, 'mocktoken');
// spec: 1.13.7 => 1.13.7 (exact)
let match: im.IGoVersion | undefined = await im.findMatch('1.13.7', true);
expect(match).toBeDefined(); expect(match).toBeDefined();
let version: string = match ? match.version : ''; expect(match!.resolvedVersion).toBe('1.9.7');
expect(version).toBe('go1.13.7'); expect(match!.type).toBe('manifest');
let fileName = match ? match.files[0].filename : ''; expect(match!.downloadUrl).toBe(
expect(fileName).toBe('go1.13.7.windows-amd64.zip'); 'https://github.com/actions/go-versions/releases/download/1.9.7/go-1.9.7-win32-x64.zip'
);
}); });
it('finds stable match for exact dot zero version', async () => { it('finds stable match for exact dot zero version', async () => {
@ -208,6 +230,7 @@ describe('setup-go', () => {
await main.run(); await main.run();
let expPath = path.join(toolPath, 'bin'); let expPath = path.join(toolPath, 'bin');
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
}); });
it('finds a version in the cache and adds it to the path', async () => { it('finds a version in the cache and adds it to the path', async () => {
@ -261,10 +284,124 @@ describe('setup-go', () => {
await main.run(); await main.run();
expect(cnSpy).toHaveBeenCalledWith( expect(cnSpy).toHaveBeenCalledWith(
`::error::Could not find a version that satisfied version spec: 9.99.9${osm.EOL}` `::error::Unable to find Go version '9.99.9' for platform linux and architecture x64.${osm.EOL}`
); );
}); });
it('downloads a version from a manifest match', async () => {
os.platform = 'linux';
os.arch = 'x64';
// a version which is in the manifest
let versionSpec = '1.12.16';
inputs['go-version'] = versionSpec;
inputs['token'] = 'faketoken';
let expectedUrl =
'https://github.com/actions/go-versions/releases/download/1.12.16-20200616.20/go-1.12.16-linux-x64.tar.gz';
// ... but not in the local cache
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
let toolPath = path.normalize('/cache/go/1.12.16/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
let expPath = path.join(toolPath, 'bin');
expect(dlSpy).toHaveBeenCalled();
expect(exSpy).toHaveBeenCalled();
expect(logSpy).not.toHaveBeenCalledWith(
'Not found in manifest. Falling back to download directly from Go'
);
expect(logSpy).toHaveBeenCalledWith(
`Acquiring 1.12.16 from ${expectedUrl}`
);
expect(logSpy).toHaveBeenCalledWith(`Added go to the path`);
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
it('downloads a major and minor from a manifest match', async () => {
os.platform = 'linux';
os.arch = 'x64';
// a version which is in the manifest
let versionSpec = '1.12';
inputs['go-version'] = versionSpec;
inputs['token'] = 'faketoken';
let expectedUrl =
'https://github.com/actions/go-versions/releases/download/1.12.17-20200616.21/go-1.12.17-linux-x64.tar.gz';
// ... but not in the local cache
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
let toolPath = path.normalize('/cache/go/1.12.17/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
let expPath = path.join(toolPath, 'bin');
expect(dlSpy).toHaveBeenCalled();
expect(exSpy).toHaveBeenCalled();
expect(logSpy).not.toHaveBeenCalledWith(
'Not found in manifest. Falling back to download directly from Go'
);
expect(logSpy).toHaveBeenCalledWith(
`Acquiring 1.12.17 from ${expectedUrl}`
);
expect(logSpy).toHaveBeenCalledWith(`Added go to the path`);
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
it('falls back to a version from node dist', async () => {
os.platform = 'linux';
os.arch = 'x64';
// a version which is not in the manifest but is in node dist
let versionSpec = '1.12.14';
inputs['go-version'] = versionSpec;
inputs['token'] = 'faketoken';
let expectedUrl =
'https://github.com/actions/go-versions/releases/download/1.12.14-20200616.18/go-1.12.14-linux-x64.tar.gz';
// ... but not in the local cache
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
let toolPath = path.normalize('/cache/go/1.12.14/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
let expPath = path.join(toolPath, 'bin');
expect(logSpy).toHaveBeenCalledWith('Setup go stable version spec 1.12.14');
expect(findSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith('Attempting to download 1.12.14...');
expect(dlSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith('matching 1.12.14...');
expect(exSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
'Not found in manifest. Falling back to download directly from Go'
);
expect(logSpy).toHaveBeenCalledWith(`Install from dist`);
expect(logSpy).toHaveBeenCalledWith(`Added go to the path`);
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
it('reports a failed download', async () => { it('reports a failed download', async () => {
let errMsg = 'unhandled download message'; let errMsg = 'unhandled download message';
os.platform = 'linux'; os.platform = 'linux';
@ -283,22 +420,6 @@ describe('setup-go', () => {
); );
}); });
it('reports empty query results', async () => {
let errMsg = 'unhandled download message';
os.platform = 'linux';
os.arch = 'x64';
inputs['go-version'] = '1.13.1';
findSpy.mockImplementation(() => '');
getSpy.mockImplementation(() => null);
await main.run();
expect(cnSpy).toHaveBeenCalledWith(
`::error::Failed to download version 1.13.1: Error: golang download url did not return results${osm.EOL}`
);
});
it('does not add BIN if go is not in path', async () => { it('does not add BIN if go is not in path', async () => {
whichSpy.mockImplementation(async () => { whichSpy.mockImplementation(async () => {
return ''; return '';

14
__tests__/verify-go.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
if [ -z "$1" ]; then
echo "Must supply go version argument"
exit 1
fi
go_version="$(go version)"
echo "Found go version '$go_version'"
if [ -z "$(echo $go_version | grep $1)" ]; then
echo "Unexpected version"
exit 1
fi

View file

@ -7,6 +7,9 @@ inputs:
stable: stable:
description: 'Whether to download only stable versions' description: 'Whether to download only stable versions'
default: 'true' default: 'true'
token:
description: Used to pull node distributions from go-versions. Since there's a default, this is typically not supplied by the user.
default: ${{ github.token }}
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/index.js' main: 'dist/index.js'

667
dist/index.js vendored

File diff suppressed because it is too large Load diff

12658
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -23,10 +23,10 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.2", "@actions/core": "^1.2.3",
"@actions/http-client": "^1.0.6", "@actions/http-client": "^1.0.6",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
"@actions/tool-cache": "^1.3.3", "@actions/tool-cache": "^1.5.5",
"semver": "^6.1.1" "semver": "^6.1.1"
}, },
"devDependencies": { "devDependencies": {
@ -39,6 +39,6 @@
"nock": "^10.0.6", "nock": "^10.0.6",
"prettier": "^1.17.1", "prettier": "^1.17.1",
"ts-jest": "^24.0.2", "ts-jest": "^24.0.2",
"typescript": "^3.5.1" "typescript": "^3.8.3"
} }
} }

View file

@ -1,46 +1,12 @@
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as core from '@actions/core';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import * as httpm from '@actions/http-client'; import * as httpm from '@actions/http-client';
import * as sys from './system'; import * as sys from './system';
import {debug} from '@actions/core'; import os from 'os';
export async function downloadGo( type InstallationType = 'dist' | 'manifest';
versionSpec: string,
stable: boolean
): Promise<string | undefined> {
let toolPath: string | undefined;
try {
let match: IGoVersion | undefined = await findMatch(versionSpec, stable);
if (match) {
// download
debug(`match ${match.version}`);
let downloadUrl: string = `https://storage.googleapis.com/golang/${match.files[0].filename}`;
console.log(`Downloading from ${downloadUrl}`);
let downloadPath: string = await tc.downloadTool(downloadUrl);
debug(`downloaded to ${downloadPath}`);
// extract
console.log('Extracting ...');
let extPath: string =
sys.getPlatform() == 'windows'
? await tc.extractZip(downloadPath)
: await tc.extractTar(downloadPath);
debug(`extracted to ${extPath}`);
// extracts with a root folder that matches the fileName downloaded
const toolRoot = path.join(extPath, 'go');
toolPath = await tc.cacheDir(toolRoot, 'go', makeSemver(match.version));
}
} catch (error) {
throw new Error(`Failed to download version ${versionSpec}: ${error}`);
}
return toolPath;
}
export interface IGoVersionFile { export interface IGoVersionFile {
filename: string; filename: string;
@ -55,6 +21,160 @@ export interface IGoVersion {
files: IGoVersionFile[]; files: IGoVersionFile[];
} }
export interface IGoVersionInfo {
type: InstallationType;
downloadUrl: string;
resolvedVersion: string;
fileName: string;
}
export async function getGo(
versionSpec: string,
stable: boolean,
auth: string | undefined
) {
let osPlat: string = os.platform();
let osArch: string = os.arch();
// check cache
let toolPath: string;
toolPath = tc.find('go', versionSpec);
// If not found in cache, download
if (toolPath) {
core.info(`Found in cache @ ${toolPath}`);
return toolPath;
}
core.info(`Attempting to download ${versionSpec}...`);
let downloadPath = '';
let info: IGoVersionInfo | null = null;
//
// Try download from internal distribution (popular versions only)
//
try {
info = await getInfoFromManifest(versionSpec, stable, auth);
if (info) {
downloadPath = await installGoVersion(info, auth);
} else {
core.info(
'Not found in manifest. Falling back to download directly from Go'
);
}
} catch (err) {
if (
err instanceof tc.HTTPError &&
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
) {
core.info(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info(err.message);
}
core.debug(err.stack);
core.info('Falling back to download directly from Go');
}
//
// Download from storage.googleapis.com
//
if (!downloadPath) {
info = await getInfoFromDist(versionSpec, stable);
if (!info) {
throw new Error(
`Unable to find Go version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
);
}
try {
core.info('Install from dist');
downloadPath = await installGoVersion(info, undefined);
} catch (err) {
throw new Error(`Failed to download version ${versionSpec}: ${err}`);
}
}
return downloadPath;
}
async function installGoVersion(
info: IGoVersionInfo,
auth: string | undefined
): Promise<string> {
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
const downloadPath = await tc.downloadTool(info.downloadUrl, undefined, auth);
core.info('Extracting Go...');
let extPath = await extractGoArchive(downloadPath);
core.info(`Successfully extracted go to ${extPath}`);
if (info.type === 'dist') {
extPath = path.join(extPath, 'go');
}
core.info('Adding to the cache ...');
const cachedDir = await tc.cacheDir(
extPath,
'go',
makeSemver(info.resolvedVersion)
);
core.info(`Successfully cached go to ${cachedDir}`);
return cachedDir;
}
export async function extractGoArchive(archivePath: string): Promise<string> {
const arch = os.arch();
let extPath: string;
if (arch === 'win32') {
extPath = await tc.extractZip(archivePath);
} else {
extPath = await tc.extractTar(archivePath);
}
return extPath;
}
export async function getInfoFromManifest(
versionSpec: string,
stable: boolean,
auth: string | undefined
): Promise<IGoVersionInfo | null> {
let info: IGoVersionInfo | null = null;
const releases = await tc.getManifestFromRepo('actions', 'go-versions', auth);
core.info(`matching ${versionSpec}...`);
const rel = await tc.findFromManifest(versionSpec, stable, releases);
if (rel && rel.files.length > 0) {
info = <IGoVersionInfo>{};
info.type = 'manifest';
info.resolvedVersion = rel.version;
info.downloadUrl = rel.files[0].download_url;
info.fileName = rel.files[0].filename;
}
return info;
}
async function getInfoFromDist(
versionSpec: string,
stable: boolean
): Promise<IGoVersionInfo | null> {
let version: IGoVersion | undefined;
version = await findMatch(versionSpec, stable);
if (!version) {
return null;
}
let downloadUrl: string = `https://storage.googleapis.com/golang/${version.files[0].filename}`;
return <IGoVersionInfo>{
type: 'dist',
downloadUrl: downloadUrl,
resolvedVersion: version.version,
fileName: version.files[0].filename
};
}
export async function findMatch( export async function findMatch(
versionSpec: string, versionSpec: string,
stable: boolean stable: boolean
@ -66,7 +186,9 @@ export async function findMatch(
let match: IGoVersion | undefined; let match: IGoVersion | undefined;
const dlUrl: string = 'https://golang.org/dl/?mode=json&include=all'; const dlUrl: string = 'https://golang.org/dl/?mode=json&include=all';
let candidates: IGoVersion[] | null = await module.exports.getVersions(dlUrl); let candidates: IGoVersion[] | null = await module.exports.getVersionsDist(
dlUrl
);
if (!candidates) { if (!candidates) {
throw new Error(`golang download url did not return results`); throw new Error(`golang download url did not return results`);
} }
@ -83,18 +205,20 @@ export async function findMatch(
version = version + '.0'; version = version + '.0';
} }
debug(`check ${version} satisfies ${versionSpec}`); core.debug(`check ${version} satisfies ${versionSpec}`);
if ( if (
semver.satisfies(version, versionSpec) && semver.satisfies(version, versionSpec) &&
(!stable || candidate.stable === stable) (!stable || candidate.stable === stable)
) { ) {
goFile = candidate.files.find(file => { goFile = candidate.files.find(file => {
debug(`${file.arch}===${archFilter} && ${file.os}===${platFilter}`); core.debug(
`${file.arch}===${archFilter} && ${file.os}===${platFilter}`
);
return file.arch === archFilter && file.os === platFilter; return file.arch === archFilter && file.os === platFilter;
}); });
if (goFile) { if (goFile) {
debug(`matched ${candidate.version}`); core.debug(`matched ${candidate.version}`);
match = candidate; match = candidate;
break; break;
} }
@ -110,9 +234,14 @@ export async function findMatch(
return result; return result;
} }
export async function getVersions(dlUrl: string): Promise<IGoVersion[] | null> { export async function getVersionsDist(
dlUrl: string
): Promise<IGoVersion[] | null> {
// this returns versions descending so latest is first // this returns versions descending so latest is first
let http: httpm.HttpClient = new httpm.HttpClient('setup-go'); let http: httpm.HttpClient = new httpm.HttpClient('setup-go', [], {
allowRedirects: true,
maxRedirects: 3
});
return (await http.getJson<IGoVersion[]>(dlUrl)).result; return (await http.getJson<IGoVersion[]>(dlUrl)).result;
} }

View file

@ -1,10 +1,10 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as io from '@actions/io'; import * as io from '@actions/io';
import * as tc from '@actions/tool-cache';
import * as installer from './installer'; import * as installer from './installer';
import path from 'path'; import path from 'path';
import cp from 'child_process'; import cp from 'child_process';
import fs from 'fs'; import fs from 'fs';
import {URL} from 'url';
export async function run() { export async function run() {
try { try {
@ -18,47 +18,35 @@ export async function run() {
// since getting unstable versions should be explicit // since getting unstable versions should be explicit
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
console.log( core.info(`Setup go ${stable ? 'stable' : ''} version spec ${versionSpec}`);
`Setup go ${stable ? 'stable' : ''} version spec ${versionSpec}`
);
if (versionSpec) { if (versionSpec) {
let installDir: string | undefined = tc.find('go', versionSpec); let token = core.getInput('token');
let auth = !token || isGhes() ? undefined : `token ${token}`;
if (!installDir) { const installDir = await installer.getGo(versionSpec, stable, auth);
console.log(
`A version satisfying ${versionSpec} not found locally, attempting to download ...`
);
installDir = await installer.downloadGo(versionSpec, stable);
console.log('Installed');
}
if (installDir) {
core.exportVariable('GOROOT', installDir); core.exportVariable('GOROOT', installDir);
core.addPath(path.join(installDir, 'bin')); core.addPath(path.join(installDir, 'bin'));
console.log('Added go to the path'); core.info('Added go to the path');
let added = addBinToPath(); let added = await addBinToPath();
core.debug(`add bin ${added}`); core.debug(`add bin ${added}`);
} else { core.info(`Successfully setup go version ${versionSpec}`);
throw new Error(
`Could not find a version that satisfied version spec: ${versionSpec}`
);
}
} }
// add problem matchers // add problem matchers
const matchersPath = path.join(__dirname, '..', 'matchers.json'); const matchersPath = path.join(__dirname, '..', 'matchers.json');
console.log(`##[add-matcher]${matchersPath}`); core.info(`##[add-matcher]${matchersPath}`);
// output the version actually being used // output the version actually being used
let goPath = await io.which('go'); let goPath = await io.which('go');
let goVersion = (cp.execSync(`${goPath} version`) || '').toString(); let goVersion = (cp.execSync(`${goPath} version`) || '').toString();
console.log(goVersion); core.info(goVersion);
core.startGroup('go env'); core.startGroup('go env');
let goEnv = (cp.execSync(`${goPath} env`) || '').toString(); let goEnv = (cp.execSync(`${goPath} env`) || '').toString();
console.log(goEnv); core.info(goEnv);
core.endGroup(); core.endGroup();
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
@ -68,25 +56,25 @@ export async function run() {
export async function addBinToPath(): Promise<boolean> { export async function addBinToPath(): Promise<boolean> {
let added = false; let added = false;
let g = await io.which('go'); let g = await io.which('go');
_debug(`which go :${g}:`); core.debug(`which go :${g}:`);
if (!g) { if (!g) {
_debug('go not in the path'); core.debug('go not in the path');
return added; return added;
} }
let buf = cp.execSync('go env GOPATH'); let buf = cp.execSync('go env GOPATH');
if (buf) { if (buf) {
let gp = buf.toString().trim(); let gp = buf.toString().trim();
_debug(`go env GOPATH :${gp}:`); core.debug(`go env GOPATH :${gp}:`);
if (!fs.existsSync(gp)) { if (!fs.existsSync(gp)) {
// some of the hosted images have go install but not profile dir // some of the hosted images have go install but not profile dir
_debug(`creating ${gp}`); core.debug(`creating ${gp}`);
io.mkdirP(gp); io.mkdirP(gp);
} }
let bp = path.join(gp, 'bin'); let bp = path.join(gp, 'bin');
if (!fs.existsSync(bp)) { if (!fs.existsSync(bp)) {
_debug(`creating ${bp}`); core.debug(`creating ${bp}`);
io.mkdirP(bp); io.mkdirP(bp);
} }
@ -96,6 +84,9 @@ export async function addBinToPath(): Promise<boolean> {
return added; return added;
} }
export function _debug(message: string) { function isGhes(): boolean {
core.debug(message); const ghUrl = new URL(
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
);
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
} }