Skip to content

Commit 88483fd

Browse files
committed
feat(node-version-file): support parsing devEngines field
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent 49933ea commit 88483fd

File tree

5 files changed

+80
-19
lines changed

5 files changed

+80
-19
lines changed

.github/workflows/versions.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,21 @@ jobs:
168168
- name: Verify node
169169
run: __tests__/verify-node.sh 20
170170

171+
version-file-dev-engines:
172+
runs-on: ${{ matrix.os }}
173+
strategy:
174+
fail-fast: false
175+
matrix:
176+
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
177+
steps:
178+
- uses: actions/checkout@v4
179+
- name: Setup node from node version file
180+
uses: ./
181+
with:
182+
node-version-file: '__tests__/data/package-dev-engines.json'
183+
- name: Verify node
184+
run: __tests__/verify-node.sh 20
185+
171186
version-file-volta:
172187
runs-on: ${{ matrix.os }}
173188
strategy:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"engines": {
3+
"node": "^20 || ^22"
4+
},
5+
"devEngines": {
6+
"runtime": {
7+
"name": "node",
8+
"version": "^20"
9+
}
10+
}
11+
}

__tests__/main.test.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,23 @@ describe('main tests', () => {
9191

9292
describe('getNodeVersionFromFile', () => {
9393
each`
94-
contents | expected
95-
${'12'} | ${'12'}
96-
${'12.3'} | ${'12.3'}
97-
${'12.3.4'} | ${'12.3.4'}
98-
${'v12.3.4'} | ${'12.3.4'}
99-
${'lts/erbium'} | ${'lts/erbium'}
100-
${'lts/*'} | ${'lts/*'}
101-
${'nodejs 12.3.4'} | ${'12.3.4'}
102-
${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'}
103-
${''} | ${''}
104-
${'unknown format'} | ${'unknown format'}
105-
${' 14.1.0 '} | ${'14.1.0'}
106-
${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'}| ${'>=14.0.0 <=17.0.0'}
107-
${'{"volta": {"extends": "./package.json"}}'}| ${'18.0.0'}
108-
${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'}
109-
${'{}'} | ${null}
94+
contents | expected
95+
${'12'} | ${'12'}
96+
${'12.3'} | ${'12.3'}
97+
${'12.3.4'} | ${'12.3.4'}
98+
${'v12.3.4'} | ${'12.3.4'}
99+
${'lts/erbium'} | ${'lts/erbium'}
100+
${'lts/*'} | ${'lts/*'}
101+
${'nodejs 12.3.4'} | ${'12.3.4'}
102+
${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'}
103+
${''} | ${''}
104+
${'unknown format'} | ${'unknown format'}
105+
${' 14.1.0 '} | ${'14.1.0'}
106+
${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'} | ${'>=14.0.0 <=17.0.0'}
107+
${'{"volta": {"extends": "./package.json"}}'} | ${'18.0.0'}
108+
${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'}
109+
${'{"devEngines": {"runtime": {"name": "node", "version": "22.0.0"}}}'} | ${'22.0.0'}
110+
${'{}'} | ${null}
110111
`.it('parses "$contents"', ({contents, expected}) => {
111112
const existsSpy = jest.spyOn(fs, 'existsSync');
112113
existsSpy.mockImplementation(() => true);

docs/advanced-usage.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,35 @@ steps:
7171
- run: npm test
7272
```
7373

74-
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`.
74+
When using the `package.json` input, the action will look in following field for a specified Node version:
75+
1. It checks `volta.node` first.
76+
2. Then it checks `devEngines.runtime`.
77+
3. Then it will look for `engines.node`.
78+
4. Otherwise it tries to resolve the file defined by [`volta.extends`](https://docs.volta.sh/advanced/workspaces)
79+
and look for `volta.node` or `engines.node` recursively.
80+
81+
### Example with `devEngines`
82+
83+
When a runtime engine (`engines.node`) is defined but also a development engine (`devEngines.runtime`) then the `devEngine` runtime version is used.
84+
This example will install a Node version based on the `^20.10` pattern.
85+
86+
```json
87+
{
88+
"engines": {
89+
"node": "^20 || ^22"
90+
},
91+
"devEngines": {
92+
"runtime": {
93+
"name": "node",
94+
"version": "^20.10"
95+
}
96+
}
97+
}
98+
```
99+
100+
### Example with volta pinned Node version
101+
102+
When both `engines.node` and `volta.node` is defined the value in `volta.node` is used.
75103

76104
```json
77105
{
@@ -84,8 +112,6 @@ When using the `package.json` input, the action will look for `volta.node` first
84112
}
85113
```
86114

87-
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.
88-
89115
## Architecture
90116

91117
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).

src/util.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ export function getNodeVersionFromFile(versionFilePath: string): string | null {
2626
return manifest.volta.node;
2727
}
2828

29+
// support devEngines from npm 11
30+
if (
31+
manifest.devEngines?.runtime?.name === 'node' &&
32+
manifest.devEngines.runtime.version
33+
) {
34+
return manifest.devEngines.runtime.version;
35+
}
36+
2937
if (manifest.engines?.node) {
3038
return manifest.engines.node;
3139
}

0 commit comments

Comments
 (0)