From 88483fd687b20893414c42d3e371c183f4c3b814 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sun, 20 Apr 2025 13:12:45 +0200 Subject: [PATCH] feat(node-version-file): support parsing `devEngines` field Signed-off-by: Ferdinand Thiessen --- .github/workflows/versions.yml | 15 +++++++++++ __tests__/data/package-dev-engines.json | 11 +++++++++ __tests__/main.test.ts | 33 +++++++++++++------------ docs/advanced-usage.md | 32 +++++++++++++++++++++--- src/util.ts | 8 ++++++ 5 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 __tests__/data/package-dev-engines.json diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index b51ba8b5..9982cbb6 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -168,6 +168,21 @@ jobs: - name: Verify node run: __tests__/verify-node.sh 20 + version-file-dev-engines: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] + steps: + - uses: actions/checkout@v4 + - name: Setup node from node version file + uses: ./ + with: + node-version-file: '__tests__/data/package-dev-engines.json' + - name: Verify node + run: __tests__/verify-node.sh 20 + version-file-volta: runs-on: ${{ matrix.os }} strategy: diff --git a/__tests__/data/package-dev-engines.json b/__tests__/data/package-dev-engines.json new file mode 100644 index 00000000..bcbdbd2a --- /dev/null +++ b/__tests__/data/package-dev-engines.json @@ -0,0 +1,11 @@ +{ + "engines": { + "node": "^20 || ^22" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^20" + } + } +} diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 501741a6..92768658 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -91,22 +91,23 @@ describe('main tests', () => { describe('getNodeVersionFromFile', () => { each` - contents | expected - ${'12'} | ${'12'} - ${'12.3'} | ${'12.3'} - ${'12.3.4'} | ${'12.3.4'} - ${'v12.3.4'} | ${'12.3.4'} - ${'lts/erbium'} | ${'lts/erbium'} - ${'lts/*'} | ${'lts/*'} - ${'nodejs 12.3.4'} | ${'12.3.4'} - ${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'} - ${''} | ${''} - ${'unknown format'} | ${'unknown format'} - ${' 14.1.0 '} | ${'14.1.0'} - ${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'}| ${'>=14.0.0 <=17.0.0'} - ${'{"volta": {"extends": "./package.json"}}'}| ${'18.0.0'} - ${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'} - ${'{}'} | ${null} + contents | expected + ${'12'} | ${'12'} + ${'12.3'} | ${'12.3'} + ${'12.3.4'} | ${'12.3.4'} + ${'v12.3.4'} | ${'12.3.4'} + ${'lts/erbium'} | ${'lts/erbium'} + ${'lts/*'} | ${'lts/*'} + ${'nodejs 12.3.4'} | ${'12.3.4'} + ${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'} + ${''} | ${''} + ${'unknown format'} | ${'unknown format'} + ${' 14.1.0 '} | ${'14.1.0'} + ${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'} | ${'>=14.0.0 <=17.0.0'} + ${'{"volta": {"extends": "./package.json"}}'} | ${'18.0.0'} + ${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'} + ${'{"devEngines": {"runtime": {"name": "node", "version": "22.0.0"}}}'} | ${'22.0.0'} + ${'{}'} | ${null} `.it('parses "$contents"', ({contents, expected}) => { const existsSpy = jest.spyOn(fs, 'existsSync'); existsSpy.mockImplementation(() => true); diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 856c5efa..58be8af1 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -71,7 +71,35 @@ steps: - run: npm test ``` -When using the `package.json` input, the action will look for `volta.node` first. If `volta.node` isn't defined, then it will look for `engines.node`. +When using the `package.json` input, the action will look in following field for a specified Node version: +1. It checks `volta.node` first. +2. Then it checks `devEngines.runtime`. +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` or `engines.node` recursively. + +### Example with `devEngines` + +When a runtime engine (`engines.node`) is defined but also a development engine (`devEngines.runtime`) then the `devEngine` runtime version is used. +This example will install a Node version based on the `^20.10` pattern. + +```json +{ + "engines": { + "node": "^20 || ^22" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^20.10" + } + } +} +``` + +### Example with volta pinned Node version + +When both `engines.node` and `volta.node` is defined the value in `volta.node` is used. ```json { @@ -84,8 +112,6 @@ When using the `package.json` input, the action will look for `volta.node` first } ``` -Otherwise, when [`volta.extends`](https://docs.volta.sh/advanced/workspaces) is defined, then it will resolve the corresponding file and look for `volta.node` or `engines.node` recursively. - ## 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). diff --git a/src/util.ts b/src/util.ts index bbe25ddf..c4127d7e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -26,6 +26,14 @@ export function getNodeVersionFromFile(versionFilePath: string): string | null { return manifest.volta.node; } + // support devEngines from npm 11 + if ( + manifest.devEngines?.runtime?.name === 'node' && + manifest.devEngines.runtime.version + ) { + return manifest.devEngines.runtime.version; + } + if (manifest.engines?.node) { return manifest.engines.node; }