mirror of
https://github.com/actions/setup-go.git
synced 2025-06-22 21:17:59 +02:00
starting v2 and proxy support
This commit is contained in:
282
src/installer.ts
282
src/installer.ts
@ -1,223 +1,91 @@
|
||||
// Load tempDirectory before it gets wiped by tool-cache
|
||||
let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || '';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as semver from 'semver';
|
||||
import * as restm from 'typed-rest-client/RestClient';
|
||||
import * as httpm from '@actions/http-client'
|
||||
import * as sys from './system'
|
||||
|
||||
let osPlat: string = os.platform();
|
||||
let osArch: string = os.arch();
|
||||
export async function downloadGo(versionSpec: string, stable: boolean): Promise<string | undefined> {
|
||||
let toolPath: string | undefined;
|
||||
|
||||
if (!tempDirectory) {
|
||||
let baseLocation;
|
||||
if (process.platform === 'win32') {
|
||||
// On windows use the USERPROFILE env variable
|
||||
baseLocation = process.env['USERPROFILE'] || 'C:\\';
|
||||
} else {
|
||||
if (process.platform === 'darwin') {
|
||||
baseLocation = '/Users';
|
||||
} else {
|
||||
baseLocation = '/home';
|
||||
}
|
||||
}
|
||||
tempDirectory = path.join(baseLocation, 'actions', 'temp');
|
||||
}
|
||||
|
||||
export async function getGo(version: string) {
|
||||
const selected = await determineVersion(version);
|
||||
if (selected) {
|
||||
version = selected;
|
||||
}
|
||||
|
||||
// check cache
|
||||
let toolPath: string;
|
||||
toolPath = tc.find('go', normalizeVersion(version));
|
||||
|
||||
if (!toolPath) {
|
||||
// download, extract, cache
|
||||
toolPath = await acquireGo(version);
|
||||
core.debug('Go tool is cached under ' + toolPath);
|
||||
}
|
||||
|
||||
setGoEnvironmentVariables(toolPath);
|
||||
|
||||
toolPath = path.join(toolPath, 'bin');
|
||||
//
|
||||
// prepend the tools path. instructs the agent to prepend for future tasks
|
||||
//
|
||||
core.addPath(toolPath);
|
||||
}
|
||||
|
||||
async function acquireGo(version: string): Promise<string> {
|
||||
//
|
||||
// Download - a tool installer intimately knows how to get the tool (and construct urls)
|
||||
//
|
||||
let fileName: string = getFileName(version);
|
||||
let downloadUrl: string = getDownloadUrl(fileName);
|
||||
|
||||
core.debug('Downloading Go from: ' + downloadUrl);
|
||||
|
||||
let downloadPath: string | null = null;
|
||||
try {
|
||||
downloadPath = await tc.downloadTool(downloadUrl);
|
||||
let match: IGoVersion | undefined = await findMatch(versionSpec, stable);
|
||||
|
||||
if (match) {
|
||||
// download
|
||||
let downloadUrl: string = `https://storage.googleapis.com/golang/${match.files[0]}`;
|
||||
let downloadPath: string = await tc.downloadTool(downloadUrl);
|
||||
|
||||
// extract
|
||||
let extPath: string = sys.getPlatform() == 'windows'?
|
||||
await tc.extractZip(downloadPath): await tc.extractTar(downloadPath);
|
||||
|
||||
// extracts with a root folder that matches the fileName downloaded
|
||||
const toolRoot = path.join(extPath, 'go');
|
||||
toolPath = await tc.cacheDir(toolRoot, 'go', versionSpec);
|
||||
}
|
||||
} catch (error) {
|
||||
core.debug(error);
|
||||
|
||||
throw `Failed to download version ${version}: ${error}`;
|
||||
throw `Failed to download version ${versionSpec}: ${error}`;
|
||||
}
|
||||
|
||||
//
|
||||
// Extract
|
||||
//
|
||||
let extPath: string = tempDirectory;
|
||||
if (!extPath) {
|
||||
throw new Error('Temp directory not set');
|
||||
}
|
||||
|
||||
if (osPlat == 'win32') {
|
||||
extPath = await tc.extractZip(downloadPath);
|
||||
} else {
|
||||
extPath = await tc.extractTar(downloadPath);
|
||||
}
|
||||
|
||||
//
|
||||
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||
//
|
||||
const toolRoot = path.join(extPath, 'go');
|
||||
version = normalizeVersion(version);
|
||||
return await tc.cacheDir(toolRoot, 'go', version);
|
||||
return toolPath;
|
||||
}
|
||||
|
||||
function getFileName(version: string): string {
|
||||
const arches: {[arch: string]: string} = {
|
||||
x64: 'amd64',
|
||||
arm: 'armv6l',
|
||||
arm64: 'arm64',
|
||||
default: '386'
|
||||
export interface IGoVersionFile {
|
||||
filename: string,
|
||||
// darwin, linux, windows
|
||||
os: string,
|
||||
arch: string
|
||||
}
|
||||
|
||||
export interface IGoVersion {
|
||||
version: string;
|
||||
stable: boolean;
|
||||
files: IGoVersionFile[];
|
||||
}
|
||||
|
||||
export async function findMatch(versionSpec: string, stable: boolean): Promise<IGoVersion | undefined> {
|
||||
let archFilter = sys.getArch();
|
||||
let platFilter = sys.getPlatform();
|
||||
|
||||
let match: IGoVersion| undefined;
|
||||
const dlUrl: string = 'https://golang.org/dl/?mode=json&include=all';
|
||||
|
||||
// this returns versions descending so latest is first
|
||||
let http: httpm.HttpClient = new httpm.HttpClient('setup-go');
|
||||
let candidates: IGoVersion[] | null = (await http.getJson<IGoVersion[]>(dlUrl)).result;
|
||||
|
||||
if (!candidates) {
|
||||
throw new Error(`golang download url did not return results: ${dlUrl}`);
|
||||
}
|
||||
|
||||
let goFile: IGoVersionFile | undefined;
|
||||
for (let i=0; i < candidates.length; i++) {
|
||||
let candidate: IGoVersion = candidates[i];
|
||||
let version = candidate.version.replace('go', '');
|
||||
|
||||
// 1.13.0 is advertised as 1.13 preventing being able to match exactly 1.13.0
|
||||
// since a semver of 1.13 would match latest 1.13
|
||||
let parts: string[] = version.split('.');
|
||||
if (parts.length == 2) {
|
||||
version = version + '.0';
|
||||
}
|
||||
|
||||
//console.log(version, versionSpec);
|
||||
if (semver.satisfies(version, versionSpec) && candidate.stable == stable) {
|
||||
goFile = candidate.files.find(file => {
|
||||
return file.arch === archFilter && file.os === platFilter;
|
||||
});
|
||||
|
||||
if (goFile) {
|
||||
match = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const platform: string = osPlat == 'win32' ? 'windows' : osPlat;
|
||||
const arch: string = arches[osArch] || arches['default'];
|
||||
const ext: string = osPlat == 'win32' ? 'zip' : 'tar.gz';
|
||||
const filename: string = util.format(
|
||||
'go%s.%s-%s.%s',
|
||||
version,
|
||||
platform,
|
||||
arch,
|
||||
ext
|
||||
);
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
function getDownloadUrl(filename: string): string {
|
||||
return util.format('https://storage.googleapis.com/golang/%s', filename);
|
||||
}
|
||||
|
||||
function setGoEnvironmentVariables(goRoot: string) {
|
||||
core.exportVariable('GOROOT', goRoot);
|
||||
|
||||
const goPath: string = process.env['GOPATH'] || '';
|
||||
const goBin: string = process.env['GOBIN'] || '';
|
||||
|
||||
// set GOPATH and GOBIN as user value
|
||||
if (goPath) {
|
||||
core.exportVariable('GOPATH', goPath);
|
||||
}
|
||||
if (goBin) {
|
||||
core.exportVariable('GOBIN', goBin);
|
||||
}
|
||||
}
|
||||
|
||||
// This function is required to convert the version 1.10 to 1.10.0.
|
||||
// Because caching utility accept only sementic version,
|
||||
// which have patch number as well.
|
||||
function normalizeVersion(version: string): string {
|
||||
const versionPart = version.split('.');
|
||||
if (versionPart[1] == null) {
|
||||
//append minor and patch version if not available
|
||||
return version.concat('.0.0');
|
||||
} else {
|
||||
// handle beta and rc: 1.10beta1 => 1.10.0-beta1, 1.10rc1 => 1.10.0-rc1
|
||||
if (versionPart[1].includes('beta') || versionPart[1].includes('rc')) {
|
||||
versionPart[1] = versionPart[1]
|
||||
.replace('beta', '.0-beta')
|
||||
.replace('rc', '.0-rc');
|
||||
return versionPart.join('.');
|
||||
}
|
||||
if (match && goFile) {
|
||||
match.files = [ goFile ];
|
||||
}
|
||||
|
||||
if (versionPart[2] == null) {
|
||||
//append patch version if not available
|
||||
return version.concat('.0');
|
||||
} else {
|
||||
// handle beta and rc: 1.8.5beta1 => 1.8.5-beta1, 1.8.5rc1 => 1.8.5-rc1
|
||||
if (versionPart[2].includes('beta') || versionPart[2].includes('rc')) {
|
||||
versionPart[2] = versionPart[2]
|
||||
.replace('beta', '-beta')
|
||||
.replace('rc', '-rc');
|
||||
return versionPart.join('.');
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
async function determineVersion(version: string): Promise<string> {
|
||||
if (!version.endsWith('.x')) {
|
||||
const versionPart = version.split('.');
|
||||
|
||||
if (versionPart[1] == null || versionPart[2] == null) {
|
||||
return await getLatestVersion(version.concat('.x'));
|
||||
} else {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
return await getLatestVersion(version);
|
||||
}
|
||||
|
||||
async function getLatestVersion(version: string): Promise<string> {
|
||||
// clean .x syntax: 1.10.x -> 1.10
|
||||
const trimmedVersion = version.slice(0, version.length - 2);
|
||||
|
||||
const versions = await getPossibleVersions(trimmedVersion);
|
||||
|
||||
core.debug(`evaluating ${versions.length} versions`);
|
||||
|
||||
if (version.length === 0) {
|
||||
throw new Error('unable to get latest version');
|
||||
}
|
||||
|
||||
core.debug(`matched: ${versions[0]}`);
|
||||
|
||||
return versions[0];
|
||||
}
|
||||
|
||||
interface IGoRef {
|
||||
version: string;
|
||||
}
|
||||
|
||||
async function getAvailableVersions(): Promise<string[]> {
|
||||
let rest: restm.RestClient = new restm.RestClient('setup-go');
|
||||
let tags: IGoRef[] =
|
||||
(await rest.get<IGoRef[]>('https://golang.org/dl/?mode=json&include=all'))
|
||||
.result || [];
|
||||
|
||||
return tags.map(tag => tag.version.replace('go', ''));
|
||||
}
|
||||
|
||||
async function getPossibleVersions(version: string): Promise<string[]> {
|
||||
const versions = await getAvailableVersions();
|
||||
const possibleVersions = versions.filter(v => v.startsWith(version));
|
||||
|
||||
const versionMap = new Map();
|
||||
possibleVersions.forEach(v => versionMap.set(normalizeVersion(v), v));
|
||||
|
||||
return Array.from(versionMap.keys())
|
||||
.sort(semver.rcompare)
|
||||
.map(v => versionMap.get(v));
|
||||
return match;
|
||||
}
|
||||
|
Reference in New Issue
Block a user