Skip to content

Commit aa759c6

Browse files
authored
Merge pull request actions#278 from jacobwgillespie/cache-pnpm
Add pnpm caching support
2 parents 38d90ce + 0ae03de commit aa759c6

File tree

12 files changed

+534
-11
lines changed

12 files changed

+534
-11
lines changed

.github/workflows/e2e-cache.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,39 @@ jobs:
3535
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
3636
shell: bash
3737

38+
node-pnpm-depencies-caching:
39+
name: Test pnpm (Node ${{ matrix.node-version}}, ${{ matrix.os }})
40+
runs-on: ${{ matrix.os }}
41+
strategy:
42+
fail-fast: false
43+
matrix:
44+
os: [ubuntu-latest, windows-latest, macos-latest]
45+
node-version: [12, 14, 16]
46+
steps:
47+
- uses: actions/checkout@v2
48+
- name: Install pnpm
49+
uses: pnpm/action-setup@v2
50+
with:
51+
version: 6.10.0
52+
- name: Generate pnpm file
53+
run: pnpm install
54+
- name: Remove dependencies
55+
shell: pwsh
56+
run: Remove-Item node_modules -Force -Recurse
57+
- name: Clean global cache
58+
run: rm -rf ~/.pnpm-store
59+
shell: bash
60+
- name: Setup Node
61+
uses: ./
62+
with:
63+
node-version: ${{ matrix.node-version }}
64+
cache: 'pnpm'
65+
- name: Install dependencies
66+
run: pnpm install
67+
- name: Verify node and pnpm
68+
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
69+
shell: bash
70+
3871
node-yarn1-depencies-caching:
3972
name: Test yarn 1 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
4073
runs-on: ${{ matrix.os }}
@@ -98,4 +131,4 @@ jobs:
98131
run: yarn install
99132
- name: Verify node and yarn
100133
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
101-
shell: bash
134+
shell: bash

README.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
This action provides the following functionality for GitHub Actions users:
88

99
- Optionally downloading and caching distribution of the requested Node.js version, and adding it to the PATH
10-
- Optionally caching npm/yarn dependencies
10+
- Optionally caching npm/yarn/pnpm dependencies
1111
- Registering problem matchers for error output
1212
- Configuring authentication for GPR or npm
1313

@@ -41,7 +41,7 @@ nvm lts syntax: `lts/erbium`, `lts/fermium`, `lts/*`
4141

4242
### Caching packages dependencies
4343

44-
The action has a built-in functionality for caching and restoring npm/yarn dependencies. Supported package managers are `npm`, `yarn`. The `cache` input is optional, and caching is turned off by default.
44+
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.
4545

4646
**Caching npm dependencies:**
4747
```yaml
@@ -66,7 +66,29 @@ steps:
6666
- run: yarn install
6767
- run: yarn test
6868
```
69-
Yarn caching handles both yarn versions: 1 or 2.
69+
Yarn caching handles both yarn versions: 1 or 2.
70+
71+
**Caching pnpm (v6.10+) dependencies:**
72+
```yaml
73+
# This workflow uses actions that are not certified by GitHub.
74+
# They are provided by a third-party and are governed by
75+
# separate terms of service, privacy policy, and support
76+
# documentation.
77+
78+
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
79+
80+
steps:
81+
- uses: actions/checkout@v2
82+
- uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
83+
with:
84+
version: 6.10.0
85+
- uses: actions/setup-node@v2
86+
with:
87+
node-version: '14'
88+
cache: 'pnpm'
89+
- run: pnpm install
90+
- run: pnpm test
91+
```
7092

7193
> At the moment, only `lock` files in the project root are supported.
7294

__tests__/cache-restore.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ describe('cache-restore', () => {
1414
const platform = process.env.RUNNER_OS;
1515
const commonPath = '/some/random/path';
1616
const npmCachePath = `${commonPath}/npm`;
17+
const pnpmCachePath = `${commonPath}/pnpm`;
1718
const yarn1CachePath = `${commonPath}/yarn1`;
1819
const yarn2CachePath = `${commonPath}/yarn2`;
1920
const yarnFileHash =
2021
'b8a0bae5243251f7c07dd52d1f78ff78281dfefaded700a176261b6b54fa245b';
2122
const npmFileHash =
2223
'abf7c9b306a3149dcfba4673e2362755503bcceaab46f0e4e6fee0ade493e20c';
24+
const pnpmFileHash =
25+
'26309058093e84713f38869c50cf1cee9b08155ede874ec1b44ce3fca8c68c70';
2326
const cachesObject = {
2427
[npmCachePath]: npmFileHash,
28+
[pnpmCachePath]: pnpmFileHash,
2529
[yarn1CachePath]: yarnFileHash,
2630
[yarn2CachePath]: yarnFileHash
2731
};
@@ -30,6 +34,8 @@ describe('cache-restore', () => {
3034
switch (command) {
3135
case utils.supportedPackageManagers.npm.getCacheFolderCommand:
3236
return npmCachePath;
37+
case utils.supportedPackageManagers.pnpm.getCacheFolderCommand:
38+
return pnpmCachePath;
3339
case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
3440
return yarn1CachePath;
3541
case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
@@ -66,6 +72,8 @@ describe('cache-restore', () => {
6672
hashFilesSpy.mockImplementation((pattern: string) => {
6773
if (pattern.includes('package-lock.json')) {
6874
return npmFileHash;
75+
} else if (pattern.includes('pnpm-lock.yaml')) {
76+
return pnpmFileHash;
6977
} else if (pattern.includes('yarn.lock')) {
7078
return yarnFileHash;
7179
} else {
@@ -97,7 +105,7 @@ describe('cache-restore', () => {
97105
});
98106

99107
describe('Validate provided package manager', () => {
100-
it.each([['npm7'], ['npm6'], ['yarn1'], ['yarn2'], ['random']])(
108+
it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])(
101109
'Throw an error because %s is not supported',
102110
async packageManager => {
103111
await expect(restoreCache(packageManager)).rejects.toThrowError(
@@ -111,7 +119,8 @@ describe('cache-restore', () => {
111119
it.each([
112120
['yarn', '2.1.2', yarnFileHash],
113121
['yarn', '1.2.3', yarnFileHash],
114-
['npm', '', npmFileHash]
122+
['npm', '', npmFileHash],
123+
['pnpm', '', pnpmFileHash]
115124
])(
116125
'restored dependencies for %s',
117126
async (packageManager, toolVersion, fileHash) => {
@@ -139,7 +148,8 @@ describe('cache-restore', () => {
139148
it.each([
140149
['yarn', '2.1.2', yarnFileHash],
141150
['yarn', '1.2.3', yarnFileHash],
142-
['npm', '', npmFileHash]
151+
['npm', '', npmFileHash],
152+
['pnpm', '', pnpmFileHash]
143153
])(
144154
'dependencies are changed %s',
145155
async (packageManager, toolVersion, fileHash) => {

__tests__/cache-save.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as core from '@actions/core';
22
import * as cache from '@actions/cache';
33
import * as glob from '@actions/glob';
4+
import fs from 'fs';
45
import path from 'path';
56

67
import * as utils from '../src/cache-utils';
@@ -12,6 +13,8 @@ describe('run', () => {
1213
'b8a0bae5243251f7c07dd52d1f78ff78281dfefaded700a176261b6b54fa245b';
1314
const npmFileHash =
1415
'abf7c9b306a3149dcfba4673e2362755503bcceaab46f0e4e6fee0ade493e20c';
16+
const pnpmFileHash =
17+
'26309058093e84713f38869c50cf1cee9b08155ede874ec1b44ce3fca8c68c70';
1518
const commonPath = '/some/random/path';
1619
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
1720

@@ -26,6 +29,7 @@ describe('run', () => {
2629
let saveCacheSpy: jest.SpyInstance;
2730
let getCommandOutputSpy: jest.SpyInstance;
2831
let hashFilesSpy: jest.SpyInstance;
32+
let existsSpy: jest.SpyInstance;
2933

3034
beforeEach(() => {
3135
getInputSpy = jest.spyOn(core, 'getInput');
@@ -61,10 +65,17 @@ describe('run', () => {
6165
}
6266
});
6367

68+
existsSpy = jest.spyOn(fs, 'existsSync');
69+
existsSpy.mockImplementation(() => true);
70+
6471
// utils
6572
getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
6673
});
6774

75+
afterEach(() => {
76+
existsSpy.mockRestore();
77+
});
78+
6879
describe('Package manager validation', () => {
6980
it('Package manager is not provided, skip caching', async () => {
7081
inputs['cache'] = '';
@@ -150,6 +161,23 @@ describe('run', () => {
150161
);
151162
expect(setFailedSpy).not.toHaveBeenCalled();
152163
});
164+
165+
it('should not save cache for pnpm', async () => {
166+
inputs['cache'] = 'pnpm';
167+
getStateSpy.mockImplementation(() => pnpmFileHash);
168+
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
169+
170+
await run();
171+
172+
expect(getInputSpy).toHaveBeenCalled();
173+
expect(getStateSpy).toHaveBeenCalledTimes(2);
174+
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
175+
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
176+
expect(infoSpy).toHaveBeenCalledWith(
177+
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
178+
);
179+
expect(setFailedSpy).not.toHaveBeenCalled();
180+
});
153181
});
154182

155183
describe('action saves the cache', () => {
@@ -239,6 +267,33 @@ describe('run', () => {
239267
);
240268
expect(setFailedSpy).not.toHaveBeenCalled();
241269
});
270+
271+
it('saves cache from pnpm', async () => {
272+
inputs['cache'] = 'pnpm';
273+
getStateSpy.mockImplementation((name: string) => {
274+
if (name === State.CacheMatchedKey) {
275+
return pnpmFileHash;
276+
} else {
277+
return npmFileHash;
278+
}
279+
});
280+
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
281+
282+
await run();
283+
284+
expect(getInputSpy).toHaveBeenCalled();
285+
expect(getStateSpy).toHaveBeenCalledTimes(2);
286+
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
287+
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
288+
expect(infoSpy).not.toHaveBeenCalledWith(
289+
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
290+
);
291+
expect(saveCacheSpy).toHaveBeenCalled();
292+
expect(infoSpy).toHaveBeenLastCalledWith(
293+
`Cache saved with the key: ${npmFileHash}`
294+
);
295+
expect(setFailedSpy).not.toHaveBeenCalled();
296+
});
242297
});
243298

244299
afterEach(() => {

__tests__/cache-utils.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ describe('cache-utils', () => {
1414
function getPackagePath(name: string) {
1515
if (name === utils.supportedPackageManagers.npm.getCacheFolderCommand) {
1616
return `${commonPath}/npm`;
17+
} else if (
18+
name === utils.supportedPackageManagers.pnpm.getCacheFolderCommand
19+
) {
20+
return `${commonPath}/pnpm`;
1721
} else {
1822
if (name === utils.supportedPackageManagers.yarn1.getCacheFolderCommand) {
1923
return `${commonPath}/yarn1`;
@@ -34,6 +38,7 @@ describe('cache-utils', () => {
3438
describe('getPackageManagerInfo', () => {
3539
it.each<[string, PackageManagerInfo | null]>([
3640
['npm', utils.supportedPackageManagers.npm],
41+
['pnpm', utils.supportedPackageManagers.pnpm],
3742
['yarn', utils.supportedPackageManagers.yarn1],
3843
['yarn1', null],
3944
['yarn2', null],

0 commit comments

Comments
 (0)