mirror of
https://github.com/actions/setup-node.git
synced 2026-05-07 07:37:31 +08:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d709998c7 | |||
| 5784c79d41 | |||
| 558ef89cd9 | |||
| f099707f6e | |||
| f658dc5bd7 | |||
| 5e2e068714 | |||
| 7a0f7a9962 | |||
| 7b558676dd | |||
| 1f8c6b94b2 | |||
| 9a74eb4e64 | |||
| 04c56d2f95 | |||
| d08cf22211 | |||
| 360ab8b75b | |||
| fd4bd829f2 | |||
| a4b8ed2f4e | |||
| 270253e841 | |||
| d1178716db | |||
| 041bafb672 | |||
| 996306e892 | |||
| 85d4122530 | |||
| 928244ce45 | |||
| 25316bbc1f | |||
| 76a4cff9ae | |||
| a869e7cc2d | |||
| a0cdab1110 | |||
| 4d0182af5e | |||
| 896ee80599 | |||
| d21ecc7c5b | |||
| 180b77fed2 | |||
| 9f31dbbbc4 | |||
| f43d8a1f27 | |||
| 3c1fbef7d3 | |||
| 5aa72c249a | |||
| d9aab2aba4 |
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report
|
||||
title: ''
|
||||
labels: bug, needs triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
|
||||
<!--- Before opening up a new bug report, please make sure to check for similar existing issues -->
|
||||
|
||||
**Description:**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Action version:**
|
||||
Specify the action version
|
||||
|
||||
**Platform:**
|
||||
- [ ] Ubuntu
|
||||
- [ ] macOS
|
||||
- [ ] Windows
|
||||
|
||||
**Runner type:**
|
||||
- [ ] Hosted
|
||||
- [ ] Self-hosted
|
||||
|
||||
**Tools version:**
|
||||
<!--- Please specify versions of node and package manager (npm, yarn, pnpm and etc)-->
|
||||
|
||||
**Repro steps:**
|
||||
A description with steps to reproduce the issue. If you have a public example or repo to share, please provide the link.
|
||||
|
||||
**Expected behavior:**
|
||||
A description of what you expected to happen.
|
||||
|
||||
**Actual behavior:**
|
||||
A description of what is actually happening.
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature request, needs triage
|
||||
assignees: ''
|
||||
---
|
||||
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
|
||||
<!--- Before opening up a new feature request, please make sure to check for similar existing issues and pull requests -->
|
||||
|
||||
**Description:**
|
||||
Describe your proposal.
|
||||
|
||||
**Justification:**
|
||||
Justification or a use case for your proposal.
|
||||
|
||||
**Are you willing to submit a PR?**
|
||||
<!--- We accept contributions! -->
|
||||
@@ -0,0 +1,9 @@
|
||||
**Description:**
|
||||
Describe your changes.
|
||||
|
||||
**Related issue:**
|
||||
Add link to the related issue.
|
||||
|
||||
**Check list:**
|
||||
- [ ] Mark if documentation changes are required.
|
||||
- [ ] Mark if tests were added or updated to cover the changes.
|
||||
@@ -3,14 +3,14 @@ name: build-test
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
push:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -19,14 +19,12 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup node 12
|
||||
- name: Setup node 16
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm run format-check
|
||||
- run: npm test
|
||||
- name: Verify no unstaged changes
|
||||
if: runner.os != 'windows'
|
||||
run: __tests__/verify-no-unstaged-changes.sh
|
||||
- run: npm test
|
||||
@@ -0,0 +1,52 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js 16.x
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Rebuild the dist/ directory
|
||||
run: npm run build
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
@@ -1,8 +1,12 @@
|
||||
name: Licensed
|
||||
|
||||
on:
|
||||
push: {branches: main}
|
||||
pull_request: {branches: main}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -14,7 +18,7 @@ jobs:
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.3.1/licensed-3.3.1-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
- run: licensed status
|
||||
|
||||
@@ -3,19 +3,17 @@ name: proxy
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
push:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
|
||||
jobs:
|
||||
test-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
container:
|
||||
image: ubuntu:latest
|
||||
options: --dns 127.0.0.1
|
||||
@@ -39,8 +37,6 @@ jobs:
|
||||
|
||||
test-bypass-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
env:
|
||||
https_proxy: http://no-such-proxy:3128
|
||||
no_proxy: api.github.com,github.com,nodejs.org,registry.npmjs.org,*.s3.amazonaws.com,s3.amazonaws.com
|
||||
|
||||
@@ -78,6 +78,21 @@ jobs:
|
||||
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||
shell: bash
|
||||
|
||||
version-file:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup node from node version file
|
||||
uses: ./
|
||||
with:
|
||||
node-version-file: '__tests__/data/.nvmrc'
|
||||
- name: Verify node
|
||||
run: __tests__/verify-node.sh 14
|
||||
|
||||
node-dist:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
||||
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
@@ -39,9 +39,13 @@ major versions: `12`, `14`, `16`
|
||||
more specific versions: `10.15`, `14.2.0`, `16.3.0`
|
||||
nvm lts syntax: `lts/erbium`, `lts/fermium`, `lts/*`
|
||||
|
||||
### Caching packages dependencies
|
||||
## 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 dependencies. It uses [actions/cache](https://github.com/actions/cache) under the 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
**Caching npm dependencies:**
|
||||
```yaml
|
||||
@@ -55,44 +59,20 @@ steps:
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
**Caching yarn dependencies:**
|
||||
**Caching npm dependencies in monorepos:**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'yarn'
|
||||
- run: yarn install
|
||||
- run: yarn test
|
||||
```
|
||||
Yarn caching handles both yarn versions: 1 or 2.
|
||||
|
||||
**Caching pnpm (v6.10+) dependencies:**
|
||||
```yaml
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
with:
|
||||
version: 6.10.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm install
|
||||
- run: pnpm test
|
||||
cache: 'npm'
|
||||
cache-dependency-path: subdir/package-lock.json
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
> At the moment, only `lock` files in the project root are supported.
|
||||
|
||||
### Matrix Testing:
|
||||
## Matrix Testing:
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
@@ -113,11 +93,13 @@ jobs:
|
||||
## Advanced usage
|
||||
|
||||
1. [Check latest version](docs/advanced-usage.md#check-latest-version)
|
||||
2. [Using different architectures](docs/advanced-usage.md#architecture)
|
||||
3. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
|
||||
4. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
|
||||
5. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
|
||||
6. [Using private packages](docs/advanced-usage.md#use-private-packages)
|
||||
2. [Using a node version file](docs/advanced-usage.md#node-version-file)
|
||||
3. [Using different architectures](docs/advanced-usage.md#architecture)
|
||||
4. [Caching packages dependencies](docs/advanced-usage.md#caching-packages-dependencies)
|
||||
5. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
|
||||
6. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
|
||||
7. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
|
||||
8. [Using private packages](docs/advanced-usage.md#use-private-packages)
|
||||
|
||||
# License
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ describe('cache-restore', () => {
|
||||
expect(infoSpy).not.toHaveBeenCalledWith(
|
||||
`${packageManager} cache is not found`
|
||||
);
|
||||
expect(setOutputSpy).toHaveBeenCalledWith('cache-hit', true);
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -167,6 +168,7 @@ describe('cache-restore', () => {
|
||||
expect(infoSpy).toHaveBeenCalledWith(
|
||||
`${packageManager} cache is not found`
|
||||
);
|
||||
expect(setOutputSpy).toHaveBeenCalledWith('cache-hit', false);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
v14
|
||||
+104
-16
@@ -1,12 +1,12 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as im from '../src/installer';
|
||||
import fs from 'fs';
|
||||
import cp from 'child_process';
|
||||
import osm = require('os');
|
||||
import path from 'path';
|
||||
import * as main from '../src/main';
|
||||
import * as im from '../src/installer';
|
||||
import * as auth from '../src/authutil';
|
||||
|
||||
let nodeTestManifest = require('./data/versions-manifest.json');
|
||||
@@ -31,9 +31,11 @@ describe('setup-node', () => {
|
||||
let dbgSpy: jest.SpyInstance;
|
||||
let whichSpy: jest.SpyInstance;
|
||||
let existsSpy: jest.SpyInstance;
|
||||
let readFileSyncSpy: jest.SpyInstance;
|
||||
let mkdirpSpy: jest.SpyInstance;
|
||||
let execSpy: jest.SpyInstance;
|
||||
let authSpy: jest.SpyInstance;
|
||||
let parseNodeVersionSpy: jest.SpyInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
// @actions/core
|
||||
@@ -58,6 +60,7 @@ describe('setup-node', () => {
|
||||
cacheSpy = jest.spyOn(tc, 'cacheDir');
|
||||
getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo');
|
||||
getDistSpy = jest.spyOn(im, 'getVersionsFromDist');
|
||||
parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile');
|
||||
|
||||
// io
|
||||
whichSpy = jest.spyOn(io, 'which');
|
||||
@@ -91,6 +94,10 @@ describe('setup-node', () => {
|
||||
// uncomment to see debug output
|
||||
// process.stderr.write(msg + '\n');
|
||||
});
|
||||
warningSpy.mockImplementation(msg => {
|
||||
// uncomment to debug
|
||||
// process.stderr.write('log:' + line + '\n');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -101,6 +108,7 @@ describe('setup-node', () => {
|
||||
|
||||
afterAll(async () => {
|
||||
console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions
|
||||
jest.restoreAllMocks();
|
||||
}, 100000);
|
||||
|
||||
//--------------------------------------------------
|
||||
@@ -171,8 +179,7 @@ describe('setup-node', () => {
|
||||
// Found in cache tests
|
||||
//--------------------------------------------------
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('finds version in cache with stable true', async () => {
|
||||
it('finds version in cache with stable true', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs.stable = 'true';
|
||||
|
||||
@@ -183,8 +190,7 @@ describe('setup-node', () => {
|
||||
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||
});
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('finds version in cache with stable not supplied', async () => {
|
||||
it('finds version in cache with stable not supplied', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
@@ -196,8 +202,7 @@ describe('setup-node', () => {
|
||||
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||
});
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('finds version in cache and adds it to the path', async () => {
|
||||
it('finds version in cache and adds it to the path', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
@@ -346,7 +351,7 @@ describe('setup-node', () => {
|
||||
expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
|
||||
});
|
||||
|
||||
it('Acquires specified architecture of node', async () => {
|
||||
it('acquires specified architecture of node', async () => {
|
||||
for (const {arch, version, osSpec} of [
|
||||
{arch: 'x86', version: '12.16.2', osSpec: 'win32'},
|
||||
{arch: 'x86', version: '14.0.0', osSpec: 'win32'}
|
||||
@@ -387,8 +392,7 @@ describe('setup-node', () => {
|
||||
}, 100000);
|
||||
|
||||
describe('check-latest flag', () => {
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('use local version and dont check manifest if check-latest is not specified', async () => {
|
||||
it('use local version and dont check manifest if check-latest is not specified', async () => {
|
||||
os.platform = 'linux';
|
||||
os.arch = 'x64';
|
||||
|
||||
@@ -409,8 +413,7 @@ describe('setup-node', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('check latest version and resolve it from local cache', async () => {
|
||||
it('check latest version and resolve it from local cache', async () => {
|
||||
os.platform = 'linux';
|
||||
os.arch = 'x64';
|
||||
|
||||
@@ -554,6 +557,93 @@ describe('setup-node', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('node-version-file flag', () => {
|
||||
it('not used if node-version is provided', async () => {
|
||||
// Arrange
|
||||
inputs['node-version'] = '12';
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('not used if node-version-file not provided', async () => {
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('reads node-version-file if provided', async () => {
|
||||
// Arrange
|
||||
const versionSpec = 'v14';
|
||||
const versionFile = '.nvmrc';
|
||||
const expectedVersionSpec = '14';
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
|
||||
existsSpy.mockImplementationOnce(
|
||||
input => input === path.join(__dirname, 'data', versionFile)
|
||||
);
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(existsSpy).toHaveReturnedWith(true);
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec);
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
`Resolved ${versionFile} as ${expectedVersionSpec}`
|
||||
);
|
||||
});
|
||||
|
||||
it('both node-version-file and node-version are provided', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
const versionSpec = 'v14';
|
||||
const versionFile = '.nvmrc';
|
||||
const expectedVersionSpec = '14';
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..');
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalledTimes(0);
|
||||
expect(parseNodeVersionSpy).not.toHaveBeenCalled();
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
'Both node-version and node-version-file inputs are specified, only node-version will be used'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if node-version-file is not found', async () => {
|
||||
const versionFile = '.nvmrc';
|
||||
const versionFilePath = path.join(__dirname, '..', versionFile);
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
existsSpy.mockImplementationOnce(
|
||||
input => input === path.join(__dirname, 'data', versionFile)
|
||||
);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalled();
|
||||
expect(existsSpy).toHaveReturnedWith(false);
|
||||
expect(parseNodeVersionSpy).not.toHaveBeenCalled();
|
||||
expect(cnSpy).toHaveBeenCalledWith(
|
||||
`::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}`
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('LTS version', () => {
|
||||
beforeEach(() => {
|
||||
os.platform = 'linux';
|
||||
@@ -561,8 +651,7 @@ describe('setup-node', () => {
|
||||
inputs.stable = 'true';
|
||||
});
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('find latest LTS version and resolve it from local cache (lts/erbium)', async () => {
|
||||
it('find latest LTS version and resolve it from local cache (lts/erbium)', async () => {
|
||||
// arrange
|
||||
inputs['node-version'] = 'lts/erbium';
|
||||
|
||||
@@ -632,8 +721,7 @@ describe('setup-node', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
xit('find latest LTS version and resolve it from local cache (lts/*)', async () => {
|
||||
it('find latest LTS version and resolve it from local cache (lts/*)', async () => {
|
||||
// arrange
|
||||
inputs['node-version'] = 'lts/*';
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$(git status --porcelain)" != "" ]]; then
|
||||
echo ----------------------------------------
|
||||
echo git status
|
||||
echo ----------------------------------------
|
||||
git status
|
||||
echo ----------------------------------------
|
||||
echo git diff
|
||||
echo ----------------------------------------
|
||||
git diff
|
||||
echo ----------------------------------------
|
||||
echo Troubleshooting
|
||||
echo ----------------------------------------
|
||||
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run pre-checkin"
|
||||
exit 1
|
||||
fi
|
||||
+9
-2
@@ -7,6 +7,8 @@ inputs:
|
||||
default: 'false'
|
||||
node-version:
|
||||
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0'
|
||||
node-version-file:
|
||||
description: 'File containing the version Spec of the version to use. Examples: .nvmrc, .node-version'
|
||||
architecture:
|
||||
description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.'
|
||||
check-latest:
|
||||
@@ -21,14 +23,19 @@ 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 the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
|
||||
# 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
|
||||
version:
|
||||
description: 'Deprecated. Use node-version instead. Will not be supported after October 1, 2019'
|
||||
deprecationMessage: 'The version property will not be supported after October 1, 2019. Use node-version instead'
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate if a cache was hit'
|
||||
runs:
|
||||
using: 'node12'
|
||||
using: 'node16'
|
||||
main: 'dist/setup/index.js'
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
post-if: success()
|
||||
|
||||
Vendored
+12735
-16150
File diff suppressed because it is too large
Load Diff
Vendored
+12282
-16237
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
# 0. Caching dependencies
|
||||
Date: 2021-05-21
|
||||
|
||||
Status: Proposed
|
||||
Status: Accepted
|
||||
|
||||
# Context
|
||||
`actions/setup-node` is the 2nd most popular action in GitHub Actions. A lot of customers use it in conjunction with [actions/cache](https://github.com/actions/cache) to speed up dependencies installation.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# 0. Support caching dependencies for mono repos
|
||||
Date: 2021-07-13
|
||||
|
||||
Status: Proposed
|
||||
|
||||
## Context
|
||||
Currently, `actions/setup-node` supports caching dependencies for Npm and Yarn package managers.
|
||||
For the first iteration, we have decided to not support cases where `package-lock.json` / `yarn.lock` are located outside of repository root.
|
||||
Current implementation searches the following file patterns in the repository root: `package-lock.json`, `yarn.lock` (in order of resolving priorities)
|
||||
|
||||
Obviously, it made build-in caching unusable for mono-repos and repos with complex structure.
|
||||
We would like to revisit this decision and add customization for dependencies lock file location.
|
||||
|
||||
## Proposal
|
||||
We have the following options:
|
||||
1. Allow to specify directory where `package-lock.json` or `yarn.lock` are located
|
||||
2. Allow to specify path to the dependencies lock file (including directory path and filename)
|
||||
|
||||
The second option looks more generic because it allows to:
|
||||
- specify multiple dependencies files using file patterns like `**/package-lock.json` ([one of recommended approaches in actions/cache](https://github.com/actions/cache/blob/main/examples.md#macos-and-ubuntu))
|
||||
- specify custom dependencies files like `src/npm-shrinkwrap.json`
|
||||
- change default resolving priority if both `yarn.lock` and `package-lock.json` exist in repository
|
||||
|
||||
## Decision
|
||||
|
||||
Add `cache-dependency-path` input that will accept path (relative to repository root) to dependencies lock file.
|
||||
If provided path contains wildcards, the action will search all maching files and calculate common hash like `${{ hashFiles('**/package-lock.json') }}` YAML construction does.
|
||||
The hash of provided matched files will be used as a part of cache key.
|
||||
|
||||
Yaml examples:
|
||||
```yml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
cache: npm
|
||||
cache-dependency-path: 'sub-project/package-lock.json'
|
||||
```
|
||||
```yml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
cache: yarn
|
||||
cache-dependency-path: 'sub-project/**/yarn.lock'
|
||||
```
|
||||
+88
-6
@@ -1,6 +1,6 @@
|
||||
# Advanced usage
|
||||
|
||||
### Check latest version:
|
||||
## Check latest version
|
||||
|
||||
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.
|
||||
|
||||
@@ -19,7 +19,23 @@ steps:
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
### Architecture:
|
||||
## Node version file
|
||||
|
||||
The `node-version-file` input accepts a path to a file containing the version of Node.js to be used by a project, for example `.nvmrc` or `.node-version`. If both the `node-version` and the `node-version-file` inputs are provided then the `node-version` input is used.
|
||||
See [supported version syntax](https://github.com/actions/setup-node#supported-version-syntax)
|
||||
> The action will search for the node version file relative to the repository root.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
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).
|
||||
|
||||
@@ -39,7 +55,73 @@ jobs:
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
### Multiple Operating Systems and Architectures:
|
||||
## Caching packages dependencies
|
||||
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.
|
||||
|
||||
**Caching yarn dependencies:**
|
||||
Yarn caching handles both yarn versions: 1 or 2.
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'yarn'
|
||||
- run: yarn install
|
||||
- run: yarn test
|
||||
```
|
||||
|
||||
**Caching pnpm (v6.10+) dependencies:**
|
||||
```yaml
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
with:
|
||||
version: 6.10.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm install
|
||||
- run: pnpm test
|
||||
```
|
||||
|
||||
**Using wildcard patterns to cache 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
|
||||
```
|
||||
|
||||
**Using a list of file paths to cache dependencies**
|
||||
```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
|
||||
```
|
||||
|
||||
## Multiple Operating Systems and Architectures
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
@@ -74,7 +156,7 @@ jobs:
|
||||
- run: npm test
|
||||
```
|
||||
|
||||
### Publish to npmjs and GPR with npm:
|
||||
## Publish to npmjs and GPR with npm
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -94,7 +176,7 @@ steps:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
### Publish to npmjs and GPR with yarn:
|
||||
## Publish to npmjs and GPR with yarn
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -114,7 +196,7 @@ steps:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
### Use private packages:
|
||||
## Use private packages
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
Generated
+1941
-6368
File diff suppressed because it is too large
Load Diff
+7
-7
@@ -23,25 +23,25 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^1.0.7",
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/cache": "^1.0.8",
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/github": "^1.1.0",
|
||||
"@actions/glob": "^0.2.0",
|
||||
"@actions/http-client": "^1.0.6",
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@actions/io": "^1.0.2",
|
||||
"@actions/tool-cache": "^1.5.4",
|
||||
"semver": "^6.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.13",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^12.0.4",
|
||||
"@types/semver": "^6.0.0",
|
||||
"@zeit/ncc": "^0.21.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-circus": "^24.7.1",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^1.19.1",
|
||||
"ts-jest": "^24.3.0",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -11,7 +11,10 @@ import {
|
||||
PackageManagerInfo
|
||||
} from './cache-utils';
|
||||
|
||||
export const restoreCache = async (packageManager: string) => {
|
||||
export const restoreCache = async (
|
||||
packageManager: string,
|
||||
cacheDependencyPath?: string
|
||||
) => {
|
||||
const packageManagerInfo = await getPackageManagerInfo(packageManager);
|
||||
if (!packageManagerInfo) {
|
||||
throw new Error(`Caching for '${packageManager}' is not supported`);
|
||||
@@ -22,15 +25,24 @@ export const restoreCache = async (packageManager: string) => {
|
||||
packageManagerInfo,
|
||||
packageManager
|
||||
);
|
||||
const lockFilePath = findLockFile(packageManagerInfo);
|
||||
const lockFilePath = cacheDependencyPath
|
||||
? cacheDependencyPath
|
||||
: findLockFile(packageManagerInfo);
|
||||
const fileHash = await glob.hashFiles(lockFilePath);
|
||||
|
||||
if (!fileHash) {
|
||||
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}`);
|
||||
|
||||
core.saveState(State.CachePrimaryKey, primaryKey);
|
||||
|
||||
const cacheKey = await cache.restoreCache([cachePath], primaryKey);
|
||||
core.setOutput('cache-hit', Boolean(cacheKey));
|
||||
|
||||
if (!cacheKey) {
|
||||
core.info(`${packageManager} cache is not found`);
|
||||
|
||||
@@ -4,6 +4,14 @@ import fs from 'fs';
|
||||
import {State} from './constants';
|
||||
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||
process.on('uncaughtException', e => {
|
||||
const warningPrefix = '[warning]';
|
||||
core.info(`${warningPrefix}${e.message}`);
|
||||
});
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
const cacheLock = core.getInput('cache');
|
||||
|
||||
+9
-2
@@ -30,9 +30,16 @@ export const supportedPackageManagers: SupportedPackageManagers = {
|
||||
};
|
||||
|
||||
export const getCommandOutput = async (toolCommand: string) => {
|
||||
const {stdout, stderr, exitCode} = await exec.getExecOutput(toolCommand);
|
||||
let {stdout, stderr, exitCode} = await exec.getExecOutput(
|
||||
toolCommand,
|
||||
undefined,
|
||||
{ignoreReturnCode: true}
|
||||
);
|
||||
|
||||
if (stderr) {
|
||||
if (exitCode) {
|
||||
stderr = !stderr.trim()
|
||||
? `The '${toolCommand}' command failed with exit code: ${exitCode}`
|
||||
: stderr;
|
||||
throw new Error(stderr);
|
||||
}
|
||||
|
||||
|
||||
+11
-3
@@ -71,8 +71,7 @@ export async function getNode(
|
||||
toolPath = tc.find('node', versionSpec, osArch);
|
||||
|
||||
// If not found in cache, download
|
||||
// Usage of pre-cached Node.js versions is temporarily disabled.
|
||||
if (false) {
|
||||
if (toolPath) {
|
||||
core.info(`Found in cache @ ${toolPath}`);
|
||||
} else {
|
||||
core.info(`Attempting to download ${versionSpec}...`);
|
||||
@@ -372,7 +371,7 @@ async function queryDistForMatch(
|
||||
}
|
||||
|
||||
let versions: string[] = [];
|
||||
let nodeVersions = await module.exports.getVersionsFromDist();
|
||||
let nodeVersions = await getVersionsFromDist();
|
||||
|
||||
nodeVersions.forEach((nodeVersion: INodeVersion) => {
|
||||
// ensure this version supports your os and platform
|
||||
@@ -465,3 +464,12 @@ function translateArchToDistUrl(arch: string): string {
|
||||
return arch;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseNodeVersionFile(contents: string): string {
|
||||
let nodeVersion = contents.trim();
|
||||
|
||||
if (/^v\d/.test(nodeVersion)) {
|
||||
nodeVersion = nodeVersion.substring(1);
|
||||
}
|
||||
return nodeVersion;
|
||||
}
|
||||
|
||||
+39
-7
@@ -1,5 +1,6 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as installer from './installer';
|
||||
import fs from 'fs';
|
||||
import * as auth from './authutil';
|
||||
import * as path from 'path';
|
||||
import {restoreCache} from './cache-restore';
|
||||
@@ -12,10 +13,7 @@ export async 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...
|
||||
//
|
||||
let version = core.getInput('node-version');
|
||||
if (!version) {
|
||||
version = core.getInput('version');
|
||||
}
|
||||
let version = resolveVersionInput();
|
||||
|
||||
let arch = core.getInput('architecture');
|
||||
const cache = core.getInput('cache');
|
||||
@@ -51,7 +49,8 @@ export async function run() {
|
||||
if (isGhes()) {
|
||||
throw new Error('Caching is not supported on GHES');
|
||||
}
|
||||
await restoreCache(cache);
|
||||
const cacheDependencyPath = core.getInput('cache-dependency-path');
|
||||
await restoreCache(cache, cacheDependencyPath);
|
||||
}
|
||||
|
||||
const matchersPath = path.join(__dirname, '../..', '.github');
|
||||
@@ -62,8 +61,8 @@ export async function run() {
|
||||
core.info(
|
||||
`##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}`
|
||||
);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
} catch (err) {
|
||||
core.setFailed(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,3 +72,36 @@ function isGhes(): boolean {
|
||||
);
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
}
|
||||
|
||||
function resolveVersionInput(): string {
|
||||
let version = core.getInput('node-version') || core.getInput('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 = installer.parseNodeVersionFile(
|
||||
fs.readFileSync(versionFilePath, 'utf8')
|
||||
);
|
||||
core.info(`Resolved ${versionFileInput} as ${version}`);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
"compilerOptions": {
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"sourceMap": true,
|
||||
|
||||
Reference in New Issue
Block a user