refactor, introduce cacheDependencyPathToProjectsDirectories

it is necessary for the next PR related yarn optimization
This commit is contained in:
Sergey Dolin 2023-05-19 19:57:43 +02:00
parent 914a8e9bcc
commit 5de08eab2b
5 changed files with 293 additions and 81 deletions

View file

@ -118,9 +118,14 @@ describe('run', () => {
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2); expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith( expect(debugSpy).toHaveBeenCalledWith(
'yarn path is /some/random/path/yarn1 (derived from cache-dependency-path: "")' 'Project directory "." derived from cache-dependency-path: ""'
);
expect(debugSpy).toHaveBeenCalledWith(
'Consumed yarn version is 1.2.3 (working dir: ".")'
);
expect(debugSpy).toHaveBeenCalledWith(
'yarn\'s cache folder "/some/random/path/yarn1" configured for the directory "."'
); );
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.` `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
); );
@ -140,9 +145,14 @@ describe('run', () => {
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2); expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith( expect(debugSpy).toHaveBeenCalledWith(
'yarn path is /some/random/path/yarn2 (derived from cache-dependency-path: "")' 'Project directory "." derived from cache-dependency-path: ""'
);
expect(debugSpy).toHaveBeenCalledWith(
'Consumed yarn version is 2.2.3 (working dir: ".")'
);
expect(debugSpy).toHaveBeenCalledWith(
'yarn\'s cache folder "/some/random/path/yarn2" configured for the directory "."'
); );
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.` `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
); );
@ -159,7 +169,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`); expect(debugSpy).toHaveBeenCalledWith(
`npm's cache folder "${commonPath}/npm" configured for the root directory`
);
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
); );
@ -176,7 +188,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`); expect(debugSpy).toHaveBeenCalledWith(
`pnpm's cache folder "${commonPath}/pnpm" configured for the root directory`
);
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
); );
@ -204,9 +218,14 @@ describe('run', () => {
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2); expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith( expect(debugSpy).toHaveBeenCalledWith(
'yarn path is /some/random/path/yarn1 (derived from cache-dependency-path: "")' 'Project directory "." derived from cache-dependency-path: ""'
);
expect(debugSpy).toHaveBeenCalledWith(
'Consumed yarn version is 1.2.3 (working dir: ".")'
);
expect(debugSpy).toHaveBeenCalledWith(
'yarn\'s cache folder "/some/random/path/yarn1" configured for the directory "."'
); );
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.` `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
); );
@ -236,9 +255,14 @@ describe('run', () => {
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2); expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith( expect(debugSpy).toHaveBeenCalledWith(
'yarn path is /some/random/path/yarn2 (derived from cache-dependency-path: "")' 'Project directory "." derived from cache-dependency-path: ""'
);
expect(debugSpy).toHaveBeenCalledWith(
'Consumed yarn version is 2.2.3 (working dir: ".")'
);
expect(debugSpy).toHaveBeenCalledWith(
'yarn\'s cache folder "/some/random/path/yarn2" configured for the directory "."'
); );
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.` `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
); );
@ -265,7 +289,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`); expect(debugSpy).toHaveBeenCalledWith(
`npm's cache folder "${commonPath}/npm" configured for the root directory`
);
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
); );
@ -292,7 +318,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`); expect(debugSpy).toHaveBeenCalledWith(
`pnpm's cache folder "${commonPath}/pnpm" configured for the root directory`
);
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
); );
@ -322,7 +350,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`); expect(debugSpy).toHaveBeenCalledWith(
`npm's cache folder "${commonPath}/npm" configured for the root directory`
);
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
); );
@ -352,7 +382,9 @@ describe('run', () => {
expect(getInputSpy).toHaveBeenCalled(); expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2); expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1); expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`); expect(debugSpy).toHaveBeenCalledWith(
`npm's cache folder "${commonPath}/npm" configured for the root directory`
);
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.` `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
); );

View file

@ -7,7 +7,8 @@ import {
isCacheFeatureAvailable, isCacheFeatureAvailable,
supportedPackageManagers, supportedPackageManagers,
getCommandOutput, getCommandOutput,
expandCacheDependencyPath expandCacheDependencyPath,
expandedPatternsMemoized
} from '../src/cache-utils'; } from '../src/cache-utils';
import fs from 'fs'; import fs from 'fs';
import * as cacheUtils from '../src/cache-utils'; import * as cacheUtils from '../src/cache-utils';
@ -104,6 +105,10 @@ describe('cache-utils', () => {
(pattern: string): Promise<Globber> => (pattern: string): Promise<Globber> =>
MockGlobber.create(['/foo', '/bar']) MockGlobber.create(['/foo', '/bar'])
); );
Object.keys(expandedPatternsMemoized).forEach(
key => delete expandedPatternsMemoized[key]
);
}); });
afterEach(() => { afterEach(() => {
@ -194,13 +199,36 @@ two
[supportedPackageManagers.yarn, '/dir/file.lock'], [supportedPackageManagers.yarn, '/dir/file.lock'],
[supportedPackageManagers.yarn, '/**/file.lock'] [supportedPackageManagers.yarn, '/**/file.lock']
])( ])(
'getCacheDirectoriesPaths should return empty array of folder in case of error', 'getCacheDirectoriesPaths should throw for getCommandOutput returning empty',
async (packageManagerInfo, cacheDependency) => { async (packageManagerInfo, cacheDependency) => {
getCommandOutputSpy.mockImplementation((command: string) => getCommandOutputSpy.mockImplementation((command: string) =>
// return empty string to indicate getCacheFolderPath failed // return empty string to indicate getCacheFolderPath failed
// --version still works // --version still works
command.includes('version') ? '1.' : '' command.includes('version') ? '1.' : ''
); );
await expect(
cacheUtils.getCacheDirectoriesPaths(
packageManagerInfo,
cacheDependency
)
).rejects.toThrow(); //'Could not get cache folder path for /dir');
}
);
it.each([
[supportedPackageManagers.npm, ''],
[supportedPackageManagers.npm, '/dir/file.lock'],
[supportedPackageManagers.npm, '/**/file.lock'],
[supportedPackageManagers.pnpm, ''],
[supportedPackageManagers.pnpm, '/dir/file.lock'],
[supportedPackageManagers.pnpm, '/**/file.lock'],
[supportedPackageManagers.yarn, ''],
[supportedPackageManagers.yarn, '/dir/file.lock'],
[supportedPackageManagers.yarn, '/**/file.lock']
])(
'getCacheDirectoriesPaths should throw in case of having not directories',
async (packageManagerInfo, cacheDependency) => {
lstatSpy.mockImplementation(arg => ({ lstatSpy.mockImplementation(arg => ({
isDirectory: () => false isDirectory: () => false
})); }));
@ -248,9 +276,8 @@ two
} }
); );
// TODO: by design - glob is not expected to return duplicates so 3 patterns do not collapse to 2
it.each(['1.1.1', '2.2.2'])( it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return 3 dirs with globbed cacheDependency expanding to duplicates', 'getCacheDirectoriesPaths yarn v%s should return 2 dirs with globbed cacheDependency expanding to duplicates',
async version => { async version => {
let dirNo = 1; let dirNo = 1;
getCommandOutputSpy.mockImplementation((command: string) => getCommandOutputSpy.mockImplementation((command: string) =>
@ -269,11 +296,7 @@ two
supportedPackageManagers.yarn, supportedPackageManagers.yarn,
'/tmp/**/file' '/tmp/**/file'
); );
expect(dirs).toEqual([ expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
`file_${version}_1`,
`file_${version}_2`,
`file_${version}_3`
]);
} }
); );

View file

@ -60434,7 +60434,7 @@ 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.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoriesPaths = exports.expandCacheDependencyPath = exports.getPackageManagerInfo = exports.getCommandOutputGuarded = exports.getCommandOutput = exports.supportedPackageManagers = exports.yarn2GetCacheFolderCommand = exports.yarn1GetCacheFolderCommand = exports.pnpmGetCacheFolderCommand = exports.npmGetCacheFolderCommand = void 0; exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoriesPaths = exports.expandCacheDependencyPath = exports.expandedPatternsMemoized = exports.getPackageManagerInfo = exports.getCommandOutputGuarded = exports.getCommandOutput = exports.supportedPackageManagers = exports.yarn2GetCacheFolderCommand = exports.yarn1GetCacheFolderCommand = exports.pnpmGetCacheFolderCommand = exports.npmGetCacheFolderCommand = void 0;
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 cache = __importStar(__nccwpck_require__(7799)); const cache = __importStar(__nccwpck_require__(7799));
@ -60462,7 +60462,7 @@ exports.supportedPackageManagers = {
lockFilePatterns: ['yarn.lock'], lockFilePatterns: ['yarn.lock'],
getCacheFolderPath: (projectDir) => __awaiter(void 0, void 0, void 0, function* () { getCacheFolderPath: (projectDir) => __awaiter(void 0, void 0, void 0, function* () {
const yarnVersion = yield exports.getCommandOutputGuarded(`yarn --version`, 'Could not retrieve version of yarn', projectDir); const yarnVersion = yield exports.getCommandOutputGuarded(`yarn --version`, 'Could not retrieve version of yarn', projectDir);
core.debug(`Consumed yarn version is ${yarnVersion}`); core.debug(`Consumed yarn version is ${yarnVersion} (working dir: "${projectDir}")`);
const stdOut = yarnVersion.startsWith('1.') const stdOut = yarnVersion.startsWith('1.')
? yield exports.getCommandOutput(exports.yarn1GetCacheFolderCommand, projectDir) ? yield exports.getCommandOutput(exports.yarn1GetCacheFolderCommand, projectDir)
: yield exports.getCommandOutput(exports.yarn2GetCacheFolderCommand, projectDir); : yield exports.getCommandOutput(exports.yarn2GetCacheFolderCommand, projectDir);
@ -60507,10 +60507,27 @@ const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void
} }
}); });
exports.getPackageManagerInfo = getPackageManagerInfo; exports.getPackageManagerInfo = getPackageManagerInfo;
exports.expandedPatternsMemoized = {};
/**
* Wrapper around `glob.create(pattern).glob()` with the memoization
* @param pattern is expected to be a globed path
* @return list of files or directories expanded from glob
*/
const globPatternToArray = (pattern) => __awaiter(void 0, void 0, void 0, function* () { const globPatternToArray = (pattern) => __awaiter(void 0, void 0, void 0, function* () {
const memoized = exports.expandedPatternsMemoized[pattern];
if (memoized)
return Promise.resolve(memoized);
const globber = yield glob.create(pattern); const globber = yield glob.create(pattern);
return globber.glob(); const expanded = yield globber.glob();
exports.expandedPatternsMemoized[pattern] = expanded;
return expanded;
}); });
/**
* Expands (converts) the string input `cache-dependency-path` to list of files' paths
* First it breaks the input by new lines and then expand glob patterns if any
* @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
* @return list of files on which the cache depends
*/
const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const multilinePaths = cacheDependencyPath const multilinePaths = cacheDependencyPath
.split(/\r?\n/) .split(/\r?\n/)
@ -60521,26 +60538,55 @@ const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, voi
return expandedPaths.length === 0 ? [''] : expandedPaths.flat(); return expandedPaths.length === 0 ? [''] : expandedPaths.flat();
}); });
exports.expandCacheDependencyPath = expandCacheDependencyPath; exports.expandCacheDependencyPath = expandCacheDependencyPath;
const cacheDependencyPathToCacheFolderPath = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { /**
const cacheDependencyPathDirectory = path_1.default.dirname(cacheDependencyPath); * Converts dependency file to the directory it resides in and ensures the directory exists
const cacheFolderPath = fs_1.default.existsSync(cacheDependencyPathDirectory) && * @param cacheDependencyPath - file name
fs_1.default.lstatSync(cacheDependencyPathDirectory).isDirectory() * @return either directory containing file or null
? yield packageManagerInfo.getCacheFolderPath(cacheDependencyPathDirectory) */
: yield packageManagerInfo.getCacheFolderPath(); const cacheDependencyPathToProjectDirectory = (cacheDependencyPath) => {
core.debug(`${packageManagerInfo.name} path is ${cacheFolderPath} (derived from cache-dependency-path: "${cacheDependencyPath}")`); const projectDirectory = path_1.default.dirname(cacheDependencyPath);
if (fs_1.default.existsSync(projectDirectory) &&
fs_1.default.lstatSync(projectDirectory).isDirectory()) {
core.debug(`Project directory "${projectDirectory}" derived from cache-dependency-path: "${cacheDependencyPath}"`);
return projectDirectory;
}
else {
core.debug(`No project directory found for cache-dependency-path: "${cacheDependencyPath}", will be skipped`);
return null;
}
};
/**
* Expands (converts) the string input `cache-dependency-path` to list of directories that
* may be project roots
* @param cacheDependencyPath
* @return list of directories and possible
*/
const cacheDependencyPathToProjectsDirectories = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const cacheDependenciesPaths = yield exports.expandCacheDependencyPath(cacheDependencyPath);
const existingDirectories = cacheDependenciesPaths
.map(cacheDependencyPath => cacheDependencyPathToProjectDirectory(cacheDependencyPath))
.filter(path => path !== null);
if (existingDirectories.length === 0)
throw Error('No existing directories found containing `cache-dependency-path`="${cacheDependencyPath}"');
// uniq
return existingDirectories.filter((cachePath, i, result) => cachePath != null && result.indexOf(cachePath) === i);
});
const projectDirectoryToCacheFolderPath = (packageManagerInfo, projectDirectory) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath(projectDirectory);
core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`);
return cacheFolderPath; return cacheFolderPath;
}); });
const cacheDependenciesPathsToCacheFoldersPaths = (packageManagerInfo, cacheDependenciesPaths) => __awaiter(void 0, void 0, void 0, function* () { const projectDirectoriesToCacheFoldersPaths = (packageManagerInfo, projectDirectories) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFoldersPaths = yield Promise.all(cacheDependenciesPaths.map(cacheDependencyPath => cacheDependencyPathToCacheFolderPath(packageManagerInfo, cacheDependencyPath))); const cacheFoldersPaths = yield Promise.all(projectDirectories.map(projectDirectory => projectDirectoryToCacheFolderPath(packageManagerInfo, projectDirectory)));
return cacheFoldersPaths.filter((cachePath, i, result) => result.indexOf(cachePath) === i); return cacheFoldersPaths.filter((cachePath, i, result) => result.indexOf(cachePath) === i);
}); });
const cacheDependencyPathToCacheFoldersPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const cacheDependencyPathToCacheFoldersPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const cacheDependenciesPaths = yield exports.expandCacheDependencyPath(cacheDependencyPath); const projectDirectories = yield cacheDependencyPathToProjectsDirectories(cacheDependencyPath);
return cacheDependenciesPathsToCacheFoldersPaths(packageManagerInfo, cacheDependenciesPaths); return projectDirectoriesToCacheFoldersPaths(packageManagerInfo, projectDirectories);
}); });
const cacheFoldersPathsForRoot = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () { const cacheFoldersPathsForRoot = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath(); const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath();
core.debug(`${packageManagerInfo.name} path is ${cacheFolderPath}`); core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the root directory`);
return [cacheFolderPath]; return [cacheFolderPath];
}); });
const getCacheDirectoriesPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const getCacheDirectoriesPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {

76
dist/setup/index.js vendored
View file

@ -71216,7 +71216,7 @@ 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.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoriesPaths = exports.expandCacheDependencyPath = exports.getPackageManagerInfo = exports.getCommandOutputGuarded = exports.getCommandOutput = exports.supportedPackageManagers = exports.yarn2GetCacheFolderCommand = exports.yarn1GetCacheFolderCommand = exports.pnpmGetCacheFolderCommand = exports.npmGetCacheFolderCommand = void 0; exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoriesPaths = exports.expandCacheDependencyPath = exports.expandedPatternsMemoized = exports.getPackageManagerInfo = exports.getCommandOutputGuarded = exports.getCommandOutput = exports.supportedPackageManagers = exports.yarn2GetCacheFolderCommand = exports.yarn1GetCacheFolderCommand = exports.pnpmGetCacheFolderCommand = exports.npmGetCacheFolderCommand = void 0;
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 cache = __importStar(__nccwpck_require__(7799)); const cache = __importStar(__nccwpck_require__(7799));
@ -71244,7 +71244,7 @@ exports.supportedPackageManagers = {
lockFilePatterns: ['yarn.lock'], lockFilePatterns: ['yarn.lock'],
getCacheFolderPath: (projectDir) => __awaiter(void 0, void 0, void 0, function* () { getCacheFolderPath: (projectDir) => __awaiter(void 0, void 0, void 0, function* () {
const yarnVersion = yield exports.getCommandOutputGuarded(`yarn --version`, 'Could not retrieve version of yarn', projectDir); const yarnVersion = yield exports.getCommandOutputGuarded(`yarn --version`, 'Could not retrieve version of yarn', projectDir);
core.debug(`Consumed yarn version is ${yarnVersion}`); core.debug(`Consumed yarn version is ${yarnVersion} (working dir: "${projectDir}")`);
const stdOut = yarnVersion.startsWith('1.') const stdOut = yarnVersion.startsWith('1.')
? yield exports.getCommandOutput(exports.yarn1GetCacheFolderCommand, projectDir) ? yield exports.getCommandOutput(exports.yarn1GetCacheFolderCommand, projectDir)
: yield exports.getCommandOutput(exports.yarn2GetCacheFolderCommand, projectDir); : yield exports.getCommandOutput(exports.yarn2GetCacheFolderCommand, projectDir);
@ -71289,10 +71289,27 @@ const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void
} }
}); });
exports.getPackageManagerInfo = getPackageManagerInfo; exports.getPackageManagerInfo = getPackageManagerInfo;
exports.expandedPatternsMemoized = {};
/**
* Wrapper around `glob.create(pattern).glob()` with the memoization
* @param pattern is expected to be a globed path
* @return list of files or directories expanded from glob
*/
const globPatternToArray = (pattern) => __awaiter(void 0, void 0, void 0, function* () { const globPatternToArray = (pattern) => __awaiter(void 0, void 0, void 0, function* () {
const memoized = exports.expandedPatternsMemoized[pattern];
if (memoized)
return Promise.resolve(memoized);
const globber = yield glob.create(pattern); const globber = yield glob.create(pattern);
return globber.glob(); const expanded = yield globber.glob();
exports.expandedPatternsMemoized[pattern] = expanded;
return expanded;
}); });
/**
* Expands (converts) the string input `cache-dependency-path` to list of files' paths
* First it breaks the input by new lines and then expand glob patterns if any
* @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
* @return list of files on which the cache depends
*/
const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const multilinePaths = cacheDependencyPath const multilinePaths = cacheDependencyPath
.split(/\r?\n/) .split(/\r?\n/)
@ -71303,26 +71320,55 @@ const expandCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, voi
return expandedPaths.length === 0 ? [''] : expandedPaths.flat(); return expandedPaths.length === 0 ? [''] : expandedPaths.flat();
}); });
exports.expandCacheDependencyPath = expandCacheDependencyPath; exports.expandCacheDependencyPath = expandCacheDependencyPath;
const cacheDependencyPathToCacheFolderPath = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { /**
const cacheDependencyPathDirectory = path_1.default.dirname(cacheDependencyPath); * Converts dependency file to the directory it resides in and ensures the directory exists
const cacheFolderPath = fs_1.default.existsSync(cacheDependencyPathDirectory) && * @param cacheDependencyPath - file name
fs_1.default.lstatSync(cacheDependencyPathDirectory).isDirectory() * @return either directory containing file or null
? yield packageManagerInfo.getCacheFolderPath(cacheDependencyPathDirectory) */
: yield packageManagerInfo.getCacheFolderPath(); const cacheDependencyPathToProjectDirectory = (cacheDependencyPath) => {
core.debug(`${packageManagerInfo.name} path is ${cacheFolderPath} (derived from cache-dependency-path: "${cacheDependencyPath}")`); const projectDirectory = path_1.default.dirname(cacheDependencyPath);
if (fs_1.default.existsSync(projectDirectory) &&
fs_1.default.lstatSync(projectDirectory).isDirectory()) {
core.debug(`Project directory "${projectDirectory}" derived from cache-dependency-path: "${cacheDependencyPath}"`);
return projectDirectory;
}
else {
core.debug(`No project directory found for cache-dependency-path: "${cacheDependencyPath}", will be skipped`);
return null;
}
};
/**
* Expands (converts) the string input `cache-dependency-path` to list of directories that
* may be project roots
* @param cacheDependencyPath
* @return list of directories and possible
*/
const cacheDependencyPathToProjectsDirectories = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const cacheDependenciesPaths = yield exports.expandCacheDependencyPath(cacheDependencyPath);
const existingDirectories = cacheDependenciesPaths
.map(cacheDependencyPath => cacheDependencyPathToProjectDirectory(cacheDependencyPath))
.filter(path => path !== null);
if (existingDirectories.length === 0)
throw Error('No existing directories found containing `cache-dependency-path`="${cacheDependencyPath}"');
// uniq
return existingDirectories.filter((cachePath, i, result) => cachePath != null && result.indexOf(cachePath) === i);
});
const projectDirectoryToCacheFolderPath = (packageManagerInfo, projectDirectory) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath(projectDirectory);
core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`);
return cacheFolderPath; return cacheFolderPath;
}); });
const cacheDependenciesPathsToCacheFoldersPaths = (packageManagerInfo, cacheDependenciesPaths) => __awaiter(void 0, void 0, void 0, function* () { const projectDirectoriesToCacheFoldersPaths = (packageManagerInfo, projectDirectories) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFoldersPaths = yield Promise.all(cacheDependenciesPaths.map(cacheDependencyPath => cacheDependencyPathToCacheFolderPath(packageManagerInfo, cacheDependencyPath))); const cacheFoldersPaths = yield Promise.all(projectDirectories.map(projectDirectory => projectDirectoryToCacheFolderPath(packageManagerInfo, projectDirectory)));
return cacheFoldersPaths.filter((cachePath, i, result) => result.indexOf(cachePath) === i); return cacheFoldersPaths.filter((cachePath, i, result) => result.indexOf(cachePath) === i);
}); });
const cacheDependencyPathToCacheFoldersPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const cacheDependencyPathToCacheFoldersPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
const cacheDependenciesPaths = yield exports.expandCacheDependencyPath(cacheDependencyPath); const projectDirectories = yield cacheDependencyPathToProjectsDirectories(cacheDependencyPath);
return cacheDependenciesPathsToCacheFoldersPaths(packageManagerInfo, cacheDependenciesPaths); return projectDirectoriesToCacheFoldersPaths(packageManagerInfo, projectDirectories);
}); });
const cacheFoldersPathsForRoot = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () { const cacheFoldersPathsForRoot = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath(); const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath();
core.debug(`${packageManagerInfo.name} path is ${cacheFolderPath}`); core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the root directory`);
return [cacheFolderPath]; return [cacheFolderPath];
}); });
const getCacheDirectoriesPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const getCacheDirectoriesPaths = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {

View file

@ -51,7 +51,9 @@ export const supportedPackageManagers: SupportedPackageManagers = {
projectDir projectDir
); );
core.debug(`Consumed yarn version is ${yarnVersion}`); core.debug(
`Consumed yarn version is ${yarnVersion} (working dir: "${projectDir}")`
);
const stdOut = yarnVersion.startsWith('1.') const stdOut = yarnVersion.startsWith('1.')
? await getCommandOutput(yarn1GetCacheFolderCommand, projectDir) ? await getCommandOutput(yarn1GetCacheFolderCommand, projectDir)
@ -110,12 +112,27 @@ export const getPackageManagerInfo = async (packageManager: string) => {
return null; return null;
} }
}; };
export const expandedPatternsMemoized: Record<string, string[]> = {};
/**
* Wrapper around `glob.create(pattern).glob()` with the memoization
* @param pattern is expected to be a globed path
* @return list of files or directories expanded from glob
*/
const globPatternToArray = async (pattern: string): Promise<string[]> => { const globPatternToArray = async (pattern: string): Promise<string[]> => {
const memoized = expandedPatternsMemoized[pattern];
if (memoized) return Promise.resolve(memoized);
const globber = await glob.create(pattern); const globber = await glob.create(pattern);
return globber.glob(); const expanded = await globber.glob();
expandedPatternsMemoized[pattern] = expanded;
return expanded;
}; };
/**
* Expands (converts) the string input `cache-dependency-path` to list of files' paths
* First it breaks the input by new lines and then expand glob patterns if any
* @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
* @return list of files on which the cache depends
*/
export const expandCacheDependencyPath = async ( export const expandCacheDependencyPath = async (
cacheDependencyPath: string cacheDependencyPath: string
): Promise<string[]> => { ): Promise<string[]> => {
@ -130,52 +147,98 @@ export const expandCacheDependencyPath = async (
return expandedPaths.length === 0 ? [''] : expandedPaths.flat(); return expandedPaths.length === 0 ? [''] : expandedPaths.flat();
}; };
const cacheDependencyPathToCacheFolderPath = async ( /**
packageManagerInfo: PackageManagerInfo, * Converts dependency file to the directory it resides in and ensures the directory exists
* @param cacheDependencyPath - file name
* @return either directory containing file or null
*/
const cacheDependencyPathToProjectDirectory = (
cacheDependencyPath: string cacheDependencyPath: string
): Promise<string> => { ): string | null => {
const cacheDependencyPathDirectory = path.dirname(cacheDependencyPath); const projectDirectory = path.dirname(cacheDependencyPath);
const cacheFolderPath = if (
fs.existsSync(cacheDependencyPathDirectory) && fs.existsSync(projectDirectory) &&
fs.lstatSync(cacheDependencyPathDirectory).isDirectory() fs.lstatSync(projectDirectory).isDirectory()
? await packageManagerInfo.getCacheFolderPath( ) {
cacheDependencyPathDirectory
)
: await packageManagerInfo.getCacheFolderPath();
core.debug( core.debug(
`${packageManagerInfo.name} path is ${cacheFolderPath} (derived from cache-dependency-path: "${cacheDependencyPath}")` `Project directory "${projectDirectory}" derived from cache-dependency-path: "${cacheDependencyPath}"`
);
return projectDirectory;
} else {
core.debug(
`No project directory found for cache-dependency-path: "${cacheDependencyPath}", will be skipped`
);
return null;
}
};
/**
* Expands (converts) the string input `cache-dependency-path` to list of directories that
* may be project roots
* @param cacheDependencyPath
* @return list of directories and possible
*/
const cacheDependencyPathToProjectsDirectories = async (
cacheDependencyPath: string
): Promise<string[]> => {
const cacheDependenciesPaths = await expandCacheDependencyPath(
cacheDependencyPath
); );
const existingDirectories: string[] = cacheDependenciesPaths
.map(cacheDependencyPath =>
cacheDependencyPathToProjectDirectory(cacheDependencyPath)
)
.filter(path => path !== null) as string[];
if (existingDirectories.length === 0)
throw Error(
'No existing directories found containing `cache-dependency-path`="${cacheDependencyPath}"'
);
// uniq
return existingDirectories.filter(
(cachePath, i, result) =>
cachePath != null && result.indexOf(cachePath) === i
);
};
const projectDirectoryToCacheFolderPath = async (
packageManagerInfo: PackageManagerInfo,
projectDirectory: string
): Promise<string> => {
const cacheFolderPath = await packageManagerInfo.getCacheFolderPath(
projectDirectory
);
core.debug(
`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`
);
return cacheFolderPath; return cacheFolderPath;
}; };
const cacheDependenciesPathsToCacheFoldersPaths = async (
const projectDirectoriesToCacheFoldersPaths = async (
packageManagerInfo: PackageManagerInfo, packageManagerInfo: PackageManagerInfo,
cacheDependenciesPaths: string[] projectDirectories: string[]
): Promise<string[]> => { ): Promise<string[]> => {
const cacheFoldersPaths = await Promise.all( const cacheFoldersPaths = await Promise.all(
cacheDependenciesPaths.map(cacheDependencyPath => projectDirectories.map(projectDirectory =>
cacheDependencyPathToCacheFolderPath( projectDirectoryToCacheFolderPath(packageManagerInfo, projectDirectory)
packageManagerInfo,
cacheDependencyPath
)
) )
); );
return cacheFoldersPaths.filter( return cacheFoldersPaths.filter(
(cachePath, i, result) => result.indexOf(cachePath) === i (cachePath, i, result) => result.indexOf(cachePath) === i
); );
}; };
const cacheDependencyPathToCacheFoldersPaths = async ( const cacheDependencyPathToCacheFoldersPaths = async (
packageManagerInfo: PackageManagerInfo, packageManagerInfo: PackageManagerInfo,
cacheDependencyPath: string cacheDependencyPath: string
): Promise<string[]> => { ): Promise<string[]> => {
const cacheDependenciesPaths = await expandCacheDependencyPath( const projectDirectories = await cacheDependencyPathToProjectsDirectories(
cacheDependencyPath cacheDependencyPath
); );
return cacheDependenciesPathsToCacheFoldersPaths( return projectDirectoriesToCacheFoldersPaths(
packageManagerInfo, packageManagerInfo,
cacheDependenciesPaths projectDirectories
); );
}; };
@ -183,7 +246,9 @@ const cacheFoldersPathsForRoot = async (
packageManagerInfo: PackageManagerInfo packageManagerInfo: PackageManagerInfo
): Promise<string[]> => { ): Promise<string[]> => {
const cacheFolderPath = await packageManagerInfo.getCacheFolderPath(); const cacheFolderPath = await packageManagerInfo.getCacheFolderPath();
core.debug(`${packageManagerInfo.name} path is ${cacheFolderPath}`); core.debug(
`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the root directory`
);
return [cacheFolderPath]; return [cacheFolderPath];
}; };