mirror of
https://github.com/actions/setup-go
synced 2024-12-22 14:22:41 +00:00
Remove toolchain directories from the cache
This commit is contained in:
parent
bfd2fb341f
commit
75d73b8577
13 changed files with 893 additions and 301 deletions
40
.github/workflows/toolchain.yml
vendored
Normal file
40
.github/workflows/toolchain.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
name: Validate 'setup-go'
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
schedule:
|
||||||
|
- cron: 0 0 * * *
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
local-cache:
|
||||||
|
name: Setup local-cache version
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
|
go: [1.21]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: substitute go.mod with toolchain
|
||||||
|
run: |
|
||||||
|
cp __tests__/toolchain.go.mod go.mod
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: setup-go ${{ matrix.go }}
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
|
- name: verify go
|
||||||
|
run: __tests__/verify-go.sh ${{ matrix.go }}
|
||||||
|
shell: bash
|
|
@ -3,6 +3,8 @@ import * as cache from '@actions/cache';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as cacheUtils from '../src/cache-utils';
|
import * as cacheUtils from '../src/cache-utils';
|
||||||
import {PackageManagerInfo} from '../src/package-managers';
|
import {PackageManagerInfo} from '../src/package-managers';
|
||||||
|
import fs, {ObjectEncodingOptions, PathLike} from 'fs';
|
||||||
|
import {getToolchainDirectoriesFromCachedDirectories} from '../src/cache-utils';
|
||||||
|
|
||||||
describe('getCommandOutput', () => {
|
describe('getCommandOutput', () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
|
@ -209,3 +211,178 @@ describe('isCacheFeatureAvailable', () => {
|
||||||
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
|
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('parseGoModForToolchainVersion', () => {
|
||||||
|
const readFileSyncSpy = jest.spyOn(fs, 'readFileSync');
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null when go.mod file not exist', async () => {
|
||||||
|
//Arrange
|
||||||
|
//Act
|
||||||
|
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion(
|
||||||
|
'/tmp/non/exist/foo.bar'
|
||||||
|
);
|
||||||
|
//Assert
|
||||||
|
expect(toolchainVersion).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null when go.mod file is empty', async () => {
|
||||||
|
//Arrange
|
||||||
|
readFileSyncSpy.mockImplementation(() => '');
|
||||||
|
//Act
|
||||||
|
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
|
||||||
|
//Assert
|
||||||
|
expect(toolchainVersion).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null when go.mod file does not contain toolchain version', async () => {
|
||||||
|
//Arrange
|
||||||
|
readFileSyncSpy.mockImplementation(() =>
|
||||||
|
`
|
||||||
|
module example-mod
|
||||||
|
|
||||||
|
go 1.21.0
|
||||||
|
|
||||||
|
require golang.org/x/tools v0.13.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
)
|
||||||
|
`.replace(/^\s+/gm, '')
|
||||||
|
);
|
||||||
|
//Act
|
||||||
|
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
|
||||||
|
//Assert
|
||||||
|
expect(toolchainVersion).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return go version when go.mod file contains go version', () => {
|
||||||
|
//Arrange
|
||||||
|
readFileSyncSpy.mockImplementation(() =>
|
||||||
|
`
|
||||||
|
module example-mod
|
||||||
|
|
||||||
|
go 1.21.0
|
||||||
|
|
||||||
|
toolchain go1.21.1
|
||||||
|
|
||||||
|
require golang.org/x/tools v0.13.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
)
|
||||||
|
`.replace(/^\s+/gm, '')
|
||||||
|
);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
|
||||||
|
//Assert
|
||||||
|
expect(toolchainVersion).toBe('1.21.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return go version when go.mod file contains more than one go version', () => {
|
||||||
|
//Arrange
|
||||||
|
readFileSyncSpy.mockImplementation(() =>
|
||||||
|
`
|
||||||
|
module example-mod
|
||||||
|
|
||||||
|
go 1.21.0
|
||||||
|
|
||||||
|
toolchain go1.21.0
|
||||||
|
toolchain go1.21.1
|
||||||
|
|
||||||
|
require golang.org/x/tools v0.13.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
)
|
||||||
|
`.replace(/^\s+/gm, '')
|
||||||
|
);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
const toolchainVersion = cacheUtils.parseGoModForToolchainVersion('go.mod');
|
||||||
|
//Assert
|
||||||
|
expect(toolchainVersion).toBe('1.21.1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getToolchainDirectoriesFromCachedDirectories', () => {
|
||||||
|
const readdirSyncSpy = jest.spyOn(fs, 'readdirSync');
|
||||||
|
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
|
||||||
|
const lstatSync = jest.spyOn(fs, 'lstatSync');
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty array when cacheDirectories is empty', async () => {
|
||||||
|
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
'foo',
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
expect(toolcacheDirectories).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty array when cacheDirectories does not contain /go/pkg', async () => {
|
||||||
|
readdirSyncSpy.mockImplementation(dir =>
|
||||||
|
[`${dir}1`, `${dir}2`, `${dir}3`].map(s => {
|
||||||
|
const de = new fs.Dirent();
|
||||||
|
de.name = s;
|
||||||
|
de.isDirectory = () => true;
|
||||||
|
return de;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
'1.1.1',
|
||||||
|
['foo', 'bar']
|
||||||
|
);
|
||||||
|
expect(toolcacheDirectories).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty array when cacheDirectories does not contain toolchain@v[0-9.]+-go{goVersion}', async () => {
|
||||||
|
readdirSyncSpy.mockImplementation(dir =>
|
||||||
|
[`${dir}1`, `${dir}2`, `${dir}3`].map(s => {
|
||||||
|
const de = new fs.Dirent();
|
||||||
|
de.name = s;
|
||||||
|
de.isDirectory = () => true;
|
||||||
|
return de;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
'foo',
|
||||||
|
['foo/go/pkg/mod', 'bar']
|
||||||
|
);
|
||||||
|
expect(toolcacheDirectories).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return one entry when cacheDirectories contains toolchain@v[0-9.]+-go{goVersion} in /pkg/mod', async () => {
|
||||||
|
let seqNo = 1;
|
||||||
|
readdirSyncSpy.mockImplementation(dir =>
|
||||||
|
[`toolchain@v0.0.1-go1.1.1.arch-${seqNo++}`].map(s => {
|
||||||
|
const de = new fs.Dirent();
|
||||||
|
de.name = s;
|
||||||
|
de.isDirectory = () => true;
|
||||||
|
return de;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
existsSyncSpy.mockReturnValue(true);
|
||||||
|
// @ts-ignore - jest does not have relaxed mocks, so we ignore not-implemented methods
|
||||||
|
lstatSync.mockImplementation(() => ({isDirectory: () => true}));
|
||||||
|
|
||||||
|
const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
'1.1.1',
|
||||||
|
['/foo/go/pkg/mod', 'bar']
|
||||||
|
);
|
||||||
|
expect(toolcacheDirectories).toEqual([
|
||||||
|
'/foo/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.1.1.arch-1'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
13
__tests__/toolchain.go.mod
Normal file
13
__tests__/toolchain.go.mod
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module example-mod
|
||||||
|
|
||||||
|
go 1.21.0
|
||||||
|
|
||||||
|
toolchain go1.21.0
|
||||||
|
toolchain go1.21.1
|
||||||
|
|
||||||
|
require golang.org/x/tools v0.13.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
)
|
52
__tests__/utils.test.ts
Normal file
52
__tests__/utils.test.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import {isSelfHosted} from '../src/utils';
|
||||||
|
|
||||||
|
describe('utils', () => {
|
||||||
|
describe('isSelfHosted', () => {
|
||||||
|
let AGENT_ISSELFHOSTED: string | undefined;
|
||||||
|
let RUNNER_ENVIRONMENT: string | undefined;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
AGENT_ISSELFHOSTED = process.env['AGENT_ISSELFHOSTED'];
|
||||||
|
delete process.env['AGENT_ISSELFHOSTED'];
|
||||||
|
RUNNER_ENVIRONMENT = process.env['RUNNER_ENVIRONMENT'];
|
||||||
|
delete process.env['RUNNER_ENVIRONMENT'];
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (AGENT_ISSELFHOSTED === undefined) {
|
||||||
|
delete process.env['AGENT_ISSELFHOSTED'];
|
||||||
|
} else {
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] = AGENT_ISSELFHOSTED;
|
||||||
|
}
|
||||||
|
if (RUNNER_ENVIRONMENT === undefined) {
|
||||||
|
delete process.env['RUNNER_ENVIRONMENT'];
|
||||||
|
} else {
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] = RUNNER_ENVIRONMENT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isSelfHosted should be true if no environment variables set', () => {
|
||||||
|
expect(isSelfHosted()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isSelfHosted should be true if environment variable is not set to denote GitHub hosted', () => {
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] = 'some';
|
||||||
|
expect(isSelfHosted()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isSelfHosted should be true if environment variable set to denote Azure Pipelines self hosted', () => {
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] = '1';
|
||||||
|
expect(isSelfHosted()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isSelfHosted should be false if environment variable set to denote GitHub hosted', () => {
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] = 'github-hosted';
|
||||||
|
expect(isSelfHosted()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isSelfHosted should be false if environment variable is not set to denote Azure Pipelines self hosted', () => {
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] = 'some';
|
||||||
|
expect(isSelfHosted()).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
52
dist/cache-save/index.js
vendored
52
dist/cache-save/index.js
vendored
|
@ -58546,6 +58546,15 @@ const cachePackages = () => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
|
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const toolchainVersion = core.getState(constants_1.State.ToolchainVersion);
|
||||||
|
// toolchainVersion is always null for self-hosted runners
|
||||||
|
if (toolchainVersion) {
|
||||||
|
const toolchainDirectories = cache_utils_1.getToolchainDirectoriesFromCachedDirectories(toolchainVersion, cachePaths);
|
||||||
|
toolchainDirectories.forEach(toolchainDirectory => {
|
||||||
|
core.warning(`Toolchain version ${toolchainVersion} will be removed from cache: ${toolchainDirectory}`);
|
||||||
|
fs_1.default.rmSync(toolchainDirectory, { recursive: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
const cacheId = yield cache.saveCache(cachePaths, primaryKey);
|
const cacheId = yield cache.saveCache(cachePaths, primaryKey);
|
||||||
if (cacheId === -1) {
|
if (cacheId === -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -58594,12 +58603,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = void 0;
|
exports.getToolchainDirectoriesFromCachedDirectories = exports.parseGoModForToolchainVersion = exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = void 0;
|
||||||
const cache = __importStar(__nccwpck_require__(7799));
|
const cache = __importStar(__nccwpck_require__(7799));
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const exec = __importStar(__nccwpck_require__(1514));
|
const exec = __importStar(__nccwpck_require__(1514));
|
||||||
const package_managers_1 = __nccwpck_require__(6663);
|
const package_managers_1 = __nccwpck_require__(6663);
|
||||||
|
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||||
const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () {
|
const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true });
|
let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true });
|
||||||
if (exitCode) {
|
if (exitCode) {
|
||||||
|
@ -58654,6 +58667,42 @@ function isCacheFeatureAvailable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
|
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
|
||||||
|
function parseGoModForToolchainVersion(goModPath) {
|
||||||
|
try {
|
||||||
|
const goMod = fs_1.default.readFileSync(goModPath, 'utf8');
|
||||||
|
const matches = Array.from(goMod.matchAll(/^toolchain\s+go(\S+)/gm));
|
||||||
|
if (matches && matches.length > 0) {
|
||||||
|
return matches[matches.length - 1][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message && error.message.startsWith('ENOENT')) {
|
||||||
|
core.warning(`go.mod file not found at ${goModPath}, can't parse toolchain version`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
exports.parseGoModForToolchainVersion = parseGoModForToolchainVersion;
|
||||||
|
function isDirent(item) {
|
||||||
|
return item instanceof fs_1.default.Dirent;
|
||||||
|
}
|
||||||
|
function getToolchainDirectoriesFromCachedDirectories(goVersion, cacheDirectories) {
|
||||||
|
const re = new RegExp(`^toolchain@v[0-9.]+-go${goVersion}\\.`);
|
||||||
|
return (cacheDirectories
|
||||||
|
// This line should be replaced with separating the cache directory from build artefact directory
|
||||||
|
// see PoC PR: https://github.com/actions/setup-go/pull/426
|
||||||
|
// Till then, the workaround is expected to work in most cases, and it won't cause any harm
|
||||||
|
.filter(dir => dir.endsWith('/pkg/mod'))
|
||||||
|
.map(dir => `${dir}/golang.org`)
|
||||||
|
.flatMap(dir => fs_1.default
|
||||||
|
.readdirSync(dir)
|
||||||
|
.map(subdir => (isDirent(subdir) ? subdir.name : dir))
|
||||||
|
.filter(subdir => re.test(subdir))
|
||||||
|
.map(subdir => `${dir}/${subdir}`)));
|
||||||
|
}
|
||||||
|
exports.getToolchainDirectoriesFromCachedDirectories = getToolchainDirectoriesFromCachedDirectories;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
@ -58669,6 +58718,7 @@ var State;
|
||||||
(function (State) {
|
(function (State) {
|
||||||
State["CachePrimaryKey"] = "CACHE_KEY";
|
State["CachePrimaryKey"] = "CACHE_KEY";
|
||||||
State["CacheMatchedKey"] = "CACHE_RESULT";
|
State["CacheMatchedKey"] = "CACHE_RESULT";
|
||||||
|
State["ToolchainVersion"] = "TOOLCACHE_VERSION";
|
||||||
})(State = exports.State || (exports.State = {}));
|
})(State = exports.State || (exports.State = {}));
|
||||||
var Outputs;
|
var Outputs;
|
||||||
(function (Outputs) {
|
(function (Outputs) {
|
||||||
|
|
67
dist/setup/index.js
vendored
67
dist/setup/index.js
vendored
|
@ -61191,6 +61191,7 @@ const path_1 = __importDefault(__nccwpck_require__(1017));
|
||||||
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||||
const constants_1 = __nccwpck_require__(9042);
|
const constants_1 = __nccwpck_require__(9042);
|
||||||
const cache_utils_1 = __nccwpck_require__(1678);
|
const cache_utils_1 = __nccwpck_require__(1678);
|
||||||
|
const utils_1 = __nccwpck_require__(1314);
|
||||||
const restoreCache = (versionSpec, packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
|
const restoreCache = (versionSpec, packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager);
|
const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager);
|
||||||
const platform = process.env.RUNNER_OS;
|
const platform = process.env.RUNNER_OS;
|
||||||
|
@ -61198,6 +61199,15 @@ const restoreCache = (versionSpec, packageManager, cacheDependencyPath) => __awa
|
||||||
const dependencyFilePath = cacheDependencyPath
|
const dependencyFilePath = cacheDependencyPath
|
||||||
? cacheDependencyPath
|
? cacheDependencyPath
|
||||||
: findDependencyFile(packageManagerInfo);
|
: findDependencyFile(packageManagerInfo);
|
||||||
|
// In order to do not duplicate evaluation of dependency paths, we get
|
||||||
|
// toolchain Version here and pass to the saveCache via the state
|
||||||
|
if (!utils_1.isSelfHosted()) {
|
||||||
|
const toolchainVersion = cacheDependencyPath && path_1.default.basename(cacheDependencyPath) === 'go.mod'
|
||||||
|
? cache_utils_1.parseGoModForToolchainVersion(cacheDependencyPath)
|
||||||
|
: null;
|
||||||
|
toolchainVersion &&
|
||||||
|
core.saveState(constants_1.State.ToolchainVersion, toolchainVersion);
|
||||||
|
}
|
||||||
const fileHash = yield glob.hashFiles(dependencyFilePath);
|
const fileHash = yield glob.hashFiles(dependencyFilePath);
|
||||||
if (!fileHash) {
|
if (!fileHash) {
|
||||||
throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
|
throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
|
||||||
|
@ -61264,12 +61274,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = void 0;
|
exports.getToolchainDirectoriesFromCachedDirectories = exports.parseGoModForToolchainVersion = exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = void 0;
|
||||||
const cache = __importStar(__nccwpck_require__(7799));
|
const cache = __importStar(__nccwpck_require__(7799));
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const exec = __importStar(__nccwpck_require__(1514));
|
const exec = __importStar(__nccwpck_require__(1514));
|
||||||
const package_managers_1 = __nccwpck_require__(6663);
|
const package_managers_1 = __nccwpck_require__(6663);
|
||||||
|
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||||
const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () {
|
const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true });
|
let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true });
|
||||||
if (exitCode) {
|
if (exitCode) {
|
||||||
|
@ -61324,6 +61338,42 @@ function isCacheFeatureAvailable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
|
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
|
||||||
|
function parseGoModForToolchainVersion(goModPath) {
|
||||||
|
try {
|
||||||
|
const goMod = fs_1.default.readFileSync(goModPath, 'utf8');
|
||||||
|
const matches = Array.from(goMod.matchAll(/^toolchain\s+go(\S+)/gm));
|
||||||
|
if (matches && matches.length > 0) {
|
||||||
|
return matches[matches.length - 1][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message && error.message.startsWith('ENOENT')) {
|
||||||
|
core.warning(`go.mod file not found at ${goModPath}, can't parse toolchain version`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
exports.parseGoModForToolchainVersion = parseGoModForToolchainVersion;
|
||||||
|
function isDirent(item) {
|
||||||
|
return item instanceof fs_1.default.Dirent;
|
||||||
|
}
|
||||||
|
function getToolchainDirectoriesFromCachedDirectories(goVersion, cacheDirectories) {
|
||||||
|
const re = new RegExp(`^toolchain@v[0-9.]+-go${goVersion}\\.`);
|
||||||
|
return (cacheDirectories
|
||||||
|
// This line should be replaced with separating the cache directory from build artefact directory
|
||||||
|
// see PoC PR: https://github.com/actions/setup-go/pull/426
|
||||||
|
// Till then, the workaround is expected to work in most cases, and it won't cause any harm
|
||||||
|
.filter(dir => dir.endsWith('/pkg/mod'))
|
||||||
|
.map(dir => `${dir}/golang.org`)
|
||||||
|
.flatMap(dir => fs_1.default
|
||||||
|
.readdirSync(dir)
|
||||||
|
.map(subdir => (isDirent(subdir) ? subdir.name : dir))
|
||||||
|
.filter(subdir => re.test(subdir))
|
||||||
|
.map(subdir => `${dir}/${subdir}`)));
|
||||||
|
}
|
||||||
|
exports.getToolchainDirectoriesFromCachedDirectories = getToolchainDirectoriesFromCachedDirectories;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
@ -61339,6 +61389,7 @@ var State;
|
||||||
(function (State) {
|
(function (State) {
|
||||||
State["CachePrimaryKey"] = "CACHE_KEY";
|
State["CachePrimaryKey"] = "CACHE_KEY";
|
||||||
State["CacheMatchedKey"] = "CACHE_RESULT";
|
State["CacheMatchedKey"] = "CACHE_RESULT";
|
||||||
|
State["ToolchainVersion"] = "TOOLCACHE_VERSION";
|
||||||
})(State = exports.State || (exports.State = {}));
|
})(State = exports.State || (exports.State = {}));
|
||||||
var Outputs;
|
var Outputs;
|
||||||
(function (Outputs) {
|
(function (Outputs) {
|
||||||
|
@ -61495,8 +61546,7 @@ function cacheWindowsDir(extPath, tool, version, arch) {
|
||||||
if (os_1.default.platform() !== 'win32')
|
if (os_1.default.platform() !== 'win32')
|
||||||
return false;
|
return false;
|
||||||
// make sure the action runs in the hosted environment
|
// make sure the action runs in the hosted environment
|
||||||
if (process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' &&
|
if (utils_1.isSelfHosted())
|
||||||
process.env['AGENT_ISSELFHOSTED'] === '1')
|
|
||||||
return false;
|
return false;
|
||||||
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
||||||
if (!defaultToolCacheRoot)
|
if (!defaultToolCacheRoot)
|
||||||
|
@ -61975,12 +62025,21 @@ exports.getArch = getArch;
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.StableReleaseAlias = void 0;
|
exports.isSelfHosted = exports.StableReleaseAlias = void 0;
|
||||||
var StableReleaseAlias;
|
var StableReleaseAlias;
|
||||||
(function (StableReleaseAlias) {
|
(function (StableReleaseAlias) {
|
||||||
StableReleaseAlias["Stable"] = "stable";
|
StableReleaseAlias["Stable"] = "stable";
|
||||||
StableReleaseAlias["OldStable"] = "oldstable";
|
StableReleaseAlias["OldStable"] = "oldstable";
|
||||||
})(StableReleaseAlias = exports.StableReleaseAlias || (exports.StableReleaseAlias = {}));
|
})(StableReleaseAlias = exports.StableReleaseAlias || (exports.StableReleaseAlias = {}));
|
||||||
|
const isSelfHosted = () => process.env['AGENT_ISSELFHOSTED'] === '1' ||
|
||||||
|
(process.env['AGENT_ISSELFHOSTED'] === undefined &&
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted');
|
||||||
|
exports.isSelfHosted = isSelfHosted;
|
||||||
|
/* the above is simplified from:
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] === undefined && process.env['AGENT_ISSELFHOSTED'] === '1'
|
||||||
|
||
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] === undefined && process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted'
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
684
package-lock.json
generated
684
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,12 @@ import fs from 'fs';
|
||||||
|
|
||||||
import {State, Outputs} from './constants';
|
import {State, Outputs} from './constants';
|
||||||
import {PackageManagerInfo} from './package-managers';
|
import {PackageManagerInfo} from './package-managers';
|
||||||
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
|
import {
|
||||||
|
getCacheDirectoryPath,
|
||||||
|
getPackageManagerInfo,
|
||||||
|
parseGoModForToolchainVersion
|
||||||
|
} from './cache-utils';
|
||||||
|
import {isSelfHosted} from './utils';
|
||||||
|
|
||||||
export const restoreCache = async (
|
export const restoreCache = async (
|
||||||
versionSpec: string,
|
versionSpec: string,
|
||||||
|
@ -21,6 +26,18 @@ export const restoreCache = async (
|
||||||
const dependencyFilePath = cacheDependencyPath
|
const dependencyFilePath = cacheDependencyPath
|
||||||
? cacheDependencyPath
|
? cacheDependencyPath
|
||||||
: findDependencyFile(packageManagerInfo);
|
: findDependencyFile(packageManagerInfo);
|
||||||
|
|
||||||
|
// In order to do not duplicate evaluation of dependency paths, we get
|
||||||
|
// toolchain Version here and pass to the saveCache via the state
|
||||||
|
if (!isSelfHosted()) {
|
||||||
|
const toolchainVersion =
|
||||||
|
cacheDependencyPath && path.basename(cacheDependencyPath) === 'go.mod'
|
||||||
|
? parseGoModForToolchainVersion(cacheDependencyPath)
|
||||||
|
: null;
|
||||||
|
toolchainVersion &&
|
||||||
|
core.saveState(State.ToolchainVersion, toolchainVersion);
|
||||||
|
}
|
||||||
|
|
||||||
const fileHash = await glob.hashFiles(dependencyFilePath);
|
const fileHash = await glob.hashFiles(dependencyFilePath);
|
||||||
|
|
||||||
if (!fileHash) {
|
if (!fileHash) {
|
||||||
|
|
|
@ -2,7 +2,11 @@ import * as core from '@actions/core';
|
||||||
import * as cache from '@actions/cache';
|
import * as cache from '@actions/cache';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {State} from './constants';
|
import {State} from './constants';
|
||||||
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
|
import {
|
||||||
|
getCacheDirectoryPath,
|
||||||
|
getPackageManagerInfo,
|
||||||
|
getToolchainDirectoriesFromCachedDirectories
|
||||||
|
} from './cache-utils';
|
||||||
|
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
// 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
|
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||||
|
@ -73,6 +77,21 @@ const cachePackages = async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toolchainVersion = core.getState(State.ToolchainVersion);
|
||||||
|
// toolchainVersion is always null for self-hosted runners
|
||||||
|
if (toolchainVersion) {
|
||||||
|
const toolchainDirectories = getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
toolchainVersion,
|
||||||
|
cachePaths
|
||||||
|
);
|
||||||
|
toolchainDirectories.forEach(toolchainDirectory => {
|
||||||
|
core.warning(
|
||||||
|
`Toolchain version ${toolchainVersion} will be removed from cache: ${toolchainDirectory}`
|
||||||
|
);
|
||||||
|
fs.rmSync(toolchainDirectory, {recursive: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const cacheId = await cache.saveCache(cachePaths, primaryKey);
|
const cacheId = await cache.saveCache(cachePaths, primaryKey);
|
||||||
if (cacheId === -1) {
|
if (cacheId === -1) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as cache from '@actions/cache';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as exec from '@actions/exec';
|
import * as exec from '@actions/exec';
|
||||||
import {supportedPackageManagers, PackageManagerInfo} from './package-managers';
|
import {supportedPackageManagers, PackageManagerInfo} from './package-managers';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
export const getCommandOutput = async (toolCommand: string) => {
|
export const getCommandOutput = async (toolCommand: string) => {
|
||||||
let {stdout, stderr, exitCode} = await exec.getExecOutput(
|
let {stdout, stderr, exitCode} = await exec.getExecOutput(
|
||||||
|
@ -83,3 +84,50 @@ export function isCacheFeatureAvailable(): boolean {
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseGoModForToolchainVersion(
|
||||||
|
goModPath: string
|
||||||
|
): string | null {
|
||||||
|
try {
|
||||||
|
const goMod = fs.readFileSync(goModPath, 'utf8');
|
||||||
|
const matches = Array.from(goMod.matchAll(/^toolchain\s+go(\S+)/gm));
|
||||||
|
if (matches && matches.length > 0) {
|
||||||
|
return matches[matches.length - 1][1];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.message && error.message.startsWith('ENOENT')) {
|
||||||
|
core.warning(
|
||||||
|
`go.mod file not found at ${goModPath}, can't parse toolchain version`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDirent(item: fs.Dirent | string): item is fs.Dirent {
|
||||||
|
return item instanceof fs.Dirent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getToolchainDirectoriesFromCachedDirectories(
|
||||||
|
goVersion: string,
|
||||||
|
cacheDirectories: string[]
|
||||||
|
): string[] {
|
||||||
|
const re = new RegExp(`^toolchain@v[0-9.]+-go${goVersion}\\.`);
|
||||||
|
return (
|
||||||
|
cacheDirectories
|
||||||
|
// This line should be replaced with separating the cache directory from build artefact directory
|
||||||
|
// see PoC PR: https://github.com/actions/setup-go/pull/426
|
||||||
|
// Till then, the workaround is expected to work in most cases, and it won't cause any harm
|
||||||
|
.filter(dir => dir.endsWith('/pkg/mod'))
|
||||||
|
.map(dir => `${dir}/golang.org`)
|
||||||
|
.flatMap(dir =>
|
||||||
|
fs
|
||||||
|
.readdirSync(dir)
|
||||||
|
.map(subdir => (isDirent(subdir) ? subdir.name : dir))
|
||||||
|
.filter(subdir => re.test(subdir))
|
||||||
|
.map(subdir => `${dir}/${subdir}`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export enum State {
|
export enum State {
|
||||||
CachePrimaryKey = 'CACHE_KEY',
|
CachePrimaryKey = 'CACHE_KEY',
|
||||||
CacheMatchedKey = 'CACHE_RESULT'
|
CacheMatchedKey = 'CACHE_RESULT',
|
||||||
|
ToolchainVersion = 'TOOLCACHE_VERSION'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Outputs {
|
export enum Outputs {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import * as httpm from '@actions/http-client';
|
||||||
import * as sys from './system';
|
import * as sys from './system';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import {StableReleaseAlias} from './utils';
|
import {isSelfHosted, StableReleaseAlias} from './utils';
|
||||||
|
|
||||||
type InstallationType = 'dist' | 'manifest';
|
type InstallationType = 'dist' | 'manifest';
|
||||||
|
|
||||||
|
@ -175,11 +175,7 @@ async function cacheWindowsDir(
|
||||||
if (os.platform() !== 'win32') return false;
|
if (os.platform() !== 'win32') return false;
|
||||||
|
|
||||||
// make sure the action runs in the hosted environment
|
// make sure the action runs in the hosted environment
|
||||||
if (
|
if (isSelfHosted()) return false;
|
||||||
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' &&
|
|
||||||
process.env['AGENT_ISSELFHOSTED'] === '1'
|
|
||||||
)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
|
||||||
if (!defaultToolCacheRoot) return false;
|
if (!defaultToolCacheRoot) return false;
|
||||||
|
|
10
src/utils.ts
10
src/utils.ts
|
@ -2,3 +2,13 @@ export enum StableReleaseAlias {
|
||||||
Stable = 'stable',
|
Stable = 'stable',
|
||||||
OldStable = 'oldstable'
|
OldStable = 'oldstable'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isSelfHosted = (): boolean =>
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] === '1' ||
|
||||||
|
(process.env['AGENT_ISSELFHOSTED'] === undefined &&
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted');
|
||||||
|
/* the above is simplified from:
|
||||||
|
process.env['RUNNER_ENVIRONMENT'] === undefined && process.env['AGENT_ISSELFHOSTED'] === '1'
|
||||||
|
||
|
||||||
|
process.env['AGENT_ISSELFHOSTED'] === undefined && process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted'
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in a new issue