Compare commits

...

95 Commits

Author SHA1 Message Date
dependabot[bot]
c2ac33f2c6
Bump undici from 5.26.5 to 5.28.3 (#965)
* Bump undici from 5.26.5 to 5.28.3

Bumps [undici](https://github.com/nodejs/undici) from 5.26.5 to 5.28.3.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.26.5...v5.28.3)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* license and other dependencies update

* updated licenses

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HarithaVattikuti <73516759+HarithaVattikuti@users.noreply.github.com>
2024-03-13 09:10:22 -05:00
Ben Greeley
25b062c917
Update README.md to update default Node version to 20 (#949)
The README's default example for setting up Node use version 16, which is at end of life. This PR updates those examples to use 20.
2024-02-13 11:33:00 -06:00
Dmitry Shibanov
60edb5dd54
Add support for arm64 Windows (#927)
* add support for arm64 Windows

* revert 7z to exe

* add comment

---------

Co-authored-by: aparnajyothi-y <147696841+aparnajyothi-y@users.noreply.github.com>
2024-02-06 22:42:16 -06:00
Manta Anantachai S
d86ebcd40b
Add support for volta.extends (#921)
* Add support for `volta.extends`

* Code review
2023-12-29 15:01:21 +05:30
NullVoxPopuli
b39b52d121
Fix node-version-file interprets entire package.json as a version (#865) 2023-12-14 13:53:26 +01:00
Róbert Papp
7247617371
Add package.json to node-version-file list of examples. (#879) 2023-12-13 13:02:47 +01:00
fusagiko / takayamaki
f3ec4ca66f
Fix README.md (#898)
* Fix URL of locally-cached Node.js version in README

* Change example of Major versions in Supported version syntax

setup-node v4 supports node v20, but these example may
cause misunderstanding like a v20 is not supported.

---------

Co-authored-by: fusagiko/takayamaki <takayamaki@users.noreply.github.com>
2023-12-13 12:46:19 +01:00
aparnajyothi-y
ec97f37504
Add fix for cache (#917) 2023-12-13 12:42:40 +01:00
MaksimZhukov
5ef044f9d0
Update reusable workflows to use Node.js v20 (#889) 2023-11-13 17:32:30 +01:00
Joel Wetzell
c45882a6ea
update to setup-node@v4 in docs (#884) 2023-11-13 17:02:44 +01:00
Trivikram Kamat
ee36e8b5c0
Ignore engines check in Yarn 1 e2e-cache tests (#882) 2023-11-10 15:16:46 +01:00
Dmitry Shibanov
8f152de45c
Update actions/checkout for documentation and yaml (#876) 2023-10-23 16:22:01 +02:00
Guillaume Membré
23755b521f
upgrade actions/checkout to v4 (#868) 2023-10-23 15:57:08 +02:00
Dmitry Shibanov
54534a2a9b
Change node version for action to node20 (#866) 2023-10-23 15:20:20 +02:00
Dmitry Shibanov
1a4442cacd
Update toolkit cache and core (#875) 2023-10-23 12:20:07 +02:00
Nikolai Laevskii
6e9e44895f
Merge pull request #872 from akv-platform/add-notice-about-binaries-not-being-updated
Add notice about binaries not being updated yet
2023-10-19 17:20:27 +02:00
Nikolai Laevskii
e52912ef25 Update tests 2023-10-19 17:12:39 +02:00
Nikolai Laevskii
ac16ae42d7 Update message to use waning instead of info 2023-10-19 16:59:10 +02:00
Nikolai Laevskii
5a8d9111e3 Update build 2023-10-19 14:31:08 +02:00
Nikolai Laevskii
9e956a555c Add notice about binaries not being updated yet 2023-10-19 13:43:56 +02:00
dependabot[bot]
7da2a7eb0c
Bump @babel/traverse from 7.15.4 to 7.23.2 (#870) 2023-10-19 10:40:59 +02:00
Nikolai Laevskii
2a017f350d
Merge pull request #859 from actions/update-temp-directory-creation
Update temp directory creation
2023-10-09 07:12:35 +02:00
Dmitry Shibanov
72c43c2d8f
Update semver (#861) 2023-09-27 12:57:35 +02:00
Nikolai Laevskii
d3ace34546 Update build 2023-09-25 16:37:45 +02:00
Nikolai Laevskii
acbf0586b1 Fix typo 2023-09-25 15:58:01 +02:00
Nikolai Laevskii
f1744b62b7 Update license 2023-09-25 15:58:01 +02:00
Nikolai Laevskii
2651591c72 Update temporary directory creation 2023-09-25 15:58:01 +02:00
Dmitry Shibanov
5e21ff4d9b
Remove filter for cached paths (#831) 2023-08-15 15:53:46 +02:00
Dmitry Shibanov
bea5baf987
change getinput to getstate for cache (#816) 2023-08-10 16:32:24 +02:00
dependabot[bot]
d82f92a0eb
Bump word-wrap from 1.2.3 to 1.2.4 (#815)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-04 09:56:30 +02:00
Vytis Valentinavičius
ca2d4e0cdd
feat: handling the case where "node" is used for tool-versions file. (#812) 2023-07-18 13:01:34 +02:00
Dmitry Shibanov
c7a93deeac
resolve SymbolicLink (#809) 2023-07-13 14:06:23 +02:00
Dmitry Shibanov
34050076a5
Add check for existing paths (#803) 2023-07-13 14:03:41 +02:00
Jeff Wen
f8aa08ed8e
Update check-dist workflow name (#710) 2023-07-12 19:35:39 +02:00
Louis Lam
e2d34eacc8
Fix armv7 cache issue (#794) 2023-07-12 16:09:57 +02:00
dependabot[bot]
ef9c88b169
Bump semver from 6.1.2 to 6.3.1 (#807) 2023-07-12 13:17:54 +02:00
dependabot[bot]
ea800d4ebc
Bump tough-cookie and @azure/ms-rest-js (#802) 2023-07-12 12:47:57 +02:00
Dmitry Shibanov
cb95c398f6
Update toolkit cache to fix zstd (#804) 2023-07-12 12:13:18 +02:00
Olle Jonsson
69b2dd252e
Refer to semver package name in README.md (#808) 2023-07-11 10:03:08 +02:00
Sergey Dolin
e33196f742
Do not ivalidate the cache entirely on lock file change (#744)
* Do not ivalidate the cache entirely on yarn3 lock file change

* Use cache prefix if all sub-projects are yarn managed

* Rename functions & add e2e tests
2023-06-27 13:07:43 +02:00
Dmitry Shibanov
c6722d36aa
update doc for frozen lock file (#789) 2023-06-22 15:55:14 +02:00
Sergey Dolin
8170e22e8f
Detect cached folders from multiple directories (#735)
* Add project-dir

* Fix find lock file

* Remove package-dir input

* format & resolve conflicts

* Add unit tests

* build dist

* Apply change request fixes

* handle non-dir cache-dependency-path

* bump cache version

* run checks

* Handle globs in cacheDependencyPath

* refactor, introduce `cacheDependencyPathToProjectsDirectories`

it is necessary for the next PR related yarn optimization

* Changes requests

* Apply fixes

* review fixes

* add e2e

* Add unique

* review updates

* review updates second stage

* Review fixes 3

* imporve e2e tests
2023-06-21 17:52:17 +02:00
Muhun Kim
698d50532e
Fix description about ensuring workflow access to private package (#704) 2023-06-15 17:10:28 +02:00
Marko Zivic
869f4dd0c7
Merge pull request #758 from akv-platform/remove-implicit-dependencies
Remove implicit dependencies
2023-05-26 08:31:08 +02:00
Nikolai Laevskii
10efafcbcf Update canary version in tests to an existing one 2023-05-25 14:57:36 +02:00
Nikolai Laevskii
7d16907b89 Add missing dependency 2023-05-23 16:33:19 +02:00
Nikolai Laevskii
d0d39bda2f Move eslint-plugin-node to dev dependencies 2023-05-23 11:58:21 +02:00
Nikolai Laevskii
15a2477e08 Install eslint-plugin-node 2023-05-23 11:43:00 +02:00
github-actions[bot]
7598dbcd6e Update configuration files 2023-05-23 08:38:21 +00:00
Philip Harrison
a9893b0cfb
Update to node 18.x (#751) 2023-05-10 16:04:46 +02:00
Dmitry Shibanov
5b32c9063c
Update xml2js (#742) 2023-04-20 12:55:12 +02:00
Adam Jones
d98fa11138
bugfix: Don't attempt to use Windows fallbacks on non-Windows OSes (#718) 2023-04-11 09:31:41 +02:00
Dmitry Shibanov
9d255ef245
Adjust usage section (#734) 2023-04-06 10:52:43 +02:00
Ivan
e828f9b7f3
Fix glob bug in package.json scripts section (#729) 2023-04-03 12:46:05 +02:00
github-actions[bot]
a4fcaaf314
Update configuration files (#708)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-03-15 00:27:36 +01:00
Marko Zivic
10f5623502
Merge pull request #705 from akv-platform/reusable-workflow
Turn on automatic update of ESLint and Prettier configuration files
2023-03-10 10:55:11 +01:00
IvanZosimov
fcd18100cc Add update-config-files.yml 2023-03-08 11:13:04 +01:00
Ivan
962678f22c
Add and configure ESLint and update configuration for Prettier (#703)
* Add ESLinter and update Prettier

* Update eslint config

* Update dependencies

* Rebuild action

* Update package.json

* Updates docs

* Update docs
2023-03-08 10:47:38 +02:00
Mark
7c29869aec
docs: fix typo in advanced-usage.md (#697) 2023-02-20 11:15:36 +01:00
Ivan
ae9f0f7448
Update workflow badges (#685) 2023-01-31 08:45:30 +02:00
MaksimZhukov
3dbcda8bc2
Update release-new-action-version.yml (#664) 2023-01-12 13:50:58 +01:00
Phan An
f38519bb96
Fix a minor typo (#662) 2023-01-11 01:01:08 +01:00
Jongwoo Han
9227cda3f0
Replace workflow badge with new badge (#653) 2023-01-10 10:59:38 +01:00
Dmitry Shibanov
64ed1c7eab
Add support for v8-canary, nightly and rc (#655) 2023-01-05 13:16:21 +01:00
Marko Zivic
92a57f4a93
Merge pull request #650 from actions/update-code-owners
Update CODEOWNERS
2022-12-27 09:28:45 +01:00
Evgenii Korolevskii
99e61d697a
Update CODEOWNERS 2022-12-26 09:44:31 +01:00
Marko Zivic
3e8819f8f2
Merge pull request #649 from actions/update-codeowners
Update CODEOWNERS
2022-12-23 08:27:39 +01:00
Evgenii Korolevskii
8cd2fb28b8
Update CODEOWNERS 2022-12-23 00:07:20 +01:00
Ivan
c406543918
Merge pull request #647 from akv-platform/apply-reusable-workflows
Update action to use reusable workflows
2022-12-22 10:48:47 +02:00
IvanZosimov
92a07fe466 Fix review points 2022-12-20 16:40:38 +01:00
IvanZosimov
217387cf3e Update action to use reusable-workflows repo 2022-12-19 13:43:06 +01:00
IvanZosimov
2db3663870 Merge branch 'main' of https://github.com/akv-platform/setup-node into apply-reusable-workflows 2022-12-19 13:41:43 +01:00
Evan Mattson
bbe2ac79a1
Fix typo in README (#646) 2022-12-19 10:12:38 +01:00
IvanZosimov
f5ab623822 Add links to reusable workflows 2022-12-15 16:39:43 +01:00
IvanZosimov
ca97bf7f80 Update workflows 2022-12-15 16:09:18 +01:00
IvanZosimov
fe4d514f1a Update codeql-analysis workflow 2022-12-15 15:05:14 +01:00
IvanZosimov
8151ea11a4 Setup codeql-analysis workflow 2022-12-15 14:41:30 +01:00
IvanZosimov
772ffdda26 Update package.json 2022-12-14 13:44:44 +01:00
IvanZosimov
da188081b1 Update workflows to use reusable-workflows 2022-12-14 13:42:03 +01:00
Sergey Dolin
377c6dae40
Merge pull request #639 from akv-platform/v-sdolin/early-return
Use early return pattern to avoid nested conditions
2022-12-12 11:12:53 +01:00
Sergey Dolin
b28830cbe2 replace throw with warn 2022-12-12 10:21:16 +01:00
Sergey Dolin
676975d9aa Use early return pattern 2022-12-09 11:41:54 +01:00
Sergey Dolin
d1b197b965
Merge pull request #637 from akv-platform/v-sdolin/npmrc-dup
Fix scoped registries are duplicated in npmrc
2022-12-06 12:14:53 +01:00
Sergey Dolin
069a4f8926 Add dist 2022-12-05 13:37:05 +01:00
Sergey Dolin
e77eaaccd3 Add unit tests 2022-12-05 13:36:23 +01:00
Sergey Dolin
a69d45adcd Add modification of scoped registry 2022-12-05 13:32:26 +01:00
James M. Greene
3ae886ede4
Update to latest actions/publish-action (#630) 2022-11-28 19:06:52 +01:00
Sergey Dolin
41acaa2e85
fix version output from file (#625) 2022-11-17 14:43:40 +01:00
Dmitry Shibanov
2349c84f5c
Add support for nightly and rc versions (#611) 2022-11-17 14:35:58 +01:00
Dmitry Shibanov
6bc15ab23c
Update minimatch (#608) 2022-11-14 13:34:05 +01:00
Dmitry Shibanov
9b8fcdc725
change datadog to ubuntu docker image (#620) 2022-11-09 18:18:47 +01:00
Dmitry Shibanov
00e1b6691b
Pass the token input through on GHES (#595) 2022-11-02 12:24:44 +01:00
Dmitry Shibanov
16352bb09b
Get rid of warnings for set-output (#607) 2022-10-25 16:37:59 +02:00
Dmitry Shibanov
788c6ccbd0
remove node-version 12 from matrix (#594) 2022-10-17 12:23:04 +02:00
Francesco Renzi
8c91899e58
Update @actions/core to 1.10.0 (#587) 2022-10-13 12:11:08 +02:00
142 changed files with 82783 additions and 38655 deletions

6
.eslintignore Normal file
View File

@ -0,0 +1,6 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!src/

51
.eslintrc.js Normal file
View File

@ -0,0 +1,51 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:eslint-plugin-jest/recommended',
'eslint-config-prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
rules: {
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-ignore': 'allow-with-description'
}
],
'no-console': 'error',
'yoda': 'error',
'prefer-const': [
'error',
{
destructuring: 'all'
}
],
'no-control-regex': 'off',
'no-constant-condition': ['error', {checkLoops: false}],
'node/no-extraneous-import': 'error'
},
overrides: [
{
files: ['**/*{test,spec}.ts'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'jest/no-standalone-expect': 'off',
'jest/no-conditional-expect': 'off',
'no-console': 'off',
}
}
],
env: {
node: true,
es6: true,
'jest/globals': true
}
};

1
.gitattributes vendored
View File

@ -1 +1,2 @@
* text=auto eol=lf
.licenses/** -diff linguist-generated=true

19
.github/workflows/basic-validation.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Basic validation
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
jobs:
call-basic-validation:
name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with:
node-version: '20.x'

View File

@ -1,30 +0,0 @@
name: build-test
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- name: Setup Node 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- run: npm ci
- run: npm run build
- run: npm run format-check
- run: npm test

View File

@ -1,9 +1,4 @@
# `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/
name: Check dist
on:
push:
@ -17,36 +12,8 @@ on:
workflow_dispatch:
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node 16.x
uses: actions/setup-node@v3
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@v3
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with:
name: dist
path: dist/
call-check-dist:
name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with:
node-version: '20.x'

14
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: CodeQL analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 3 * * 0'
jobs:
call-codeQL-analysis:
name: CodeQL analysis
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main

View File

@ -21,7 +21,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [12, 14, 16]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Clean global cache
run: npm cache clean --force
- name: Setup Node
@ -44,7 +44,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [12, 14, 16]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
@ -75,9 +75,9 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [12, 14, 16]
node-version: [14, 16]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Yarn version
run: yarn --version
- name: Generate yarn file
@ -93,13 +93,13 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Install dependencies
run: yarn install
run: yarn install --ignore-engines
- name: Verify node and yarn
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash
node-yarn2-depencies-caching:
name: Test yarn 2 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
node-yarn3-depencies-caching:
name: Test yarn 3 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
@ -109,9 +109,9 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [12, 14, 16]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Update yarn
run: yarn set version berry
run: yarn set version 3.6.4
- name: Yarn version
run: yarn --version
- name: Generate simple .yarnrc.yml
@ -134,3 +134,112 @@ jobs:
- name: Verify node and yarn
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash
yarn-subprojects:
name: Test yarn subprojects
strategy:
matrix:
node-version: [12, 14, 16]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh yarn1
# expect
# - no errors
# - log
# ##[debug]Cache Paths:
# ##[debug]["sub2/.yarn/cache","sub3/.yarn/cache","../../../.cache/yarn/v6"]
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
**/*.lock
yarn.lock
yarn-subprojects-berry-local:
name: Test yarn subprojects all locally managed
strategy:
matrix:
node-version: [12, 14, 16]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh keepcache keepcache
# expect
# - no errors
# - log
# ##[info]All dependencies are managed locally by yarn3, the previous cache can be used
# ##[debug]["node-cache-Linux-yarn-401024703386272f1a950c9f014cbb1bb79a7a5b6e1fb00e8b90d06734af41ee","node-cache-Linux-yarn"]
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
sub2/*.lock
sub3/*.lock
yarn-subprojects-berry-global:
name: Test yarn subprojects some locally managed
strategy:
matrix:
node-version: [12, 14, 16]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh global
# expect
# - no errors
# - log must
# ##[debug]"/home/runner/work/setup-node-test/setup-node-test/sub2" dependencies are managed by yarn 3 locally
# ##[debug]"/home/runner/work/setup-node-test/setup-node-test/sub3" dependencies are not managed by yarn 3 locally
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
sub2/*.lock
sub3/*.lock
yarn-subprojects-berry-git:
name: Test yarn subprojects managed by git
strategy:
matrix:
node-version: [12, 14, 16]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: prepare sub-projects
run: /bin/bash __tests__/prepare-yarn-subprojects.sh keepcache
# expect
# - no errors
# - log
# [debug]"/home/runner/work/setup-node-test/setup-node-test/sub2" has .yarn/cache - dependencies are kept in the repository
# [debug]"/home/runner/work/setup-node-test/setup-node-test/sub3" has .yarn/cache - dependencies are kept in the repository
# [debug]["node-cache-Linux-yarn-401024703386272f1a950c9f014cbb1bb79a7a5b6e1fb00e8b90d06734af41ee"]
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
sub2/*.lock
sub3/*.lock

View File

@ -7,18 +7,9 @@ on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v3
- run: npm ci
- name: Install licensed
run: |
cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz
sudo tar -xzf licensed.tar.gz
sudo mv licensed /usr/local/bin/licensed
- run: licensed status
call-licensed:
name: Licensed
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main

View File

@ -19,13 +19,13 @@ jobs:
options: --dns 127.0.0.1
services:
squid-proxy:
image: datadog/squid:latest
image: ubuntu/squid:latest
ports:
- 3128:3128
env:
https_proxy: http://squid-proxy:3128
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 14
@ -41,7 +41,7 @@ jobs:
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
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 11

View File

@ -1,4 +1,5 @@
name: Release new action version
on:
release:
types: [released]
@ -20,8 +21,8 @@ jobs:
name: releaseNewActionVersion
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.1.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.2.2
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@ -0,0 +1,11 @@
name: Update configuration files
on:
schedule:
- cron: '0 3 * * 0'
workflow_dispatch:
jobs:
call-update-configuration-files:
name: Update configuration files
uses: actions/reusable-workflows/.github/workflows/update-config-files.yml@main

View File

@ -20,7 +20,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
@ -37,7 +37,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [lts/dubnium, lts/erbium, lts/fermium, lts/*, lts/-1]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
@ -51,6 +51,72 @@ jobs:
__tests__/verify-node.sh "${BASH_REMATCH[1]}"
shell: bash
v8-canary-syntax:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version:
[
'20-v8-canary',
'20.0.0-v8-canary',
'20.0.0-v8-canary20221101e50e45c9f8'
]
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
- name: Verify node and npm
run: |
canaryVersion="${{ matrix.node-version }}"
majorVersion=$(echo $canaryVersion | cut -d- -f1)
__tests__/verify-node.sh "$majorVersion"
shell: bash
nightly-syntax:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version:
[16.0.0-nightly20210420a0261d231c, 17-nightly, 18.0.0-nightly]
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
- name: Verify node and npm
run: |
nightlyVersion="${{ matrix.node-version }}"
majorVersion=$(echo $nightlyVersion | cut -d- -f1)
__tests__/verify-node.sh "$majorVersion"
shell: bash
rc-syntax:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16.0.0-rc.1, 18.0.0-rc.2, 19.0.0-rc.0]
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
- name: Verify node and npm
run: |
rcVersion="${{ matrix.node-version }}"
majorVersion=$(echo $rcVersion | cut -d- -f1)
__tests__/verify-node.sh "$majorVersion"
shell: bash
manifest:
runs-on: ${{ matrix.os }}
strategy:
@ -59,7 +125,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10.15, 12.16.0, 14.2.0, 16.3.0]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
@ -76,7 +142,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node and check latest
uses: ./
with:
@ -92,12 +158,10 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version-file: [.nvmrc, .tool-versions, package.json]
node-version-file:
[.nvmrc, .tool-versions, .tool-versions-node, package.json]
steps:
- uses: actions/checkout@v3
- name: Remove volta from package.json
shell: bash
run: cat <<< "$(jq 'del(.volta)' ./__tests__/data/package.json)" > ./__tests__/data/package.json
- uses: actions/checkout@v4
- name: Setup node from node version file
uses: ./
with:
@ -110,13 +174,28 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup node from node version file
uses: ./
with:
node-version-file: '__tests__/data/package.json'
node-version-file: '__tests__/data/package-volta.json'
- name: Verify node
run: __tests__/verify-node.sh 16
version-file-volta-extends:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Setup node from node version file
uses: ./
with:
node-version-file: '__tests__/data/package-volta-extends.json'
- name: Verify node
run: __tests__/verify-node.sh 16
@ -128,7 +207,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [11, 13]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node from dist
uses: ./
with:
@ -144,7 +223,7 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# test old versions which didn't have npm and layout different
- name: Setup node 0.12.18 from dist
uses: ./
@ -157,7 +236,7 @@ jobs:
arch:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup node 14 x86 from dist
uses: ./
with:
@ -178,10 +257,10 @@ jobs:
- name: Get node version
run: |
latestNodeVersion=$(curl https://nodejs.org/dist/index.json | jq -r '. [0].version')
echo "::set-output name=LATEST_NODE_VERSION::$latestNodeVersion"
echo "LATEST_NODE_VERSION=$latestNodeVersion" >> $GITHUB_OUTPUT
id: version
shell: bash
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Node
uses: ./
with:
@ -189,7 +268,7 @@ jobs:
- name: Retrieve version after install
run: |
updatedVersion=$(echo $(node --version))
echo "::set-output name=NODE_VERSION_UPDATED::$updatedVersion"
echo "NODE_VERSION_UPDATED=$updatedVersion" >> $GITHUB_OUTPUT
id: updatedVersion
shell: bash
- name: Compare versions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

7
.prettierignore Normal file
View File

@ -0,0 +1,7 @@
# Ignore list
/*
# Do not ignore these folders:
!__tests__/
!.github/
!src/

11
.prettierrc.js Normal file
View File

@ -0,0 +1,11 @@
// This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
trailingComma: 'none',
bracketSpacing: false,
arrowParens: 'avoid'
};

View File

@ -1,11 +0,0 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

View File

@ -1 +1 @@
* @actions/actions-service
* @actions/setup-actions-team

128
README.md
View File

@ -1,7 +1,8 @@
# setup-node
[![build-test](https://github.com/actions/setup-node/actions/workflows/build-test.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/build-test.yml)
[![basic-validation](https://github.com/actions/setup-node/actions/workflows/basic-validation.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/basic-validation.yml)
[![versions](https://github.com/actions/setup-node/actions/workflows/versions.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/versions.yml)
[![e2e-cache](https://github.com/actions/setup-node/actions/workflows/e2e-cache.yml/badge.svg?branch=main)](https://github.com/actions/setup-node/actions/workflows/e2e-cache.yml)
[![proxy](https://github.com/actions/setup-node/actions/workflows/proxy.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/proxy.yml)
This action provides the following functionality for GitHub Actions users:
@ -15,14 +16,77 @@ This action provides the following functionality for GitHub Actions users:
See [action.yml](action.yml)
<!-- start usage -->
```yaml
- uses: actions/setup-node@v4
with:
# Version Spec of the version to use in SemVer notation.
# It also emits such aliases as lts, latest, nightly and canary builds
# Examples: 12.x, 10.15.1, >=10.15.0, lts/Hydrogen, 16-nightly, latest, node
node-version: ''
# File containing the version Spec of the version to use. Examples: package.json, .nvmrc, .node-version, .tool-versions.
# If node-version and node-version-file are both provided the action will use version from node-version.
node-version-file: ''
# Set this option if you want the action to check for the latest available version
# that satisfies the version spec.
# It will only get affect for lts Nodejs versions (12.x, >=10.15.0, lts/Hydrogen).
# Default: false
check-latest: false
# Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.
# Default: ''. The action use system architecture by default
architecture: ''
# Used to pull node distributions from https://github.com/actions/node-versions.
# Since there's a default, this is typically not supplied by the user.
# When running this action on github.com, the default value is sufficient.
# When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting.
#
# We recommend using a service account with the least permissions necessary. Also
# when generating a new PAT, select the least scopes necessary.
#
# [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
#
# Default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
token: ''
# Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.
# Package manager should be pre-installed
# Default: ''
cache: ''
# Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc.
# It will generate hash from the target file for primary key. It works only If cache is specified.
# Supports wildcards or a list of file names for caching multiple dependencies.
# Default: ''
cache-dependency-path: ''
# Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file,
# and set up auth to read in from env.NODE_AUTH_TOKEN.
# Default: ''
registry-url: ''
# Optional scope for authenticating against scoped registries.
# Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/).
# Default: ''
scope: ''
# Set always-auth option in npmrc file.
# Default: ''
always-auth: ''
```
<!-- end usage -->
**Basic:**
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
node-version: 18
- run: npm ci
- run: npm test
```
@ -35,16 +99,16 @@ For information regarding locally cached versions of Node.js on GitHub hosted ru
### Supported version syntax
The `node-version` input supports the Semantic Versioning Specification, for more detailed examples please refer to the [documentation](https://github.com/npm/node-semver).
The `node-version` input supports the Semantic Versioning Specification, for more detailed examples please refer to [the semver package documentation](https://github.com/npm/node-semver).
Examples:
- Major versions: `14`, `16`, `18`
- Major versions: `18`, `20`
- More specific versions: `10.15`, `16.15.1` , `18.4.0`
- NVM LTS syntax: `lts/erbium`, `lts/fermium`, `lts/*`, `lts/-n`
- Latest release: `*` or `latest`/`current`/`node`
**Note:** Like the other values, `*` will get the latest [locally-cached Node.js version](https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md#nodejs), or the latest version from [actions/node-versions](https://github.com/actions/node-versions/blob/main/versions-manifest.json), depending on the [`check-latest`](docs/advanced-usage.md#check-latest-version) input.
**Note:** Like the other values, `*` will get the latest [locally-cached Node.js version](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md#nodejs), or the latest version from [actions/node-versions](https://github.com/actions/node-versions/blob/main/versions-manifest.json), depending on the [`check-latest`](docs/advanced-usage.md#check-latest-version) input.
`current`/`latest`/`node` always resolve to the latest [dist version](https://nodejs.org/dist/index.json).
That version is then downloaded from actions/node-versions if possible, or directly from Node.js if not.
@ -68,10 +132,10 @@ See the examples of using cache for `yarn`/`pnpm` and `cache-dependency-path` in
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test
@ -81,10 +145,10 @@ steps:
```yaml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16
node-version: 20
cache: 'npm'
cache-dependency-path: subdir/package-lock.json
- run: npm ci
@ -102,25 +166,43 @@ jobs:
node: [ 14, 16, 18 ]
name: Node ${{ matrix.node }} sample
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
```
## Using `setup-node` on GHES
`setup-node` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Nodejs distributions, `setup-node` downloads distributions from [`actions/node-versions`](https://github.com/actions/node-versions) on github.com (outside of the appliance). These calls to `actions/node-versions` are made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then you will start to see rate-limit errors during downloading that looks like: `##[error]API rate limit exceeded for...`. After that error the action will try to download versions directly from the official site, but it also can have rate limit so it's better to put token.
To get a higher rate limit, you can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action:
```yaml
uses: actions/setup-node@v4
with:
token: ${{ secrets.GH_DOTCOM_TOKEN }}
node-version: 20
```
If the runner is not able to access github.com, any Nodejs versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.
## Advanced usage
1. [Check latest version](docs/advanced-usage.md#check-latest-version)
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 data](docs/advanced-usage.md#caching-packages-data)
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)
- [Check latest version](docs/advanced-usage.md#check-latest-version)
- [Using a node version file](docs/advanced-usage.md#node-version-file)
- [Using different architectures](docs/advanced-usage.md#architecture)
- [Using v8 canary versions](docs/advanced-usage.md#v8-canary-versions)
- [Using nightly versions](docs/advanced-usage.md#nightly-versions)
- [Using rc versions](docs/advanced-usage.md#rc-versions)
- [Caching packages data](docs/advanced-usage.md#caching-packages-data)
- [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
- [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
- [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
- [Using private packages](docs/advanced-usage.md#use-private-packages)
## License

10
__tests__/README.md Normal file
View File

@ -0,0 +1,10 @@
Files located in data directory are used only for testing purposes.
## Here the list of files in the data directory
- `.nvmrc`, `.tools-versions` and `package.json` are used to test node-version-file logic
- `package-lock.json`, `pnpm-lock.yaml` and `yarn.lock` are used to test cache logic
- `versions-manifest.json` is used for unit testing to check downloading Node.js versions from the node-versions repository.
- `node-dist-index.json` is used for unit testing to check downloading Node.js versions from the official site. The file was constructed from https://nodejs.org/dist/index.json
- `node-rc-index.json` is used for unit testing to check downloading Node.js rc versions from the official site. The file was constructed from https://nodejs.org/download/rc/index.json
- `node-nightly-index.json` is used for unit testing to check downloading Node.js nightly builds from the official site. The file was constructed from https://nodejs.org/download/nightly/index.json

View File

@ -1,9 +1,10 @@
import os = require('os');
import * as fs from 'fs';
import os from 'os';
import fs from 'fs';
import * as path from 'path';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as auth from '../src/authutil';
import * as cacheUtils from '../src/cache-utils';
let rcFile: string;
@ -15,11 +16,7 @@ describe('authutil tests', () => {
let dbgSpy: jest.SpyInstance;
beforeAll(async () => {
const randPath = path.join(
Math.random()
.toString(36)
.substring(7)
);
const randPath = path.join(Math.random().toString(36).substring(7));
console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions
process.env['GITHUB_ENV'] = ''; // Stub out Environment file functionality so we can verify it writes to standard out (toolkit is backwards compatible)
const tempDir = path.join(_runnerDir, randPath, 'temp');
@ -67,10 +64,10 @@ describe('authutil tests', () => {
}, 100000);
function readRcFile(rcFile: string) {
let rc = {};
let contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
const rc = {};
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
for (const line of contents.split(os.EOL)) {
let parts = line.split('=');
const parts = line.split('=');
if (parts.length == 2) {
rc[parts[0].trim()] = parts[1].trim();
}
@ -82,8 +79,8 @@ describe('authutil tests', () => {
await auth.configAuthentication('https://registry.npmjs.org/', 'false');
expect(fs.statSync(rcFile)).toBeDefined();
let contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
let rc = readRcFile(rcFile);
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
});
@ -92,7 +89,7 @@ describe('authutil tests', () => {
await auth.configAuthentication('https://registry.npmjs.org', 'false');
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
});
@ -102,7 +99,7 @@ describe('authutil tests', () => {
await auth.configAuthentication('https://registry.npmjs.org', 'false');
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
const rc = readRcFile(rcFile);
expect(rc['@myscope:registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
});
@ -111,7 +108,7 @@ describe('authutil tests', () => {
await auth.configAuthentication('npm.pkg.github.com', 'false');
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
const rc = readRcFile(rcFile);
expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/');
expect(rc['always-auth']).toBe('false');
});
@ -119,17 +116,98 @@ describe('authutil tests', () => {
it('Sets up npmrc for always-auth true', async () => {
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('true');
});
it('It is already set the NODE_AUTH_TOKEN export it ', async () => {
it('is already set the NODE_AUTH_TOKEN export it', async () => {
process.env.NODE_AUTH_TOKEN = 'foobar';
await auth.configAuthentication('npm.pkg.github.com', 'false');
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
const rc = readRcFile(rcFile);
expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/');
expect(rc['always-auth']).toBe('false');
expect(process.env.NODE_AUTH_TOKEN).toEqual('foobar');
});
it('configAuthentication should overwrite non-scoped with non-scoped', async () => {
fs.writeFileSync(rcFile, 'registry=NNN');
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should overwrite only non-scoped', async () => {
fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`@myscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should add non-scoped to scoped', async () => {
fs.writeFileSync(rcFile, '@myscope:registry=NNN');
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`@myscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should overwrite scoped with scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `@myscope:registry=NNN`);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should overwrite only scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should add scoped to non-scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should overwrite only one scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(
rcFile,
`@otherscope:registry=NNN${os.EOL}@myscope:registry=MMM`
);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`@otherscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
it('configAuthentication should add scoped to another scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `@otherscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe(
`@otherscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
);
});
});

View File

@ -32,13 +32,13 @@ describe('cache-restore', () => {
function findCacheFolder(command: string) {
switch (command) {
case utils.supportedPackageManagers.npm.getCacheFolderCommand:
case 'npm config get cache':
return npmCachePath;
case utils.supportedPackageManagers.pnpm.getCacheFolderCommand:
case 'pnpm store path --silent':
return pnpmCachePath;
case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
case 'yarn cache dir':
return yarn1CachePath;
case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
case 'yarn config get cacheFolder':
return yarn2CachePath;
default:
return 'packge/not/found';
@ -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.toThrow(
`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}`
@ -163,7 +163,7 @@ describe('cache-restore', () => {
});
restoreCacheSpy.mockImplementationOnce(() => undefined);
await restoreCache(packageManager);
await restoreCache(packageManager, '');
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`${packageManager} cache is not found`

View File

@ -18,7 +18,7 @@ describe('run', () => {
const commonPath = '/some/random/path';
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
let inputs = {} as any;
const inputs = {} as any;
let getInputSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
@ -92,6 +92,9 @@ describe('run', () => {
it('Package manager is not valid, skip caching', async () => {
inputs['cache'] = 'yarn3';
getStateSpy.mockImplementation(key =>
key === State.CachePackageManager ? inputs['cache'] : ''
);
await run();
@ -107,18 +110,22 @@ describe('run', () => {
describe('Validate unchanged cache is not saved', () => {
it('should not save cache for yarn1', async () => {
inputs['cache'] = 'yarn';
getStateSpy.mockImplementation(() => yarnFileHash);
getCommandOutputSpy
.mockImplementationOnce(() => '1.2.3')
.mockImplementationOnce(() => `${commonPath}/yarn1`);
getStateSpy.mockImplementation(key =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
);
@ -127,18 +134,22 @@ describe('run', () => {
it('should not save cache for yarn2', async () => {
inputs['cache'] = 'yarn';
getStateSpy.mockImplementation(() => yarnFileHash);
getCommandOutputSpy
.mockImplementationOnce(() => '2.2.3')
.mockImplementationOnce(() => `${commonPath}/yarn2`);
getStateSpy.mockImplementation(key =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
);
@ -147,35 +158,44 @@ describe('run', () => {
it('should not save cache for npm', async () => {
inputs['cache'] = 'npm';
getStateSpy.mockImplementation(() => npmFileHash);
getStateSpy.mockImplementation(key =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(setFailedSpy).not.toHaveBeenCalled();
});
it('should not save cache for pnpm', async () => {
inputs['cache'] = 'pnpm';
getStateSpy.mockImplementation(() => pnpmFileHash);
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
getStateSpy.mockImplementation(key =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
expect(infoSpy).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(setFailedSpy).not.toHaveBeenCalled();
});
});
@ -183,24 +203,24 @@ describe('run', () => {
describe('action saves the cache', () => {
it('saves cache from yarn 1', async () => {
inputs['cache'] = 'yarn';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return yarnFileHash;
} else {
return npmFileHash;
}
});
getCommandOutputSpy
.mockImplementationOnce(() => '1.2.3')
.mockImplementationOnce(() => `${commonPath}/yarn1`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
);
@ -213,24 +233,24 @@ describe('run', () => {
it('saves cache from yarn 2', async () => {
inputs['cache'] = 'yarn';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return yarnFileHash;
} else {
return npmFileHash;
}
});
getCommandOutputSpy
.mockImplementationOnce(() => '2.2.3')
.mockImplementationOnce(() => `${commonPath}/yarn2`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
);
@ -243,21 +263,24 @@ describe('run', () => {
it('saves cache from npm', async () => {
inputs['cache'] = 'npm';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return npmFileHash;
} else {
return yarnFileHash;
}
});
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
);
@ -270,21 +293,24 @@ describe('run', () => {
it('saves cache from pnpm', async () => {
inputs['cache'] = 'pnpm';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return pnpmFileHash;
} else {
return npmFileHash;
}
});
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? pnpmFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
);
@ -297,24 +323,27 @@ describe('run', () => {
it('save with -1 cacheId , should not fail workflow', async () => {
inputs['cache'] = 'npm';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return npmFileHash;
} else {
return yarnFileHash;
}
});
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
saveCacheSpy.mockImplementation(() => {
return -1;
});
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
);
@ -327,24 +356,27 @@ describe('run', () => {
it('saves with error from toolkit, should fail workflow', async () => {
inputs['cache'] = 'npm';
getStateSpy.mockImplementation((name: string) => {
if (name === State.CacheMatchedKey) {
return npmFileHash;
} else {
return yarnFileHash;
}
});
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
getStateSpy.mockImplementation((key: string) =>
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
saveCacheSpy.mockImplementation(() => {
throw new cache.ValidationError('Validation failed');
});
await run();
expect(getInputSpy).toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(2);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
expect(getInputSpy).not.toHaveBeenCalled();
expect(getStateSpy).toHaveBeenCalledTimes(4);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
expect(debugSpy).toHaveBeenCalledTimes(0);
expect(infoSpy).not.toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
);

View File

@ -2,7 +2,18 @@ import * as core from '@actions/core';
import * as cache from '@actions/cache';
import path from 'path';
import * as utils from '../src/cache-utils';
import {PackageManagerInfo, isCacheFeatureAvailable} from '../src/cache-utils';
import {
PackageManagerInfo,
isCacheFeatureAvailable,
supportedPackageManagers,
getCommandOutput,
resetProjectDirectoriesMemoized
} from '../src/cache-utils';
import fs from 'fs';
import * as cacheUtils from '../src/cache-utils';
import * as glob from '@actions/glob';
import {Globber} from '@actions/glob';
import {MockGlobber} from './mock/glob-mock';
describe('cache-utils', () => {
const versionYarn1 = '1.2.3';
@ -12,8 +23,10 @@ describe('cache-utils', () => {
let isFeatureAvailable: jest.SpyInstance;
let info: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let fsRealPathSyncSpy: jest.SpyInstance;
beforeEach(() => {
console.log('::stop-commands::stoptoken');
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(msg => {});
@ -24,13 +37,29 @@ describe('cache-utils', () => {
isFeatureAvailable = jest.spyOn(cache, 'isFeatureAvailable');
getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
fsRealPathSyncSpy = jest.spyOn(fs, 'realpathSync');
fsRealPathSyncSpy.mockImplementation(dirName => {
return dirName;
});
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
//jest.restoreAllMocks();
});
afterAll(async () => {
console.log('::stoptoken::');
jest.restoreAllMocks();
}, 100000);
describe('getPackageManagerInfo', () => {
it.each<[string, PackageManagerInfo | null]>([
['npm', utils.supportedPackageManagers.npm],
['pnpm', utils.supportedPackageManagers.pnpm],
['yarn', utils.supportedPackageManagers.yarn1],
['yarn', utils.supportedPackageManagers.yarn],
['yarn1', null],
['yarn2', null],
['npm7', null]
@ -46,7 +75,8 @@ describe('cache-utils', () => {
isFeatureAvailable.mockImplementation(() => false);
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
expect(() => isCacheFeatureAvailable()).toThrowError(
expect(isCacheFeatureAvailable()).toBeFalsy();
expect(warningSpy).toHaveBeenCalledWith(
'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'
);
});
@ -71,4 +101,263 @@ describe('cache-utils', () => {
jest.resetAllMocks();
jest.clearAllMocks();
});
describe('getCacheDirectoriesPaths', () => {
let existsSpy: jest.SpyInstance;
let lstatSpy: jest.SpyInstance;
let globCreateSpy: jest.SpyInstance;
beforeEach(() => {
existsSpy = jest.spyOn(fs, 'existsSync');
existsSpy.mockImplementation(() => true);
lstatSpy = jest.spyOn(fs, 'lstatSync');
lstatSpy.mockImplementation(arg => ({
isDirectory: () => true
}));
globCreateSpy = jest.spyOn(glob, 'create');
globCreateSpy.mockImplementation(
(pattern: string): Promise<Globber> =>
MockGlobber.create(['/foo', '/bar'])
);
resetProjectDirectoriesMemoized();
});
afterEach(() => {
existsSpy.mockRestore();
lstatSpy.mockRestore();
globCreateSpy.mockRestore();
});
it.each([
[supportedPackageManagers.npm, ''],
[supportedPackageManagers.npm, '/dir/file.lock'],
[supportedPackageManagers.npm, '/**/file.lock'],
[supportedPackageManagers.pnpm, ''],
[supportedPackageManagers.pnpm, '/dir/file.lock'],
[supportedPackageManagers.pnpm, '/**/file.lock']
])(
'getCacheDirectoriesPaths should return one dir for non yarn',
async (packageManagerInfo, cacheDependency) => {
getCommandOutputSpy.mockImplementation(() => 'foo');
const dirs = await cacheUtils.getCacheDirectories(
packageManagerInfo,
cacheDependency
);
expect(dirs).toEqual(['foo']);
// to do not call for a version
// call once for get cache folder
expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
}
);
it('getCacheDirectoriesPaths should return one dir for yarn without cacheDependency', async () => {
getCommandOutputSpy.mockImplementation(() => 'foo');
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
''
);
expect(dirs).toEqual(['foo']);
});
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 for getCommandOutput returning empty',
async (packageManagerInfo, cacheDependency) => {
getCommandOutputSpy.mockImplementation((command: string) =>
// return empty string to indicate getCacheFolderPath failed
// --version still works
command.includes('version') ? '1.' : ''
);
await expect(
cacheUtils.getCacheDirectories(packageManagerInfo, cacheDependency)
).rejects.toThrow(); //'Could not get cache folder path for /dir');
}
);
it.each([
[supportedPackageManagers.yarn, '/dir/file.lock'],
[supportedPackageManagers.yarn, '/**/file.lock']
])(
'getCacheDirectoriesPaths should nothrow in case of having not directories',
async (packageManagerInfo, cacheDependency) => {
lstatSpy.mockImplementation(arg => ({
isDirectory: () => false
}));
await cacheUtils.getCacheDirectories(
packageManagerInfo,
cacheDependency
);
expect(warningSpy).toHaveBeenCalledTimes(1);
expect(warningSpy).toHaveBeenCalledWith(
`No existing directories found containing cache-dependency-path="${cacheDependency}"`
);
}
);
it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return one dir without cacheDependency',
async version => {
getCommandOutputSpy.mockImplementationOnce(() => version);
getCommandOutputSpy.mockImplementationOnce(() => `foo${version}`);
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
''
);
expect(dirs).toEqual([`foo${version}`]);
}
);
it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return 2 dirs with globbed cacheDependency',
async version => {
let dirNo = 1;
getCommandOutputSpy.mockImplementation((command: string) =>
command.includes('version') ? version : `file_${version}_${dirNo++}`
);
globCreateSpy.mockImplementation(
(pattern: string): Promise<Globber> =>
MockGlobber.create(['/tmp/dir1/file', '/tmp/dir2/file'])
);
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
'/tmp/**/file'
);
expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
}
);
it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return 2 dirs with globbed cacheDependency expanding to duplicates',
async version => {
let dirNo = 1;
getCommandOutputSpy.mockImplementation((command: string) =>
command.includes('version') ? version : `file_${version}_${dirNo++}`
);
globCreateSpy.mockImplementation(
(pattern: string): Promise<Globber> =>
MockGlobber.create([
'/tmp/dir1/file',
'/tmp/dir2/file',
'/tmp/dir1/file'
])
);
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
'/tmp/**/file'
);
expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
}
);
it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return 2 uniq dirs despite duplicate cache directories',
async version => {
let dirNo = 1;
getCommandOutputSpy.mockImplementation((command: string) =>
command.includes('version')
? version
: `file_${version}_${dirNo++ % 2}`
);
globCreateSpy.mockImplementation(
(pattern: string): Promise<Globber> =>
MockGlobber.create([
'/tmp/dir1/file',
'/tmp/dir2/file',
'/tmp/dir3/file'
])
);
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
'/tmp/**/file'
);
expect(dirs).toEqual([`file_${version}_1`, `file_${version}_0`]);
expect(getCommandOutputSpy).toHaveBeenCalledTimes(6);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
'yarn --version',
'/tmp/dir1'
);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
'yarn --version',
'/tmp/dir2'
);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
'yarn --version',
'/tmp/dir3'
);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
version.startsWith('1.')
? 'yarn cache dir'
: 'yarn config get cacheFolder',
'/tmp/dir1'
);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
version.startsWith('1.')
? 'yarn cache dir'
: 'yarn config get cacheFolder',
'/tmp/dir2'
);
expect(getCommandOutputSpy).toHaveBeenCalledWith(
version.startsWith('1.')
? 'yarn cache dir'
: 'yarn config get cacheFolder',
'/tmp/dir3'
);
}
);
it.each(['1.1.1', '2.2.2'])(
'getCacheDirectoriesPaths yarn v%s should return 4 dirs with multiple globs',
async version => {
// simulate wrong indents
const cacheDependencyPath = `/tmp/dir1/file
/tmp/dir2/file
/tmp/**/file
`;
globCreateSpy.mockImplementation(
(pattern: string): Promise<Globber> =>
MockGlobber.create([
'/tmp/dir1/file',
'/tmp/dir2/file',
'/tmp/dir3/file',
'/tmp/dir4/file'
])
);
let dirNo = 1;
getCommandOutputSpy.mockImplementation((command: string) =>
command.includes('version') ? version : `file_${version}_${dirNo++}`
);
const dirs = await cacheUtils.getCacheDirectories(
supportedPackageManagers.yarn,
cacheDependencyPath
);
expect(dirs).toEqual([
`file_${version}_1`,
`file_${version}_2`,
`file_${version}_3`,
`file_${version}_4`
]);
}
);
});
});

Some files were not shown because too many files have changed in this diff Show More