Skip to content

Commit 25316bb

Browse files
authored
Merge pull request actions#305 from MaksimZhukov/mazhuk/adding-support-for-monorepos
Support caching for mono repos and repositories with complex structure
2 parents a0cdab1 + 76a4cff commit 25316bb

File tree

6 files changed

+115
-48
lines changed

6 files changed

+115
-48
lines changed

README.md

+17-36
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ major versions: `12`, `14`, `16`
3939
more specific versions: `10.15`, `14.2.0`, `16.3.0`
4040
nvm lts syntax: `lts/erbium`, `lts/fermium`, `lts/*`
4141

42-
### Caching packages dependencies
42+
## 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`, `pnpm`. The `cache` input is optional, and caching is turned off by default.
44+
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional, and caching is turned off by default.
45+
46+
The action defaults to search for the dependency file (`package-lock.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
47+
48+
See the examples of using cache for `yarn` / `pnpm` and `cache-dependency-path` input in the [Advanced usage](docs/advanced-usage.md#caching-packages-dependencies) guide.
4549

4650
**Caching npm dependencies:**
4751
```yaml
@@ -55,44 +59,20 @@ steps:
5559
- run: npm test
5660
```
5761

58-
**Caching yarn dependencies:**
62+
**Caching npm dependencies in monorepos:**
5963
```yaml
6064
steps:
6165
- uses: actions/checkout@v2
6266
- uses: actions/setup-node@v2
6367
with:
6468
node-version: '14'
65-
cache: 'yarn'
66-
- run: yarn install
67-
- run: yarn test
68-
```
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
69+
cache: 'npm'
70+
cache-dependency-path: subdir/package-lock.json
71+
- run: npm install
72+
- run: npm test
9173
```
9274

93-
> At the moment, only `lock` files in the project root are supported.
94-
95-
### Matrix Testing:
75+
## Matrix Testing:
9676
```yaml
9777
jobs:
9878
build:
@@ -114,10 +94,11 @@ jobs:
11494

11595
1. [Check latest version](docs/advanced-usage.md#check-latest-version)
11696
2. [Using different architectures](docs/advanced-usage.md#architecture)
117-
3. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
118-
4. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
119-
5. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
120-
6. [Using private packages](docs/advanced-usage.md#use-private-packages)
97+
3. [Caching packages dependencies](docs/advanced-usage.md#caching-packages-dependencies)
98+
4. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
99+
5. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
100+
6. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
101+
7. [Using private packages](docs/advanced-usage.md#use-private-packages)
121102

122103
# License
123104

action.yml

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ inputs:
2121
default: ${{ github.token }}
2222
cache:
2323
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm'
24+
cache-dependency-path:
25+
description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
2426
# TODO: add input to control forcing to pull from cloud or dist.
2527
# escape valve for someone having issues or needing the absolute latest which isn't cached yet
2628
# Deprecated option, do not use. Will not be supported after October 1, 2019

dist/setup/index.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -6894,7 +6894,8 @@ function run() {
68946894
if (isGhes()) {
68956895
throw new Error('Caching is not supported on GHES');
68966896
}
6897-
yield cache_restore_1.restoreCache(cache);
6897+
const cacheDependencyPath = core.getInput('cache-dependency-path');
6898+
yield cache_restore_1.restoreCache(cache, cacheDependencyPath);
68986899
}
68996900
const matchersPath = path.join(__dirname, '../..', '.github');
69006901
core.info(`##[add-matcher]${path.join(matchersPath, 'tsc.json')}`);
@@ -44655,15 +44656,20 @@ const path_1 = __importDefault(__webpack_require__(622));
4465544656
const fs_1 = __importDefault(__webpack_require__(747));
4465644657
const constants_1 = __webpack_require__(196);
4465744658
const cache_utils_1 = __webpack_require__(570);
44658-
exports.restoreCache = (packageManager) => __awaiter(void 0, void 0, void 0, function* () {
44659+
exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
4465944660
const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager);
4466044661
if (!packageManagerInfo) {
4466144662
throw new Error(`Caching for '${packageManager}' is not supported`);
4466244663
}
4466344664
const platform = process.env.RUNNER_OS;
4466444665
const cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo, packageManager);
44665-
const lockFilePath = findLockFile(packageManagerInfo);
44666+
const lockFilePath = cacheDependencyPath
44667+
? cacheDependencyPath
44668+
: findLockFile(packageManagerInfo);
4466644669
const fileHash = yield glob.hashFiles(lockFilePath);
44670+
if (!fileHash) {
44671+
throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
44672+
}
4466744673
const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`;
4466844674
core.debug(`primary key is ${primaryKey}`);
4466944675
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);

docs/advanced-usage.md

+72-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Advanced usage
22

3-
### Check latest version:
3+
## Check latest version
44

55
The `check-latest` flag defaults to `false`. When set to `false`, the action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js. It will pull LTS versions from [node-versions releases](https://github.com/actions/node-versions/releases) and on miss or failure will fall back to the previous behavior of downloading directly from [node dist](https://nodejs.org/dist/). Use the default or set `check-latest` to `false` if you prefer stability and if you want to ensure a specific version of Node.js is always used.
66

@@ -19,7 +19,7 @@ steps:
1919
- run: npm test
2020
```
2121
22-
### Architecture:
22+
## Architecture
2323
2424
You can use any of the [supported operating systems](https://docs.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners), and the compatible `architecture` can be selected using `architecture`. Values are `x86`, `x64`, `arm64`, `armv6l`, `armv7l`, `ppc64le`, `s390x` (not all of the architectures are available on all platforms).
2525

@@ -39,7 +39,73 @@ jobs:
3939
- run: npm test
4040
```
4141

42-
### Multiple Operating Systems and Architectures:
42+
## Caching packages dependencies
43+
The action follows [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) guidelines, and caches global cache on the machine instead of `node_modules`, so cache can be reused between different Node.js versions.
44+
45+
**Caching yarn dependencies:**
46+
Yarn caching handles both yarn versions: 1 or 2.
47+
```yaml
48+
steps:
49+
- uses: actions/checkout@v2
50+
- uses: actions/setup-node@v2
51+
with:
52+
node-version: '14'
53+
cache: 'yarn'
54+
- run: yarn install
55+
- run: yarn test
56+
```
57+
58+
**Caching pnpm (v6.10+) dependencies:**
59+
```yaml
60+
# This workflow uses actions that are not certified by GitHub.
61+
# They are provided by a third-party and are governed by
62+
# separate terms of service, privacy policy, and support
63+
# documentation.
64+
65+
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
66+
67+
steps:
68+
- uses: actions/checkout@v2
69+
- uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
70+
with:
71+
version: 6.10.0
72+
- uses: actions/setup-node@v2
73+
with:
74+
node-version: '14'
75+
cache: 'pnpm'
76+
- run: pnpm install
77+
- run: pnpm test
78+
```
79+
80+
**Using wildcard patterns to cache dependencies**
81+
```yaml
82+
steps:
83+
- uses: actions/checkout@v2
84+
- uses: actions/setup-node@v2
85+
with:
86+
node-version: '14'
87+
cache: 'npm'
88+
cache-dependency-path: '**/package-lock.json'
89+
- run: npm install
90+
- run: npm test
91+
```
92+
93+
**Using a list of file paths to cache dependencies**
94+
```yaml
95+
steps:
96+
- uses: actions/checkout@v2
97+
- uses: actions/setup-node@v2
98+
with:
99+
node-version: '14'
100+
cache: 'npm'
101+
cache-dependency-path: |
102+
server/app/package-lock.json
103+
frontend/app/package-lock.json
104+
- run: npm install
105+
- run: npm test
106+
```
107+
108+
## Multiple Operating Systems and Architectures
43109

44110
```yaml
45111
jobs:
@@ -74,7 +140,7 @@ jobs:
74140
- run: npm test
75141
```
76142

77-
### Publish to npmjs and GPR with npm:
143+
## Publish to npmjs and GPR with npm
78144
```yaml
79145
steps:
80146
- uses: actions/checkout@v2
@@ -94,7 +160,7 @@ steps:
94160
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
95161
```
96162

97-
### Publish to npmjs and GPR with yarn:
163+
## Publish to npmjs and GPR with yarn
98164
```yaml
99165
steps:
100166
- uses: actions/checkout@v2
@@ -114,7 +180,7 @@ steps:
114180
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
115181
```
116182

117-
### Use private packages:
183+
## Use private packages
118184
```yaml
119185
steps:
120186
- uses: actions/checkout@v2

src/cache-restore.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import {
1111
PackageManagerInfo
1212
} from './cache-utils';
1313

14-
export const restoreCache = async (packageManager: string) => {
14+
export const restoreCache = async (
15+
packageManager: string,
16+
cacheDependencyPath?: string
17+
) => {
1518
const packageManagerInfo = await getPackageManagerInfo(packageManager);
1619
if (!packageManagerInfo) {
1720
throw new Error(`Caching for '${packageManager}' is not supported`);
@@ -22,9 +25,17 @@ export const restoreCache = async (packageManager: string) => {
2225
packageManagerInfo,
2326
packageManager
2427
);
25-
const lockFilePath = findLockFile(packageManagerInfo);
28+
const lockFilePath = cacheDependencyPath
29+
? cacheDependencyPath
30+
: findLockFile(packageManagerInfo);
2631
const fileHash = await glob.hashFiles(lockFilePath);
2732

33+
if (!fileHash) {
34+
throw new Error(
35+
'Some specified paths were not resolved, unable to cache dependencies.'
36+
);
37+
}
38+
2839
const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`;
2940
core.debug(`primary key is ${primaryKey}`);
3041

src/main.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export async function run() {
5151
if (isGhes()) {
5252
throw new Error('Caching is not supported on GHES');
5353
}
54-
await restoreCache(cache);
54+
const cacheDependencyPath = core.getInput('cache-dependency-path');
55+
await restoreCache(cache, cacheDependencyPath);
5556
}
5657

5758
const matchersPath = path.join(__dirname, '../..', '.github');

0 commit comments

Comments
 (0)