## File: README.md

# setup-node

[](https://github.com/actions/setup-node/actions/workflows/basic-validation.yml)
[](https://github.com/actions/setup-node/actions/workflows/versions.yml)
[](https://github.com/actions/setup-node/actions/workflows/e2e-cache.yml)
[](https://github.com/actions/setup-node/actions/workflows/proxy.yml)

This action provides the following functionality for GitHub Actions users:

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

## What's new in V7

- Migrated action internals to ESM for compatibility with latest `@actions/*` packages. No changes to action inputs, outputs, or behavior.

### Breaking change

- The dummy `NODE_AUTH_TOKEN` fallback has been removed, as it could unintentionally affect the generated `.npmrc` with a non-functional token. With this change, if `registry-url` is set without `NODE_AUTH_TOKEN`, legacy Yarn Classic (1.x) and older Node/npm versions may fail, and pnpm may warn. npm Trusted Publishing (OIDC) is not affected, since it does not use `NODE_AUTH_TOKEN`.

## 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.

- The `always-auth` input has been removed, as it is deprecated and will no longer be supported in future npm releases. To ensure your workflows continue to run without warnings or errors, please remove any references to `always-auth` from your configuration.

## 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)

## Usage

See [action.yml](action.yml)


```
/* Detailed source-code truncated for AI context efficiency. */
```


**Basic:**

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: 24
    package-manager-cache: false # Disable automatic npm caching if not required
- run: npm ci
- run: npm test
```

The `node-version` input is optional. If not supplied, the node version from PATH will be used. However, it is recommended to always specify Node.js version and not rely on the system one.

The action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js. It will pull LTS versions from [node-versions releases](https://github.com/actions/node-versions/releases) and on miss or failure will fall back to the previous behavior of downloading directly from [node dist](https://nodejs.org/dist/).

For information regarding locally cached versions of Node.js on GitHub hosted runners, check out [GitHub Actions Runner Images](https://github.com/actions/runner-images).

### Supported version syntax

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: `22`, `24`
 - More specific versions: `20.19`, `22.17.1` , `24.8.0`
 - NVM LTS syntax: `lts/iron`, `lts/jod`, `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.

`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.
Since it will not be cached always, there is possibility of hitting rate limit when downloading from dist

### Checking in lockfiles

It's **strongly recommended** to commit the lockfile of your package manager for security and performance reasons. For more information consult the "Working with lockfiles" section of the [Advanced usage](docs/advanced-usage.md#working-with-lockfiles) guide.

## 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 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.

**Note:** The action does not cache `node_modules`

See the examples of using cache for `yarn`/`pnpm` and `cache-dependency-path` input in the [Advanced usage](docs/advanced-usage.md#caching-packages-data) guide.

**Caching npm dependencies:**

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: 24
    cache: 'npm'
- run: npm ci
- run: npm test
```

**Caching npm dependencies in monorepos:**

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: 24
    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@v7
- uses: actions/setup-node@v7
  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
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [ 20, 22, 24 ]
    name: Node ${{ matrix.node }} sample
    steps:
      - uses: actions/checkout@v7
      - name: Setup node
        uses: actions/setup-node@v7
        with:
          node-version: ${{ matrix.node }}
          package-manager-cache: false # Disable automatic npm caching if not required
      - 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@v7
with:
  token: ${{ secrets.GH_DOTCOM_TOKEN }}
  node-version: 24
  package-manager-cache: false # Disable automatic npm caching if not required
```

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

 - [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)
 - [Publishing to npm with Trusted Publisher (OIDC)](docs/advanced-usage.md#publishing-to-npm-with-trusted-publisher-oidc)
 - [Using private mirror](docs/advanced-usage.md#use-private-mirror)

## Recommended permissions

When using the `setup-node` action in your GitHub Actions workflow, it is recommended to set the following permissions to ensure proper functionality:

```yaml
permissions:
  contents: read # access to check out code and install dependencies
```

## License

The scripts and documentation in this project are released under the [MIT License](LICENSE)

## Contributions

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)

---

## File: docs/adrs/0000-caching-dependencies.md

# 0. Caching dependencies
Date: 2021-05-21

Status: Accepted

# Context
`actions/setup-node` is the 2nd most popular action in GitHub Actions. A lot of customers use it in conjunction with [actions/cache](https://github.com/actions/cache) to speed up dependencies installation.  
See more examples on proper usage in [actions/cache documentation](https://github.com/actions/cache/blob/main/examples.md#node---npm).

# Goals & Anti-Goals
Integration of caching functionality into `actions/setup-node` action will bring the following benefits for action users:
- Decrease the entry threshold for using the cache for Node.js dependencies and simplify initial configuration
- Simplify YAML pipelines because no need additional steps to enable caching
- More users will use cache for Node.js so more customers will have fast builds!

We will add support for NPM and Yarn dependencies caching.  
As the first stage, we won't support custom locations for `package-lock.json`, `yarn.lock` files and action will work only when files are located in repository root. 

We don't pursue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly.

# Decision
- Add `cache` input parameter to `actions/setup-node`. For now, input will accept the following values: 
  - `npm` - enable caching for npm dependencies
  - `yarn` - enable caching for yarn dependencies
  - `''` - disable caching (default value)
- Cache feature will be disabled by default to make sure that we don't break existing customers. We will consider enabling cache by default in next major release (`v3`)
- Action will try to search `package-lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found
- The hash of found file will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends)
- The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}`
- Action will cache global cache:
  - Npm (retrieved via `npm config get cache`)
  - Yarn 1 (retrieved via `yarn cache dir`)
  - Yarn 2 (retrieved via `yarn config get cacheFolder`)

# Example of real use-cases
Npm package manager:
```yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
  with:
    node-version: '14'
    cache: npm
```

Yarn package manager:
```yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
  with:
    node-version: '14'
    cache: yarn
```

# Release process

As soon as functionality is implemented, we will release minor update of action. No need to bump major version since there are no breaking changes for existing users.
After that, we will update [starter-workflows](https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml) and [GitHub Action documentation](https://docs.github.com/en/actions/guides/building-and-testing-nodejs#example-caching-dependencies).

---

## File: docs/adrs/0001-support-caching-deps-for-monorepos.md

# 0. Support caching dependencies for mono repos
Date: 2021-07-13

Status: Proposed

## Context
Currently, `actions/setup-node` supports caching dependencies for Npm and Yarn package managers.  
For the first iteration, we have decided to not support cases where `package-lock.json` / `yarn.lock` are located outside of repository root.  
Current implementation searches the following file patterns in the repository root: `package-lock.json`, `yarn.lock` (in order of resolving priorities)

Obviously, it made built-in caching unusable for mono-repos and repos with complex structure.  
We would like to revisit this decision and add customization for dependencies lock file location.

## Proposal
We have the following options:
1. Allow to specify  directory where `package-lock.json` or `yarn.lock` are located
2. Allow to specify path to the dependencies lock file (including directory path and filename)

The second option looks more generic because it allows to:
- specify multiple dependencies files using file patterns like `**/package-lock.json` ([one of recommended approaches in actions/cache](https://github.com/actions/cache/blob/main/examples.md#macos-and-ubuntu))
- specify custom dependencies files like `src/npm-shrinkwrap.json`
- change default resolving priority if both `yarn.lock` and `package-lock.json` exist in repository

## Decision

Add `cache-dependency-path` input that will accept path (relative to repository root) to dependencies lock file.  
If provided path contains wildcards, the action will search all matching files and calculate common hash like `${{ hashFiles('**/package-lock.json') }}` YAML construction does.  
The hash of provided matched files will be used as a part of cache key.

Yaml examples:
```yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
  with:
    node-version: 14
    cache: npm
    cache-dependency-path: 'sub-project/package-lock.json'
```
```yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
  with:
    node-version: 14
    cache: yarn
    cache-dependency-path: 'sub-project/**/yarn.lock'
```

---

## File: docs/advanced-usage.md

## Working with lockfiles

Most supported package managers recommend that you **always** commit the lockfile, although implementations vary doing so generally provides the following benefits:

- Enables faster installation for CI and production environments, due to being able to skip package resolution.
- Describes a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
- Provides a facility for users to "time-travel" to previous states of `node_modules` without having to commit the directory itself.
- Facilitates greater visibility of tree changes through readable source control diffs.

In order to get the most out of using your lockfile on continuous integration follow the conventions outlined below for your respective package manager.

### NPM

Ensure that `package-lock.json` is always committed, use `npm ci` instead of `npm install` when installing packages.

**See also:**
- [Documentation of `package-lock.json`](https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json)
- [Documentation of `npm ci`](https://docs.npmjs.com/cli/v8/commands/npm-ci)

### Yarn

To ensure that `yarn.lock` is always committed, use `yarn install --immutable` when installing packages.

**See also:**
- [Documentation of `yarn.lock`](https://classic.yarnpkg.com/en/docs/yarn-lock)
- [Documentation of `--frozen-lockfile` option](https://classic.yarnpkg.com/en/docs/cli/install#toc-yarn-install-frozen-lockfile)
- [QA - Should lockfiles be committed to the repository?](https://yarnpkg.com/getting-started/qa/#should-lockfiles-be-committed-to-the-repository)
- [Documentation of `yarn install`](https://yarnpkg.com/cli/install)

### PNPM

Ensure that `pnpm-lock.yaml` is always committed, when on CI pass `--frozen-lockfile` to `pnpm install` when installing packages.

**See also:**
- [Working with Git - Lockfiles](https://pnpm.io/git#lockfiles)
- [Documentation of `--frozen-lockfile` option](https://pnpm.io/cli/install#--frozen-lockfile)

### Running without a lockfile

If you choose not to use a lockfile, you must ensure that **caching is disabled**. The `cache` feature relies on the lockfile to generate a unique key for the cache entry.

To run without a lockfile:
1. Do not set the `cache` input.
2. If your `package.json` contains a `packageManager` field set to npm (or devEngines.packageManager), automatic caching is enabled by default. Override this by setting `package-manager-cache: false`.

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    package-manager-cache: false # Explicitly disable caching if you don't have a lockfile
- run: npm install
- run: npm test
```

## Check latest version

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

If `check-latest` is set to `true`, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, a version of Node.js will then be downloaded. Set `check-latest` to `true` it you want the most up-to-date version of Node.js to always be used.

> Setting `check-latest` to `true` has performance implications as downloading versions of Node is slower than using cached versions.

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    check-latest: true
    package-manager-cache: false # Disable automatic npm caching if not required
- run: npm ci
- run: npm test
```

## Node version file

The `node-version-file` input accepts a path to a file containing the version of Node.js to be used by a project, for example `.nvmrc`, `.node-version`, `.tool-versions`, `mise.toml`, or `package.json`. If both the `node-version` and the `node-version-file` inputs are provided then the `node-version` input is used.
See [supported version syntax](https://github.com/actions/setup-node#supported-version-syntax).

> The action will search for the node version file relative to the repository root.

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version-file: '.nvmrc'
    package-manager-cache: false # Disable automatic npm caching if not required
- run: npm ci
- run: npm test
```

When using the `package.json` input, the action will look in the following fields for a specified Node version:
1. It checks `volta.node` first.
2. Then it checks `devEngines.runtime` for an entry with `"name": "node"`.
3. Then it will look for `engines.node`.
4. Otherwise it tries to resolve the file defined by [`volta.extends`](https://docs.volta.sh/advanced/workspaces)
   and look for `volta.node`, `devEngines.runtime`, or `engines.node` recursively.


```json
{
  "engines": {
    "node": "^22 || ^24"
  },
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": "^24.3"
    }
  },
  "volta": {
    "node": "24.11.1"
  }
}
```

## Architecture

You can use any of the [supported operating systems](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners), and the compatible `architecture` can be selected using `architecture`. Values are `x86`, `x64`, `arm64`, `armv6l`, `armv7l`, `ppc64le`, `s390x` (not all of the architectures are available on all platforms).

When using `architecture`, `node-version` must be provided as well.
```yaml
jobs:
  build:
    runs-on: windows-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24'
          architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

## V8 Canary versions

You can specify a nightly version to download it from https://nodejs.org/download/v8-canary.

### Install v8 canary build for specific node version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24.0.0-v8-canary' # it will install the latest v8 canary release for node 24.0.0
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```
### Install v8 canary build for major node version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24-v8-canary' # it will install the latest v8 canary release for node 24
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

### Install the exact v8 canary version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 'v24.0.0-v8-canary2025030537242e55ac'
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

## Nightly versions

You can specify a nightly version to download it from https://nodejs.org/download/nightly. 

### Install the nightly build for a major version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24-nightly' # it will install the latest nightly release for node 24
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

### Install the nightly build for a specific version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24.0.0-nightly' # it will install the latest nightly release for node 24.0.0
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

### Install an exact nightly version

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24.0.0-nightly202505066102159fa1'
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

## RC versions

You can use specify a rc version to download it from https://nodejs.org/download/rc.

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    name: Node sample
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: '24.0.0-rc.4'
          package-manager-cache: false # Disable automatic npm caching if not required
      - 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`.

## 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+).

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    cache: 'yarn'
- run: yarn install --frozen-lockfile # optional, --immutable
- run: yarn test
```

**Caching pnpm (v6.10+) dependencies:**
```yaml
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# NOTE: pnpm caching support requires pnpm version >= 6.10.0

steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
  with:
    version: 10
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    cache: 'pnpm'
- run: pnpm install
- run: pnpm test
```

> **Note**: By default `--frozen-lockfile` option is passed starting from pnpm `6.10.x`. It will be automatically added if you run it on [CI](https://pnpm.io/cli/install#--frozen-lockfile). 
> If the `pnpm-lock.yaml` file changes then pass `--frozen-lockfile` option.


**Using wildcard patterns to cache dependencies**
```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    cache: 'npm'
    cache-dependency-path: '**/package-lock.json'
- run: npm ci
- run: npm test
```

**Using a list of file paths to cache dependencies**
```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24'
    cache: 'npm'
    cache-dependency-path: |
      server/app/package-lock.json
      frontend/app/package-lock.json
- run: npm ci
- run: npm test
```

**Restore-only cache**

You can restore caches without saving new entries, which helps reduce cache writes and storage usage in read-only cache workflows.

```yaml
steps:
- uses: actions/checkout@v7
# - uses: pnpm/action-setup@v6 
#   with:
#     version: 10

- name: Setup Node.js
  uses: actions/setup-node@v7
  with:
    node-version: '24'
    package-manager-cache: false # Disable automatic npm caching if not required

- name: Normalize runner architecture
  shell: bash
  run: echo "ARCH=$(echo '${{ runner.arch }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
    
- name: Output of cache path
  id: cachepath
  shell: bash
  run: echo "path=$(npm config get cache)" >> $GITHUB_OUTPUT
  # run: echo "path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
  # For yarn workflow, output of yarn cache dir (v1) or yarn config get cacheFolder (v2+)
  # run: echo "path=$(yarn cache dir)" >> $GITHUB_OUTPUT 
    
- name: Restore Node cache
  uses: actions/cache/restore@v5
  with:
    path: ${{ steps.cachepath.outputs.path }}
    key: node-cache-${{ runner.os }}-${{ env.ARCH }}-npm-${{ hashFiles('**/package-lock.json') }}
    # key: node-cache-${{ runner.os }}-${{ env.ARCH }}-yarn-${{ hashFiles('**/yarn.lock') }}
    # key: node-cache-${{ runner.os }}-${{ env.ARCH }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
    
- run: npm ci
# - run: yarn install --frozen-lockfile # optional, --immutable
# - run: pnpm install
```
> **Note**: Uncomment the commands relevant to your project's package manager.

> For more details related to cache scenarios, please refer [actions/cache/restore](https://github.com/actions/cache/tree/main/restore#only-restore-cache).

## Multiple operating systems and architectures

```yaml
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
        node_version:
          - 22
          - 24
          - 26
        architecture:
          - x64
        # an extra windows-x86 run:
        include:
          - os: windows-latest
            node_version: 24
            architecture: x86
    name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v7
      - name: Setup node
        uses: actions/setup-node@v7
        with:
          node-version: ${{ matrix.node_version }}
          architecture: ${{ matrix.architecture }}
          package-manager-cache: false # Disable automatic npm caching if not required
      - run: npm ci
      - run: npm test
```

## Publish to npmjs and GPR with npm
```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24.x'
    registry-url: 'https://registry.npmjs.org'
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
- run: npm ci
- run: npm publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: actions/setup-node@v7
  with:
    registry-url: 'https://npm.pkg.github.com'
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
- run: npm publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

## Publish to npmjs and GPR with yarn
```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24.x'
    registry-url: <registry url>
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
- run: yarn install --frozen-lockfile
- run: yarn publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }}
- uses: actions/setup-node@v7
  with:
    registry-url: 'https://npm.pkg.github.com'
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
- run: yarn publish
  env:
    NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

## Use private packages
```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24.x'
    registry-url: 'https://registry.npmjs.org'
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
# Skip post-install scripts here, as a malicious
# script could steal NODE_AUTH_TOKEN.
- run: npm ci --ignore-scripts
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# `npm rebuild` will run all those post-install scripts for us.
- run: npm rebuild && npm run prepare --if-present
```
### Yarn2 configuration
Yarn2 ignores both .npmrc and .yarnrc files created by the action, so before installing dependencies from the private repo it is necessary either to create or to modify existing yarnrc.yml file with `yarn config set` commands.

Below you can find a sample "Setup .yarnrc.yml" step, that is going to allow you to configure a private GitHub registry for 'my-org' organisation.

```yaml
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
  with:
    node-version: '24.x'
    package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk
- name: Setup .yarnrc.yml
  run: |
    yarn config set npmScopes.my-org.npmRegistryServer "https://npm.pkg.github.com"
    yarn config set npmScopes.my-org.npmAlwaysAuth true
    yarn config set npmScopes.my-org.npmAuthToken $NPM_AUTH_TOKEN
  env:
    NPM_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
  run: yarn install --immutable
```

To access private GitHub Packages within the same organization, go to "Manage Actions access" in Package settings and set the repositories you want to access.

Please refer to the [Ensuring workflow access to your package - Configuring a package's access control and visibility](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#ensuring-workflow-access-to-your-package) for more details.

## Publishing to npm with Trusted Publisher (OIDC)

npm supports Trusted Publishers, enabling packages to be published from GitHub Actions using OpenID Connect (OIDC) instead of long-lived npm tokens. This improves security by replacing static credentials with short-lived tokens, reducing the risk of credential leakage and simplifying authentication in CI/CD workflows.

### Requirements

Trusted publishing requires a compatible npm version:

* **npm ≥ 11.5.1 (required)**
* **Node.js 24 or newer (recommended)** — includes a compatible npm version by default

> If npm is below 11.5.1, publishing will fail even if OIDC permissions are correctly configured.

You must also configure a **Trusted Publisher** in npm for your package/scope that matches your GitHub repository and workflow (and optional environment, if used).

> **Note**: In publishing workflows, set `package-manager-cache: false` because setup-node enables npm caching automatically when `package.json` specifies npm via `packageManager` or `devEngines.packageManager` (see [Running without a lockfile](#running-without-a-lockfile)), and a poisoned cache may expose credentials (including OIDC tokens) to attacker-controlled code.

### Example workflow

```yaml
    permissions:
      contents: read
      id-token: write  # Required for OIDC

    steps:
      - uses: actions/checkout@v7

      - uses: actions/setup-node@v7
        with:
          node-version: '24'
          registry-url: 'https://registry.npmjs.org'
          package-manager-cache: false # Disable automatic npm dependency caching to reduce cache poisoning risk

      - run: npm ci
      - run: npm run build --if-present
      - run: npm publish
```

> **Note**: If the Trusted Publisher configuration (GitHub owner/repo/workflow file, and optional environment) does not match the workflow run identity exactly, publishing may fail with **E404 Not Found** even if the package exists on npm.

For more details, see the [npm Trusted Publishers documentation](https://docs.npmjs.com/trusted-publishers) and the [GitHub Actions OpenID Connect (OIDC) overview](https://docs.github.com/en/actions/concepts/security/openid-connect).

## Use private mirror

It is possible to use a private mirror hosting Node.js binaries. This mirror must be a full mirror of the official Node.js distribution.
The mirror URL can be set using the `mirror` input.
It is possible to specify a token to authenticate with the mirror using the `mirror-token` input.
The token will be passed in the `Authorization` header.

```yaml
- uses: actions/setup-node@v7
  with:
    node-version: '24.x'
    mirror: 'https://nodejs.org/dist'
    mirror-token: 'your-mirror-token'
    package-manager-cache: false # Disable automatic npm caching if not required
```

---

## File: docs/contributors.md

# Contributors

Thank you for contributing!

We have prepared a short guide so that the process of making your contribution is as simple and clear as possible. Please check it out before you contribute!

## How can I contribute...

* [Contribute Documentation:green_book:](#contribute-documentation)

* [Contribute Code :computer:](#contribute-code)

* [Provide Support on Issues:pencil:](#provide-support-on-issues)

* [Review Pull Requests:mag:](#review-pull-requests)

## Contribute documentation

Documentation is a super important, critical part of this project. Docs are how we keep track of what we're doing, how, and why. It's how we stay on the same page about our policies and how we tell others everything they need to be able to use this project or contribute to it. 

Documentation contributions of any size are welcome! Feel free to contribute even if you're just rewording a sentence to be more clear, or fixing a spelling mistake!

**How to contribute:**

Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.

- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request 
- Make sure your changes are formatted properly and consistently with the rest of the documentation
- Re-read what you wrote, and run a spellchecker on it to make sure you didn't miss anything
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated

**Once you've filed the pull request:**

- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about this request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:

## Contribute code

We like code commits a lot! They're super handy, and they keep the project going and doing the work it needs to do to be useful to others.

Code contributions of just about any size are acceptable!

The main difference between code contributions and documentation contributions is that contributing code requires the inclusion of relevant tests for the code being added or changed. Contributions without accompanying tests will be held off until a test is added unless the maintainers consider the specific tests to be either impossible or way too much of a burden for such a contribution.

**How to contribute:**

Pull requests are the easiest way to contribute changes to git repos at GitHub. They are the preferred contribution method, as they offer a convenient way of commenting and amending the proposed changes.

- Please check that no one else has already created a pull request with these or similar changes
- Use a "feature branch" for your changes. That separates the changes in the pull request from your other changes and makes it easy to edit/amend commits in the pull request
-  **Run `pre-checkin` script to format, lint, build and test changes**
- Make sure your changes are well formatted and that all tests are passing
- If your pull request is connected to an open issue, please, leave a link to this issue in the `Related issue:` section
- If you later need to add new commits to the pull request, you can simply commit the changes to the local branch and then push them. The pull request gets automatically updated

**Learn more about how to work with the repository:**

- To implement new features or fix bugs, you need to make changes to the `.ts` files, which are located in the `src` folder
- To comply with the code style, **you need to run the `format` script**
- To lint the code, **you need to run the `lint:fix` script**
- To transpile source code to `javascript` we use [NCC](https://github.com/vercel/ncc). **It is very important to run the `build` script after making changes**, otherwise your changes will not get into the final `javascript` build
- You can also start formatting, building code, and testing with a single `pre-checkin` command

**Learn more about how to implement tests:**

Adding or changing tests is an integral part of making a change to the code. 
Unit tests are in the `__tests__` folder, and end-to-end tests are in the `workflows` folder, particularly in the [versions.yml](https://github.com/actions/setup-node/blob/main/.github/workflows/versions.yml) and [e2e-cache.yml](https://github.com/actions/setup-node/blob/main/.github/workflows/e2e-cache.yml) files.

- The contributor can add various types of tests (like unit tests or end-to-end tests), which, in his opinion, will be necessary and sufficient for testing new or changed functionality
- Tests should cover a successful execution, as well as some edge cases and possible errors
- As already mentioned, pull requests without tests will be considered more carefully by maintainers. If you are sure that in this situation the tests are not needed or cannot be implemented with a commensurate effort - please add this clarification message to your pull request

**Once you've filed the pull request:**

- CI will start automatically with some checks. Wait until the end of the execution and make sure that all checks passed successfully. If some checks fail, you can open them one by one, try to find the reason for failing and make changes to your code to resolve the problem
- Maintainers will review your pull request
- If a maintainer requests changes, first of all, try to think about his request critically and only after that implement and request another review
- If your PR gets accepted, it will soon be merged into the main branch. But your contribution will take effect only after the release of a new version of the action and updating the major tag
> Sometimes maintainers reject pull requests and that's ok! Usually, along with rejection, we supply the reason for it. Nonetheless, we still really appreciate you taking the time to do it, and we don't take that lightly :heart:

## Provide support on issues

Helping out other users with their questions is an awesome way of contributing to any community. It's not uncommon for most of the issues on open source projects to be support-related questions by users trying to understand something they ran into or find their way around a known bug.

**To help other folks out with their questions:**

- Go to the [issue tracker](https://github.com/actions/setup-node/issues)
- Read through the list until you find something that you're familiar enough with to answer to
- Respond to the issue with whatever details are needed to clarify the question, or get more details about what's going on
- Once the discussion wraps up and things are clarified, ask the original issue filer (or a maintainer) to close it for you
 
*Some notes on picking up support issues:*

- Avoid responding to issues you don't know you can answer accurately
- Try to refer to past issues with accepted answers as much as possible. Link to them from your replies
- Be kind and patient with users. Often, folks who have run into confusing things might be upset or impatient. This is natural. If you feel uncomfortable in conversation with them, it's better to stay away or withdraw from the issue.

 > If some user is violating our code of conduct [standards](https://github.com/actions/setup-node/blob/main/CODE_OF_CONDUCT.md#our-standards), refer to the [Enforcement](https://github.com/actions/setup-node/blob/main/CODE_OF_CONDUCT.md#enforcement) section of the Code of Conduct to resolve the conflict
 

## Review pull requests
 

Another great way to contribute is to review pull request. Please, be extra kind: people who submit code/doc contributions are putting themselves in a pretty vulnerable position, and have put time and care into what they've done (even if that's not obvious to you!) Please, always respond with respect, and be understanding, but don't feel like you need to sacrifice your standards for their sake, either.
 
**How to review:**

- Go to the [pull requests](https://github.com/actions/setup-node/pulls)
- Make sure you're familiar with the code or documentation is updated, unless it's a minor change (spellchecking, minor formatting, etc.)
- Review changes using the GitHub functionality. You can ask a clarifying question, point out an error or suggest an alternative. 
> Note: You may ask for minor changes - "nitpicks", but consider whether they are real blockers to merging or not
- Submit your review, which may include comments, an approval, or a changes request