Skip to content

Commit 994a278

Browse files
committed
feat: set ci versions from engines
1 parent de319e8 commit 994a278

20 files changed

+251
-344
lines changed

.github/workflows/audit.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ jobs:
2727
uses: actions/setup-node@v3
2828
id: node
2929
with:
30-
node-version: 18.x
31-
check-latest: contains('18.x', '.x')
30+
node-version: 20.x
31+
check-latest: contains('20.x', '.x')
3232

3333
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
3434
- name: Update Windows npm

.github/workflows/ci-release.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ jobs:
8282
uses: actions/setup-node@v3
8383
id: node
8484
with:
85-
node-version: 18.x
86-
check-latest: contains('18.x', '.x')
85+
node-version: 20.x
86+
check-latest: contains('20.x', '.x')
8787

8888
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
8989
- name: Update Windows npm
@@ -167,6 +167,7 @@ jobs:
167167
- 16.x
168168
- 18.0.0
169169
- 18.x
170+
- 20.x
170171
runs-on: ${{ matrix.platform.os }}
171172
defaults:
172173
run:

.github/workflows/ci-test-workspace.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ jobs:
3535
uses: actions/setup-node@v3
3636
id: node
3737
with:
38-
node-version: 18.x
39-
check-latest: contains('18.x', '.x')
38+
node-version: 20.x
39+
check-latest: contains('20.x', '.x')
4040

4141
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
4242
- name: Update Windows npm
@@ -113,6 +113,7 @@ jobs:
113113
- 16.x
114114
- 18.0.0
115115
- 18.x
116+
- 20.x
116117
runs-on: ${{ matrix.platform.os }}
117118
defaults:
118119
run:

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ jobs:
3535
uses: actions/setup-node@v3
3636
id: node
3737
with:
38-
node-version: 18.x
39-
check-latest: contains('18.x', '.x')
38+
node-version: 20.x
39+
check-latest: contains('20.x', '.x')
4040

4141
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
4242
- name: Update Windows npm
@@ -113,6 +113,7 @@ jobs:
113113
- 16.x
114114
- 18.0.0
115115
- 18.x
116+
- 20.x
116117
runs-on: ${{ matrix.platform.os }}
117118
defaults:
118119
run:

.github/workflows/post-dependabot.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ jobs:
2828
uses: actions/setup-node@v3
2929
id: node
3030
with:
31-
node-version: 18.x
32-
check-latest: contains('18.x', '.x')
31+
node-version: 20.x
32+
check-latest: contains('20.x', '.x')
3333

3434
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
3535
- name: Update Windows npm

.github/workflows/pull-request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ jobs:
3131
uses: actions/setup-node@v3
3232
id: node
3333
with:
34-
node-version: 18.x
35-
check-latest: contains('18.x', '.x')
34+
node-version: 20.x
35+
check-latest: contains('20.x', '.x')
3636

3737
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
3838
- name: Update Windows npm

.github/workflows/release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ jobs:
4444
uses: actions/setup-node@v3
4545
id: node
4646
with:
47-
node-version: 18.x
48-
check-latest: contains('18.x', '.x')
47+
node-version: 20.x
48+
check-latest: contains('20.x', '.x')
4949

5050
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
5151
- name: Update Windows npm
@@ -201,8 +201,8 @@ jobs:
201201
uses: actions/setup-node@v3
202202
id: node
203203
with:
204-
node-version: 18.x
205-
check-latest: contains('18.x', '.x')
204+
node-version: 20.x
205+
check-latest: contains('20.x', '.x')
206206

207207
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
208208
- name: Update Windows npm

lib/config.js

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
const { relative, dirname, join, extname, posix, win32 } = require('path')
2-
const { defaults, pick, omit, uniq } = require('lodash')
3-
const semver = require('semver')
4-
const parseCIVersions = require('./util/parse-ci-versions.js')
2+
const { defaults, pick, omit, uniq, isPlainObject } = require('lodash')
3+
const ciVersions = require('./util/ci-versions.js')
54
const parseDependabot = require('./util/dependabot.js')
65
const git = require('./util/git.js')
76
const gitignore = require('./util/gitignore.js')
8-
const { mergeWithArrays } = require('./util/merge.js')
7+
const { mergeWithCustomizers, customizers } = require('./util/merge.js')
98
const { FILE_KEYS, parseConfig: parseFiles, getAddedFiles, mergeFiles } = require('./util/files.js')
109

1110
const CONFIG_KEY = 'templateOSS'
@@ -15,7 +14,14 @@ const { name: NAME, version: LATEST_VERSION } = require('../package.json')
1514
const MERGE_KEYS = [...FILE_KEYS, 'defaultContent', 'content']
1615
const DEFAULT_CONTENT = require.resolve(NAME)
1716

18-
const merge = mergeWithArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths')
17+
const merge = mergeWithCustomizers(
18+
customizers.mergeArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths'),
19+
(value, srcValue, key) => {
20+
if (key === 'ciVersions' && (Array.isArray(srcValue) || isPlainObject(srcValue))) {
21+
return { ...ciVersions.parse(value), ...ciVersions.parse(srcValue) }
22+
}
23+
}
24+
)
1925

2026
const makePosix = (v) => v.split(win32.sep).join(posix.sep)
2127
const deglob = (v) => makePosix(v).replace(/[/*]+$/, '')
@@ -235,6 +241,8 @@ const getFullConfig = async ({
235241
// lockfiles are only present at the root, so this only should be set for
236242
// all workspaces based on the root
237243
lockfile: rootPkgConfig.lockfile,
244+
// ci versions / engines
245+
ciVersions: ciVersions.get(pkg.pkgJson.engines?.node, pkgConfig),
238246
// gitignore
239247
ignorePaths: [
240248
...gitignore.sort([
@@ -259,33 +267,6 @@ const getFullConfig = async ({
259267
__PARTIAL_DIRS__: fileDirs,
260268
}
261269

262-
if (pkgConfig.ciVersions) {
263-
let versions = pkgConfig.ciVersions
264-
if (versions === 'latest' || (Array.isArray(versions) && versions.includes('latest'))) {
265-
const { ciVersions } = [isWorkspace ? rootPkgConfig : {}, defaultConfig]
266-
.find(c => Array.isArray(c.ciVersions))
267-
const defaultLatest = ciVersions[ciVersions.length - 1]
268-
versions = [].concat(versions).map(v => v === 'latest' ? defaultLatest : v)
269-
}
270-
271-
const { targets, engines } = parseCIVersions(versions)
272-
273-
// get just a list of the target versions (not ranges)
274-
// these are used for the node version when doing engines checks
275-
// since we want to test in the lowest version of each major
276-
let targetVersions = targets.filter(t => semver.valid(t))
277-
// if the versions are all ranges then convert them to the lower bound of each range
278-
if (!targetVersions.length) {
279-
targetVersions = targets.filter(t => semver.validRange(t)).map(t => {
280-
return new semver.Range(t).set[0][0].semver.version
281-
})
282-
}
283-
284-
derived.ciVersions = targets
285-
derived.baseCiVersions = targetVersions
286-
derived.engines = pkgConfig.engines || engines
287-
}
288-
289270
if (!pkgConfig.eslint) {
290271
derived.ignorePaths = derived.ignorePaths.filter(p => !p.includes('eslint'))
291272
if (Array.isArray(pkgConfig.requiredPackages?.devDependencies)) {

lib/content/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ module.exports = {
158158
'/CHANGELOG*',
159159
],
160160
ignorePaths: [],
161-
ciVersions: ['14.17.0', '14.x', '16.13.0', '16.x', '18.0.0', '18.x'],
161+
ciVersions: {},
162+
latestCiVersion: 20,
162163
lockfile: false,
163164
codeowner: '@npm/cli-team',
164165
eslint: true,

lib/content/pkg.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@
2121
"postpublish": {{{ del }}}
2222
},
2323
"repository": {{#if repository}}{{{ json repository }}}{{else}}{{{ del }}}{{/if}},
24-
"engines": {
25-
{{#if engines}}
26-
"node": {{{ json engines }}}
27-
{{/if}}
28-
},
2924
{{{ json __CONFIG_KEY__ }}}: {
3025
"version": {{#if isDogFood}}{{{ del }}}{{else}}{{{ json __VERSION__ }}}{{/if}}
3126
},

lib/util/ci-versions.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const { uniq, range, isPlainObject } = require('lodash')
2+
const semver = require('semver')
3+
4+
const parseCiVersions = (ciVersions) => {
5+
if (Array.isArray(ciVersions)) {
6+
return Object.fromEntries(ciVersions.map((v) => [v, true]))
7+
}
8+
if (isPlainObject(ciVersions)) {
9+
return ciVersions
10+
}
11+
}
12+
13+
const getLowerBounds = (sRange) => {
14+
return new semver.Range(sRange).set.map(c => c[0])
15+
}
16+
17+
const getCiVersions = (nodeEngines, pkgConfig) => {
18+
let allCiVersions = {}
19+
20+
// get ci versions
21+
const { latestCiVersion, ciVersions } = pkgConfig
22+
23+
if (latestCiVersion) {
24+
allCiVersions[`${latestCiVersion}.x`] = true
25+
}
26+
27+
// determine the ci versions from the node engines set
28+
if (nodeEngines) {
29+
const lowerBounds = getLowerBounds(nodeEngines)
30+
.map(v => v.semver)
31+
.filter(v => v.version)
32+
33+
for (const version of lowerBounds) {
34+
allCiVersions[version.version] = true
35+
allCiVersions[`${version.major}.x`] = true
36+
}
37+
38+
const lowestCiVersion = semver.sort(lowerBounds)[0]?.major
39+
if (lowestCiVersion && latestCiVersion) {
40+
for (const major of range(lowestCiVersion, latestCiVersion, 2)) {
41+
allCiVersions[`${major}.x`] = true
42+
}
43+
}
44+
}
45+
46+
if (ciVersions === 'latest' && latestCiVersion) {
47+
// the plain string 'latest' means latest only and everything else is removed
48+
allCiVersions = { [`${latestCiVersion}.x`]: true }
49+
} else {
50+
// this allows ciVersions to turn off default versions by setting them to a falsy value
51+
Object.assign(allCiVersions, parseCiVersions(ciVersions))
52+
}
53+
54+
if (allCiVersions.latest && latestCiVersion) {
55+
delete allCiVersions.latest
56+
allCiVersions[`${latestCiVersion}.x`] = true
57+
}
58+
59+
const filteredCiVersions = Object.entries(allCiVersions)
60+
.filter(([, v]) => v)
61+
.map(([k]) => k)
62+
63+
return uniq(filteredCiVersions).sort((a, b) => {
64+
const aComp = getLowerBounds(a)[0]
65+
const bComp = getLowerBounds(b)[0]
66+
67+
if (aComp.semver.major > bComp.semver.major) {
68+
return 1
69+
} else if (aComp.semver.major < bComp.semver.major) {
70+
return -1
71+
}
72+
73+
return aComp.operator ? 1 : -1
74+
})
75+
}
76+
77+
module.exports = {
78+
parse: parseCiVersions,
79+
get: getCiVersions,
80+
}

lib/util/merge.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ const customizers = {
6565
module.exports = {
6666
// default merge is to overwrite arrays
6767
merge: mergeWithCustomizers(customizers.overwriteArrays),
68-
mergeWithArrays: (...keys) => mergeWithCustomizers(customizers.mergeArrays(...keys)),
6968
mergeWithCustomizers,
7069
mergeWith,
7170
customizers,

lib/util/parse-ci-versions.js

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)