From ae7b4ff6adf03a4c8b7af9e6d42e932e3691df5b Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 28 Jul 2021 16:51:18 +0300 Subject: [PATCH 1/5] add cache-dependency-path --- action.yml | 2 ++ dist/setup/index.js | 12 +++++++++--- src/cache-restore.ts | 13 +++++++++++-- src/main.ts | 3 ++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 943d53102..a7e9fe13b 100644 --- a/action.yml +++ b/action.yml @@ -21,6 +21,8 @@ inputs: default: ${{ github.token }} cache: description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm' + cache-dependency-path: + description: 'Used to specify paths dependency files' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet # Deprecated option, do not use. Will not be supported after October 1, 2019 diff --git a/dist/setup/index.js b/dist/setup/index.js index 1a213700a..632fe5e0c 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -6891,10 +6891,11 @@ function run() { auth.configAuthentication(registryUrl, alwaysAuth); } if (cache) { + const cacheDependencyPath = core.getInput('cache-dependency-path'); if (isGhes()) { throw new Error('Caching is not supported on GHES'); } - yield cache_restore_1.restoreCache(cache); + yield cache_restore_1.restoreCache(cache, cacheDependencyPath); } const matchersPath = path.join(__dirname, '../..', '.github'); core.info(`##[add-matcher]${path.join(matchersPath, 'tsc.json')}`); @@ -44655,15 +44656,20 @@ const path_1 = __importDefault(__webpack_require__(622)); const fs_1 = __importDefault(__webpack_require__(747)); const constants_1 = __webpack_require__(196); const cache_utils_1 = __webpack_require__(570); -exports.restoreCache = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { +exports.restoreCache = (packageManager, cacheDependencyPaths) => __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 cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo, packageManager); - const lockFilePath = findLockFile(packageManagerInfo); + const lockFilePath = cacheDependencyPaths + ? cacheDependencyPaths + : findLockFile(packageManagerInfo); const fileHash = yield glob.hashFiles(lockFilePath); + if (!fileHash) { + throw new Error('One of the specified path does not exist'); + } const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`; core.debug(`primary key is ${primaryKey}`); core.saveState(constants_1.State.CachePrimaryKey, primaryKey); diff --git a/src/cache-restore.ts b/src/cache-restore.ts index a9100252e..d45193001 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -11,7 +11,10 @@ import { PackageManagerInfo } from './cache-utils'; -export const restoreCache = async (packageManager: string) => { +export const restoreCache = async ( + packageManager: string, + cacheDependencyPaths: string +) => { const packageManagerInfo = await getPackageManagerInfo(packageManager); if (!packageManagerInfo) { throw new Error(`Caching for '${packageManager}' is not supported`); @@ -22,9 +25,15 @@ export const restoreCache = async (packageManager: string) => { packageManagerInfo, packageManager ); - const lockFilePath = findLockFile(packageManagerInfo); + const lockFilePath = cacheDependencyPaths + ? cacheDependencyPaths + : findLockFile(packageManagerInfo); const fileHash = await glob.hashFiles(lockFilePath); + if (!fileHash) { + throw new Error('One of the specified path does not exist'); + } + const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`; core.debug(`primary key is ${primaryKey}`); diff --git a/src/main.ts b/src/main.ts index 2590c9cee..afc01cda8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -48,10 +48,11 @@ export async function run() { } if (cache) { + const cacheDependencyPath = core.getInput('cache-dependency-path'); if (isGhes()) { throw new Error('Caching is not supported on GHES'); } - await restoreCache(cache); + await restoreCache(cache, cacheDependencyPath); } const matchersPath = path.join(__dirname, '../..', '.github'); From 46ee8b7e76efa1af0cac9a23cb1dc33baadf1817 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 28 Jul 2021 17:34:56 +0300 Subject: [PATCH 2/5] fix tests --- __tests__/cache-restore.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/__tests__/cache-restore.test.ts b/__tests__/cache-restore.test.ts index 483f8eb6d..e70b94213 100644 --- a/__tests__/cache-restore.test.ts +++ b/__tests__/cache-restore.test.ts @@ -108,7 +108,7 @@ describe('cache-restore', () => { it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])( 'Throw an error because %s is not supported', async packageManager => { - await expect(restoreCache(packageManager)).rejects.toThrowError( + await expect(restoreCache(packageManager, "")).rejects.toThrowError( `Caching for '${packageManager}' is not supported` ); } @@ -132,7 +132,7 @@ describe('cache-restore', () => { } }); - await restoreCache(packageManager); + await restoreCache(packageManager, ""); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}` @@ -162,7 +162,7 @@ describe('cache-restore', () => { }); restoreCacheSpy.mockImplementationOnce(() => undefined); - await restoreCache(packageManager); + await restoreCache(packageManager, ""); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `${packageManager} cache is not found` From 894d35665444c50cda458650d73049cd83efb195 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 28 Jul 2021 17:55:11 +0300 Subject: [PATCH 3/5] fix e2e test --- .github/workflows/e2e-cache.yml | 2 ++ __tests__/cache-restore.test.ts | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e-cache.yml b/.github/workflows/e2e-cache.yml index 9c294f16c..69e75fece 100644 --- a/.github/workflows/e2e-cache.yml +++ b/.github/workflows/e2e-cache.yml @@ -101,6 +101,8 @@ jobs: node-yarn2-depencies-caching: name: Test yarn 2 (Node ${{ matrix.node-version}}, ${{ matrix.os }}) runs-on: ${{ matrix.os }} + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false strategy: fail-fast: false matrix: diff --git a/__tests__/cache-restore.test.ts b/__tests__/cache-restore.test.ts index e70b94213..c2b757947 100644 --- a/__tests__/cache-restore.test.ts +++ b/__tests__/cache-restore.test.ts @@ -108,7 +108,7 @@ describe('cache-restore', () => { it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])( 'Throw an error because %s is not supported', async packageManager => { - await expect(restoreCache(packageManager, "")).rejects.toThrowError( + await expect(restoreCache(packageManager, '')).rejects.toThrowError( `Caching for '${packageManager}' is not supported` ); } @@ -132,7 +132,7 @@ describe('cache-restore', () => { } }); - await restoreCache(packageManager, ""); + await restoreCache(packageManager, ''); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}` @@ -162,7 +162,7 @@ describe('cache-restore', () => { }); restoreCacheSpy.mockImplementationOnce(() => undefined); - await restoreCache(packageManager, ""); + await restoreCache(packageManager, ''); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `${packageManager} cache is not found` From b031d7dfbddf2deff4985077f28c6266e4036e1a Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 29 Jul 2021 13:00:57 +0300 Subject: [PATCH 4/5] fix comments --- README.md | 34 ++++++++++++++++++++++++++++++--- __tests__/cache-restore.test.ts | 6 +++--- action.yml | 2 +- dist/setup/index.js | 8 ++++---- src/cache-restore.ts | 6 +++--- src/main.ts | 2 +- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1b66c7b1b..229b52895 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,9 @@ nvm lts syntax: `lts/erbium`, `lts/fermium`, `lts/*` ### Caching packages dependencies -The action has a built-in functionality for caching and restoring npm/yarn dependencies. Supported package managers are `npm`, `yarn`, `pnpm`. The `cache` input is optional, and caching is turned off by default. +The action has a built-in functionality for caching and restoring npm/yarn dependencies. Supported package managers are `npm`, `yarn`, `pnpm`. The `cache` input is optional, and caching is turned off by default. By default action hashes dependency +file from the root of the project. To override file dependency search use `cache-dependency-path`. The field accepts wildcards or +input array of files to be cached. **Caching npm dependencies:** ```yaml @@ -66,6 +68,34 @@ steps: - run: yarn install - run: yarn test ``` + +**Caching all npm dependencies:** +```yaml +steps: +- uses: actions/checkout@v2 +- uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'npm' + cache-dependency-path: '**/package-lock.json' +- run: npm install +- run: npm test +``` + +**Caching specific paths** +```yaml +steps: +- uses: actions/checkout@v2 +- uses: actions/setup-node@v2 + with: + node-version: '14' + cache: 'npm' + cache-dependency-path: | + server/app/package-lock.json + frontend/app/package-lock.json +- run: npm install +- run: npm test +``` Yarn caching handles both yarn versions: 1 or 2. **Caching pnpm (v6.10+) dependencies:** @@ -90,8 +120,6 @@ steps: - run: pnpm test ``` -> At the moment, only `lock` files in the project root are supported. - ### Matrix Testing: ```yaml jobs: diff --git a/__tests__/cache-restore.test.ts b/__tests__/cache-restore.test.ts index c2b757947..483f8eb6d 100644 --- a/__tests__/cache-restore.test.ts +++ b/__tests__/cache-restore.test.ts @@ -108,7 +108,7 @@ describe('cache-restore', () => { it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])( 'Throw an error because %s is not supported', async packageManager => { - await expect(restoreCache(packageManager, '')).rejects.toThrowError( + await expect(restoreCache(packageManager)).rejects.toThrowError( `Caching for '${packageManager}' is not supported` ); } @@ -132,7 +132,7 @@ describe('cache-restore', () => { } }); - await restoreCache(packageManager, ''); + await restoreCache(packageManager); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}` @@ -162,7 +162,7 @@ describe('cache-restore', () => { }); restoreCacheSpy.mockImplementationOnce(() => undefined); - await restoreCache(packageManager, ''); + await restoreCache(packageManager); expect(hashFilesSpy).toHaveBeenCalled(); expect(infoSpy).toHaveBeenCalledWith( `${packageManager} cache is not found` diff --git a/action.yml b/action.yml index a7e9fe13b..32e805c97 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ inputs: cache: description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm' cache-dependency-path: - description: 'Used to specify paths dependency files' + description: 'Used to specify path to dependencies lock file: package-lock.json, yarn.lock and etc' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet # Deprecated option, do not use. Will not be supported after October 1, 2019 diff --git a/dist/setup/index.js b/dist/setup/index.js index 632fe5e0c..9ca3e4384 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -6891,10 +6891,10 @@ function run() { auth.configAuthentication(registryUrl, alwaysAuth); } if (cache) { - const cacheDependencyPath = core.getInput('cache-dependency-path'); if (isGhes()) { throw new Error('Caching is not supported on GHES'); } + const cacheDependencyPath = core.getInput('cache-dependency-path'); yield cache_restore_1.restoreCache(cache, cacheDependencyPath); } const matchersPath = path.join(__dirname, '../..', '.github'); @@ -44656,15 +44656,15 @@ const path_1 = __importDefault(__webpack_require__(622)); const fs_1 = __importDefault(__webpack_require__(747)); const constants_1 = __webpack_require__(196); const cache_utils_1 = __webpack_require__(570); -exports.restoreCache = (packageManager, cacheDependencyPaths) => __awaiter(void 0, void 0, void 0, function* () { +exports.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 cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo, packageManager); - const lockFilePath = cacheDependencyPaths - ? cacheDependencyPaths + const lockFilePath = cacheDependencyPath + ? cacheDependencyPath : findLockFile(packageManagerInfo); const fileHash = yield glob.hashFiles(lockFilePath); if (!fileHash) { diff --git a/src/cache-restore.ts b/src/cache-restore.ts index d45193001..cc8eef2c4 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -13,7 +13,7 @@ import { export const restoreCache = async ( packageManager: string, - cacheDependencyPaths: string + cacheDependencyPath?: string ) => { const packageManagerInfo = await getPackageManagerInfo(packageManager); if (!packageManagerInfo) { @@ -25,8 +25,8 @@ export const restoreCache = async ( packageManagerInfo, packageManager ); - const lockFilePath = cacheDependencyPaths - ? cacheDependencyPaths + const lockFilePath = cacheDependencyPath + ? cacheDependencyPath : findLockFile(packageManagerInfo); const fileHash = await glob.hashFiles(lockFilePath); diff --git a/src/main.ts b/src/main.ts index afc01cda8..956bc1449 100644 --- a/src/main.ts +++ b/src/main.ts @@ -48,10 +48,10 @@ export async function run() { } if (cache) { - const cacheDependencyPath = core.getInput('cache-dependency-path'); if (isGhes()) { throw new Error('Caching is not supported on GHES'); } + const cacheDependencyPath = core.getInput('cache-dependency-path'); await restoreCache(cache, cacheDependencyPath); } From e2dec9741b1ef9d232b5156945919c105e9c71a5 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 29 Jul 2021 14:28:01 +0300 Subject: [PATCH 5/5] resolving comments --- README.md | 4 +--- action.yml | 2 +- dist/setup/index.js | 2 +- src/cache-restore.ts | 4 +++- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 229b52895..44384203f 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,7 @@ nvm lts syntax: `lts/erbium`, `lts/fermium`, `lts/*` ### Caching packages dependencies -The action has a built-in functionality for caching and restoring npm/yarn dependencies. Supported package managers are `npm`, `yarn`, `pnpm`. The `cache` input is optional, and caching is turned off by default. By default action hashes dependency -file from the root of the project. To override file dependency search use `cache-dependency-path`. The field accepts wildcards or -input array of files to be cached. +The action has a built-in functionality for caching and restoring npm/yarn dependencies. Supported package managers are `npm`, `yarn`, `pnpm`. The `cache` input is optional, and caching is turned off by default. By default, action hashes the dependency file from the project root. Use `cache-dependency-path` to specify custom file dependency lookup path. The field accepts wildcards or an array of files to be cached. **Caching npm dependencies:** ```yaml diff --git a/action.yml b/action.yml index 32e805c97..2da00f3e3 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ inputs: cache: description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm' cache-dependency-path: - description: 'Used to specify path to dependencies lock file: package-lock.json, yarn.lock and etc' + description: 'Used to specify path to a dependencies lock file: package-lock.json, yarn.lock, etc. Supports wildcards or an array of file names.' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet # Deprecated option, do not use. Will not be supported after October 1, 2019 diff --git a/dist/setup/index.js b/dist/setup/index.js index 9ca3e4384..d0f495dd9 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -44668,7 +44668,7 @@ exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0 : findLockFile(packageManagerInfo); const fileHash = yield glob.hashFiles(lockFilePath); if (!fileHash) { - throw new Error('One of the specified path does not exist'); + throw new Error('Some specified paths were not resolved, unable to cache dependencies.'); } const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`; core.debug(`primary key is ${primaryKey}`); diff --git a/src/cache-restore.ts b/src/cache-restore.ts index cc8eef2c4..cd128cb15 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -31,7 +31,9 @@ export const restoreCache = async ( const fileHash = await glob.hashFiles(lockFilePath); if (!fileHash) { - throw new Error('One of the specified path does not exist'); + throw new Error( + 'Some specified paths were not resolved, unable to cache dependencies.' + ); } const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`;