Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set ci versions from engines #356

Merged
merged 2 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ci-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down Expand Up @@ -167,6 +167,7 @@ jobs:
- 16.x
- 18.0.0
- 18.x
- 20.x
runs-on: ${{ matrix.platform.os }}
defaults:
run:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ci-test-workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down Expand Up @@ -113,6 +113,7 @@ jobs:
- 16.x
- 18.0.0
- 18.x
- 20.x
runs-on: ${{ matrix.platform.os }}
defaults:
run:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down Expand Up @@ -113,6 +113,7 @@ jobs:
- 16.x
- 18.0.0
- 18.x
- 20.x
runs-on: ${{ matrix.platform.os }}
defaults:
run:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/post-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ jobs:
uses: actions/setup-node@v3
id: node
with:
node-version: 18.x
check-latest: contains('18.x', '.x')
node-version: 20.x
check-latest: contains('20.x', '.x')

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

# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
- name: Update Windows npm
Expand Down
45 changes: 13 additions & 32 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
const { relative, dirname, join, extname, posix, win32 } = require('path')
const { defaults, pick, omit, uniq } = require('lodash')
const semver = require('semver')
const parseCIVersions = require('./util/parse-ci-versions.js')
const { defaults, pick, omit, uniq, isPlainObject } = require('lodash')
const ciVersions = require('./util/ci-versions.js')
const parseDependabot = require('./util/dependabot.js')
const git = require('./util/git.js')
const gitignore = require('./util/gitignore.js')
const { mergeWithArrays } = require('./util/merge.js')
const { mergeWithCustomizers, customizers } = require('./util/merge.js')
const { FILE_KEYS, parseConfig: parseFiles, getAddedFiles, mergeFiles } = require('./util/files.js')

const CONFIG_KEY = 'templateOSS'
Expand All @@ -16,7 +15,14 @@ const { minimatch } = require('minimatch')
const MERGE_KEYS = [...FILE_KEYS, 'defaultContent', 'content']
const DEFAULT_CONTENT = require.resolve(NAME)

const merge = mergeWithArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths')
const merge = mergeWithCustomizers(
customizers.mergeArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths'),
(value, srcValue, key) => {
if (key === 'ciVersions' && (Array.isArray(srcValue) || isPlainObject(srcValue))) {
return { ...ciVersions.parse(value), ...ciVersions.parse(srcValue) }
}
}
)

const makePosix = (v) => v.split(win32.sep).join(posix.sep)
const deglob = (v) => makePosix(v).replace(/[/*]+$/, '')
Expand Down Expand Up @@ -218,6 +224,8 @@ const getFullConfig = async ({
// lockfiles are only present at the root, so this only should be set for
// all workspaces based on the root
lockfile: rootPkgConfig.lockfile,
// ci versions / engines
ciVersions: ciVersions.get(pkg.pkgJson.engines?.node, pkgConfig),
// gitignore
ignorePaths: [
...gitignore.sort([
Expand All @@ -242,33 +250,6 @@ const getFullConfig = async ({
__PARTIAL_DIRS__: fileDirs,
}

if (pkgConfig.ciVersions) {
let versions = pkgConfig.ciVersions
if (versions === 'latest' || (Array.isArray(versions) && versions.includes('latest'))) {
const { ciVersions } = [isWorkspace ? rootPkgConfig : {}, defaultConfig]
.find(c => Array.isArray(c.ciVersions))
const defaultLatest = ciVersions[ciVersions.length - 1]
versions = [].concat(versions).map(v => v === 'latest' ? defaultLatest : v)
}

const { targets, engines } = parseCIVersions(versions)

// get just a list of the target versions (not ranges)
// these are used for the node version when doing engines checks
// since we want to test in the lowest version of each major
let targetVersions = targets.filter(t => semver.valid(t))
// if the versions are all ranges then convert them to the lower bound of each range
if (!targetVersions.length) {
targetVersions = targets.filter(t => semver.validRange(t)).map(t => {
return new semver.Range(t).set[0][0].semver.version
})
}

derived.ciVersions = targets
derived.baseCiVersions = targetVersions
derived.engines = pkgConfig.engines || engines
}

if (!pkgConfig.eslint) {
derived.ignorePaths = derived.ignorePaths.filter(p => !p.includes('eslint'))
if (Array.isArray(pkgConfig.requiredPackages?.devDependencies)) {
Expand Down
3 changes: 2 additions & 1 deletion lib/content/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ module.exports = {
'/CHANGELOG*',
],
ignorePaths: [],
ciVersions: ['14.17.0', '14.x', '16.13.0', '16.x', '18.0.0', '18.x'],
ciVersions: {},
latestCiVersion: 20,
lockfile: false,
codeowner: '@npm/cli-team',
eslint: true,
Expand Down
5 changes: 0 additions & 5 deletions lib/content/pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@
"postpublish": {{{ del }}}
},
"repository": {{#if repository}}{{{ json repository }}}{{else}}{{{ del }}}{{/if}},
"engines": {
{{#if engines}}
"node": {{{ json engines }}}
{{/if}}
},
{{{ json __CONFIG_KEY__ }}}: {
"version": {{#if isDogFood}}{{{ del }}}{{else}}{{{ json __VERSION__ }}}{{/if}}
},
Expand Down
80 changes: 80 additions & 0 deletions lib/util/ci-versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const { uniq, range, isPlainObject } = require('lodash')
const semver = require('semver')

const parseCiVersions = (ciVersions) => {
if (Array.isArray(ciVersions)) {
return Object.fromEntries(ciVersions.map((v) => [v, true]))
}
if (isPlainObject(ciVersions)) {
return ciVersions
}
}

const getLowerBounds = (sRange) => {
return new semver.Range(sRange).set.map(c => c[0])
}

const getCiVersions = (nodeEngines, pkgConfig) => {
let allCiVersions = {}

// get ci versions
const { latestCiVersion, ciVersions } = pkgConfig

if (latestCiVersion) {
allCiVersions[`${latestCiVersion}.x`] = true
}

// determine the ci versions from the node engines set
if (nodeEngines) {
const lowerBounds = getLowerBounds(nodeEngines)
.map(v => v.semver)
.filter(v => v.version)

for (const version of lowerBounds) {
allCiVersions[version.version] = true
allCiVersions[`${version.major}.x`] = true
}

const lowestCiVersion = semver.sort(lowerBounds)[0]?.major
if (lowestCiVersion && latestCiVersion) {
for (const major of range(lowestCiVersion, latestCiVersion, 2)) {
allCiVersions[`${major}.x`] = true
}
}
}

if (ciVersions === 'latest' && latestCiVersion) {
// the plain string 'latest' means latest only and everything else is removed
allCiVersions = { [`${latestCiVersion}.x`]: true }
} else {
// this allows ciVersions to turn off default versions by setting them to a falsy value
Object.assign(allCiVersions, parseCiVersions(ciVersions))
}

if (allCiVersions.latest && latestCiVersion) {
delete allCiVersions.latest
allCiVersions[`${latestCiVersion}.x`] = true
}

const filteredCiVersions = Object.entries(allCiVersions)
.filter(([, v]) => v)
.map(([k]) => k)

return uniq(filteredCiVersions).sort((a, b) => {
const aComp = getLowerBounds(a)[0]
const bComp = getLowerBounds(b)[0]

if (aComp.semver.major > bComp.semver.major) {
return 1
} else if (aComp.semver.major < bComp.semver.major) {
return -1
}

return aComp.operator ? 1 : -1
})
}

module.exports = {
parse: parseCiVersions,
get: getCiVersions,
}
1 change: 0 additions & 1 deletion lib/util/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ const customizers = {
module.exports = {
// default merge is to overwrite arrays
merge: mergeWithCustomizers(customizers.overwriteArrays),
mergeWithArrays: (...keys) => mergeWithCustomizers(customizers.mergeArrays(...keys)),
mergeWithCustomizers,
mergeWith,
customizers,
Expand Down
78 changes: 0 additions & 78 deletions lib/util/parse-ci-versions.js

This file was deleted.

Loading