actions/setup-go v5 (local mirror)

This commit is contained in:
ci
2026-06-22 13:07:03 +09:00
commit 3e78b7a158
130 changed files with 212928 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as glob from '@actions/glob';
import path from 'path';
import fs from 'fs';
import {State, Outputs} from './constants';
import {PackageManagerInfo} from './package-managers';
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
export const restoreCache = async (
versionSpec: string,
packageManager: string,
cacheDependencyPath?: string
) => {
const packageManagerInfo = await getPackageManagerInfo(packageManager);
const platform = process.env.RUNNER_OS;
const arch = process.arch;
const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
const dependencyFilePath = cacheDependencyPath
? cacheDependencyPath
: findDependencyFile(packageManagerInfo);
const fileHash = await glob.hashFiles(dependencyFilePath);
if (!fileHash) {
throw new Error(
'Some specified paths were not resolved, unable to cache dependencies.'
);
}
const linuxVersion =
process.env.RUNNER_OS === 'Linux' ? `${process.env.ImageOS}-` : '';
const primaryKey = `setup-go-${platform}-${arch}-${linuxVersion}go-${versionSpec}-${fileHash}`;
core.debug(`primary key is ${primaryKey}`);
core.saveState(State.CachePrimaryKey, primaryKey);
const cacheKey = await cache.restoreCache(cachePaths, primaryKey);
core.setOutput(Outputs.CacheHit, Boolean(cacheKey));
if (!cacheKey) {
core.info(`Cache is not found`);
core.setOutput(Outputs.CacheHit, false);
return;
}
core.saveState(State.CacheMatchedKey, cacheKey);
core.info(`Cache restored from key: ${cacheKey}`);
};
const findDependencyFile = (packageManager: PackageManagerInfo) => {
const dependencyFile = packageManager.dependencyFilePattern;
const workspace = process.env.GITHUB_WORKSPACE!;
const rootContent = fs.readdirSync(workspace);
const goSumFileExists = rootContent.includes(dependencyFile);
if (!goSumFileExists) {
throw new Error(
`Dependencies file is not found in ${workspace}. Supported file pattern: ${dependencyFile}`
);
}
return path.join(workspace, dependencyFile);
};
+93
View File
@@ -0,0 +1,93 @@
import * as core from '@actions/core';
import * as cache from '@actions/cache';
import fs from 'fs';
import {State} from './constants';
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
// throw an uncaught exception. Instead of failing this action, just warn.
process.on('uncaughtException', e => {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${e.message}`);
});
// Added early exit to resolve issue with slow post action step:
// - https://github.com/actions/setup-node/issues/878
// https://github.com/actions/cache/pull/1217
export async function run(earlyExit?: boolean) {
try {
const cacheInput = core.getBooleanInput('cache');
if (cacheInput) {
await cachePackages();
if (earlyExit) {
process.exit(0);
}
}
} catch (error) {
let message = 'Unknown error!';
if (error instanceof Error) {
message = error.message;
}
if (typeof error === 'string') {
message = error;
}
core.warning(message);
}
}
const cachePackages = async () => {
const packageManager = 'default';
const state = core.getState(State.CacheMatchedKey);
const primaryKey = core.getState(State.CachePrimaryKey);
const packageManagerInfo = await getPackageManagerInfo(packageManager);
const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
const nonExistingPaths = cachePaths.filter(
cachePath => !fs.existsSync(cachePath)
);
if (nonExistingPaths.length === cachePaths.length) {
core.warning('There are no cache folders on the disk');
return;
}
if (nonExistingPaths.length) {
logWarning(
`Cache folder path is retrieved but doesn't exist on disk: ${nonExistingPaths.join(
', '
)}`
);
}
if (!primaryKey) {
core.info(
'Primary key was not generated. Please check the log messages above for more errors or information'
);
return;
}
if (primaryKey === state) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
return;
}
const cacheId = await cache.saveCache(cachePaths, primaryKey);
if (cacheId === -1) {
return;
}
core.info(`Cache saved with the key: ${primaryKey}`);
};
function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}
run(true);
+91
View File
@@ -0,0 +1,91 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import {supportedPackageManagers, PackageManagerInfo} from './package-managers';
export const getCommandOutput = async (toolCommand: string) => {
let {stdout, stderr, exitCode} = await exec.getExecOutput(
toolCommand,
undefined,
{ignoreReturnCode: true}
);
if (exitCode) {
stderr = !stderr.trim()
? `The '${toolCommand}' command failed with exit code: ${exitCode}`
: stderr;
throw new Error(stderr);
}
return stdout.trim();
};
export const getPackageManagerInfo = async (packageManager: string) => {
if (!supportedPackageManagers[packageManager]) {
throw new Error(
`It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.`
);
}
const obtainedPackageManager = supportedPackageManagers[packageManager];
return obtainedPackageManager;
};
export const getCacheDirectoryPath = async (
packageManagerInfo: PackageManagerInfo
) => {
const pathOutputs = await Promise.allSettled(
packageManagerInfo.cacheFolderCommandList.map(async command =>
getCommandOutput(command)
)
);
const results = pathOutputs.map(item => {
if (item.status === 'fulfilled') {
return item.value;
} else {
core.info(`[warning]getting cache directory path failed: ${item.reason}`);
}
return '';
});
const cachePaths = results.filter(item => item);
if (!cachePaths.length) {
throw new Error(`Could not get cache folder paths.`);
}
return cachePaths;
};
export function isGhes(): boolean {
const ghUrl = new URL(
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
);
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
const isGitHubHost = hostname === 'GITHUB.COM';
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
const isLocalHost = hostname.endsWith('.LOCALHOST');
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
}
export function isCacheFeatureAvailable(): boolean {
if (cache.isFeatureAvailable()) {
return true;
}
if (isGhes()) {
core.warning(
'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'
);
return false;
}
core.warning(
'The runner was not able to contact the cache service. Caching will be skipped'
);
return false;
}
+8
View File
@@ -0,0 +1,8 @@
export enum State {
CachePrimaryKey = 'CACHE_KEY',
CacheMatchedKey = 'CACHE_RESULT'
}
export enum Outputs {
CacheHit = 'cache-hit'
}
+565
View File
@@ -0,0 +1,565 @@
import * as tc from '@actions/tool-cache';
import * as core from '@actions/core';
import * as path from 'path';
import * as semver from 'semver';
import * as httpm from '@actions/http-client';
import * as sys from './system';
import fs from 'fs';
import os from 'os';
import {StableReleaseAlias, isSelfHosted} from './utils';
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'go-versions';
const MANIFEST_REPO_BRANCH = 'main';
const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
type InstallationType = 'dist' | 'manifest';
export interface IGoVersionFile {
filename: string;
// darwin, linux, windows
os: string;
arch: string;
}
export interface IGoVersion {
version: string;
stable: boolean;
files: IGoVersionFile[];
}
export interface IGoVersionInfo {
type: InstallationType;
downloadUrl: string;
resolvedVersion: string;
fileName: string;
}
export async function getGo(
versionSpec: string,
checkLatest: boolean,
auth: string | undefined,
arch = os.arch()
) {
let manifest: tc.IToolRelease[] | undefined;
const osPlat: string = os.platform();
if (
versionSpec === StableReleaseAlias.Stable ||
versionSpec === StableReleaseAlias.OldStable
) {
manifest = await getManifest(auth);
let stableVersion = await resolveStableVersionInput(
versionSpec,
arch,
osPlat,
manifest
);
if (!stableVersion) {
stableVersion = await resolveStableVersionDist(versionSpec, arch);
if (!stableVersion) {
throw new Error(
`Unable to find Go version '${versionSpec}' for platform ${osPlat} and architecture ${arch}.`
);
}
}
core.info(`${versionSpec} version resolved as ${stableVersion}`);
versionSpec = stableVersion;
}
if (checkLatest) {
core.info('Attempting to resolve the latest version from the manifest...');
const resolvedVersion = await resolveVersionFromManifest(
versionSpec,
true,
auth,
arch,
manifest
);
if (resolvedVersion) {
versionSpec = resolvedVersion;
core.info(`Resolved as '${versionSpec}'`);
} else {
core.info(`Failed to resolve version ${versionSpec} from manifest`);
}
}
// check cache
const toolPath = tc.find('go', versionSpec, arch);
// 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, true, auth, arch, manifest);
if (info) {
downloadPath = await installGoVersion(info, auth, arch);
} 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 as Error).message);
}
core.debug((err as Error).stack ?? '');
core.info('Falling back to download directly from Go');
}
//
// Download from https://go.dev/dl
//
if (!downloadPath) {
info = await getInfoFromDist(versionSpec, arch);
if (!info) {
throw new Error(
`Unable to find Go version '${versionSpec}' for platform ${osPlat} and architecture ${arch}.`
);
}
try {
core.info('Install from dist');
downloadPath = await installGoVersion(info, undefined, arch);
} catch (err) {
throw new Error(`Failed to download version ${versionSpec}: ${err}`);
}
}
return downloadPath;
}
async function resolveVersionFromManifest(
versionSpec: string,
stable: boolean,
auth: string | undefined,
arch: string,
manifest: tc.IToolRelease[] | undefined
): Promise<string | undefined> {
try {
const info = await getInfoFromManifest(
versionSpec,
stable,
auth,
arch,
manifest
);
return info?.resolvedVersion;
} catch (err) {
core.info('Unable to resolve a version from the manifest...');
core.debug((err as Error).message);
}
}
// for github hosted windows runner handle latency of OS drive
// by avoiding write operations to C:
async function cacheWindowsDir(
extPath: string,
tool: string,
version: string,
arch: string
): Promise<string | false> {
if (os.platform() !== 'win32') return false;
// make sure the action runs in the hosted environment
if (isSelfHosted()) return false;
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
if (!defaultToolCacheRoot) return false;
if (!fs.existsSync('d:\\') || !fs.existsSync('c:\\')) return false;
const actualToolCacheRoot = defaultToolCacheRoot
.replace('C:', 'D:')
.replace('c:', 'd:');
// make toolcache root to be on drive d:
process.env['RUNNER_TOOL_CACHE'] = actualToolCacheRoot;
const actualToolCacheDir = await tc.cacheDir(extPath, tool, version, arch);
// create a link from c: to d:
const defaultToolCacheDir = actualToolCacheDir.replace(
actualToolCacheRoot,
defaultToolCacheRoot
);
fs.mkdirSync(path.dirname(defaultToolCacheDir), {recursive: true});
fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction');
core.info(`Created link ${defaultToolCacheDir} => ${actualToolCacheDir}`);
const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`;
const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`;
fs.symlinkSync(
actualToolCacheCompleteFile,
defaultToolCacheCompleteFile,
'file'
);
core.info(
`Created link ${defaultToolCacheCompleteFile} => ${actualToolCacheCompleteFile}`
);
// make outer code to continue using toolcache as if it were installed on c:
// restore toolcache root to default drive c:
process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot;
return defaultToolCacheDir;
}
async function addExecutablesToToolCache(
extPath: string,
info: IGoVersionInfo,
arch: string
): Promise<string> {
const tool = 'go';
const version = makeSemver(info.resolvedVersion);
return (
(await cacheWindowsDir(extPath, tool, version, arch)) ||
(await tc.cacheDir(extPath, tool, version, arch))
);
}
async function installGoVersion(
info: IGoVersionInfo,
auth: string | undefined,
arch: string
): Promise<string> {
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
// Windows requires that we keep the extension (.zip) for extraction
const isWindows = os.platform() === 'win32';
const tempDir = process.env.RUNNER_TEMP || '.';
const fileName = isWindows ? path.join(tempDir, info.fileName) : undefined;
const downloadPath = await tc.downloadTool(info.downloadUrl, fileName, 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 toolCacheDir = await addExecutablesToToolCache(extPath, info, arch);
core.info(`Successfully cached go to ${toolCacheDir}`);
return toolCacheDir;
}
export async function extractGoArchive(archivePath: string): Promise<string> {
const platform = os.platform();
let extPath: string;
if (platform === 'win32') {
extPath = await tc.extractZip(archivePath);
} else {
extPath = await tc.extractTar(archivePath);
}
return extPath;
}
function isIToolRelease(obj: any): obj is tc.IToolRelease {
return (
typeof obj === 'object' &&
obj !== null &&
typeof obj.version === 'string' &&
typeof obj.stable === 'boolean' &&
Array.isArray(obj.files) &&
obj.files.every(
(file: any) =>
typeof file.filename === 'string' &&
typeof file.platform === 'string' &&
typeof file.arch === 'string' &&
typeof file.download_url === 'string'
)
);
}
export async function getManifest(
auth: string | undefined
): Promise<tc.IToolRelease[]> {
try {
const manifest = await getManifestFromRepo(auth);
if (
Array.isArray(manifest) &&
manifest.length &&
manifest.every(isIToolRelease)
) {
return manifest;
}
let errorMessage =
'An unexpected error occurred while fetching the manifest.';
if (
typeof manifest === 'object' &&
manifest !== null &&
'message' in manifest
) {
errorMessage = (manifest as {message: string}).message;
}
throw new Error(errorMessage);
} catch (err) {
core.debug('Fetching the manifest via the API failed.');
if (err instanceof Error) {
core.debug(err.message);
}
}
return await getManifestFromURL();
}
function getManifestFromRepo(
auth: string | undefined
): Promise<tc.IToolRelease[]> {
core.debug(
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
);
return tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
auth,
MANIFEST_REPO_BRANCH
);
}
async function getManifestFromURL(): Promise<tc.IToolRelease[]> {
core.debug('Falling back to fetching the manifest using raw URL.');
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
const response = await http.getJson<tc.IToolRelease[]>(MANIFEST_URL);
if (!response.result) {
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
}
return response.result;
}
export async function getInfoFromManifest(
versionSpec: string,
stable: boolean,
auth: string | undefined,
arch = os.arch(),
manifest?: tc.IToolRelease[] | undefined
): Promise<IGoVersionInfo | null> {
let info: IGoVersionInfo | null = null;
if (!manifest) {
core.debug('No manifest cached');
manifest = await getManifest(auth);
}
core.info(`matching ${versionSpec}...`);
const rel = await tc.findFromManifest(versionSpec, stable, manifest, arch);
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,
arch: string
): Promise<IGoVersionInfo | null> {
const version: IGoVersion | undefined = await findMatch(versionSpec, arch);
if (!version) {
return null;
}
const downloadUrl = `https://go.dev/dl/${version.files[0].filename}`;
return <IGoVersionInfo>{
type: 'dist',
downloadUrl: downloadUrl,
resolvedVersion: version.version,
fileName: version.files[0].filename
};
}
export async function findMatch(
versionSpec: string,
arch = os.arch()
): Promise<IGoVersion | undefined> {
const archFilter = sys.getArch(arch);
const platFilter = sys.getPlatform();
let result: IGoVersion | undefined;
let match: IGoVersion | undefined;
const dlUrl = 'https://golang.org/dl/?mode=json&include=all';
const candidates: IGoVersion[] | null = await module.exports.getVersionsDist(
dlUrl
);
if (!candidates) {
throw new Error(`golang download url did not return results`);
}
let goFile: IGoVersionFile | undefined;
for (let i = 0; i < candidates.length; i++) {
const candidate: IGoVersion = candidates[i];
const version = makeSemver(candidate.version);
core.debug(`check ${version} satisfies ${versionSpec}`);
if (semver.satisfies(version, versionSpec)) {
goFile = candidate.files.find(file => {
core.debug(
`${file.arch}===${archFilter} && ${file.os}===${platFilter}`
);
return file.arch === archFilter && file.os === platFilter;
});
if (goFile) {
core.debug(`matched ${candidate.version}`);
match = candidate;
break;
}
}
}
if (match && goFile) {
// clone since we're mutating the file list to be only the file that matches
result = <IGoVersion>Object.assign({}, match);
result.files = [goFile];
}
return result;
}
export async function getVersionsDist(
dlUrl: string
): Promise<IGoVersion[] | null> {
// this returns versions descending so latest is first
const http: httpm.HttpClient = new httpm.HttpClient('setup-go', [], {
allowRedirects: true,
maxRedirects: 3
});
return (await http.getJson<IGoVersion[]>(dlUrl)).result;
}
//
// Convert the go version syntax into semver for semver matching
// 1.13.1 => 1.13.1
// 1.13 => 1.13.0
// 1.10beta1 => 1.10.0-beta.1, 1.10rc1 => 1.10.0-rc.1
// 1.8.5beta1 => 1.8.5-beta.1, 1.8.5rc1 => 1.8.5-rc.1
export function makeSemver(version: string): string {
version = version.replace('go', '');
version = version.replace('beta', '-beta.').replace('rc', '-rc.');
const parts = version.split('-');
const semVersion = semver.coerce(parts[0])?.version;
if (!semVersion) {
throw new Error(
`The version: ${version} can't be changed to SemVer notation`
);
}
if (!parts[1]) {
return semVersion;
}
const fullVersion = semver.valid(`${semVersion}-${parts[1]}`);
if (!fullVersion) {
throw new Error(
`The version: ${version} can't be changed to SemVer notation`
);
}
return fullVersion;
}
export function parseGoVersionFile(versionFilePath: string): string {
const contents = fs.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] : '';
}
return contents.trim();
}
async function resolveStableVersionDist(versionSpec: string, arch: string) {
const archFilter = sys.getArch(arch);
const platFilter = sys.getPlatform();
const dlUrl = 'https://golang.org/dl/?mode=json&include=all';
const candidates: IGoVersion[] | null = await module.exports.getVersionsDist(
dlUrl
);
if (!candidates) {
throw new Error(`golang download url did not return results`);
}
const fixedCandidates = candidates.map(item => {
return {
...item,
version: makeSemver(item.version)
};
});
const stableVersion = await resolveStableVersionInput(
versionSpec,
archFilter,
platFilter,
fixedCandidates
);
return stableVersion;
}
export async function resolveStableVersionInput(
versionSpec: string,
arch: string,
platform: string,
manifest: tc.IToolRelease[] | IGoVersion[]
) {
const releases = manifest
.map(item => {
const index = item.files.findIndex(
item => item.arch === arch && item.filename.includes(platform)
);
if (index === -1) {
return '';
}
return item.version;
})
.filter(item => !!item && !semver.prerelease(item));
if (versionSpec === StableReleaseAlias.Stable) {
return releases[0];
} else {
const versions = releases.map(
release => `${semver.major(release)}.${semver.minor(release)}`
);
const uniqueVersions = Array.from(new Set(versions));
const oldstableVersion = releases.find(item =>
item.startsWith(uniqueVersions[1])
);
return oldstableVersion;
}
}
+162
View File
@@ -0,0 +1,162 @@
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as installer from './installer';
import * as semver from 'semver';
import path from 'path';
import {restoreCache} from './cache-restore';
import {isCacheFeatureAvailable} from './cache-utils';
import cp from 'child_process';
import fs from 'fs';
import os from 'os';
export async function run() {
try {
//
// 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.
//
const versionSpec = resolveVersionInput();
const cache = core.getBooleanInput('cache');
core.info(`Setup go version spec ${versionSpec}`);
let arch = core.getInput('architecture');
if (!arch) {
arch = os.arch();
}
if (versionSpec) {
const token = core.getInput('token');
const auth = !token ? undefined : `token ${token}`;
const checkLatest = core.getBooleanInput('check-latest');
const installDir = await installer.getGo(
versionSpec,
checkLatest,
auth,
arch
);
const installDirVersion = path.basename(path.dirname(installDir));
core.addPath(path.join(installDir, 'bin'));
core.info('Added go to the path');
const version = installer.makeSemver(installDirVersion);
// Go versions less than 1.9 require GOROOT to be set
if (semver.lt(version, '1.9.0')) {
core.info('Setting GOROOT for Go version < 1.9');
core.exportVariable('GOROOT', installDir);
}
core.info(`Successfully set up Go version ${versionSpec}`);
} else {
core.info(
'[warning]go-version input was not specified. The action will try to use pre-installed version.'
);
}
const added = await addBinToPath();
core.debug(`add bin ${added}`);
const goPath = await io.which('go');
const goVersion = (cp.execSync(`${goPath} version`) || '').toString();
if (cache && isCacheFeatureAvailable()) {
const packageManager = 'default';
const cacheDependencyPath = core.getInput('cache-dependency-path');
try {
await restoreCache(
parseGoVersion(goVersion),
packageManager,
cacheDependencyPath
);
} catch (error) {
core.warning(`Restore cache failed: ${(error as Error).message}`);
}
}
// add problem matchers
const matchersPath = path.join(__dirname, '../..', 'matchers.json');
core.info(`##[add-matcher]${matchersPath}`);
// output the version actually being used
core.info(goVersion);
core.setOutput('go-version', parseGoVersion(goVersion));
core.startGroup('go env');
const goEnv = (cp.execSync(`${goPath} env`) || '').toString();
core.info(goEnv);
core.endGroup();
} catch (error) {
core.setFailed((error as Error).message);
}
}
export async function addBinToPath(): Promise<boolean> {
let added = false;
const g = await io.which('go');
core.debug(`which go :${g}:`);
if (!g) {
core.debug('go not in the path');
return added;
}
const buf = cp.execSync('go env GOPATH');
if (buf.length > 1) {
const gp = buf.toString().trim();
core.debug(`go env GOPATH :${gp}:`);
if (!fs.existsSync(gp)) {
// some of the hosted images have go install but not profile dir
core.debug(`creating ${gp}`);
await io.mkdirP(gp);
}
const bp = path.join(gp, 'bin');
if (!fs.existsSync(bp)) {
core.debug(`creating ${bp}`);
await io.mkdirP(bp);
}
core.addPath(bp);
added = true;
}
return added;
}
export function parseGoVersion(versionString: string): string {
// get the installed version as an Action output
// based on go/src/cmd/go/internal/version/version.go:
// fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
// expecting go<version> for runtime.Version()
return versionString.split(' ')[2].slice('go'.length);
}
function resolveVersionInput(): string {
let version = core.getInput('go-version');
const versionFilePath = core.getInput('go-version-file');
if (version && versionFilePath) {
core.warning(
'Both go-version and go-version-file inputs are specified, only go-version will be used'
);
}
if (version) {
return version;
}
if (versionFilePath) {
if (!fs.existsSync(versionFilePath)) {
throw new Error(
`The specified go version file at: ${versionFilePath} does not exist`
);
}
version = installer.parseGoVersionFile(versionFilePath);
}
return version;
}
+15
View File
@@ -0,0 +1,15 @@
type SupportedPackageManagers = {
[prop: string]: PackageManagerInfo;
};
export interface PackageManagerInfo {
dependencyFilePattern: string;
cacheFolderCommandList: string[];
}
export const supportedPackageManagers: SupportedPackageManagers = {
default: {
dependencyFilePattern: 'go.sum',
cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
}
};
+3
View File
@@ -0,0 +1,3 @@
import {run} from './main';
run();
+39
View File
@@ -0,0 +1,39 @@
import os from 'os';
export function getPlatform(): string {
// darwin and linux match already
// freebsd not supported yet but future proofed.
// 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', and 'win32'
let plat: string = os.platform();
// wants 'darwin', 'freebsd', 'linux', 'windows'
if (plat === 'win32') {
plat = 'windows';
}
return plat;
}
export function getArch(arch: string): string {
// 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'.
// wants amd64, 386, arm64, armv61, ppc641e, s390x
// currently not supported by runner but future proofed mapping
switch (arch) {
case 'x64':
arch = 'amd64';
break;
// case 'ppc':
// arch = 'ppc64';
// break;
case 'x32':
arch = '386';
break;
case 'arm':
arch = 'armv6l';
break;
}
return arch;
}
+14
View File
@@ -0,0 +1,14 @@
export enum StableReleaseAlias {
Stable = 'stable',
OldStable = 'oldstable'
}
export const isSelfHosted = (): boolean =>
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' &&
(process.env['AGENT_ISSELFHOSTED'] === '1' ||
process.env['AGENT_ISSELFHOSTED'] === undefined);
/* the above is simplified from:
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === '1'
||
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === undefined
*/