Skip to content

Commit

Permalink
POC
Browse files Browse the repository at this point in the history
  • Loading branch information
dsame committed May 8, 2023
1 parent 085ca9a commit c4d05fd
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 64 deletions.
9 changes: 8 additions & 1 deletion __tests__/cache-restore.test.ts
Expand Up @@ -45,13 +45,15 @@ describe('cache-restore', () => {
}
}

let inputs = {} as any;
let saveStateSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;
let getCommandOutputSpy: jest.SpyInstance;
let restoreCacheSpy: jest.SpyInstance;
let hashFilesSpy: jest.SpyInstance;
let inSpy: jest.SpyInstance;

beforeEach(() => {
// core
Expand All @@ -67,6 +69,10 @@ describe('cache-restore', () => {
saveStateSpy = jest.spyOn(core, 'saveState');
saveStateSpy.mockImplementation(() => undefined);

inputs = {};
inSpy = jest.spyOn(core, 'getInput');
inSpy.mockImplementation(name => inputs[name]);

// glob
hashFilesSpy = jest.spyOn(glob, 'hashFiles');
hashFilesSpy.mockImplementation((pattern: string) => {
Expand Down Expand Up @@ -131,11 +137,12 @@ describe('cache-restore', () => {
return findCacheFolder(command);
}
});
inputs['node-version'] = 'vABC';

await restoreCache(packageManager);
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: node-cache-${platform}-${packageManager}-v2-${fileHash}`
`Cache restored from key: node-cache-${platform}-${packageManager}-v2-vABC-${fileHash}`
);
expect(infoSpy).not.toHaveBeenCalledWith(
`${packageManager} cache is not found`
Expand Down
26 changes: 25 additions & 1 deletion dist/cache-save/index.js
Expand Up @@ -59248,7 +59248,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getPackageManagerVersion = exports.getPackageManagerCommandOutput = exports.getPackageManagerWorkingDir = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
exports.isYarn3OfflineCache = exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getPackageManagerVersion = exports.getPackageManagerCommandOutput = exports.getPackageManagerWorkingDir = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
const core = __importStar(__nccwpck_require__(2186));
const exec = __importStar(__nccwpck_require__(1514));
const cache = __importStar(__nccwpck_require__(7799));
Expand Down Expand Up @@ -59356,6 +59356,30 @@ function isCacheFeatureAvailable() {
return false;
}
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
// a hack for further possible compatibility issues and a syntax sugar
const getYarn3ProjectDirectoryPath = () => exports.getCacheDirectoryPath(exports.supportedPackageManagers.yarn2, 'yarn');
// see https://yarnpkg.com/features/offline-cache
let isYarn3OfflineCacheMemoized = null;
const isYarn3OfflineCache = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
if (isYarn3OfflineCacheMemoized !== null)
return isYarn3OfflineCacheMemoized;
isYarn3OfflineCacheMemoized = false;
if (packageManagerInfo !== exports.supportedPackageManagers.yarn2)
return isYarn3OfflineCacheMemoized;
const yarnDir = yield getYarn3ProjectDirectoryPath();
const workDir = yarnDir || process.env.GITHUB_WORKSPACE;
const yarnCacheFile = path_1.default.join(workDir, '.yarn', 'cache');
if (fs_1.default.existsSync(yarnCacheFile) && fs_1.default.lstatSync(yarnCacheFile).isDirectory())
return isYarn3OfflineCacheMemoized;
const yarnRcPath = path_1.default.join(workDir, '.yarnrc.yml');
if (!(fs_1.default.existsSync(yarnRcPath) && fs_1.default.lstatSync(yarnRcPath).isFile()))
return isYarn3OfflineCacheMemoized;
const yarnRc = fs_1.default.readFileSync(path_1.default.join(workDir, '.yarnrc.yml')).toString();
const globalCache = yarnRc.match(/^enableGlobalCache:\s*true/m);
isYarn3OfflineCacheMemoized = !globalCache;
return isYarn3OfflineCacheMemoized;
});
exports.isYarn3OfflineCache = isYarn3OfflineCache;


/***/ }),
Expand Down
89 changes: 64 additions & 25 deletions dist/setup/index.js
Expand Up @@ -71138,12 +71138,14 @@ const path_1 = __importDefault(__nccwpck_require__(1017));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const constants_1 = __nccwpck_require__(9042);
const cache_utils_1 = __nccwpck_require__(1678);
const util_1 = __nccwpck_require__(2629);
const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager);
if (!packageManagerInfo) {
throw new Error(`Caching for '${packageManager}' is not supported`);
}
const platform = process.env.RUNNER_OS;
const nodeVersion = util_1.resolveVersionInput();
const cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo, packageManager);
const lockFilePath = cacheDependencyPath
? cacheDependencyPath
Expand All @@ -71152,10 +71154,13 @@ const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0,
if (!fileHash) {
throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
}
const primaryKey = `node-cache-${platform}-${packageManager}-v2-${fileHash}`;
const keyPrefix = `node-cache-${platform}-${packageManager}-v2-${nodeVersion}`;
const primaryKey = `${keyPrefix}-${fileHash}`;
core.debug(`primary key is ${primaryKey}`);
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
const cacheKey = yield cache.restoreCache([cachePath], primaryKey);
const cacheKey = (yield cache_utils_1.isYarn3OfflineCache(packageManagerInfo))
? yield cache.restoreCache([cachePath], primaryKey, [keyPrefix])
: yield cache.restoreCache([cachePath], primaryKey);
core.setOutput('cache-hit', Boolean(cacheKey));
if (!cacheKey) {
core.info(`${packageManager} cache is not found`);
Expand Down Expand Up @@ -71216,7 +71221,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getPackageManagerVersion = exports.getPackageManagerCommandOutput = exports.getPackageManagerWorkingDir = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
exports.isYarn3OfflineCache = exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getPackageManagerVersion = exports.getPackageManagerCommandOutput = exports.getPackageManagerWorkingDir = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
const core = __importStar(__nccwpck_require__(2186));
const exec = __importStar(__nccwpck_require__(1514));
const cache = __importStar(__nccwpck_require__(7799));
Expand Down Expand Up @@ -71324,6 +71329,30 @@ function isCacheFeatureAvailable() {
return false;
}
exports.isCacheFeatureAvailable = isCacheFeatureAvailable;
// a hack for further possible compatibility issues and a syntax sugar
const getYarn3ProjectDirectoryPath = () => exports.getCacheDirectoryPath(exports.supportedPackageManagers.yarn2, 'yarn');
// see https://yarnpkg.com/features/offline-cache
let isYarn3OfflineCacheMemoized = null;
const isYarn3OfflineCache = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
if (isYarn3OfflineCacheMemoized !== null)
return isYarn3OfflineCacheMemoized;
isYarn3OfflineCacheMemoized = false;
if (packageManagerInfo !== exports.supportedPackageManagers.yarn2)
return isYarn3OfflineCacheMemoized;
const yarnDir = yield getYarn3ProjectDirectoryPath();
const workDir = yarnDir || process.env.GITHUB_WORKSPACE;
const yarnCacheFile = path_1.default.join(workDir, '.yarn', 'cache');
if (fs_1.default.existsSync(yarnCacheFile) && fs_1.default.lstatSync(yarnCacheFile).isDirectory())
return isYarn3OfflineCacheMemoized;
const yarnRcPath = path_1.default.join(workDir, '.yarnrc.yml');
if (!(fs_1.default.existsSync(yarnRcPath) && fs_1.default.lstatSync(yarnRcPath).isFile()))
return isYarn3OfflineCacheMemoized;
const yarnRc = fs_1.default.readFileSync(path_1.default.join(workDir, '.yarnrc.yml')).toString();
const globalCache = yarnRc.match(/^enableGlobalCache:\s*true/m);
isYarn3OfflineCacheMemoized = !globalCache;
return isYarn3OfflineCacheMemoized;
});
exports.isYarn3OfflineCache = isYarn3OfflineCache;


/***/ }),
Expand Down Expand Up @@ -72064,7 +72093,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
const core = __importStar(__nccwpck_require__(2186));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const os_1 = __importDefault(__nccwpck_require__(2037));
const auth = __importStar(__nccwpck_require__(7573));
const path = __importStar(__nccwpck_require__(1017));
Expand All @@ -72079,7 +72107,7 @@ function run() {
// Version is optional. If supplied, install / use from the tool cache
// If not supplied then task is still used to setup proxy, auth, etc...
//
const version = resolveVersionInput();
const version = util_1.resolveVersionInput();
let arch = core.getInput('architecture');
const cache = core.getInput('cache');
// if architecture supplied but node-version is not
Expand Down Expand Up @@ -72126,25 +72154,6 @@ function run() {
});
}
exports.run = run;
function resolveVersionInput() {
let version = core.getInput('node-version');
const versionFileInput = core.getInput('node-version-file');
if (version && versionFileInput) {
core.warning('Both node-version and node-version-file inputs are specified, only node-version will be used');
}
if (version) {
return version;
}
if (versionFileInput) {
const versionFilePath = path.join(process.env.GITHUB_WORKSPACE, versionFileInput);
if (!fs_1.default.existsSync(versionFilePath)) {
throw new Error(`The specified node version file at: ${versionFilePath} does not exist`);
}
version = util_1.parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8'));
core.info(`Resolved ${versionFileInput} as ${version}`);
}
return version;
}


/***/ }),
Expand Down Expand Up @@ -72182,10 +72191,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
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 }));
exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0;
exports.resolveVersionInput = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0;
const core = __importStar(__nccwpck_require__(2186));
const exec = __importStar(__nccwpck_require__(1514));
const path_1 = __importDefault(__nccwpck_require__(1017));
const fs_1 = __importDefault(__nccwpck_require__(7147));
function parseNodeVersionFile(contents) {
var _a, _b, _c;
let nodeVersion;
Expand Down Expand Up @@ -72245,6 +72259,31 @@ function getToolVersion(tool, options) {
}
});
}
let resolvedVersionInputMemoized = null;
function resolveVersionInput() {
if (resolvedVersionInputMemoized !== null)
return resolvedVersionInputMemoized;
let version = core.getInput('node-version');
const versionFileInput = core.getInput('node-version-file');
if (version && versionFileInput) {
core.warning('Both node-version and node-version-file inputs are specified, only node-version will be used');
}
if (version) {
resolvedVersionInputMemoized = version;
return version;
}
if (versionFileInput) {
const versionFilePath = path_1.default.join(process.env.GITHUB_WORKSPACE, versionFileInput);
if (!fs_1.default.existsSync(versionFilePath)) {
throw new Error(`The specified node version file at: ${versionFilePath} does not exist`);
}
version = parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8'));
core.info(`Resolved ${versionFileInput} as ${version}`);
}
resolvedVersionInputMemoized = version;
return version;
}
exports.resolveVersionInput = resolveVersionInput;


/***/ }),
Expand Down
11 changes: 9 additions & 2 deletions src/cache-restore.ts
Expand Up @@ -8,8 +8,10 @@ import {State} from './constants';
import {
getCacheDirectoryPath,
getPackageManagerInfo,
isYarn3OfflineCache,
PackageManagerInfo
} from './cache-utils';
import {resolveVersionInput} from './util';

export const restoreCache = async (
packageManager: string,
Expand All @@ -20,6 +22,7 @@ export const restoreCache = async (
throw new Error(`Caching for '${packageManager}' is not supported`);
}
const platform = process.env.RUNNER_OS;
const nodeVersion = resolveVersionInput();

const cachePath = await getCacheDirectoryPath(
packageManagerInfo,
Expand All @@ -36,12 +39,16 @@ export const restoreCache = async (
);
}

const primaryKey = `node-cache-${platform}-${packageManager}-v2-${fileHash}`;
const keyPrefix = `node-cache-${platform}-${packageManager}-v2-${nodeVersion}`;
const primaryKey = `${keyPrefix}-${fileHash}`;
core.debug(`primary key is ${primaryKey}`);

core.saveState(State.CachePrimaryKey, primaryKey);

const cacheKey = await cache.restoreCache([cachePath], primaryKey);
const cacheKey = (await isYarn3OfflineCache(packageManagerInfo))
? await cache.restoreCache([cachePath], primaryKey, [keyPrefix])
: await cache.restoreCache([cachePath], primaryKey);

core.setOutput('cache-hit', Boolean(cacheKey));

if (!cacheKey) {
Expand Down
35 changes: 35 additions & 0 deletions src/cache-utils.ts
Expand Up @@ -150,3 +150,38 @@ export function isCacheFeatureAvailable(): boolean {

return false;
}

// a hack for further possible compatibility issues and a syntax sugar
const getYarn3ProjectDirectoryPath = () =>
getCacheDirectoryPath(supportedPackageManagers.yarn2, 'yarn');

// see https://yarnpkg.com/features/offline-cache
let isYarn3OfflineCacheMemoized: boolean | null = null;
export const isYarn3OfflineCache = async (
packageManagerInfo: PackageManagerInfo
): Promise<boolean> => {
if (isYarn3OfflineCacheMemoized !== null) return isYarn3OfflineCacheMemoized;

isYarn3OfflineCacheMemoized = false;

if (packageManagerInfo !== supportedPackageManagers.yarn2)
return isYarn3OfflineCacheMemoized;

const yarnDir = await getYarn3ProjectDirectoryPath();

const workDir = yarnDir || process.env.GITHUB_WORKSPACE!;

const yarnCacheFile = path.join(workDir, '.yarn', 'cache');
if (fs.existsSync(yarnCacheFile) && fs.lstatSync(yarnCacheFile).isDirectory())
return isYarn3OfflineCacheMemoized;

const yarnRcPath = path.join(workDir, '.yarnrc.yml');
if (!(fs.existsSync(yarnRcPath) && fs.lstatSync(yarnRcPath).isFile()))
return isYarn3OfflineCacheMemoized;

const yarnRc = fs.readFileSync(path.join(workDir, '.yarnrc.yml')).toString();
const globalCache = yarnRc.match(/^enableGlobalCache:\s*true/m);

isYarn3OfflineCacheMemoized = !globalCache;
return isYarn3OfflineCacheMemoized;
};
40 changes: 5 additions & 35 deletions src/main.ts
Expand Up @@ -8,7 +8,11 @@ import * as path from 'path';
import {restoreCache} from './cache-restore';
import {isCacheFeatureAvailable} from './cache-utils';
import {getNodejsDistribution} from './distributions/installer-factory';
import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util';
import {
parseNodeVersionFile,

Check warning on line 12 in src/main.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (ubuntu-latest)

'parseNodeVersionFile' is defined but never used

Check warning on line 12 in src/main.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (windows-latest)

'parseNodeVersionFile' is defined but never used

Check warning on line 12 in src/main.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (macos-latest)

'parseNodeVersionFile' is defined but never used
printEnvDetailsAndSetOutput,
resolveVersionInput
} from './util';

export async function run() {
try {
Expand Down Expand Up @@ -76,37 +80,3 @@ export async function run() {
core.setFailed(err.message);
}
}

function resolveVersionInput(): string {
let version = core.getInput('node-version');
const versionFileInput = core.getInput('node-version-file');

if (version && versionFileInput) {
core.warning(
'Both node-version and node-version-file inputs are specified, only node-version will be used'
);
}

if (version) {
return version;
}

if (versionFileInput) {
const versionFilePath = path.join(
process.env.GITHUB_WORKSPACE!,
versionFileInput
);

if (!fs.existsSync(versionFilePath)) {
throw new Error(
`The specified node version file at: ${versionFilePath} does not exist`
);
}

version = parseNodeVersionFile(fs.readFileSync(versionFilePath, 'utf8'));

core.info(`Resolved ${versionFileInput} as ${version}`);
}

return version;
}

0 comments on commit c4d05fd

Please sign in to comment.