Merge pull request #3 from IvanZosimov/compiler-caching

Added caching for compiler's dependencies
This commit is contained in:
IvanZosimov 2022-04-20 17:53:23 +02:00 committed by GitHub
commit 3a3f8d0d3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 833 additions and 802 deletions

View file

@ -23,8 +23,8 @@ describe('restoreCache', () => {
beforeEach(() => { beforeEach(() => {
getCacheDirectoryPathSpy.mockImplementation( getCacheDirectoryPathSpy.mockImplementation(
(PackageManager: PackageManagerInfo) => { (PackageManager: PackageManagerInfo) => {
return new Promise<string>(resolve => { return new Promise<string[]>(resolve => {
resolve('cache_directory_path'); resolve(['cache_directory_path', 'cache_directory_path']);
}); });
} }
); );

View file

@ -48,7 +48,7 @@ describe('getPackageManagerInfo', () => {
const packageManagerName = 'default'; const packageManagerName = 'default';
const expectedResult = { const expectedResult = {
dependencyFilePattern: 'go.sum', dependencyFilePattern: 'go.sum',
getCacheFolderCommand: 'go env GOMODCACHE' cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
}; };
//Act + Assert //Act + Assert
@ -74,10 +74,10 @@ describe('getCacheDirectoryPath', () => {
const validPackageManager: PackageManagerInfo = { const validPackageManager: PackageManagerInfo = {
dependencyFilePattern: 'go.sum', dependencyFilePattern: 'go.sum',
getCacheFolderCommand: 'go env GOMODCACHE' cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
}; };
it('should return path to the cache folder which specified package manager uses', async () => { it('should return path to the cache folders which specified package manager uses', async () => {
//Arrange //Arrange
getExecOutputSpy.mockImplementation((commandLine: string) => { getExecOutputSpy.mockImplementation((commandLine: string) => {
return new Promise<exec.ExecOutput>(resolve => { return new Promise<exec.ExecOutput>(resolve => {
@ -85,7 +85,7 @@ describe('getCacheDirectoryPath', () => {
}); });
}); });
const expectedResult = 'path/to/cache/folder'; const expectedResult = ['path/to/cache/folder', 'path/to/cache/folder'];
//Act + Assert //Act + Assert
return cacheUtils return cacheUtils

View file

@ -3983,83 +3983,84 @@ exports.debug = debug; // for test
/***/ (function(__unusedmodule, exports, __webpack_require__) { /***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict"; "use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
})); }));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v }); Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) { }) : function(o, v) {
o["default"] = v; o["default"] = v;
}); });
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod; if (mod && mod.__esModule) return mod;
var result = {}; var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) { return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next()); step((generator = generator.apply(thisArg, _arguments || [])).next());
}); });
}; };
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.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = void 0;
const cache = __importStar(__webpack_require__(692)); const cache = __importStar(__webpack_require__(692));
const core = __importStar(__webpack_require__(470)); const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986)); const exec = __importStar(__webpack_require__(986));
const package_managers_1 = __webpack_require__(813); const package_managers_1 = __webpack_require__(813);
exports.getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () { exports.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) {
stderr = !stderr.trim() stderr = !stderr.trim()
? `The '${toolCommand}' command failed with exit code: ${exitCode}` ? `The '${toolCommand}' command failed with exit code: ${exitCode}`
: stderr; : stderr;
throw new Error(stderr); throw new Error(stderr);
} }
return stdout.trim(); return stdout.trim();
}); });
exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () {
if (!package_managers_1.supportedPackageManagers[packageManager]) { if (!package_managers_1.supportedPackageManagers[packageManager]) {
throw new Error(`It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.`); throw new Error(`It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.`);
} }
const obtainedPackageManager = package_managers_1.supportedPackageManagers[packageManager]; const obtainedPackageManager = package_managers_1.supportedPackageManagers[packageManager];
return obtainedPackageManager; return obtainedPackageManager;
}); });
exports.getCacheDirectoryPath = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () { exports.getCacheDirectoryPath = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
const stdout = yield exports.getCommandOutput(packageManagerInfo.getCacheFolderCommand); let pathList = yield Promise.all(packageManagerInfo.cacheFolderCommandList.map((command) => __awaiter(void 0, void 0, void 0, function* () { return exports.getCommandOutput(command); })));
if (!stdout) { const emptyPaths = pathList.filter(item => !item);
throw new Error(`Could not get cache folder path.`); if (emptyPaths.length) {
} throw new Error(`Could not get cache folder paths.`);
return stdout; }
}); return pathList;
function isGhes() { });
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com'); function isGhes() {
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
} return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
exports.isGhes = isGhes; }
function isCacheFeatureAvailable() { exports.isGhes = isGhes;
if (!cache.isFeatureAvailable()) { function isCacheFeatureAvailable() {
if (isGhes()) { if (!cache.isFeatureAvailable()) {
throw new Error('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.'); if (isGhes()) {
} throw new Error('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.');
else { }
core.warning('The runner was not able to contact the cache service. Caching will be skipped'); else {
} core.warning('The runner was not able to contact the cache service. Caching will be skipped');
return false; }
} return false;
return true; }
} return true;
exports.isCacheFeatureAvailable = isCacheFeatureAvailable; }
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
/***/ }), /***/ }),
@ -4807,18 +4808,18 @@ exports.default = _default;
/***/ (function(__unusedmodule, exports) { /***/ (function(__unusedmodule, exports) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.Outputs = exports.State = void 0; exports.Outputs = exports.State = void 0;
var State; var State;
(function (State) { (function (State) {
State["CachePrimaryKey"] = "CACHE_KEY"; State["CachePrimaryKey"] = "CACHE_KEY";
State["CacheMatchedKey"] = "CACHE_RESULT"; State["CacheMatchedKey"] = "CACHE_RESULT";
})(State = exports.State || (exports.State = {})); })(State = exports.State || (exports.State = {}));
var Outputs; var Outputs;
(function (Outputs) { (function (Outputs) {
Outputs["CacheHit"] = "cache-hit"; Outputs["CacheHit"] = "cache-hit";
})(Outputs = exports.Outputs || (exports.Outputs = {})); })(Outputs = exports.Outputs || (exports.Outputs = {}));
/***/ }), /***/ }),
@ -49135,97 +49136,106 @@ module.exports = require("stream");
/***/ (function(__unusedmodule, exports, __webpack_require__) { /***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict"; "use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
})); }));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v }); Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) { }) : function(o, v) {
o["default"] = v; o["default"] = v;
}); });
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod; if (mod && mod.__esModule) return mod;
var result = {}; var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod); __setModuleDefault(result, mod);
return result; return result;
}; };
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) { return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next()); step((generator = generator.apply(thisArg, _arguments || [])).next());
}); });
}; };
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0; exports.logWarning = exports.run = void 0;
const core = __importStar(__webpack_require__(470)); const core = __importStar(__webpack_require__(470));
const cache = __importStar(__webpack_require__(692)); const cache = __importStar(__webpack_require__(692));
const fs_1 = __importDefault(__webpack_require__(747)); const fs_1 = __importDefault(__webpack_require__(747));
const constants_1 = __webpack_require__(196); const constants_1 = __webpack_require__(196);
const cache_utils_1 = __webpack_require__(143); const cache_utils_1 = __webpack_require__(143);
// 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
// throw an uncaught exception. Instead of failing this action, just warn. // throw an uncaught exception. Instead of failing this action, just warn.
process.on('uncaughtException', e => { process.on('uncaughtException', e => {
const warningPrefix = '[warning]'; const warningPrefix = '[warning]';
core.info(`${warningPrefix}${e.message}`); core.info(`${warningPrefix}${e.message}`);
}); });
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
yield cachePackages(); yield cachePackages();
} }
catch (error) { catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }
}); });
} }
exports.run = run; exports.run = run;
const cachePackages = () => __awaiter(void 0, void 0, void 0, function* () { const cachePackages = () => __awaiter(void 0, void 0, void 0, function* () {
const cacheInput = core.getBooleanInput('cache'); const cacheInput = core.getBooleanInput('cache');
if (!cacheInput) { if (!cacheInput) {
return; return;
} }
const packageManager = 'default'; const packageManager = 'default';
const state = core.getState(constants_1.State.CacheMatchedKey); const state = core.getState(constants_1.State.CacheMatchedKey);
const primaryKey = core.getState(constants_1.State.CachePrimaryKey); const primaryKey = core.getState(constants_1.State.CachePrimaryKey);
const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager); const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager);
const cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo); const cachePaths = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo);
if (!fs_1.default.existsSync(cachePath)) { const nonExistingPaths = cachePaths.filter(cachePath => !fs_1.default.existsSync(cachePath));
throw new Error(`Cache folder path is retrieved but doesn't exist on disk: ${cachePath}`); if (nonExistingPaths.length === cachePaths.length) {
} throw new Error(`No cache folders exist on disk`);
if (primaryKey === state) { }
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`); if (nonExistingPaths.length) {
return; logWarning(`Cache folder path is retrieved but doesn't exist on disk: ${nonExistingPaths.join(', ')}`);
} }
try { if (primaryKey === state) {
yield cache.saveCache([cachePath], primaryKey); core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
core.info(`Cache saved with the key: ${primaryKey}`); return;
} }
catch (error) { try {
if (error.name === cache.ValidationError.name) { yield cache.saveCache(cachePaths, primaryKey);
throw error; core.info(`Cache saved with the key: ${primaryKey}`);
} }
else if (error.name === cache.ReserveCacheError.name) { catch (error) {
core.info(error.message); if (error.name === cache.ValidationError.name) {
} throw error;
else { }
core.warning(`${error.message}`); else if (error.name === cache.ReserveCacheError.name) {
} core.info(error.message);
} }
}); else {
run(); core.warning(`${error.message}`);
}
}
});
function logWarning(message) {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}
exports.logWarning = logWarning;
run();
/***/ }), /***/ }),
@ -49309,15 +49319,15 @@ run();
/***/ (function(__unusedmodule, exports) { /***/ (function(__unusedmodule, exports) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.supportedPackageManagers = void 0; exports.supportedPackageManagers = void 0;
exports.supportedPackageManagers = { exports.supportedPackageManagers = {
default: { default: {
dependencyFilePattern: 'go.sum', dependencyFilePattern: 'go.sum',
getCacheFolderCommand: 'go env GOMODCACHE' cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
} }
}; };
/***/ }), /***/ }),

1187
dist/setup/index.js vendored

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@ export const restoreCache = async (
const platform = process.env.RUNNER_OS; const platform = process.env.RUNNER_OS;
const versionSpec = core.getInput('go-version'); const versionSpec = core.getInput('go-version');
const cachePath = await getCacheDirectoryPath(packageManagerInfo); const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
const dependencyFilePath = cacheDependencyPath const dependencyFilePath = cacheDependencyPath
? cacheDependencyPath ? cacheDependencyPath
@ -34,7 +34,7 @@ export const restoreCache = async (
core.saveState(State.CachePrimaryKey, primaryKey); core.saveState(State.CachePrimaryKey, primaryKey);
const cacheKey = await cache.restoreCache([cachePath], primaryKey); const cacheKey = await cache.restoreCache(cachePaths, primaryKey);
core.setOutput('cache-hit', Boolean(cacheKey)); core.setOutput('cache-hit', Boolean(cacheKey));
if (!cacheKey) { if (!cacheKey) {

View file

@ -33,11 +33,21 @@ const cachePackages = async () => {
const packageManagerInfo = await getPackageManagerInfo(packageManager); const packageManagerInfo = await getPackageManagerInfo(packageManager);
const cachePath = await getCacheDirectoryPath(packageManagerInfo); const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
if (!fs.existsSync(cachePath)) { const nonExistingPaths = cachePaths.filter(
throw new Error( cachePath => !fs.existsSync(cachePath)
`Cache folder path is retrieved but doesn't exist on disk: ${cachePath}` );
if (nonExistingPaths.length === cachePaths.length) {
throw new Error(`No cache folders exist on disk`);
}
if (nonExistingPaths.length) {
logWarning(
`Cache folder path is retrieved but doesn't exist on disk: ${nonExistingPaths.join(
', '
)}`
); );
} }
@ -49,7 +59,7 @@ const cachePackages = async () => {
} }
try { try {
await cache.saveCache([cachePath], primaryKey); await cache.saveCache(cachePaths, primaryKey);
core.info(`Cache saved with the key: ${primaryKey}`); core.info(`Cache saved with the key: ${primaryKey}`);
} catch (error) { } catch (error) {
if (error.name === cache.ValidationError.name) { if (error.name === cache.ValidationError.name) {
@ -62,4 +72,9 @@ const cachePackages = async () => {
} }
}; };
export function logWarning(message: string): void {
const warningPrefix = '[warning]';
core.info(`${warningPrefix}${message}`);
}
run(); run();

View file

@ -1,6 +1,7 @@
import * as cache from '@actions/cache'; 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 path from 'path';
import {supportedPackageManagers, PackageManagerInfo} from './package-managers'; import {supportedPackageManagers, PackageManagerInfo} from './package-managers';
export const getCommandOutput = async (toolCommand: string) => { export const getCommandOutput = async (toolCommand: string) => {
@ -34,15 +35,19 @@ export const getPackageManagerInfo = async (packageManager: string) => {
export const getCacheDirectoryPath = async ( export const getCacheDirectoryPath = async (
packageManagerInfo: PackageManagerInfo packageManagerInfo: PackageManagerInfo
) => { ) => {
const stdout = await getCommandOutput( let pathList = await Promise.all(
packageManagerInfo.getCacheFolderCommand packageManagerInfo.cacheFolderCommandList.map(async command =>
getCommandOutput(command)
)
); );
if (!stdout) { const emptyPaths = pathList.filter(item => !item);
throw new Error(`Could not get cache folder path.`);
if (emptyPaths.length) {
throw new Error(`Could not get cache folder paths.`);
} }
return stdout; return pathList;
}; };
export function isGhes(): boolean { export function isGhes(): boolean {

View file

@ -4,12 +4,12 @@ type SupportedPackageManagers = {
export interface PackageManagerInfo { export interface PackageManagerInfo {
dependencyFilePattern: string; dependencyFilePattern: string;
getCacheFolderCommand: string; cacheFolderCommandList: string[];
} }
export const supportedPackageManagers: SupportedPackageManagers = { export const supportedPackageManagers: SupportedPackageManagers = {
default: { default: {
dependencyFilePattern: 'go.sum', dependencyFilePattern: 'go.sum',
getCacheFolderCommand: 'go env GOMODCACHE' cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
} }
}; };