Compare commits

..

4 Commits

Author SHA1 Message Date
Priya Gupta
746f200ccd Refactor GitHub Actions workflow for OS and Node versions
Updated the workflow to support multiple OS and Node.js versions, and upgraded checkout action from v4 to v5.
2025-10-03 16:22:50 +05:30
Priya Gupta
4fcdf84cf4 Revise CI workflow for multi-OS and Node.js support
Updated the GitHub Actions workflow to support multiple OS and Node.js versions. Changed checkout action version and modified yarn install command to ignore engines.
2025-10-03 16:20:21 +05:30
Priyagupta108
7299ce5c60 Test macos-14-large x64 runner 2025-07-29 16:21:33 +05:30
Priyagupta108
1ea62dc588 Test macos-14-large x64 runner 2025-07-29 16:16:10 +05:30
60 changed files with 12069 additions and 21947 deletions

View File

@@ -16,4 +16,4 @@ jobs:
name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with:
node-version: '24.x'
node-version: '20.x'

View File

@@ -16,4 +16,4 @@ jobs:
name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with:
node-version: '24.x'
node-version: '20.x'

View File

@@ -6,7 +6,7 @@ on:
- '**.md'
push:
branches:
- main
- test-macos-x64-runner
- releases/*
paths-ignore:
- '**.md'

View File

@@ -25,15 +25,15 @@ jobs:
env:
https_proxy: http://squid-proxy:3128
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 24
- name: Setup node 14
uses: ./
with:
node-version: 24.x
node-version: 14.x
- name: Verify node and npm
run: __tests__/verify-node.sh 24
run: __tests__/verify-node.sh 14
test-bypass-proxy:
runs-on: ubuntu-latest
@@ -41,12 +41,12 @@ 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@v5
- uses: actions/checkout@v4
- name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 24
- name: Setup node 11
uses: ./
with:
node-version: 24
node-version: 11
- name: Verify node and npm
run: __tests__/verify-node.sh 24
run: __tests__/verify-node.sh 11

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checking out
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Publish
id: publish
uses: actions/publish-immutable-action@v0.0.4

View File

@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.4.0
uses: actions/publish-action@v0.3.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@@ -6,7 +6,7 @@ on:
- '**.md'
push:
branches:
- main
- test-macos-x64-runner
- releases/*
paths-ignore:
- '**.md'

View File

@@ -1,6 +1,6 @@
---
name: "@types/node"
version: 24.1.0
version: 20.11.25
type: npm
summary: TypeScript definitions for node
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node

View File

@@ -1,35 +0,0 @@
---
name: data-uri-to-buffer
version: 4.0.1
type: npm
summary: Generate a Buffer instance from a Data URI string
homepage: https://github.com/TooTallNate/node-data-uri-to-buffer
license: mit
licenses:
- sources: README.md
text: |-
(The MIT License)
Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[rfc]: http://tools.ietf.org/html/rfc2397
notices: []

View File

@@ -1,32 +0,0 @@
---
name: node-domexception
version: 1.0.0
type: npm
summary: An implementation of the DOMException class from NodeJS
homepage: https://github.com/jimmywarting/node-domexception#readme
license: mit
licenses:
- sources: LICENSE
text: |
MIT License
Copyright (c) 2021 Jimmy Wärting
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []

View File

@@ -1,16 +1,16 @@
---
name: node-fetch
version: 3.3.2
version: 2.7.0
type: npm
summary: A light-weight module that brings Fetch API to node.js
homepage: https://github.com/node-fetch/node-fetch
summary: A light-weight module that brings window.fetch to node.js
homepage: https://github.com/bitinn/node-fetch
license: mit
licenses:
- sources: LICENSE.md
text: |+
The MIT License (MIT)
Copyright (c) 2016 - 2020 Node Fetch Team
Copyright (c) 2016 David Frank
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -32,14 +32,25 @@ licenses:
- sources: README.md
text: |-
[MIT](LICENSE.md)
MIT
[npm-image]: https://flat.badgen.net/npm/v/node-fetch
[npm-url]: https://www.npmjs.com/package/node-fetch
[travis-image]: https://flat.badgen.net/travis/bitinn/node-fetch
[travis-url]: https://travis-ci.org/bitinn/node-fetch
[codecov-image]: https://flat.badgen.net/codecov/c/github/bitinn/node-fetch/master
[codecov-url]: https://codecov.io/gh/bitinn/node-fetch
[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch
[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch
[discord-image]: https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord&style=flat-square
[discord-url]: https://discord.gg/Zxbndcm
[opencollective-image]: https://opencollective.com/node-fetch/backers.svg
[opencollective-url]: https://opencollective.com/node-fetch
[whatwg-fetch]: https://fetch.spec.whatwg.org/
[response-init]: https://fetch.spec.whatwg.org/#responseinit
[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
[error-handling.md]: https://github.com/node-fetch/node-fetch/blob/master/docs/ERROR-HANDLING.md
[FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[Blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob
[File]: https://developer.mozilla.org/en-US/docs/Web/API/File
[LIMITS.md]: https://github.com/bitinn/node-fetch/blob/master/LIMITS.md
[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md
[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md
notices: []

View File

@@ -1,6 +1,6 @@
---
name: semver
version: 7.7.2
version: 7.6.3
type: npm
summary: The semantic version parser used by npm.
homepage:

View File

@@ -1,17 +1,15 @@
---
name: formdata-polyfill
version: 4.0.10
name: tr46
version: 0.0.3
type: npm
summary: HTML5 `FormData` for Browsers and Node.
homepage: https://github.com/jimmywarting/FormData#readme
summary: An implementation of the Unicode TR46 spec
homepage: https://github.com/Sebmaster/tr46.js#readme
license: mit
licenses:
- sources: LICENSE
- sources: Auto-generated MIT license text
text: |
MIT License
Copyright (c) 2016 Jimmy Karl Roland Wärting
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -1,17 +1,15 @@
---
name: undici-types
version: 7.8.0
version: 5.26.5
type: npm
summary: A stand-alone types package for Undici
homepage: https://undici.nodejs.org
license: mit
licenses:
- sources: LICENSE
- sources: Auto-generated MIT license text
text: |
MIT License
Copyright (c) Matteo Collina and Undici contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -1,33 +0,0 @@
---
name: web-streams-polyfill
version: 3.3.3
type: npm
summary: Web Streams, based on the WHATWG spec reference implementation
homepage: https://github.com/MattiasBuelens/web-streams-polyfill#readme
license: mit
licenses:
- sources: LICENSE
text: |
The MIT License (MIT)
Copyright (c) 2024 Mattias Buelens
Copyright (c) 2016 Diwank Singh Tomer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []

23
.licenses/npm/webidl-conversions.dep.yml generated Normal file
View File

@@ -0,0 +1,23 @@
---
name: webidl-conversions
version: 3.0.1
type: npm
summary: Implements the WebIDL algorithms for converting to and from JavaScript values
homepage:
license: bsd-2-clause
licenses:
- sources: LICENSE.md
text: |
# The BSD 2-Clause License
Copyright (c) 2014, Domenic Denicola
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
notices: []

View File

@@ -1,16 +1,16 @@
---
name: fetch-blob
version: 3.2.0
name: whatwg-url
version: 5.0.0
type: npm
summary: Blob & File implementation in Node.js, originally from node-fetch.
homepage: https://github.com/node-fetch/fetch-blob#readme
summary: An implementation of the WHATWG URL Standard's URL API and parsing machinery
homepage:
license: mit
licenses:
- sources: LICENSE
- sources: LICENSE.txt
text: |
MIT License
The MIT License (MIT)
Copyright (c) 2019 David Frank
Copyright (c) 20152016 Sebastian Mayr
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -19,14 +19,14 @@ licenses:
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
notices: []

View File

@@ -1,5 +1,5 @@
// 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.
export default {
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,

View File

@@ -12,27 +12,13 @@ This action provides the following functionality for GitHub Actions users:
- Registering problem matchers for error output
- Configuring authentication for GPR or npm
## Breaking changes in V6
- Caching is now automatically enabled for npm projects when either the `devEngines.packageManager` field or the top-level `packageManager` field in `package.json` is set to `npm`. For other package managers, such as Yarn and pnpm, caching is disabled by default and must be configured manually using the `cache` input.
## Breaking changes in V5
- Enabled caching by default with package manager detection if no cache input is provided.
> For workflows with elevated privileges or access to sensitive information, we recommend disabling automatic caching by setting `package-manager-cache: false` when caching is not needed for secure operation.
- Upgraded action from node20 to node24.
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. [See Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
For more details, see the full release notes on the [releases page](https://github.com/actions/setup-node/releases/v5.0.0)
## Usage
See [action.yml](action.yml)
<!-- start usage -->
```yaml
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
# Version Spec of the version to use in SemVer notation.
# It also admits such aliases as lts/*, latest, nightly and canary builds
@@ -71,11 +57,6 @@ See [action.yml](action.yml)
# Default: ''
cache: ''
# Controls automatic caching for npm. By default, caching for npm is enabled if either the devEngines.packageManager field or the top-level packageManager field in package.json specifies npm and no explicit cache input is provided.
# To disable automatic caching for npm, set package-manager-cache to false.
# default: true
package-manager-cache: true
# 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.
@@ -117,10 +98,10 @@ See [action.yml](action.yml)
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
node-version: 18
- run: npm ci
- run: npm test
```
@@ -137,9 +118,9 @@ The `node-version` input supports the Semantic Versioning Specification, for mor
Examples:
- Major versions: `22`, `24`
- More specific versions: `20.19`, `22.17.1` , `24.8.0`
- NVM LTS syntax: `lts/iron`, `lts/jod`, `lts/*`, `lts/-n`
- 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/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.
@@ -154,7 +135,7 @@ It's **always** recommended to commit the lockfile of your package manager for s
## Caching global packages data
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 global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional.
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 global packages data 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`, `npm-shrinkwrap.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.
@@ -166,10 +147,10 @@ See the examples of using cache for `yarn`/`pnpm` and `cache-dependency-path` in
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test
@@ -179,30 +160,16 @@ steps:
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
node-version: 20
cache: 'npm'
cache-dependency-path: subdir/package-lock.json
- run: npm ci
- run: npm test
```
Caching for npm dependencies is automatically enabled when your `package.json` contains either `devEngines.packageManager` field or top-level `packageManager` field set to `npm`, and no explicit cache input is provided.
This behavior is controlled by the `package-manager-cache` input, which defaults to `true`. To turn off automatic caching, set `package-manager-cache` to `false`.
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
package-manager-cache: false
- run: npm ci
```
> If your `package.json` file does not include a `packageManager` field set to `npm`, caching will be disabled unless you explicitly enable it. For workflows with elevated privileges or access to sensitive information, we recommend disabling automatic caching for npm by setting `package-manager-cache: false` when caching is not required for secure operation.
## Matrix Testing
```yaml
@@ -211,12 +178,12 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [ 20, 22, 24 ]
node: [ 14, 16, 18 ]
name: Node ${{ matrix.node }} sample
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
@@ -230,10 +197,10 @@ jobs:
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@v6
uses: actions/setup-node@v4
with:
token: ${{ secrets.GH_DOTCOM_TOKEN }}
node-version: 24
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.
@@ -271,4 +238,4 @@ Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
## Code of Conduct
:wave: Be nice. See [our code of conduct](CODE_OF_CONDUCT.md)
:wave: Be nice. See [our code of conduct](CODE_OF_CONDUCT.md)

View File

@@ -3,22 +3,17 @@ 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.js';
import * as cacheUtils from '../src/cache-utils.js';
import {fileURLToPath} from 'url';
import {jest, describe, beforeEach, afterEach, it, expect} from '@jest/globals';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import * as auth from '../src/authutil';
import * as cacheUtils from '../src/cache-utils';
let rcFile: string;
describe('authutil tests', () => {
const _runnerDir = path.join(__dirname, 'runner');
let cnSpy: ReturnType<typeof jest.spyOn>;
let logSpy: ReturnType<typeof jest.spyOn>;
let dbgSpy: ReturnType<typeof jest.spyOn>;
let cnSpy: jest.SpyInstance;
let logSpy: jest.SpyInstance;
let dbgSpy: jest.SpyInstance;
beforeAll(async () => {
const randPath = path.join(Math.random().toString(36).substring(7));

View File

@@ -3,13 +3,9 @@ import * as cache from '@actions/cache';
import * as path from 'path';
import * as glob from '@actions/glob';
import osm from 'os';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import * as utils from '../src/cache-utils.js';
import {restoreCache} from '../src/cache-restore.js';
import * as utils from '../src/cache-utils';
import {restoreCache} from '../src/cache-restore';
describe('cache-restore', () => {
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');

View File

@@ -3,14 +3,10 @@ import * as cache from '@actions/cache';
import * as glob from '@actions/glob';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import * as utils from '../src/cache-utils.js';
import {run} from '../src/cache-save.js';
import {State} from '../src/constants.js';
import * as utils from '../src/cache-utils';
import {run} from '../src/cache-save';
import {State} from '../src/constants';
describe('run', () => {
const yarnFileHash =
@@ -118,10 +114,10 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -142,10 +138,10 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -166,10 +162,10 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
@@ -188,10 +184,10 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CachePrimaryKey || key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -211,12 +207,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -241,12 +237,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? yarnFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -271,12 +267,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -301,12 +297,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? pnpmFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? pnpmFileHash
: key === State.CachePrimaryKey
? npmFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
await run();
@@ -331,12 +327,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
saveCacheSpy.mockImplementation(() => {
return -1;
@@ -364,12 +360,12 @@ describe('run', () => {
key === State.CachePackageManager
? inputs['cache']
: key === State.CacheMatchedKey
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
? npmFileHash
: key === State.CachePrimaryKey
? yarnFileHash
: key === State.CachePaths
? '["/foo/bar"]'
: 'not expected'
);
saveCacheSpy.mockImplementation(() => {
throw new cache.ValidationError('Validation failed');

View File

@@ -1,23 +1,19 @@
import * as core from '@actions/core';
import * as cache from '@actions/cache';
import path from 'path';
import * as utils from '../src/cache-utils.js';
import * as utils from '../src/cache-utils';
import {
PackageManagerInfo,
isCacheFeatureAvailable,
supportedPackageManagers,
isGhes,
resetProjectDirectoriesMemoized
} from '../src/cache-utils.js';
} from '../src/cache-utils';
import fs from 'fs';
import * as cacheUtils from '../src/cache-utils.js';
import * as cacheUtils from '../src/cache-utils';
import * as glob from '@actions/glob';
import {Globber} from '@actions/glob';
import {MockGlobber} from './mock/glob-mock.js';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import {MockGlobber} from './mock/glob-mock';
describe('cache-utils', () => {
const versionYarn1 = '1.2.3';

View File

@@ -8,9 +8,9 @@ import fs from 'fs';
import cp from 'child_process';
import osm from 'os';
import path from 'path';
import * as main from '../src/main.js';
import * as auth from '../src/authutil.js';
import {INodeVersion} from '../src/distributions/base-models.js';
import * as main from '../src/main';
import * as auth from '../src/authutil';
import {INodeVersion} from '../src/distributions/base-models';
import nodeTestManifest from './data/versions-manifest.json';
import nodeTestDist from './data/node-dist-index.json';

View File

@@ -1 +1 @@
v24
v20

View File

@@ -1 +1 @@
nodejs 24.0.0
nodejs 20.0.0

View File

@@ -1 +1 @@
node 24.0.0
node 20.0.0

View File

@@ -3,6 +3,6 @@
"node": "^14.0.0"
},
"volta": {
"node": "24.0.0"
"node": "20.0.0"
}
}

View File

@@ -1,5 +1,5 @@
{
"engines": {
"node": "^24.0.0"
"node": "^20.0.0"
}
}

View File

@@ -7,42 +7,36 @@ import * as io from '@actions/io';
import fs from 'fs';
import path from 'path';
import osm from 'os';
import {fileURLToPath} from 'url';
import {jest, describe, beforeEach, afterEach, it, expect} from '@jest/globals';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import each from 'jest-each';
import * as main from '../src/main.js';
import * as util from '../src/util.js';
import OfficialBuilds from '../src/distributions/official_builds/official_builds.js';
import * as main from '../src/main';
import * as util from '../src/util';
import OfficialBuilds from '../src/distributions/official_builds/official_builds';
describe('main tests', () => {
let inputs = {} as any;
let os = {} as any;
let infoSpy: ReturnType<typeof jest.spyOn>;
let warningSpy: ReturnType<typeof jest.spyOn>;
let saveStateSpy: ReturnType<typeof jest.spyOn>;
let inSpy: ReturnType<typeof jest.spyOn>;
let setOutputSpy: ReturnType<typeof jest.spyOn>;
let startGroupSpy: ReturnType<typeof jest.spyOn>;
let endGroupSpy: ReturnType<typeof jest.spyOn>;
let infoSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance;
let inSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;
let startGroupSpy: jest.SpyInstance;
let endGroupSpy: jest.SpyInstance;
let whichSpy: ReturnType<typeof jest.spyOn>;
let whichSpy: jest.SpyInstance;
let existsSpy: ReturnType<typeof jest.spyOn>;
let existsSpy: jest.SpyInstance;
let getExecOutputSpy: ReturnType<typeof jest.spyOn>;
let getExecOutputSpy: jest.SpyInstance;
let getNodeVersionFromFileSpy: ReturnType<typeof jest.spyOn>;
let cnSpy: ReturnType<typeof jest.spyOn>;
let findSpy: ReturnType<typeof jest.spyOn>;
let isCacheActionAvailable: ReturnType<typeof jest.spyOn>;
let getNodeVersionFromFileSpy: jest.SpyInstance;
let cnSpy: jest.SpyInstance;
let findSpy: jest.SpyInstance;
let isCacheActionAvailable: jest.SpyInstance;
let setupNodeJsSpy: ReturnType<typeof jest.spyOn>;
let setupNodeJsSpy: jest.SpyInstance;
beforeEach(() => {
inputs = {};
@@ -59,8 +53,6 @@ describe('main tests', () => {
setOutputSpy.mockImplementation(() => {});
warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => {});
saveStateSpy = jest.spyOn(core, 'saveState');
saveStateSpy.mockImplementation(() => {});
startGroupSpy = jest.spyOn(core, 'startGroup');
startGroupSpy.mockImplementation(() => {});
endGroupSpy = jest.spyOn(core, 'endGroup');
@@ -288,149 +280,4 @@ describe('main tests', () => {
);
});
});
describe('cache feature tests', () => {
it('Should enable caching when packageManager is npm and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'npm@10.8.2'
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager.name is "npm" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'npm'}
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager is array and one entry has name "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'npm'}]
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should not enable caching if packageManager is "pnpm@8.0.0" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'pnpm@8.0.0'
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager.name is "pnpm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'pnpm'}
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager is array without "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'yarn'}]
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if packageManager field is missing in package.json and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
// packageManager field is not present
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should skip caching when package-manager-cache is false', async () => {
inputs['package-manager-cache'] = 'false';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should enable caching with cache input explicitly provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = 'npm';
inSpy.mockImplementation(name => inputs[name]);
isCacheActionAvailable.mockImplementation(() => true);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
});
});

View File

@@ -1,4 +1,4 @@
import {MockGlobber} from './glob-mock.js';
import {MockGlobber} from './glob-mock';
describe('mocked globber tests', () => {
it('globber should return generator', async () => {

View File

@@ -8,9 +8,9 @@ import fs from 'fs';
import cp from 'child_process';
import osm from 'os';
import path from 'path';
import * as main from '../src/main.js';
import * as auth from '../src/authutil.js';
import {INodeVersion} from '../src/distributions/base-models.js';
import * as main from '../src/main';
import * as auth from '../src/authutil';
import {INodeVersion} from '../src/distributions/base-models';
import nodeTestManifest from './data/versions-manifest.json';
import nodeTestDist from './data/node-dist-index.json';

View File

@@ -8,9 +8,9 @@ import fs from 'fs';
import cp from 'child_process';
import osm from 'os';
import path from 'path';
import * as main from '../src/main.js';
import * as auth from '../src/authutil.js';
import {INodeVersion} from '../src/distributions/base-models.js';
import * as main from '../src/main';
import * as auth from '../src/authutil';
import {INodeVersion} from '../src/distributions/base-models';
import nodeTestDist from './data/node-dist-index.json';
import nodeTestDistNightly from './data/node-nightly-index.json';

View File

@@ -7,13 +7,8 @@ fi
node_version="$(node --version)"
echo "Found node version '$node_version'"
# Extract the major version from the node version (remove the 'v' prefix)
actual_major_version=$(echo $node_version | sed -E 's/^v([0-9]+)\..*/\1/')
expected_major_version=$(echo $1 | sed -E 's/^([0-9]+)\..*/\1/') # Extract major version from argument
if [ "$actual_major_version" != "$expected_major_version" ]; then
echo "Expected Node.js $expected_major_version.x.x but found $node_version"
if [ -z "$(echo $node_version | grep --fixed-strings v$1)" ]; then
echo "Unexpected version"
exit 1
fi

View File

@@ -23,9 +23,6 @@ inputs:
default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
cache:
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.'
package-manager-cache:
description: 'Set to false to disable automatic caching. By default, caching is enabled when either devEngines.packageManager or the top-level packageManager field in package.json specifies npm as the package manager.'
default: true
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.'
mirror:
@@ -40,7 +37,7 @@ outputs:
node-version:
description: 'The installed node version.'
runs:
using: 'node24'
using: 'node20'
main: 'dist/setup/index.js'
post: 'dist/cache-save/index.js'
post-if: success()

View File

@@ -1,449 +0,0 @@
export const id = 101;
export const ids = [101];
export const modules = {
/***/ 9101:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ toFormData: () => (/* binding */ toFormData)
/* harmony export */ });
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9802);
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3018);
let s = 0;
const S = {
START_BOUNDARY: s++,
HEADER_FIELD_START: s++,
HEADER_FIELD: s++,
HEADER_VALUE_START: s++,
HEADER_VALUE: s++,
HEADER_VALUE_ALMOST_DONE: s++,
HEADERS_ALMOST_DONE: s++,
PART_DATA_START: s++,
PART_DATA: s++,
END: s++
};
let f = 1;
const F = {
PART_BOUNDARY: f,
LAST_BOUNDARY: f *= 2
};
const LF = 10;
const CR = 13;
const SPACE = 32;
const HYPHEN = 45;
const COLON = 58;
const A = 97;
const Z = 122;
const lower = c => c | 0x20;
const noop = () => {};
class MultipartParser {
/**
* @param {string} boundary
*/
constructor(boundary) {
this.index = 0;
this.flags = 0;
this.onHeaderEnd = noop;
this.onHeaderField = noop;
this.onHeadersEnd = noop;
this.onHeaderValue = noop;
this.onPartBegin = noop;
this.onPartData = noop;
this.onPartEnd = noop;
this.boundaryChars = {};
boundary = '\r\n--' + boundary;
const ui8a = new Uint8Array(boundary.length);
for (let i = 0; i < boundary.length; i++) {
ui8a[i] = boundary.charCodeAt(i);
this.boundaryChars[ui8a[i]] = true;
}
this.boundary = ui8a;
this.lookbehind = new Uint8Array(this.boundary.length + 8);
this.state = S.START_BOUNDARY;
}
/**
* @param {Uint8Array} data
*/
write(data) {
let i = 0;
const length_ = data.length;
let previousIndex = this.index;
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
const boundaryLength = this.boundary.length;
const boundaryEnd = boundaryLength - 1;
const bufferLength = data.length;
let c;
let cl;
const mark = name => {
this[name + 'Mark'] = i;
};
const clear = name => {
delete this[name + 'Mark'];
};
const callback = (callbackSymbol, start, end, ui8a) => {
if (start === undefined || start !== end) {
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
}
};
const dataCallback = (name, clear) => {
const markSymbol = name + 'Mark';
if (!(markSymbol in this)) {
return;
}
if (clear) {
callback(name, this[markSymbol], i, data);
delete this[markSymbol];
} else {
callback(name, this[markSymbol], data.length, data);
this[markSymbol] = 0;
}
};
for (i = 0; i < length_; i++) {
c = data[i];
switch (state) {
case S.START_BOUNDARY:
if (index === boundary.length - 2) {
if (c === HYPHEN) {
flags |= F.LAST_BOUNDARY;
} else if (c !== CR) {
return;
}
index++;
break;
} else if (index - 1 === boundary.length - 2) {
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
state = S.END;
flags = 0;
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
index = 0;
callback('onPartBegin');
state = S.HEADER_FIELD_START;
} else {
return;
}
break;
}
if (c !== boundary[index + 2]) {
index = -2;
}
if (c === boundary[index + 2]) {
index++;
}
break;
case S.HEADER_FIELD_START:
state = S.HEADER_FIELD;
mark('onHeaderField');
index = 0;
// falls through
case S.HEADER_FIELD:
if (c === CR) {
clear('onHeaderField');
state = S.HEADERS_ALMOST_DONE;
break;
}
index++;
if (c === HYPHEN) {
break;
}
if (c === COLON) {
if (index === 1) {
// empty header field
return;
}
dataCallback('onHeaderField', true);
state = S.HEADER_VALUE_START;
break;
}
cl = lower(c);
if (cl < A || cl > Z) {
return;
}
break;
case S.HEADER_VALUE_START:
if (c === SPACE) {
break;
}
mark('onHeaderValue');
state = S.HEADER_VALUE;
// falls through
case S.HEADER_VALUE:
if (c === CR) {
dataCallback('onHeaderValue', true);
callback('onHeaderEnd');
state = S.HEADER_VALUE_ALMOST_DONE;
}
break;
case S.HEADER_VALUE_ALMOST_DONE:
if (c !== LF) {
return;
}
state = S.HEADER_FIELD_START;
break;
case S.HEADERS_ALMOST_DONE:
if (c !== LF) {
return;
}
callback('onHeadersEnd');
state = S.PART_DATA_START;
break;
case S.PART_DATA_START:
state = S.PART_DATA;
mark('onPartData');
// falls through
case S.PART_DATA:
previousIndex = index;
if (index === 0) {
// boyer-moore derrived algorithm to safely skip non-boundary data
i += boundaryEnd;
while (i < bufferLength && !(data[i] in boundaryChars)) {
i += boundaryLength;
}
i -= boundaryEnd;
c = data[i];
}
if (index < boundary.length) {
if (boundary[index] === c) {
if (index === 0) {
dataCallback('onPartData', true);
}
index++;
} else {
index = 0;
}
} else if (index === boundary.length) {
index++;
if (c === CR) {
// CR = part boundary
flags |= F.PART_BOUNDARY;
} else if (c === HYPHEN) {
// HYPHEN = end boundary
flags |= F.LAST_BOUNDARY;
} else {
index = 0;
}
} else if (index - 1 === boundary.length) {
if (flags & F.PART_BOUNDARY) {
index = 0;
if (c === LF) {
// unset the PART_BOUNDARY flag
flags &= ~F.PART_BOUNDARY;
callback('onPartEnd');
callback('onPartBegin');
state = S.HEADER_FIELD_START;
break;
}
} else if (flags & F.LAST_BOUNDARY) {
if (c === HYPHEN) {
callback('onPartEnd');
state = S.END;
flags = 0;
} else {
index = 0;
}
} else {
index = 0;
}
}
if (index > 0) {
// when matching a possible boundary, keep a lookbehind reference
// in case it turns out to be a false lead
lookbehind[index - 1] = c;
} else if (previousIndex > 0) {
// if our boundary turned out to be rubbish, the captured lookbehind
// belongs to partData
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
callback('onPartData', 0, previousIndex, _lookbehind);
previousIndex = 0;
mark('onPartData');
// reconsider the current character even so it interrupted the sequence
// it could be the beginning of a new sequence
i--;
}
break;
case S.END:
break;
default:
throw new Error(`Unexpected state entered: ${state}`);
}
}
dataCallback('onHeaderField');
dataCallback('onHeaderValue');
dataCallback('onPartData');
// Update properties for the next call
this.index = index;
this.state = state;
this.flags = flags;
}
end() {
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
this.onPartEnd();
} else if (this.state !== S.END) {
throw new Error('MultipartParser.end(): stream ended unexpectedly');
}
}
}
function _fileName(headerValue) {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
if (!m) {
return;
}
const match = m[2] || m[3] || '';
let filename = match.slice(match.lastIndexOf('\\') + 1);
filename = filename.replace(/%22/g, '"');
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
return String.fromCharCode(code);
});
return filename;
}
async function toFormData(Body, ct) {
if (!/multipart/i.test(ct)) {
throw new TypeError('Failed to fetch');
}
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
if (!m) {
throw new TypeError('no or bad content-type header, no multipart boundary');
}
const parser = new MultipartParser(m[1] || m[2]);
let headerField;
let headerValue;
let entryValue;
let entryName;
let contentType;
let filename;
const entryChunks = [];
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .fS();
const onPartData = ui8a => {
entryValue += decoder.decode(ui8a, {stream: true});
};
const appendToFile = ui8a => {
entryChunks.push(ui8a);
};
const appendFileToFormData = () => {
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .ZH(entryChunks, filename, {type: contentType});
formData.append(entryName, file);
};
const appendEntryToFormData = () => {
formData.append(entryName, entryValue);
};
const decoder = new TextDecoder('utf-8');
decoder.decode();
parser.onPartBegin = function () {
parser.onPartData = onPartData;
parser.onPartEnd = appendEntryToFormData;
headerField = '';
headerValue = '';
entryValue = '';
entryName = '';
contentType = '';
filename = null;
entryChunks.length = 0;
};
parser.onHeaderField = function (ui8a) {
headerField += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderValue = function (ui8a) {
headerValue += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderEnd = function () {
headerValue += decoder.decode();
headerField = headerField.toLowerCase();
if (headerField === 'content-disposition') {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
if (m) {
entryName = m[2] || m[3] || '';
}
filename = _fileName(headerValue);
if (filename) {
parser.onPartData = appendToFile;
parser.onPartEnd = appendFileToFormData;
}
} else if (headerField === 'content-type') {
contentType = headerValue;
}
headerValue = '';
headerField = '';
};
for await (const chunk of Body) {
parser.write(chunk);
}
parser.end();
return formData;
}
/***/ })
};

14157
dist/cache-save/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

View File

@@ -1,449 +0,0 @@
export const id = 101;
export const ids = [101];
export const modules = {
/***/ 9101:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ toFormData: () => (/* binding */ toFormData)
/* harmony export */ });
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9802);
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3018);
let s = 0;
const S = {
START_BOUNDARY: s++,
HEADER_FIELD_START: s++,
HEADER_FIELD: s++,
HEADER_VALUE_START: s++,
HEADER_VALUE: s++,
HEADER_VALUE_ALMOST_DONE: s++,
HEADERS_ALMOST_DONE: s++,
PART_DATA_START: s++,
PART_DATA: s++,
END: s++
};
let f = 1;
const F = {
PART_BOUNDARY: f,
LAST_BOUNDARY: f *= 2
};
const LF = 10;
const CR = 13;
const SPACE = 32;
const HYPHEN = 45;
const COLON = 58;
const A = 97;
const Z = 122;
const lower = c => c | 0x20;
const noop = () => {};
class MultipartParser {
/**
* @param {string} boundary
*/
constructor(boundary) {
this.index = 0;
this.flags = 0;
this.onHeaderEnd = noop;
this.onHeaderField = noop;
this.onHeadersEnd = noop;
this.onHeaderValue = noop;
this.onPartBegin = noop;
this.onPartData = noop;
this.onPartEnd = noop;
this.boundaryChars = {};
boundary = '\r\n--' + boundary;
const ui8a = new Uint8Array(boundary.length);
for (let i = 0; i < boundary.length; i++) {
ui8a[i] = boundary.charCodeAt(i);
this.boundaryChars[ui8a[i]] = true;
}
this.boundary = ui8a;
this.lookbehind = new Uint8Array(this.boundary.length + 8);
this.state = S.START_BOUNDARY;
}
/**
* @param {Uint8Array} data
*/
write(data) {
let i = 0;
const length_ = data.length;
let previousIndex = this.index;
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
const boundaryLength = this.boundary.length;
const boundaryEnd = boundaryLength - 1;
const bufferLength = data.length;
let c;
let cl;
const mark = name => {
this[name + 'Mark'] = i;
};
const clear = name => {
delete this[name + 'Mark'];
};
const callback = (callbackSymbol, start, end, ui8a) => {
if (start === undefined || start !== end) {
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
}
};
const dataCallback = (name, clear) => {
const markSymbol = name + 'Mark';
if (!(markSymbol in this)) {
return;
}
if (clear) {
callback(name, this[markSymbol], i, data);
delete this[markSymbol];
} else {
callback(name, this[markSymbol], data.length, data);
this[markSymbol] = 0;
}
};
for (i = 0; i < length_; i++) {
c = data[i];
switch (state) {
case S.START_BOUNDARY:
if (index === boundary.length - 2) {
if (c === HYPHEN) {
flags |= F.LAST_BOUNDARY;
} else if (c !== CR) {
return;
}
index++;
break;
} else if (index - 1 === boundary.length - 2) {
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
state = S.END;
flags = 0;
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
index = 0;
callback('onPartBegin');
state = S.HEADER_FIELD_START;
} else {
return;
}
break;
}
if (c !== boundary[index + 2]) {
index = -2;
}
if (c === boundary[index + 2]) {
index++;
}
break;
case S.HEADER_FIELD_START:
state = S.HEADER_FIELD;
mark('onHeaderField');
index = 0;
// falls through
case S.HEADER_FIELD:
if (c === CR) {
clear('onHeaderField');
state = S.HEADERS_ALMOST_DONE;
break;
}
index++;
if (c === HYPHEN) {
break;
}
if (c === COLON) {
if (index === 1) {
// empty header field
return;
}
dataCallback('onHeaderField', true);
state = S.HEADER_VALUE_START;
break;
}
cl = lower(c);
if (cl < A || cl > Z) {
return;
}
break;
case S.HEADER_VALUE_START:
if (c === SPACE) {
break;
}
mark('onHeaderValue');
state = S.HEADER_VALUE;
// falls through
case S.HEADER_VALUE:
if (c === CR) {
dataCallback('onHeaderValue', true);
callback('onHeaderEnd');
state = S.HEADER_VALUE_ALMOST_DONE;
}
break;
case S.HEADER_VALUE_ALMOST_DONE:
if (c !== LF) {
return;
}
state = S.HEADER_FIELD_START;
break;
case S.HEADERS_ALMOST_DONE:
if (c !== LF) {
return;
}
callback('onHeadersEnd');
state = S.PART_DATA_START;
break;
case S.PART_DATA_START:
state = S.PART_DATA;
mark('onPartData');
// falls through
case S.PART_DATA:
previousIndex = index;
if (index === 0) {
// boyer-moore derrived algorithm to safely skip non-boundary data
i += boundaryEnd;
while (i < bufferLength && !(data[i] in boundaryChars)) {
i += boundaryLength;
}
i -= boundaryEnd;
c = data[i];
}
if (index < boundary.length) {
if (boundary[index] === c) {
if (index === 0) {
dataCallback('onPartData', true);
}
index++;
} else {
index = 0;
}
} else if (index === boundary.length) {
index++;
if (c === CR) {
// CR = part boundary
flags |= F.PART_BOUNDARY;
} else if (c === HYPHEN) {
// HYPHEN = end boundary
flags |= F.LAST_BOUNDARY;
} else {
index = 0;
}
} else if (index - 1 === boundary.length) {
if (flags & F.PART_BOUNDARY) {
index = 0;
if (c === LF) {
// unset the PART_BOUNDARY flag
flags &= ~F.PART_BOUNDARY;
callback('onPartEnd');
callback('onPartBegin');
state = S.HEADER_FIELD_START;
break;
}
} else if (flags & F.LAST_BOUNDARY) {
if (c === HYPHEN) {
callback('onPartEnd');
state = S.END;
flags = 0;
} else {
index = 0;
}
} else {
index = 0;
}
}
if (index > 0) {
// when matching a possible boundary, keep a lookbehind reference
// in case it turns out to be a false lead
lookbehind[index - 1] = c;
} else if (previousIndex > 0) {
// if our boundary turned out to be rubbish, the captured lookbehind
// belongs to partData
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
callback('onPartData', 0, previousIndex, _lookbehind);
previousIndex = 0;
mark('onPartData');
// reconsider the current character even so it interrupted the sequence
// it could be the beginning of a new sequence
i--;
}
break;
case S.END:
break;
default:
throw new Error(`Unexpected state entered: ${state}`);
}
}
dataCallback('onHeaderField');
dataCallback('onHeaderValue');
dataCallback('onPartData');
// Update properties for the next call
this.index = index;
this.state = state;
this.flags = flags;
}
end() {
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
this.onPartEnd();
} else if (this.state !== S.END) {
throw new Error('MultipartParser.end(): stream ended unexpectedly');
}
}
}
function _fileName(headerValue) {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
if (!m) {
return;
}
const match = m[2] || m[3] || '';
let filename = match.slice(match.lastIndexOf('\\') + 1);
filename = filename.replace(/%22/g, '"');
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
return String.fromCharCode(code);
});
return filename;
}
async function toFormData(Body, ct) {
if (!/multipart/i.test(ct)) {
throw new TypeError('Failed to fetch');
}
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
if (!m) {
throw new TypeError('no or bad content-type header, no multipart boundary');
}
const parser = new MultipartParser(m[1] || m[2]);
let headerField;
let headerValue;
let entryValue;
let entryName;
let contentType;
let filename;
const entryChunks = [];
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .fS();
const onPartData = ui8a => {
entryValue += decoder.decode(ui8a, {stream: true});
};
const appendToFile = ui8a => {
entryChunks.push(ui8a);
};
const appendFileToFormData = () => {
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .ZH(entryChunks, filename, {type: contentType});
formData.append(entryName, file);
};
const appendEntryToFormData = () => {
formData.append(entryName, entryValue);
};
const decoder = new TextDecoder('utf-8');
decoder.decode();
parser.onPartBegin = function () {
parser.onPartData = onPartData;
parser.onPartEnd = appendEntryToFormData;
headerField = '';
headerValue = '';
entryValue = '';
entryName = '';
contentType = '';
filename = null;
entryChunks.length = 0;
};
parser.onHeaderField = function (ui8a) {
headerField += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderValue = function (ui8a) {
headerValue += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderEnd = function () {
headerValue += decoder.decode();
headerField = headerField.toLowerCase();
if (headerField === 'content-disposition') {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
if (m) {
entryName = m[2] || m[3] || '';
}
filename = _fileName(headerValue);
if (filename) {
parser.onPartData = appendToFile;
parser.onPartEnd = appendFileToFormData;
}
} else if (headerField === 'content-type') {
contentType = headerValue;
}
headerValue = '';
headerField = '';
};
for await (const chunk of Body) {
parser.write(chunk);
}
parser.end();
return formData;
}
/***/ })
};

BIN
dist/setup/7zr.exe vendored

Binary file not shown.

16498
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

View File

@@ -45,10 +45,10 @@ If `check-latest` is set to `true`, the action first checks if the cached versio
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '16'
check-latest: true
- run: npm ci
- run: npm test
@@ -63,8 +63,8 @@ See [supported version syntax](https://github.com/actions/setup-node#supported-v
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- run: npm ci
@@ -97,10 +97,10 @@ jobs:
runs-on: windows-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '14'
architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default
- run: npm ci
- run: npm test
@@ -118,10 +118,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.0.0-v8-canary' # it will install the latest v8 canary release for node 24.0.0
node-version: '20.0.0-v8-canary' # it will install the latest v8 canary release for node 20.0.0
- run: npm ci
- run: npm test
```
@@ -133,10 +133,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24-v8-canary' # it will install the latest v8 canary release for node 24
node-version: '20-v8-canary' # it will install the latest v8 canary release for node 20
- run: npm ci
- run: npm test
```
@@ -149,10 +149,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'v24.0.0-v8-canary2025030537242e55ac'
node-version: 'v20.1.1-v8-canary20221103f7e2421e91'
- run: npm ci
- run: npm test
```
@@ -169,10 +169,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24-nightly' # it will install the latest nightly release for node 24
node-version: '16-nightly' # it will install the latest nightly release for node 16
- run: npm ci
- run: npm test
```
@@ -185,10 +185,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.0.0-nightly' # it will install the latest nightly release for node 24.0.0
node-version: '16.0.0-nightly' # it will install the latest nightly release for node 16.0.0
- run: npm ci
- run: npm test
```
@@ -201,10 +201,10 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.0.0-nightly202505066102159fa1'
node-version: '16.0.0-nightly20210420a0261d231c'
- run: npm ci
- run: npm test
```
@@ -219,28 +219,27 @@ jobs:
runs-on: ubuntu-latest
name: Node sample
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.0.0-rc.4'
node-version: '16.0.0-rc.1'
- run: npm ci
- run: npm test
```
**Note:** Unlike nightly versions, which support version range specifiers, you must specify the exact version for a release candidate: `24.0.0-rc.4`.
**Note:** Unlike nightly versions, which support version range specifiers, you must specify the exact version for a release candidate: `16.0.0-rc.1`.
## Caching packages data
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 Classic (v1) and Yarn Berry (v2, v3, v4+).
Yarn caching handles both yarn versions: 1 or 2.
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '14'
cache: 'yarn'
- run: yarn install --frozen-lockfile # optional, --immutable
- run: yarn test
@@ -256,13 +255,13 @@ steps:
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 10
- uses: actions/setup-node@v6
version: 6.32.9
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '14'
cache: 'pnpm'
- run: pnpm install
- run: pnpm test
@@ -275,10 +274,10 @@ steps:
**Using wildcard patterns to cache dependencies**
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '14'
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
- run: npm ci
@@ -288,10 +287,10 @@ steps:
**Using a list of file paths to cache dependencies**
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
node-version: '14'
cache: 'npm'
cache-dependency-path: |
server/app/package-lock.json
@@ -313,21 +312,21 @@ jobs:
- macos-latest
- windows-latest
node_version:
- 20
- 22
- 24
- 12
- 14
- 16
architecture:
- x64
# an extra windows-x86 run:
include:
- os: windows-latest
node_version: 24
- os: windows-2016
node_version: 12
architecture: x86
name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node_version }}
architecture: ${{ matrix.architecture }}
@@ -338,16 +337,16 @@ jobs:
## Publish to npmjs and GPR with npm
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.x'
node-version: '14.x'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
registry-url: 'https://npm.pkg.github.com'
- run: npm publish
@@ -358,16 +357,16 @@ steps:
## Publish to npmjs and GPR with yarn
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.x'
node-version: '14.x'
registry-url: <registry url>
- run: yarn install --frozen-lockfile
- run: yarn publish
env:
NODE_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }}
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
registry-url: 'https://npm.pkg.github.com'
- run: yarn publish
@@ -378,10 +377,10 @@ steps:
## Use private packages
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.x'
node-version: '14.x'
registry-url: 'https://registry.npmjs.org'
# Skip post-install scripts here, as a malicious
# script could steal NODE_AUTH_TOKEN.
@@ -398,10 +397,10 @@ Below you can find a sample "Setup .yarnrc.yml" step, that is going to allow you
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.x'
node-version: '14.x'
- name: Setup .yarnrc.yml
run: |
yarn config set npmScopes.my-org.npmRegistryServer "https://npm.pkg.github.com"
@@ -428,9 +427,9 @@ It is possible to specify a token to authenticate with the mirror using the `mir
The token will be passed as a bearer token in the `Authorization` header.
```yaml
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
node-version: '24.x'
node-version: '14.x'
mirror: 'https://nodejs.org/dist'
mirror-token: 'your-mirror-token'
```

View File

@@ -1,25 +1,11 @@
export default {
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
extensionsToTreatAsEsm: ['.ts'],
transform: {
'^.+\\.ts$': ['ts-jest', {
useESM: true,
tsconfig: {
module: 'es2022',
target: 'es2022'
}
}]
'^.+\\.ts$': 'ts-jest'
},
preset: 'ts-jest/presets/default-esm',
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1'
},
transformIgnorePatterns: [
'node_modules/(?!(node-fetch|fetch-blob|formdata-polyfill|data-uri-to-buffer)/)'
],
verbose: true
}

1454
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,16 @@
{
"name": "setup-node",
"version": "6.0.0",
"version": "4.0.0",
"private": true,
"type": "module",
"description": "setup node action",
"main": "lib/setup-node.js",
"engines": {
"node": ">=24.0.0"
},
"scripts": {
"build": "ncc build -o dist/setup src/setup-node.ts && ncc build -o dist/cache-save src/cache-save.ts",
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
"format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check \"**/*.{ts,yml,yaml}\"",
"lint": "eslint --config ./.eslintrc.cjs \"**/*.ts\"",
"lint:fix": "eslint --config ./.eslintrc.cjs \"**/*.ts\" --fix",
"test": "node --experimental-vm-modules node_modules/.bin/jest --coverage",
"lint": "eslint --config ./.eslintrc.js \"**/*.ts\"",
"lint:fix": "eslint --config ./.eslintrc.js \"**/*.ts\" --fix",
"test": "jest --coverage",
"pre-checkin": "npm run format && npm run lint:fix && npm run build && npm test"
},
"repository": {
@@ -41,9 +37,8 @@
"uuid": "^11.1.0"
},
"devDependencies": {
"@jest/globals": "^30.2.0",
"@types/jest": "^29.5.14",
"@types/node": "^24.1.0",
"@types/node": "^20.11.25",
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
@@ -55,11 +50,8 @@
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"jest-each": "^29.7.0",
"prettier": "^3.6.2",
"ts-jest": "^29.4.1",
"prettier": "^2.8.4",
"ts-jest": "^29.1.2",
"typescript": "^5.4.2"
},
"overrides": {
"node-fetch": "^3.3.2"
}
}

View File

@@ -5,13 +5,13 @@ import path from 'path';
import fs from 'fs';
import os from 'os';
import {State} from './constants.js';
import {State} from './constants';
import {
getCacheDirectories,
getPackageManagerInfo,
repoHasYarnBerryManagedDependencies,
PackageManagerInfo
} from './cache-utils.js';
} from './cache-utils';
export const restoreCache = async (
packageManager: string,

View File

@@ -1,13 +1,12 @@
import * as core from '@actions/core';
import * as cache from '@actions/cache';
import {State} from './constants.js';
import {getPackageManagerInfo} from './cache-utils.js';
import {State} from './constants';
import {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}`);

View File

@@ -4,7 +4,7 @@ import * as cache from '@actions/cache';
import * as glob from '@actions/glob';
import path from 'path';
import fs from 'fs';
import {unique} from './util.js';
import {unique} from './util';
export interface PackageManagerInfo {
name: string;
@@ -167,12 +167,14 @@ const getCacheDirectoriesFromCacheDependencyPath = async (
packageManagerInfo: PackageManagerInfo,
cacheDependencyPath: string
): Promise<string[]> => {
const projectDirectories =
await getProjectDirectoriesFromCacheDependencyPath(cacheDependencyPath);
const projectDirectories = await getProjectDirectoriesFromCacheDependencyPath(
cacheDependencyPath
);
const cacheFoldersPaths = await Promise.all(
projectDirectories.map(async projectDirectory => {
const cacheFolderPath =
await packageManagerInfo.getCacheFolderPath(projectDirectory);
const cacheFolderPath = await packageManagerInfo.getCacheFolderPath(
projectDirectory
);
core.debug(
`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`
);

View File

@@ -2,8 +2,8 @@ import * as tc from '@actions/tool-cache';
import semver from 'semver';
import BaseDistribution from './base-distribution.js';
import {NodeInputs} from './base-models.js';
import BaseDistribution from './base-distribution';
import {NodeInputs} from './base-models';
export default abstract class BasePrereleaseNodejs extends BaseDistribution {
protected abstract distribution: string;

View File

@@ -10,12 +10,8 @@ import * as assert from 'assert';
import * as path from 'path';
import os from 'os';
import fs from 'fs';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import {NodeInputs, INodeVersion, INodeVersionInfo} from './base-models.js';
import {NodeInputs, INodeVersion, INodeVersionInfo} from './base-models';
export default abstract class BaseDistribution {
protected httpClient: hc.HttpClient;

View File

@@ -1,9 +1,9 @@
import BaseDistribution from './base-distribution.js';
import {NodeInputs} from './base-models.js';
import NightlyNodejs from './nightly/nightly_builds.js';
import OfficialBuilds from './official_builds/official_builds.js';
import RcBuild from './rc/rc_builds.js';
import CanaryBuild from './v8-canary/canary_builds.js';
import BaseDistribution from './base-distribution';
import {NodeInputs} from './base-models';
import NightlyNodejs from './nightly/nightly_builds';
import OfficialBuilds from './official_builds/official_builds';
import RcBuild from './rc/rc_builds';
import CanaryBuild from './v8-canary/canary_builds';
enum Distributions {
DEFAULT = '',

View File

@@ -1,5 +1,5 @@
import BasePrereleaseNodejs from '../base-distribution-prerelease.js';
import {NodeInputs} from '../base-models.js';
import BasePrereleaseNodejs from '../base-distribution-prerelease';
import {NodeInputs} from '../base-models';
export default class NightlyNodejs extends BasePrereleaseNodejs {
protected distribution = 'nightly';

View File

@@ -2,8 +2,8 @@ import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import path from 'path';
import BaseDistribution from '../base-distribution.js';
import {NodeInputs, INodeVersion, INodeVersionInfo} from '../base-models.js';
import BaseDistribution from '../base-distribution';
import {NodeInputs, INodeVersion, INodeVersionInfo} from '../base-models';
interface INodeRelease extends tc.IToolRelease {
lts?: string;
@@ -221,8 +221,8 @@ export default class OfficialBuilds extends BaseDistribution {
alias === '*'
? numbered[numbered.length - 1]
: n < 0
? numbered[numbered.length - 1 + n]
: aliases[alias];
? numbered[numbered.length - 1 + n]
: aliases[alias];
if (!release) {
throw new Error(

View File

@@ -1,5 +1,5 @@
import BaseDistribution from '../base-distribution.js';
import {NodeInputs} from '../base-models.js';
import BaseDistribution from '../base-distribution';
import {NodeInputs} from '../base-models';
export default class RcBuild extends BaseDistribution {
constructor(nodeInfo: NodeInputs) {

View File

@@ -1,5 +1,5 @@
import BasePrereleaseNodejs from '../base-distribution-prerelease.js';
import {NodeInputs} from '../base-models.js';
import BasePrereleaseNodejs from '../base-distribution-prerelease';
import {NodeInputs} from '../base-models';
export default class CanaryBuild extends BasePrereleaseNodejs {
protected distribution = 'v8-canary';

View File

@@ -1,19 +1,14 @@
import * as core from '@actions/core';
import os from 'os';
import fs from 'fs';
import * as auth from './authutil.js';
import * as auth from './authutil';
import * as path from 'path';
import {restoreCache} from './cache-restore.js';
import {isCacheFeatureAvailable} from './cache-utils.js';
import {getNodejsDistribution} from './distributions/installer-factory.js';
import {getNodeVersionFromFile, printEnvDetailsAndSetOutput} from './util.js';
import {State} from './constants.js';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import {restoreCache} from './cache-restore';
import {isCacheFeatureAvailable} from './cache-utils';
import {getNodejsDistribution} from './distributions/installer-factory';
import {getNodeVersionFromFile, printEnvDetailsAndSetOutput} from './util';
import {State} from './constants';
export async function run() {
try {
@@ -25,9 +20,6 @@ export async function run() {
let arch = core.getInput('architecture');
const cache = core.getInput('cache');
const packagemanagercache =
(core.getInput('package-manager-cache') || 'true').toUpperCase() ===
'TRUE';
// if architecture supplied but node-version is not
// if we don't throw a warning, the already installed x64 node will be used which is not probably what user meant.
@@ -71,25 +63,10 @@ export async function run() {
auth.configAuthentication(registryUrl, alwaysAuth);
}
const cacheDependencyPath = core.getInput('cache-dependency-path');
if (isCacheFeatureAvailable()) {
// if the cache input is provided, use it for caching.
if (cache) {
core.saveState(State.CachePackageManager, cache);
await restoreCache(cache, cacheDependencyPath);
// package manager npm is detected from package.json, enable auto-caching for npm.
} else if (packagemanagercache) {
const resolvedPackageManager = getNameFromPackageManagerField();
if (resolvedPackageManager) {
core.info(
"Detected npm as the package manager from package.json's packageManager field. " +
'Auto caching has been enabled for npm. If you want to disable it, set package-manager-cache input to false'
);
core.saveState(State.CachePackageManager, resolvedPackageManager);
await restoreCache(resolvedPackageManager, cacheDependencyPath);
}
}
if (cache && isCacheFeatureAvailable()) {
core.saveState(State.CachePackageManager, cache);
const cacheDependencyPath = core.getInput('cache-dependency-path');
await restoreCache(cache, cacheDependencyPath);
}
const matchersPath = path.join(__dirname, '../..', '.github');
@@ -140,34 +117,3 @@ function resolveVersionInput(): string {
return version;
}
export function getNameFromPackageManagerField(): string | undefined {
const npmRegex = /^(\^)?npm(@.*)?$/; // matches "npm", "npm@...", "^npm@..."
try {
const packageJson = JSON.parse(
fs.readFileSync(
path.join(process.env.GITHUB_WORKSPACE!, 'package.json'),
'utf-8'
)
);
// Check devEngines.packageManager first (object or array)
const devPM = packageJson?.devEngines?.packageManager;
const devPMArray = devPM ? (Array.isArray(devPM) ? devPM : [devPM]) : [];
for (const obj of devPMArray) {
if (typeof obj?.name === 'string' && npmRegex.test(obj.name)) {
return 'npm';
}
}
// Check top-level packageManager
const topLevelPM = packageJson?.packageManager;
if (typeof topLevelPM === 'string' && npmRegex.test(topLevelPM)) {
return 'npm';
}
return undefined;
} catch {
return undefined;
}
}

View File

@@ -1,3 +1,3 @@
import {run} from './main.js';
import {run} from './main';
run();

View File

@@ -1,14 +1,14 @@
{
"compilerOptions": {
"target": "es2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "es2022", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' or 'classic'. */
"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'. */
"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,
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"resolveJsonModule": true, /* Allows importing modules with a '.json' extension, which is a common practice in node projects. */
},
"exclude": ["lib", "node_modules"]
"exclude": ["__tests__", "lib", "node_modules"]
}