diff --git a/bin/apply.js b/bin/apply.js index 2405a3e0..6a7d2f60 100755 --- a/bin/apply.js +++ b/bin/apply.js @@ -3,10 +3,7 @@ const apply = require('../lib/apply/index.js') const main = async () => { - const { - npm_config_global: globalMode, - npm_config_local_prefix: root, - } = process.env + const { npm_config_global: globalMode, npm_config_local_prefix: root } = process.env // do nothing in global mode or when the local prefix isn't set if (globalMode === 'true' || !root) { @@ -16,7 +13,7 @@ const main = async () => { await apply(root) } -module.exports = main().catch((err) => { +module.exports = main().catch(err => { console.error(err.stack) process.exitCode = 1 }) diff --git a/bin/check.js b/bin/check.js index 8b3417cb..d5772946 100755 --- a/bin/check.js +++ b/bin/check.js @@ -4,9 +4,7 @@ const check = require('../lib/check/index.js') const output = require('../lib/util/output.js') const main = async () => { - const { - npm_config_local_prefix: root, - } = process.env + const { npm_config_local_prefix: root } = process.env if (!root) { throw new Error('This package requires npm >7.21.1') @@ -20,7 +18,7 @@ const main = async () => { } } -module.exports = main().catch((err) => { +module.exports = main().catch(err => { console.error(err.stack) process.exitCode = 1 }) diff --git a/bin/release-manager.js b/bin/release-manager.js index 2ab6dcd6..e42c2686 100755 --- a/bin/release-manager.js +++ b/bin/release-manager.js @@ -19,7 +19,7 @@ ReleaseManager.run({ }, }).values, }) - .then((result) => { + .then(result => { core.setOutput('result', result) return null }) diff --git a/bin/release-please.js b/bin/release-please.js index f11a4dc9..a4229e5b 100755 --- a/bin/release-please.js +++ b/bin/release-please.js @@ -18,23 +18,27 @@ ReleasePlease.run({ // `RELEASE_PLEASE_` // (eg`RELEASE_PLEASE_lastReleaseSha=`) to set one-off config items for // the release please run without needing to commit and push the config. - overrides: Object.fromEntries(Object.entries(process.env) - .filter(([k, v]) => k.startsWith('RELEASE_PLEASE_') && v != null) - .map(([k, v]) => [k.replace('RELEASE_PLEASE_', ''), v])), -}).then(({ pr, releases }) => { - if (pr) { - core.setOutput('pr', JSON.stringify(pr)) - core.setOutput('pr-branch', pr.headBranchName) - core.setOutput('pr-number', pr.number) - core.setOutput('pr-sha', pr.sha) - } + overrides: Object.fromEntries( + Object.entries(process.env) + .filter(([k, v]) => k.startsWith('RELEASE_PLEASE_') && v != null) + .map(([k, v]) => [k.replace('RELEASE_PLEASE_', ''), v]), + ), +}) + .then(({ pr, releases }) => { + if (pr) { + core.setOutput('pr', JSON.stringify(pr)) + core.setOutput('pr-branch', pr.headBranchName) + core.setOutput('pr-number', pr.number) + core.setOutput('pr-sha', pr.sha) + } - if (releases) { - core.setOutput('releases', JSON.stringify(releases)) - } + if (releases) { + core.setOutput('releases', JSON.stringify(releases)) + } - return null -}).catch(err => { - core.setFailed('Release Please failed') - core.error(err) -}) + return null + }) + .catch(err => { + core.setFailed('Release Please failed') + core.error(err) + }) diff --git a/lib/apply/apply-files.js b/lib/apply/apply-files.js index 175bbbd8..d656964f 100644 --- a/lib/apply/apply-files.js +++ b/lib/apply/apply-files.js @@ -6,26 +6,21 @@ const run = async (dir, files, options) => { const { rm, add } = files log.verbose('apply-files', 'rm', rm) - await rmEach(dir, rm, options, (f) => fs.rm(f)) + await rmEach(dir, rm, options, f => fs.rm(f)) log.verbose('apply-files', 'add', add) - await parseEach(dir, add, options, {}, (p) => p.applyWrite()) + await parseEach(dir, add, options, {}, p => p.applyWrite()) } -module.exports = [{ - run: (options) => run( - options.config.repoDir, - options.config.repoFiles, - options - ), - when: ({ config: c }) => c.applyRepo && c.needsUpdate, - name: 'apply-repo', -}, { - run: (options) => run( - options.config.moduleDir, - options.config.moduleFiles, - options - ), - when: ({ config: c }) => c.applyModule && c.needsUpdate, - name: 'apply-module', -}] +module.exports = [ + { + run: options => run(options.config.repoDir, options.config.repoFiles, options), + when: ({ config: c }) => c.applyRepo && c.needsUpdate, + name: 'apply-repo', + }, + { + run: options => run(options.config.moduleDir, options.config.moduleFiles, options), + when: ({ config: c }) => c.applyModule && c.needsUpdate, + name: 'apply-module', + }, +] diff --git a/lib/apply/apply-version.js b/lib/apply/apply-version.js index e3bddbdd..d7ebbe8c 100644 --- a/lib/apply/apply-version.js +++ b/lib/apply/apply-version.js @@ -2,11 +2,7 @@ const { log } = require('proc-log') const PackageJson = require('@npmcli/package-json') const run = async ({ config: c }) => { - const { - moduleDir: dir, - __CONFIG_KEY__: key, - __VERSION__: version, - } = c + const { moduleDir: dir, __CONFIG_KEY__: key, __VERSION__: version } = c log.verbose('apply-version', dir) diff --git a/lib/apply/index.js b/lib/apply/index.js index 75e66a43..15e90a12 100644 --- a/lib/apply/index.js +++ b/lib/apply/index.js @@ -1,6 +1,3 @@ const run = require('../index.js') -module.exports = (root) => run(root, [ - require('./apply-files.js'), - require('./apply-version.js'), -]) +module.exports = root => run(root, [require('./apply-files.js'), require('./apply-version.js')]) diff --git a/lib/check/check-apply.js b/lib/check/check-apply.js index 749ca60f..1fb46174 100644 --- a/lib/check/check-apply.js +++ b/lib/check/check-apply.js @@ -8,22 +8,25 @@ const solution = 'npx template-oss-apply --force' const run = async (type, dir, files, options) => { const res = [] - const rel = (f) => relative(options.root, f) + const rel = f => relative(options.root, f) const { add: addFiles, rm: rmFiles } = files - const rm = await rmEach(dir, rmFiles, options, (f) => rel(f)) - const [add, update] = partition(await parseEach(dir, addFiles, options, {}, async (p) => { - const diff = await p.applyDiff() - const target = rel(p.target) - if (diff === null) { - // needs to be added - return target - } else if (diff === true) { - // its ok, no diff, this is filtered out - return null - } - return { file: target, diff } - }), (d) => typeof d === 'string') + const rm = await rmEach(dir, rmFiles, options, f => rel(f)) + const [add, update] = partition( + await parseEach(dir, addFiles, options, {}, async p => { + const diff = await p.applyDiff() + const target = rel(p.target) + if (diff === null) { + // needs to be added + return target + } else if (diff === true) { + // its ok, no diff, this is filtered out + return null + } + return { file: target, diff } + }), + d => typeof d === 'string', + ) log.verbose('check-apply', 'rm', rm) if (rm.length) { @@ -44,31 +47,28 @@ const run = async (type, dir, files, options) => { } log.verbose('check-apply', 'update', update) - res.push(...update.sort((a, b) => localeCompare(a.file, b.file)).map(({ file, diff }) => ({ - title: `The ${type} file ${basename(file)} needs to be updated:`, - body: [`${file}\n${'='.repeat(40)}\n${diff}`], - solution, - }))) + res.push( + ...update + .sort((a, b) => localeCompare(a.file, b.file)) + .map(({ file, diff }) => ({ + title: `The ${type} file ${basename(file)} needs to be updated:`, + body: [`${file}\n${'='.repeat(40)}\n${diff}`], + solution, + })), + ) return res } -module.exports = [{ - run: (options) => run( - 'repo', - options.config.repoDir, - options.config.repoFiles, - options - ), - when: ({ config: c }) => c.applyRepo, - name: 'check-repo', -}, { - run: (options) => run( - 'module', - options.config.moduleDir, - options.config.moduleFiles, - options - ), - when: ({ config: c }) => c.applyModule, - name: 'check-module', -}] +module.exports = [ + { + run: options => run('repo', options.config.repoDir, options.config.repoFiles, options), + when: ({ config: c }) => c.applyRepo, + name: 'check-repo', + }, + { + run: options => run('module', options.config.moduleDir, options.config.moduleFiles, options), + when: ({ config: c }) => c.applyModule, + name: 'check-module', + }, +] diff --git a/lib/check/check-changelog.js b/lib/check/check-changelog.js index 11053aec..cae54f29 100644 --- a/lib/check/check-changelog.js +++ b/lib/check/check-changelog.js @@ -14,10 +14,7 @@ const run = async ({ root, path }) => { if (!mustStart.test(content)) { return { title: `The ${relative(root, changelog)} is incorrect:`, - body: [ - 'The changelog should start with', - `"# Changelog\n\n#"`, - ], + body: ['The changelog should start with', `"# Changelog\n\n#"`], solution: 'reformat the changelog to have the correct heading', } } diff --git a/lib/check/check-engines.js b/lib/check/check-engines.js index 4a2a0ad5..2a863074 100644 --- a/lib/check/check-engines.js +++ b/lib/check/check-engines.js @@ -27,15 +27,14 @@ const run = async ({ root, path, pkg, config: { omitEngines = [] } }) => { } if (invalid.length) { - const title = `The following production dependencies are not compatible with ` + + const title = + `The following production dependencies are not compatible with ` + `\`engines.node: ${engines}\` found in \`${pkgPath}\`:` return { title, - body: invalid.map((dep) => [ - `${dep.name}:`, - ` engines.node: ${dep.engines}`, - ` location: ${dep.location}`, - ].join('\n')).join('\n'), + body: invalid + .map(dep => [`${dep.name}:`, ` engines.node: ${dep.engines}`, ` location: ${dep.location}`].join('\n')) + .join('\n'), solution: 'Remove them or move them to devDependencies.', } } diff --git a/lib/check/check-gitignore.js b/lib/check/check-gitignore.js index e22cc361..9868e370 100644 --- a/lib/check/check-gitignore.js +++ b/lib/check/check-gitignore.js @@ -13,34 +13,34 @@ const NAME = 'check-gitignore' const run = async ({ root, path, config }) => { log.verbose(NAME, { root, path }) - const relativeToRoot = (f) => relative(root, resolve(path, f)) + const relativeToRoot = f => relative(root, resolve(path, f)) // use the root to detect a git repo but the project directory (path) for the // ignore check const ignoreFile = resolve(path, '.gitignore') - if (!await git.is({ cwd: root }) || !existsSync(ignoreFile)) { + if (!(await git.is({ cwd: root })) || !existsSync(ignoreFile)) { log.verbose(NAME, 'no git or no gitignore') return null } log.verbose(NAME, `using ignore file ${ignoreFile}`) - const res = await git.spawn([ - 'ls-files', - '--cached', - '--ignored', - // https://git-scm.com/docs/git-ls-files#_exclude_patterns - `--${config.isRoot ? 'exclude-from' : 'exclude-per-directory'}=${basename(ignoreFile)}`, - ], { cwd: path }) + const res = await git.spawn( + [ + 'ls-files', + '--cached', + '--ignored', + // https://git-scm.com/docs/git-ls-files#_exclude_patterns + `--${config.isRoot ? 'exclude-from' : 'exclude-per-directory'}=${basename(ignoreFile)}`, + ], + { cwd: path }, + ) log.verbose(NAME, 'ls-files', res) // TODO: files should be filtered if they have already been moved/deleted // but not committed. Currently you must commit for this check to pass. - const files = res.stdout - .trim() - .split('\n') - .filter(Boolean) + const files = res.stdout.trim().split('\n').filter(Boolean) if (!files.length) { return null @@ -49,7 +49,7 @@ const run = async ({ root, path, config }) => { const ignores = (await fs.readFile(ignoreFile)) .toString() .split(/\r?\n/) - .filter((l) => l && !l.trim().startsWith('#')) + .filter(l => l && !l.trim().startsWith('#')) const relIgnore = relativeToRoot(ignoreFile) diff --git a/lib/check/check-required.js b/lib/check/check-required.js index 9f04ef9f..781f5b45 100644 --- a/lib/check/check-required.js +++ b/lib/check/check-required.js @@ -3,25 +3,21 @@ const npa = require('npm-package-arg') const { partition } = require('lodash') const hasPackage = require('../util/has-package.js') -const rmCommand = (specs) => - `npm rm ${specs.map((s) => s.name).join(' ')}`.trim() +const rmCommand = specs => `npm rm ${specs.map(s => s.name).join(' ')}`.trim() -const installCommand = (specs, flags) => specs.length ? - `npm i ${specs.map((s) => `${s.name}@${s.fetchSpec}`).join(' ')} ${flags.join(' ')}`.trim() : '' +const installCommand = (specs, flags) => + specs.length ? `npm i ${specs.map(s => `${s.name}@${s.fetchSpec}`).join(' ')} ${flags.join(' ')}`.trim() : '' // ensure required packages are present in the correct place const run = ({ pkg, path, config: { requiredPackages = {} } }) => { // keys are the dependency location in package.json // values are a filtered list of parsed specs that dont exist in the current package // { [location]: [spec1, spec2] } - const requiredByLocation = Object.entries(requiredPackages) - .reduce((acc, [location, pkgs]) => { - acc[location] = pkgs - .filter((spec) => !hasPackage(pkg, spec, [location], path)) - .map((spec) => npa(spec)) - log.verbose(location, pkg, pkgs) - return acc - }, {}) + const requiredByLocation = Object.entries(requiredPackages).reduce((acc, [location, pkgs]) => { + acc[location] = pkgs.filter(spec => !hasPackage(pkg, spec, [location], path)).map(spec => npa(spec)) + log.verbose(location, pkg, pkgs) + return acc + }, {}) const requiredEntries = Object.entries(requiredByLocation) @@ -30,19 +26,21 @@ const run = ({ pkg, path, config: { requiredPackages = {} } }) => { if (requiredEntries.flatMap(([, specs]) => specs).length) { return requiredEntries.map(([location, specs]) => { const locationFlag = hasPackage.flags[location] - const [exactSpecs, saveSpecs] = partition(specs, (s) => s.type === 'version') + const [exactSpecs, saveSpecs] = partition(specs, s => s.type === 'version') log.verbose('check-required', location, specs) return { title: `The following required ${location} were not found:`, - body: specs.map((s) => s.rawSpec === '*' ? s.name : `${s.name}@${s.rawSpec}`), + body: specs.map(s => (s.rawSpec === '*' ? s.name : `${s.name}@${s.rawSpec}`)), // solution is to remove any existing all at once but add back in by --save- solution: [ rmCommand(specs), installCommand(saveSpecs, [locationFlag]), installCommand(exactSpecs, [locationFlag, '--save-exact']), - ].filter(Boolean).join(' && '), + ] + .filter(Boolean) + .join(' && '), } }) } diff --git a/lib/check/check-unwanted.js b/lib/check/check-unwanted.js index 13eb27fb..9b838628 100644 --- a/lib/check/check-unwanted.js +++ b/lib/check/check-unwanted.js @@ -1,11 +1,10 @@ - const hasPackage = require('../util/has-package.js') const run = ({ pkg, config: { allowedPackages = [], unwantedPackages = [] } }) => { // ensure packages that should not be present are removed const hasUnwanted = unwantedPackages - .filter((name) => !allowedPackages.includes(name)) - .filter((name) => hasPackage(pkg, name)) + .filter(name => !allowedPackages.includes(name)) + .filter(name => hasPackage(pkg, name)) if (hasUnwanted.length) { return { diff --git a/lib/check/index.js b/lib/check/index.js index 9310099c..ab7e03d4 100644 --- a/lib/check/index.js +++ b/lib/check/index.js @@ -1,10 +1,11 @@ const run = require('../index.js') -module.exports = (root) => run(root, [ - require('./check-apply.js'), - require('./check-required.js'), - require('./check-unwanted.js'), - require('./check-gitignore.js'), - require('./check-changelog.js'), - require('./check-engines.js'), -]) +module.exports = root => + run(root, [ + require('./check-apply.js'), + require('./check-required.js'), + require('./check-unwanted.js'), + require('./check-gitignore.js'), + require('./check-changelog.js'), + require('./check-engines.js'), + ]) diff --git a/lib/config.js b/lib/config.js index a1d6fd0a..86ad9fb4 100644 --- a/lib/config.js +++ b/lib/config.js @@ -16,7 +16,7 @@ const { name: NAME, version: LATEST_VERSION } = require('../package.json') const CONFIG_KEY = 'templateOSS' const MERGE_KEYS = [...FILE_KEYS, 'defaultContent', 'content'] const DEFAULT_CONTENT = require.resolve(NAME) -const getPkgConfig = (pkg) => pkg[CONFIG_KEY] || {} +const getPkgConfig = pkg => pkg[CONFIG_KEY] || {} const merge = mergeWithCustomizers( customizers.mergeArrays( @@ -27,13 +27,13 @@ const merge = mergeWithCustomizers( 'lintIgnorePaths', 'lintExtensions', 'formatIgnorePaths', - 'formatExtensions' + 'formatExtensions', ), (value, srcValue, key) => { if (key === 'ciVersions' && (Array.isArray(srcValue) || isPlainObject(srcValue))) { return { ...ciVersions.parse(value), ...ciVersions.parse(srcValue) } } - } + }, ) const mergeConfigs = (...configs) => { @@ -48,7 +48,7 @@ const mergeConfigs = (...configs) => { }) } -const readContentPath = async (path) => { +const readContentPath = async path => { if (!path) { return {} } @@ -71,10 +71,7 @@ const getFiles = async (path, rawConfig, templateSettings) => { if (!dir) { return [] } - return [ - parseFiles(pick(content, FILE_KEYS), dir, pick(rawConfig, FILE_KEYS), templateSettings), - dir, - ] + return [parseFiles(pick(content, FILE_KEYS), dir, pick(rawConfig, FILE_KEYS), templateSettings), dir] } const getFullConfig = async ({ @@ -124,13 +121,11 @@ const getFullConfig = async ({ const publicPkgs = pkgs.filter(p => !p.pkgJson.private) const allPrivate = pkgs.every(p => p.pkgJson.private) - const branches = uniq([...pkgConfig.branches ?? [], pkgConfig.releaseBranch]).filter(Boolean) + const branches = uniq([...(pkgConfig.branches ?? []), pkgConfig.releaseBranch]).filter(Boolean) const gitBranches = await git.getBranches(rootPkg.path, branches) - const defaultBranch = await git.defaultBranch(rootPkg.path) ?? 'main' + const defaultBranch = (await git.defaultBranch(rootPkg.path)) ?? 'main' const isReleaseBranch = !!pkgConfig.backport - const releaseBranch = isReleaseBranch - ? pkgConfig.releaseBranch.replace(/\*/g, pkgConfig.backport) - : defaultBranch + const releaseBranch = isReleaseBranch ? pkgConfig.releaseBranch.replace(/\*/g, pkgConfig.backport) : defaultBranch const esm = pkg.pkgJson?.type === 'module' || !!pkgConfig.typescript || !!pkgConfig.esm @@ -201,8 +196,9 @@ const getFullConfig = async ({ } if (!pkgConfig.eslint && Array.isArray(pkgConfig.requiredPackages?.devDependencies)) { - pkgConfig.requiredPackages.devDependencies = - pkgConfig.requiredPackages.devDependencies.filter(p => !p.includes('eslint')) + pkgConfig.requiredPackages.devDependencies = pkgConfig.requiredPackages.devDependencies.filter( + p => !p.includes('eslint'), + ) } pkgConfig.lintIgnorePaths = [ @@ -229,7 +225,7 @@ const getFullConfig = async ({ 'typescript', 'tshy', '@typescript-eslint/parser', - ...derived.tap16 ? ['c8', 'ts-node'] : [], + ...(derived.tap16 ? ['c8', 'ts-node'] : []), ]) } @@ -280,13 +276,13 @@ const getFullConfig = async ({ ...getAddedFiles(moduleFiles).map(s => template(s, fullConfig)), ...(isRoot ? [ - // in the root allow all repo files - ...getAddedFiles(repoFiles).map(s => template(s, fullConfig)), - // and allow all workspace repo level files in the root - ...pkgs - .filter(p => p.path !== rootPkg.path && p.config.workspaceRepo !== false) - .flatMap(() => getAddedFiles(files.workspaceRepo)), - ] + // in the root allow all repo files + ...getAddedFiles(repoFiles).map(s => template(s, fullConfig)), + // and allow all workspace repo level files in the root + ...pkgs + .filter(p => p.path !== rootPkg.path && p.config.workspaceRepo !== false) + .flatMap(() => getAddedFiles(files.workspaceRepo)), + ] : []), ]), ...(isRoot && pkgConfig.lockfile ? ['!/package-lock.json'] : []), @@ -317,10 +313,8 @@ const getFullConfig = async ({ ]), // these cant be sorted since they rely on order // to allow a previously ignored directoy - ...isRoot - ? gitignore.allowDir(wsPkgs.map((p) => makePosix(relative(rootPkg.path, p.path)))) - : [], - ].filter(p => !pkgConfig.eslint ? !p.includes('eslint') : true), + ...(isRoot ? gitignore.allowDir(wsPkgs.map(p => makePosix(relative(rootPkg.path, p.path)))) : []), + ].filter(p => (!pkgConfig.eslint ? !p.includes('eslint') : true)), }) return fullConfig diff --git a/lib/content/index.js b/lib/content/index.js index f4f68e8a..4100bb7b 100644 --- a/lib/content/index.js +++ b/lib/content/index.js @@ -1,8 +1,8 @@ const { name: NAME, version: LATEST_VERSION } = require('../../package.json') -const isPublic = (p) => p.config.isPublic +const isPublic = p => p.config.isPublic -const sharedRootAdd = (name) => ({ +const sharedRootAdd = name => ({ // release '.github/workflows/release.yml': { file: 'release-yml.hbs', @@ -19,17 +19,17 @@ const sharedRootAdd = (name) => ({ '.release-please-manifest.json': { file: 'release-please-manifest-json.hbs', filter: isPublic, - parser: (p) => p.JsonMergeNoComment, + parser: p => p.JsonMergeNoComment, }, 'release-please-config.json': { file: 'release-please-config-json.hbs', filter: isPublic, - parser: (p) => p.JsonMergeNoComment, + parser: p => p.JsonMergeNoComment, }, 'tsconfig.json': { file: 'tsconfig-json.hbs', - filter: (p) => p.config.typescript, - parser: (p) => p.JsonMergeNoComment, + filter: p => p.config.typescript, + parser: p => p.JsonMergeNoComment, }, // this lint commits which is only necessary for releases '.github/workflows/pull-request.yml': { @@ -42,15 +42,15 @@ const sharedRootAdd = (name) => ({ // dependabot '.github/dependabot.yml': { file: 'dependabot-yml.hbs', - filter: (p) => p.config.dependabot, + filter: p => p.config.dependabot, }, '.github/workflows/post-dependabot.yml': { file: 'post-dependabot-yml.hbs', - filter: (p) => p.config.dependabot, + filter: p => p.config.dependabot, }, '.github/settings.yml': { file: 'settings-yml.hbs', - filter: (p) => !p.config.isReleaseBranch, + filter: p => !p.config.isReleaseBranch, }, // composite actions '.github/actions/install-latest-npm/action.yml': 'action-install-latest-npm-yml.hbs', @@ -59,10 +59,10 @@ const sharedRootAdd = (name) => ({ const sharedRootRm = () => ({ '.github/workflows/pull-request.yml': { - filter: (p) => p.config.allPrivate, + filter: p => p.config.allPrivate, }, '.github/settings.yml': { - filter: (p) => p.config.isReleaseBranch, + filter: p => p.config.isReleaseBranch, }, }) @@ -94,15 +94,15 @@ const rootModule = { add: { '.eslintrc.{{ cjsExt }}': { file: 'eslintrc-js.hbs', - filter: (p) => p.config.eslint, + filter: p => p.config.eslint, }, '.prettierrc.{{ cjsExt }}': { file: 'prettier-js.hbs', - filter: (p) => p.config.prettier, + filter: p => p.config.prettier, }, '.prettierignore': { file: 'prettierignore.hbs', - filter: (p) => p.config.prettier, + filter: p => p.config.prettier, }, '.gitignore': 'gitignore.hbs', '.npmrc': 'npmrc.hbs', @@ -111,9 +111,7 @@ const rootModule = { 'CONTRIBUTING.md': 'CONTRIBUTING-md.hbs', 'package.json': 'package-json.hbs', }, - rm: [ - '.eslintrc.!({{ cjsExt }}|local.*)', - ], + rm: ['.eslintrc.!({{ cjsExt }}|local.*)'], } // Changes for each workspace but applied to the root of the repo @@ -133,16 +131,12 @@ const workspaceModule = { add: { '.eslintrc.{{ cjsExt }}': { file: 'eslintrc-js.hbs', - filter: (p) => p.config.eslint, + filter: p => p.config.eslint, }, '.gitignore': 'gitignore.hbs', 'package.json': 'package-json.hbs', }, - rm: [ - '.npmrc', - '.eslintrc.!({{ cjsExt }}|local.*)', - 'SECURITY.md', - ], + rm: ['.npmrc', '.eslintrc.!({{ cjsExt }}|local.*)', 'SECURITY.md'], } module.exports = { @@ -159,10 +153,7 @@ module.exports = { // {{major}} to have the major version being published replaced in the string. defaultPublishTag: 'latest', releaseBranch: 'release/v*', - distPaths: [ - 'bin/', - 'lib/', - ], + distPaths: ['bin/', 'lib/'], allowDistPaths: true, allowPaths: [ '/.eslintrc.local.*', @@ -205,11 +196,7 @@ module.exports = { 'standard', ], requiredPackages: { - devDependencies: [ - `${NAME}@${LATEST_VERSION}`, - '@npmcli/eslint-config', - 'tap', - ], + devDependencies: [`${NAME}@${LATEST_VERSION}`, '@npmcli/eslint-config', 'tap'], }, allowedPackages: [], changelogTypes: [ diff --git a/lib/index.js b/lib/index.js index a1e01bc2..c43d1ba9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,7 +4,7 @@ const getConfig = require('./config.js') const PackageJson = require('@npmcli/package-json') const mapWorkspaces = require('@npmcli/map-workspaces') -const getPkg = async (path) => { +const getPkg = async path => { log.verbose('get-pkg', path) const pkgJson = (await PackageJson.load(path)).content @@ -27,7 +27,7 @@ const getWsPkgs = async (root, rootPkg) => { // Include all by default const { workspaces } = rootPkg.config - const include = (name) => Array.isArray(workspaces) ? workspaces.includes(name) : true + const include = name => (Array.isArray(workspaces) ? workspaces.includes(name) : true) // Look through all workspaces on the root pkg const rootWorkspaces = await mapWorkspaces({ pkg: rootPkg.pkgJson, cwd: root }) @@ -43,7 +43,7 @@ const getWsPkgs = async (root, rootPkg) => { return wsPkgs } -const getPkgs = async (root) => { +const getPkgs = async root => { log.verbose('get-pkgs', 'root', root) const rootPkg = await getPkg(root) diff --git a/lib/release/changelog.js b/lib/release/changelog.js index 8358e6c2..9ee059a7 100644 --- a/lib/release/changelog.js +++ b/lib/release/changelog.js @@ -11,7 +11,7 @@ class Changelog { [Changelog.BREAKING]: '⚠️ BREAKING CHANGES', } - constructor ({ version, url, sections }) { + constructor({ version, url, sections }) { this.#title = `## ${url ? link(version, url) : version} (${formatDate()})` for (const section of sections) { this.#types.add(section.type) @@ -20,7 +20,7 @@ class Changelog { } } - add (type, ...entries) { + add(type, ...entries) { if (!this.#types.has(type) || !entries.length) { return } @@ -28,11 +28,11 @@ class Changelog { this.#entries[type].push(...entries) } - #getEntries (type) { + #getEntries(type) { return this.#entries[type].map(list).join('\n') } - toString () { + toString() { const body = [this.#title] const includedTypes = [] @@ -47,7 +47,7 @@ class Changelog { // empty string which will skip the release PR being created. // We do this because we don't want PRs opened if they only contain // chores but we do want to rebuild existing PRs if chores are added. - if (includedTypes.every((type) => this.#sections[type]?.hidden)) { + if (includedTypes.every(type => this.#sections[type]?.hidden)) { return '' } @@ -62,7 +62,7 @@ class ChangelogNotes { #graphql #ghUrl - constructor (github) { + constructor(github) { this.#owner = github.repository.owner this.#repo = github.repository.repo this.#rest = github.octokit.rest @@ -70,7 +70,7 @@ class ChangelogNotes { this.#ghUrl = makeGitHubUrl(this.#owner, this.#repo) } - async #getAuthorsForCommits (commits) { + async #getAuthorsForCommits(commits) { const shas = commits .filter(c => c.type !== 'deps') .map(c => c.sha) @@ -82,7 +82,7 @@ class ChangelogNotes { const authorsByCommit = {} const { repository } = await this.#graphql( - `fragment CommitAuthors on GitObject { + `fragment CommitAuthors on GitObject { ... on Commit { authors (first:10) { nodes { @@ -94,23 +94,23 @@ class ChangelogNotes { } query { repository (owner:"${this.#owner}", name:"${this.#repo}") { - ${shas.map((s) => { + ${shas.map(s => { return `_${s}: object (expression: "${s}") { ...CommitAuthors }` })} } - }` + }`, ) for (const [key, commit] of Object.entries(repository)) { if (commit) { authorsByCommit[key.slice(1)] = commit.authors.nodes - .map((a) => a.user && a.user.login ? `@${a.user.login}` : a.name) + .map(a => (a.user && a.user.login ? `@${a.user.login}` : a.name)) .filter(Boolean) } } return authorsByCommit } - async #getPullRequestNumbersForCommits (commits) { + async #getPullRequestNumbersForCommits(commits) { const shas = commits .filter(c => !c.pullRequest?.number) .map(c => c.sha) @@ -122,19 +122,20 @@ class ChangelogNotes { const pullRequestsByCommit = {} for (const sha of shas) { - pullRequestsByCommit[sha] = await this.#rest.repos.listPullRequestsAssociatedWithCommit({ - owner: this.#owner, - repo: this.#repo, - commit_sha: sha, - per_page: 1, - }) - .then((r) => r.data[0].number) + pullRequestsByCommit[sha] = await this.#rest.repos + .listPullRequestsAssociatedWithCommit({ + owner: this.#owner, + repo: this.#repo, + commit_sha: sha, + per_page: 1, + }) + .then(r => r.data[0].number) .catch(() => null) } return pullRequestsByCommit } - #buildEntry (commit) { + #buildEntry(commit) { const entry = [] if (commit.sha) { @@ -161,7 +162,7 @@ class ChangelogNotes { return entry.join(' ') } - #filterCommits (commits) { + #filterCommits(commits) { const filteredCommits = [] const keyedDuplicates = {} @@ -186,8 +187,8 @@ class ChangelogNotes { // Sort all our duplicates so we get the latest verion (by PR number) of each type. // Then flatten so we can put them all back into the changelog const sortedDupes = Object.values(keyedDuplicates) - .filter((items) => Boolean(items.length)) - .map((items) => items.sort((a, b) => b.pullRequestNumber - a.pullRequestNumber)) + .filter(items => Boolean(items.length)) + .map(items => items.sort((a, b) => b.pullRequestNumber - a.pullRequestNumber)) .flatMap(items => items[0]) // This moves them to the bottom of their changelog section which is not @@ -199,7 +200,7 @@ class ChangelogNotes { return filteredCommits } - async buildNotes (rawCommits, { version, previousTag, currentTag, changelogSections }) { + async buildNotes(rawCommits, { version, previousTag, currentTag, changelogSections }) { // get authors for commits for each sha const authors = await this.#getAuthorsForCommits(rawCommits) @@ -208,7 +209,7 @@ class ChangelogNotes { // lookup commits without a pr number and find one if it exists const prNumbers = await this.#getPullRequestNumbersForCommits(rawCommits) - const fullCommits = rawCommits.map((commit) => { + const fullCommits = rawCommits.map(commit => { commit.authors = authors[commit.sha] ?? [] commit.pullRequestNumber = Number(commit.pullRequest?.number ?? prNumbers[commit.sha]) return commit @@ -216,9 +217,7 @@ class ChangelogNotes { const changelog = new Changelog({ version, - url: previousTag - ? this.#ghUrl('compare', `${previousTag.toString()}...${currentTag.toString()}`) - : null, + url: previousTag ? this.#ghUrl('compare', `${previousTag.toString()}...${currentTag.toString()}`) : null, sections: changelogSections, }) @@ -227,9 +226,7 @@ class ChangelogNotes { changelog.add(commit.type, this.#buildEntry(commit)) // And breaking changes to its own section - changelog.add(Changelog.BREAKING, ...commit.notes - .filter(n => n.title === 'BREAKING CHANGE') - .map(n => n.text)) + changelog.add(Changelog.BREAKING, ...commit.notes.filter(n => n.title === 'BREAKING CHANGE').map(n => n.text)) } return changelog.toString() diff --git a/lib/release/node-workspace-format.js b/lib/release/node-workspace-format.js index 57135d1a..78a86be9 100644 --- a/lib/release/node-workspace-format.js +++ b/lib/release/node-workspace-format.js @@ -12,7 +12,7 @@ module.exports = class extends ManifestPlugin { #releasesByPackage = new Map() #pathsByComponent = new Map() - async preconfigure (strategiesByPath) { + async preconfigure(strategiesByPath) { // First build a list of all releases that will happen based on // the conventional commits for (const path in strategiesByPath) { @@ -25,17 +25,19 @@ module.exports = class extends ManifestPlugin { return strategiesByPath } - run (candidates) { + run(candidates) { this.#rewriteWorkspaceChangelogItems(candidates) this.#sortReleases(candidates) return candidates } - #replaceWorkspace ({ name, versionRange }) { + #replaceWorkspace({ name, versionRange }) { const version = versionRange.replace(/^[\^~]/, '') const { path, component } = this.#releasesByPackage.get(name) const { tagSeparator, includeVInTag } = this.repositoryConfig[path] - const { repository: { owner, repo } } = this.github + const { + repository: { owner, repo }, + } = this.github const tag = new TagName(version, component, tagSeparator, includeVInTag).toString() const url = `https://github.com/${owner}/${repo}/releases/tag/${tag}` return list(`${link('workspace', url)}: ${wrapSpecs(`${name}@${version}`)}`) @@ -46,7 +48,7 @@ module.exports = class extends ManifestPlugin { // be part of the changelog plugin since they are written after that by the // node-workspace plugin. A possible PR to release-please could add an option // to customize these or run them through the changelog notes generator. - #rewriteWorkspaceChangelogItems (candidates) { + #rewriteWorkspaceChangelogItems(candidates) { for (const candidate of candidates) { for (const release of candidate.pullRequest.body.releaseData) { // Update notes with a link to each workspaces release notes @@ -57,13 +59,11 @@ module.exports = class extends ManifestPlugin { .replace(/^\s{2}\* devDependencies\n/gm, '') .replace(/^\s{2}\* peerDependencies\n/gm, '') .replace(/^\s{2}\* optionalDependencies\n/gm, '') - .replace( - /^\s{4}\* (?[^\s]+) bumped to (?[^\s]+)/gm, - (...args) => this.#replaceWorkspace(args.at(-1)) + .replace(/^\s{4}\* (?[^\s]+) bumped to (?[^\s]+)/gm, (...args) => + this.#replaceWorkspace(args.at(-1)), ) - .replace( - /^\s{4}\* (?[^\s]+) bumped from (?:[^\s]+) to (?[^\s]+)/gm, - (...args) => this.#replaceWorkspace(args.at(-1)) + .replace(/^\s{4}\* (?[^\s]+) bumped from (?:[^\s]+) to (?[^\s]+)/gm, (...args) => + this.#replaceWorkspace(args.at(-1)), ) // Find the associated changelog and update that too @@ -79,7 +79,7 @@ module.exports = class extends ManifestPlugin { // Sort root release to the top of the pull request // release please pre sorts based on graph order so - #sortReleases (candidates) { + #sortReleases(candidates) { for (const candidate of candidates) { candidate.pullRequest.body.releaseData.sort((a, b) => { const aPath = this.#pathsByComponent.get(a.component) diff --git a/lib/release/release-manager.js b/lib/release/release-manager.js index 69e58ee8..91b673a9 100644 --- a/lib/release/release-manager.js +++ b/lib/release/release-manager.js @@ -21,17 +21,7 @@ class ReleaseManager { #info - constructor ({ - token, - repo, - cwd = process.cwd(), - pr, - backport, - defaultTag, - lockfile, - publish, - silent, - }) { + constructor({ token, repo, cwd = process.cwd(), pr, backport, defaultTag, lockfile, publish, silent }) { assert(token, 'GITHUB_TOKEN is required') assert(repo, 'GITHUB_REPOSITORY is required') assert(cwd, 'cwd is required') @@ -51,12 +41,12 @@ class ReleaseManager { this.#info = silent ? noop : core.info } - static async run (options) { + static async run(options) { const manager = new ReleaseManager(options) return manager.run() } - async run () { + async run() { const { data: pullRequest } = await this.#octokit.rest.pulls.get({ owner: this.#owner, repo: this.#repo, @@ -84,51 +74,55 @@ class ReleaseManager { return `### Release Checklist for ${release.tag}\n\n${checklist}` } - async #getPrReleases ({ pullRequest }) { + async #getPrReleases({ pullRequest }) { return /
.*<\/summary>/.test(pullRequest.body) ? await this.#getPrMonoRepoReleases({ pullRequest }) : [this.#getPrRootRelease({ pullRequest }), []] } - async #getPrMonoRepoReleases ({ pullRequest }) { + async #getPrMonoRepoReleases({ pullRequest }) { const releases = pullRequest.body.match(/
.*<\/summary>/g) this.#info(`Found ${releases.length} releases`) - const workspacesComponents = [...await mapWorkspaces({ - cwd: this.#cwd, - pkg: require(join(this.#cwd, 'package.json')), - })] - .reduce((acc, [k]) => { - const wsComponentName = k.startsWith('@') ? k.split('/')[1] : k - acc[wsComponentName] = k - return acc - }, {}) + const workspacesComponents = [ + ...(await mapWorkspaces({ + cwd: this.#cwd, + pkg: require(join(this.#cwd, 'package.json')), + })), + ].reduce((acc, [k]) => { + const wsComponentName = k.startsWith('@') ? k.split('/')[1] : k + acc[wsComponentName] = k + return acc + }, {}) const MONO_VERSIONS = /
(?:(.*?):\s)?(.*?)<\/summary>/ - return releases.reduce((acc, r) => { - const [, name, version] = r.match(MONO_VERSIONS) + return releases.reduce( + (acc, r) => { + const [, name, version] = r.match(MONO_VERSIONS) - const release = this.#getPrReleaseInfo({ - pullRequest, - name, - version, - workspaces: workspacesComponents, - }) + const release = this.#getPrReleaseInfo({ + pullRequest, + name, + version, + workspaces: workspacesComponents, + }) - if (release.isRoot) { - this.#info(`Found root: ${JSON.stringify(release)}`) - acc[0] = release - } else { - this.#info(`Found workspace: ${JSON.stringify(release)}`) - acc[1].push(release) - } + if (release.isRoot) { + this.#info(`Found root: ${JSON.stringify(release)}`) + acc[0] = release + } else { + this.#info(`Found workspace: ${JSON.stringify(release)}`) + acc[1].push(release) + } - return acc - }, [null, []]) + return acc + }, + [null, []], + ) } - #getPrRootRelease ({ pullRequest }) { + #getPrRootRelease({ pullRequest }) { this.#info('Found no monorepo, checking for single root version') const match = pullRequest.body.match(/\n##\s\[(.*?)\]/) @@ -140,7 +134,7 @@ class ReleaseManager { return this.#getPrReleaseInfo({ pullRequest, version }) } - #getPrReleaseInfo ({ pullRequest, workspaces = {}, name = null, version: rawVersion }) { + #getPrReleaseInfo({ pullRequest, workspaces = {}, name = null, version: rawVersion }) { const version = semver.parse(rawVersion) const prerelease = !!version.prerelease.length const tag = `${name ? `${name}-` : ''}v${rawVersion}` @@ -156,51 +150,47 @@ class ReleaseManager { version: rawVersion, major: version.major, url: `https://github.com/${pullRequest.base.repo.full_name}/releases/tag/${tag}`, - flags: [ - workspaces[name] ? `-w ${workspaces[name]}` : null, - `--tag=${publishTag}`, - ].filter(Boolean).join(' '), + flags: [workspaces[name] ? `-w ${workspaces[name]}` : null, `--tag=${publishTag}`].filter(Boolean).join(' '), } } - async #getReleaseProcess ({ release, workspaces }) { + async #getReleaseProcess({ release, workspaces }) { const RELEASE_LIST_ITEM = /^\d+\.\s/gm this.#info(`Fetching release process from repo wiki: ${this.#owner}/${this.#repo}`) const releaseProcess = await fetch( - `https://raw.githubusercontent.com/wiki/${this.#owner}/${this.#repo}/Release-Process.md` - ) - .then(r => { - // If the url fails with anything but a 404 we want the process to blow - // up because that means something is very wrong. This is a rare edge - // case that isn't worth testing. - /* istanbul ignore else */ - if (r.statusCode === 200) { - this.#info('Found release process from wiki') - return r.body.text() - } else if (r.statusCode === 404) { - this.#info('No release process found in wiki, falling back to default process') - return this.#getReleaseSteps() - } else { - throw new Error(`Release process fetch failed with status: ${r.statusCode}`) - } - }) + `https://raw.githubusercontent.com/wiki/${this.#owner}/${this.#repo}/Release-Process.md`, + ).then(r => { + // If the url fails with anything but a 404 we want the process to blow + // up because that means something is very wrong. This is a rare edge + // case that isn't worth testing. + /* istanbul ignore else */ + if (r.statusCode === 200) { + this.#info('Found release process from wiki') + return r.body.text() + } else if (r.statusCode === 404) { + this.#info('No release process found in wiki, falling back to default process') + return this.#getReleaseSteps() + } else { + throw new Error(`Release process fetch failed with status: ${r.statusCode}`) + } + }) // XXX: the release steps need to always be the last thing in the doc for this to work const releaseLines = releaseProcess.split('\n') - const releaseStartLine = releaseLines.reduce((acc, l, i) => l.match(/^#+\s/) ? i : acc, 0) + const releaseStartLine = releaseLines.reduce((acc, l, i) => (l.match(/^#+\s/) ? i : acc), 0) const section = releaseLines.slice(releaseStartLine).join('\n') return section .split({ - [Symbol.split]: (str) => { + [Symbol.split]: str => { const [, ...matches] = str.split(RELEASE_LIST_ITEM) this.#info(`Found ${matches.length} release items`) - return matches.map((m) => `- [ ] . ${m}`.trim()) + return matches.map(m => `- [ ] . ${m}`.trim()) }, }) - .filter((item) => { + .filter(item => { if (release.prerelease && item.includes('> NOT FOR PRERELEASE')) { return false } @@ -214,7 +204,7 @@ class ReleaseManager { .map((item, index) => item.replace('', index + 1)) } - #getReleaseSteps () { + #getReleaseSteps() { const R = `-R ${this.#owner}/${this.#repo}` const manualSteps = ` @@ -275,12 +265,7 @@ class ReleaseManager { ` /* eslint-enable max-len */ - return [ - this.#publish ? autoSteps : manualSteps, - alwaysSteps, - ] - .map(v => dedent(v)) - .join('\n\n') + return [this.#publish ? autoSteps : manualSteps, alwaysSteps].map(v => dedent(v)).join('\n\n') } } diff --git a/lib/release/release-please.js b/lib/release/release-please.js index 96811c2b..d4b515da 100644 --- a/lib/release/release-please.js +++ b/lib/release/release-please.js @@ -1,10 +1,6 @@ const RP = require('release-please') -const { - DefaultVersioningStrategy, -} = require('release-please/build/src/versioning-strategies/default.js') -const { - PrereleaseVersioningStrategy, -} = require('release-please/build/src/versioning-strategies/prerelease.js') +const { DefaultVersioningStrategy } = require('release-please/build/src/versioning-strategies/default.js') +const { PrereleaseVersioningStrategy } = require('release-please/build/src/versioning-strategies/prerelease.js') const { ROOT_PROJECT_PATH } = require('release-please/build/src/manifest.js') const { CheckpointLogger, logger } = require('release-please/build/src/util/logger.js') const assert = require('assert') @@ -31,16 +27,7 @@ class ReleasePlease { #octokit #manifest - constructor ({ - token, - repo, - branch, - backport, - defaultTag, - overrides, - silent, - trace, - }) { + constructor({ token, repo, branch, backport, defaultTag, overrides, silent, trace }) { assert(token, 'token is required') assert(repo, 'repo is required') assert(branch, 'branch is required') @@ -57,28 +44,33 @@ class ReleasePlease { this.#trace = trace } - static async run (options) { + static async run(options) { const releasePlease = new ReleasePlease(options) await releasePlease.init() return releasePlease.run() } - async init () { - RP.registerChangelogNotes('default', ({ github, ...o }) => - new ChangelogNotes(github, o)) - RP.registerVersioningStrategy('default', (o) => - o.prerelease ? new PrereleaseVersioningStrategy(o) : new DefaultVersioningStrategy(o)) - RP.registerPlugin('node-workspace-format', ({ github, targetBranch, repositoryConfig, ...o }) => - new NodeWorkspaceFormat(github, targetBranch, repositoryConfig, o)) + async init() { + RP.registerChangelogNotes('default', ({ github, ...o }) => new ChangelogNotes(github, o)) + RP.registerVersioningStrategy('default', o => + o.prerelease ? new PrereleaseVersioningStrategy(o) : new DefaultVersioningStrategy(o), + ) + RP.registerPlugin( + 'node-workspace-format', + ({ github, targetBranch, repositoryConfig, ...o }) => + new NodeWorkspaceFormat(github, targetBranch, repositoryConfig, o), + ) if (this.#silent) { this.#info = noop - RP.setLogger(Object.entries(logger).reduce((acc, [k, v]) => { - if (typeof v === 'function') { - acc[k] = noop - } - return acc - }, {})) + RP.setLogger( + Object.entries(logger).reduce((acc, [k, v]) => { + if (typeof v === 'function') { + acc[k] = noop + } + return acc + }, {}), + ) } else { this.#info = core.info RP.setLogger(new CheckpointLogger(true, !!this.#trace)) @@ -90,16 +82,10 @@ class ReleasePlease { token: this.#token, }) this.#octokit = this.#github.octokit - this.#manifest = await RP.Manifest.fromManifest( - this.#github, - this.#branch, - undefined, - undefined, - this.#overrides - ) + this.#manifest = await RP.Manifest.fromManifest(this.#github, this.#branch, undefined, undefined, this.#overrides) } - async run () { + async run() { const rootPr = await this.#getRootPullRequest() const releases = await this.#getReleases() @@ -108,11 +94,13 @@ class ReleasePlease { // release please does not guarantee that the release PR will have the latest sha, // but we always need it so we can attach the relevant checks to the sha. - rootPr.sha = await this.#octokit.paginate(this.#octokit.rest.pulls.listCommits, { - owner: this.#owner, - repo: this.#repo, - pull_number: rootPr.number, - }).then(r => r[r.length - 1].sha) + rootPr.sha = await this.#octokit + .paginate(this.#octokit.rest.pulls.listCommits, { + owner: this.#owner, + repo: this.#repo, + pull_number: rootPr.number, + }) + .then(r => r[r.length - 1].sha) } if (releases) { @@ -126,19 +114,23 @@ class ReleasePlease { defaultTag: this.#defaultTag, }) - release.prNumber = await this.#octokit.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: this.#owner, - repo: this.#repo, - commit_sha: release.sha, - per_page: 1, - }).then(r => r.data[0]?.number) - - release.pkgName = await this.#octokit.rest.repos.getContent({ - owner: this.#owner, - repo: this.#repo, - ref: this.#branch, - path: `${release.path === '.' ? '' : release.path}/package.json`, - }).then(r => JSON.parse(Buffer.from(r.data.content, r.data.encoding)).name) + release.prNumber = await this.#octokit.rest.repos + .listPullRequestsAssociatedWithCommit({ + owner: this.#owner, + repo: this.#repo, + commit_sha: release.sha, + per_page: 1, + }) + .then(r => r.data[0]?.number) + + release.pkgName = await this.#octokit.rest.repos + .getContent({ + owner: this.#owner, + repo: this.#repo, + ref: this.#branch, + path: `${release.path === '.' ? '' : release.path}/package.json`, + }) + .then(r => JSON.parse(Buffer.from(r.data.content, r.data.encoding)).name) } } @@ -148,14 +140,14 @@ class ReleasePlease { } } - async #getRootPullRequest () { + async #getRootPullRequest() { // We only ever get a single pull request with our current release-please settings // Update this if we start creating individual PRs per workspace release const pullRequests = await this.#manifest.createPullRequests() return pullRequests.filter(Boolean)[0] ?? null } - async #getReleases () { + async #getReleases() { // if we have a root release, always put it as the first item in the array const rawReleases = await this.#manifest.createReleases().then(r => r.filter(Boolean)) let rootRelease = null diff --git a/lib/release/util.js b/lib/release/util.js index d614ce39..671919e8 100644 --- a/lib/release/util.js +++ b/lib/release/util.js @@ -1,11 +1,11 @@ const semver = require('semver') const SPEC = new RegExp(`([^\\s]+@${semver.src[semver.tokens.FULLPLAIN]})`, 'g') -const code = (c) => `\`${c}\`` -const wrapSpecs = (str) => str.replace(SPEC, code('$1')) -const block = (lang) => `\`\`\`${lang ? `${lang}` : ''}` +const code = c => `\`${c}\`` +const wrapSpecs = str => str.replace(SPEC, code('$1')) +const block = lang => `\`\`\`${lang ? `${lang}` : ''}` const link = (text, url) => `[${text}](${url})` -const list = (text) => `* ${text}` +const list = text => `* ${text}` const formatDate = (date = new Date()) => { const year = date.getFullYear() const month = (date.getMonth() + 1).toString().padStart(2, '0') @@ -17,12 +17,15 @@ const getPublishTag = (v, { backport, defaultTag }) => { const version = semver.parse(v) return version.prerelease.length ? `prerelease-${version.major}` - : backport ? `latest-${backport}` - : defaultTag.replace(/{{\s*major\s*}}/, version.major) + : backport + ? `latest-${backport}` + : defaultTag.replace(/{{\s*major\s*}}/, version.major) } -const makeGitHubUrl = (owner, repo) => - (...p) => `https://github.com/${owner}/${repo}/${p.join('/')}` +const makeGitHubUrl = + (owner, repo) => + (...p) => + `https://github.com/${owner}/${repo}/${p.join('/')}` const noop = () => {} diff --git a/lib/util/ci-versions.js b/lib/util/ci-versions.js index ac42e96f..91042547 100644 --- a/lib/util/ci-versions.js +++ b/lib/util/ci-versions.js @@ -1,16 +1,16 @@ const { uniq, range, isPlainObject } = require('lodash') const semver = require('semver') -const parseCiVersions = (ciVersions) => { +const parseCiVersions = ciVersions => { if (Array.isArray(ciVersions)) { - return Object.fromEntries(ciVersions.map((v) => [v, true])) + return Object.fromEntries(ciVersions.map(v => [v, true])) } if (isPlainObject(ciVersions)) { return ciVersions } } -const getLowerBounds = (sRange) => { +const getLowerBounds = sRange => { return new semver.Range(sRange).set.map(c => c[0]) } diff --git a/lib/util/dependabot.js b/lib/util/dependabot.js index 913657f0..38f4dd8e 100644 --- a/lib/util/dependabot.js +++ b/lib/util/dependabot.js @@ -1,7 +1,7 @@ const { name: NAME } = require('../../package.json') const { minimatch } = require('minimatch') -const parseDependabotConfig = (v) => typeof v === 'string' ? { strategy: v } : (v ?? {}) +const parseDependabotConfig = v => (typeof v === 'string' ? { strategy: v } : v ?? {}) module.exports = (config, defaultConfig, branches) => { const { dependabot } = config @@ -12,7 +12,7 @@ module.exports = (config, defaultConfig, branches) => { } return branches - .filter((b) => dependabot[b] !== false) + .filter(b => dependabot[b] !== false) .map(branch => { const isReleaseBranch = minimatch(branch, config.releaseBranch) return { diff --git a/lib/util/files.js b/lib/util/files.js index 0842c6e8..71703220 100644 --- a/lib/util/files.js +++ b/lib/util/files.js @@ -12,21 +12,17 @@ const FILE_KEYS = ['rootRepo', 'rootModule', 'workspaceRepo', 'workspaceModule'] const globify = pattern => pattern.split('\\').join('/') -const deepMapKeys = (obj, fn) => Object.entries(obj).reduce((acc, [key, value]) => { - acc[fn(key)] = isPlainObject(value) ? deepMapKeys(value, fn) : value - return acc -}, {}) +const deepMapKeys = (obj, fn) => + Object.entries(obj).reduce((acc, [key, value]) => { + acc[fn(key)] = isPlainObject(value) ? deepMapKeys(value, fn) : value + return acc + }, {}) const mergeFiles = mergeWithCustomizers((value, srcValue, key, target, source, stack) => { // This will merge all files except if the src file has overwrite:false. Then // the files will be turned into an array so they can be applied on top of // each other in the parser. - if ( - stack[0] === ADD_KEY && - FILE_KEYS.includes(stack[1]) && - value?.file && - srcValue?.overwrite === false - ) { + if (stack[0] === ADD_KEY && FILE_KEYS.includes(stack[1]) && value?.file && srcValue?.overwrite === false) { return [value, omit(srcValue, 'overwrite')] } }, customizers.overwriteArrays) @@ -47,10 +43,14 @@ const fileEntries = (dir, files, options) => { // applied or diffed against the target. This is how overwrite:false // works and they are merged. const source = Array.isArray(value) - ? value.reduce((acc, { file, ...rest }) => { - acc.file.push(file) - return Object.assign(acc, rest) - }, { file: [] }) : value + ? value.reduce( + (acc, { file, ...rest }) => { + acc.file.push(file) + return Object.assign(acc, rest) + }, + { file: [] }, + ) + : value results.push([target, source]) } @@ -110,12 +110,12 @@ const parseEach = async (dir, files, options, parseOptions, fn) => { } const parseConfig = (files, dir, overrides, templateSettings) => { - const normalizeFiles = (v) => { - v = deepMapKeys(v, (s) => template(s, templateSettings)) + const normalizeFiles = v => { + v = deepMapKeys(v, s => template(s, templateSettings)) return deepMapValues(v, (value, key) => { if (key === RM_KEY && Array.isArray(value)) { return value.reduce((acc, k) => { - // template files nows since they need to be normalized before merging + // template files nows since they need to be normalized before merging acc[template(k, templateSettings)] = true return acc }, {}) @@ -132,15 +132,18 @@ const parseConfig = (files, dir, overrides, templateSettings) => { } const merged = mergeFiles(normalizeFiles(files), normalizeFiles(overrides)) - const withDefaults = defaultsDeep(merged, FILE_KEYS.reduce((acc, k) => { - acc[k] = { [ADD_KEY]: {}, [RM_KEY]: {} } - return acc - }, {})) + const withDefaults = defaultsDeep( + merged, + FILE_KEYS.reduce((acc, k) => { + acc[k] = { [ADD_KEY]: {}, [RM_KEY]: {} } + return acc + }, {}), + ) return withDefaults } -const getAddedFiles = (files) => files ? Object.keys(files[ADD_KEY] || {}) : [] +const getAddedFiles = files => (files ? Object.keys(files[ADD_KEY] || {}) : []) module.exports = { rmEach, diff --git a/lib/util/git.js b/lib/util/git.js index 681af788..06439830 100644 --- a/lib/util/git.js +++ b/lib/util/git.js @@ -5,7 +5,7 @@ const { minimatch } = require('minimatch') const cache = new Map() const tryGit = async (path, ...args) => { - if (!await git.is({ cwd: path })) { + if (!(await git.is({ cwd: path }))) { throw new Error('no git') } const key = [path, ...args].join(',') @@ -31,7 +31,7 @@ const getRemoteUrl = async (path, remote) => { } } -const getUrl = async (path) => { +const getUrl = async path => { return (await getRemoteUrl(path, 'upstream')) ?? (await getRemoteUrl(path, 'origin')) } @@ -41,7 +41,10 @@ const getBranches = async (path, branchPatterns) => { try { const res = await tryGit(path, 'ls-remote', '--heads', 'origin').then(r => r.split('\n')) - const remotes = res.map((h) => h.match(/refs\/heads\/(.*)$/)).filter(Boolean).map(h => h[1]) + const remotes = res + .map(h => h.match(/refs\/heads\/(.*)$/)) + .filter(Boolean) + .map(h => h[1]) for (const branch of remotes) { for (const pattern of branchPatterns) { if (minimatch(branch, pattern)) { @@ -61,7 +64,7 @@ const getBranches = async (path, branchPatterns) => { } } -const defaultBranch = async (path) => { +const defaultBranch = async path => { try { const remotes = await tryGit(path, 'remote', 'show', 'origin') return remotes.match(/HEAD branch: (.*)$/m)?.[1] diff --git a/lib/util/gitignore.js b/lib/util/gitignore.js index 665e1009..28e719cf 100644 --- a/lib/util/gitignore.js +++ b/lib/util/gitignore.js @@ -4,17 +4,19 @@ const localeCompare = require('@isaacs/string-locale-compare')('en') const sortGitPaths = (a, b) => localeCompare(a.replace(/^!/g, ''), b.replace(/^!/g, '')) -const allowDir = (p) => { +const allowDir = p => { const parts = p.split(posix.sep) - return parts.flatMap((part, index, list) => { - const prev = list.slice(0, index) - const isLast = index === list.length - 1 - const ignorePart = ['', ...prev, part, ''].join(posix.sep) - return [`!${ignorePart}`, !isLast && `${ignorePart}*`] - }).filter(Boolean) + return parts + .flatMap((part, index, list) => { + const prev = list.slice(0, index) + const isLast = index === list.length - 1 + const ignorePart = ['', ...prev, part, ''].join(posix.sep) + return [`!${ignorePart}`, !isLast && `${ignorePart}*`] + }) + .filter(Boolean) } -const allowRootDir = (p) => { +const allowRootDir = p => { // This negates the first part of each path for the gitignore // files. It should be used to allow directories where everything // should be allowed inside such as .github/. It shouldn't be used on @@ -26,9 +28,9 @@ const allowRootDir = (p) => { } const gitignore = { - allowDir: (dirs) => uniq(dirs.map(allowDir).flat()), - allowRootDir: (dirs) => dirs.map(allowRootDir).map((p) => `!${posix.sep}${p}`), - sort: (arr) => uniq(arr.sort(sortGitPaths)), + allowDir: dirs => uniq(dirs.map(allowDir).flat()), + allowRootDir: dirs => dirs.map(allowRootDir).map(p => `!${posix.sep}${p}`), + sort: arr => uniq(arr.sort(sortGitPaths)), } module.exports = gitignore diff --git a/lib/util/has-package.js b/lib/util/has-package.js index bffddfad..639c5b52 100644 --- a/lib/util/has-package.js +++ b/lib/util/has-package.js @@ -39,16 +39,11 @@ const getSpecVersion = (spec, where) => { return null } -const isVersion = (s) => s instanceof semver.SemVer +const isVersion = s => s instanceof semver.SemVer // Returns whether the pkg has the dependency in a semver // compatible version in one or more locationscccc -const hasPackage = ( - pkg, - spec, - locations = installLocations, - path -) => { +const hasPackage = (pkg, spec, locations = installLocations, path) => { const name = npa(spec).name const requested = getSpecVersion(spec) @@ -57,16 +52,16 @@ const hasPackage = ( } const existingByLocation = locations - .map((location) => pkg[location]) - .filter((deps) => has(deps, name)) - .map((deps) => getSpecVersion(`${name}@${deps[name]}`, path)) + .map(location => pkg[location]) + .filter(deps => has(deps, name)) + .map(deps => getSpecVersion(`${name}@${deps[name]}`, path)) .filter(Boolean) - return existingByLocation.some((existing) => { + return existingByLocation.some(existing => { if (existing === true) { return true } - switch ([existing, requested].map((t) => isVersion(t) ? 'VER' : 'RNG').join('-')) { + switch ([existing, requested].map(t => (isVersion(t) ? 'VER' : 'RNG')).join('-')) { case `VER-VER`: // two versions, use semver.eq to check equality return semver.eq(existing, requested) diff --git a/lib/util/import-or-require.js b/lib/util/import-or-require.js index 8fc7ef97..0fb0ef4b 100644 --- a/lib/util/import-or-require.js +++ b/lib/util/import-or-require.js @@ -7,7 +7,7 @@ const { pathToFileURL } = require('url') const importOrRequireCache = new Map() -const importOrRequire = async (path) => { +const importOrRequire = async path => { if (importOrRequireCache.has(path)) { return importOrRequireCache.get(path) } diff --git a/lib/util/json-diff.js b/lib/util/json-diff.js index ccc32b6d..faeac0ac 100644 --- a/lib/util/json-diff.js +++ b/lib/util/json-diff.js @@ -6,28 +6,29 @@ const j = (obj, replacer = null) => JSON.stringify(obj, replacer, 2) // DELETE is a special string that will be the value of updated if it exists // but should be deleted -const jsonDiff = (s1, s2, DELETE) => diff(s1, s2) - .map(({ op, path, value }) => { - // there could be cases where a whole object is reported - // as missing and the expected value does not need to show - // special DELETED values so filter those out here - const msgVal = j(value, (_, v) => v === DELETE ? undefined : v) - const prev = j(get(s1, path)) - const key = j(path.reduce((acc, p) => acc + (typeof p === 'number' ? `[${p}]` : `.${p}`))) +const jsonDiff = (s1, s2, DELETE) => + diff(s1, s2) + .map(({ op, path, value }) => { + // there could be cases where a whole object is reported + // as missing and the expected value does not need to show + // special DELETED values so filter those out here + const msgVal = j(value, (_, v) => (v === DELETE ? undefined : v)) + const prev = j(get(s1, path)) + const key = j(path.reduce((acc, p) => acc + (typeof p === 'number' ? `[${p}]` : `.${p}`))) - const msg = (...args) => format('%s is %s, expected %s', ...args) - const AD = msg(key, 'missing', msgVal) - const RM = msg(key, prev, 'to be removed') - const UP = msg(key, prev, msgVal) + const msg = (...args) => format('%s is %s, expected %s', ...args) + const AD = msg(key, 'missing', msgVal) + const RM = msg(key, prev, 'to be removed') + const UP = msg(key, prev, msgVal) - if (op === 'replace') { - return value === DELETE ? RM : UP - } else if (op === 'add' && value !== DELETE) { - return AD - } - }) - .filter(Boolean) - .sort((a, b) => a.localeCompare(b)) - .join('\n') + if (op === 'replace') { + return value === DELETE ? RM : UP + } else if (op === 'add' && value !== DELETE) { + return AD + } + }) + .filter(Boolean) + .sort((a, b) => a.localeCompare(b)) + .join('\n') module.exports = jsonDiff diff --git a/lib/util/merge.js b/lib/util/merge.js index 05a24300..c889d359 100644 --- a/lib/util/merge.js +++ b/lib/util/merge.js @@ -32,16 +32,17 @@ const mergeWith = (...args) => { // Create a merge function that will run a set of customizer functions const mergeWithCustomizers = (...customizers) => { - return (...objects) => mergeWith({}, ...objects, (...args) => { - for (const customizer of customizers) { - const result = customizer(...args) - // undefined means the customizer will defer to the next one - // the default behavior of undefined in lodash is to merge - if (result !== undefined) { - return result + return (...objects) => + mergeWith({}, ...objects, (...args) => { + for (const customizer of customizers) { + const result = customizer(...args) + // undefined means the customizer will defer to the next one + // the default behavior of undefined in lodash is to merge + if (result !== undefined) { + return result + } } - } - }) + }) } const customizers = { @@ -52,14 +53,16 @@ const customizers = { } }, // Merge arrays if their key matches one of the passed in keys - mergeArrays: (...keys) => (value, srcValue, key) => { - if (Array.isArray(srcValue)) { - if (keys.includes(key)) { - return (Array.isArray(value) ? value : []).concat(srcValue) + mergeArrays: + (...keys) => + (value, srcValue, key) => { + if (Array.isArray(srcValue)) { + if (keys.includes(key)) { + return (Array.isArray(value) ? value : []).concat(srcValue) + } + return srcValue } - return srcValue - } - }, + }, } module.exports = { diff --git a/lib/util/output.js b/lib/util/output.js index d96bea23..b9e32f6d 100644 --- a/lib/util/output.js +++ b/lib/util/output.js @@ -1,8 +1,12 @@ const indent = (v, i = 2) => { if (Array.isArray(v)) { - return v.map((a) => indent(a, i)).join('\n') + return v.map(a => indent(a, i)).join('\n') } - return v.toString().split('\n').map((l) => ' '.repeat(i) + l).join('\n') + return v + .toString() + .split('\n') + .map(l => ' '.repeat(i) + l) + .join('\n') } const output = () => { @@ -15,13 +19,12 @@ const output = () => { } } -const outputProblems = (problems) => { +const outputProblems = problems => { const o = output() o.push('', 'Some problems were detected:') o.sep() for (const { title, body, solution } of problems) { - const [solutionTitle, ...solutionRest] = Array.isArray(solution) - ? solution : [solution] + const [solutionTitle, ...solutionRest] = Array.isArray(solution) ? solution : [solution] o.push(title, '', indent(body), '', `To correct it: ${solutionTitle}`) if (solutionRest.length) { o.push('', indent(solutionRest)) diff --git a/lib/util/parser.js b/lib/util/parser.js index 2156f6cd..c70c783b 100644 --- a/lib/util/parser.js +++ b/lib/util/parser.js @@ -27,7 +27,7 @@ const traverse = (value, visit, keys = []) => { } } -const fsOk = (code) => (error) => { +const fsOk = code => error => { if (error.code === 'ENOENT') { return null } @@ -37,107 +37,114 @@ const fsOk = (code) => (error) => { class Base { static types = [] static header = 'This file is automatically added by {{ __NAME__ }}. Do not edit.' - comment = (v) => v + comment = v => v merge = false // supply a merge function which runs on prepare for certain types DELETE = template.DELETE - constructor (target, source, options, fileOptions) { + constructor(target, source, options, fileOptions) { this.target = target this.source = source this.options = options this.fileOptions = fileOptions } - header () { + header() { if (typeof this.comment === 'function') { return this.comment(this.template(this.constructor.header || '')) } } - clean () { + clean() { if (this.fileOptions.clean) { return fs.rm(this.target).catch(fsOk()) } return null } - read (s) { + read(s) { if (Array.isArray(s)) { return Promise.all(s.map(f => this.read(f))) } return fs.readFile(s, { encoding: 'utf-8' }) } - template (s) { + template(s) { if (Array.isArray(s)) { return Promise.all(s.map(f => this.template(f))) } return template(s, this.options) } - parse (s) { + parse(s) { return s } - prepare (s) { + prepare(s) { const header = this.header() return header ? `${header}\n\n${s}` : s } - prepareTarget (s) { + prepareTarget(s) { return s } - toString (s) { + toString(s) { return s.toString() } - async write (s) { + async write(s) { // XXX: find more efficient way to do this. we can build all possible dirs before get here await fs.mkdir(dirname(this.target), { owner: 'inherit', recursive: true, force: true }) return fs.writeFile(this.target, this.toString(s), { owner: 'inherit' }) } - diffPatch (t, s) { + diffPatch(t, s) { // create a patch and strip out the filename. if it ends up an empty string // then return true since the files are equal - return Diff.createPatch('', t.replace(/\r\n/g, '\n'), s.replace(/\r\n/g, '\n')) - .split('\n').slice(4).join('\n') + return Diff.createPatch('', t.replace(/\r\n/g, '\n'), s.replace(/\r\n/g, '\n')).split('\n').slice(4).join('\n') } - diff (t, s) { + diff(t, s) { return this.diffPatch(t, s) } // the apply methods are the only ones that should be called publically // XXX: everything is allowed to be overridden in base classes but we could // find a different solution than making everything public - applyWrite () { - return Promise.resolve(this.clean()) - .then(() => this.read(this.source)) - // replace template vars first, this will throw for nonexistant vars - // because it must be parseable after this step - .then((s) => this.template(s)) - // parse into whatever data structure is necessary for maniuplating - // diffing, merging, etc. by default its a string - .then((s) => { - this.sourcePreParse = s - return this.parse(s) - }) - // prepare the source for writing and diffing, pass in current - // target for merging. errors parsing or preparing targets are ok here - .then((s) => this.applyTarget().catch(() => null).then((t) => this.prepare(s, t))) - .then((s) => this.write(s)) - } - - applyTarget () { - return Promise.resolve(this.read(this.target)) - .then((s) => this.parse(s)) - // for only preparing the target for diffing - .then((s) => this.prepareTarget(s)) - } - - async applyDiff () { + applyWrite() { + return ( + Promise.resolve(this.clean()) + .then(() => this.read(this.source)) + // replace template vars first, this will throw for nonexistant vars + // because it must be parseable after this step + .then(s => this.template(s)) + // parse into whatever data structure is necessary for maniuplating + // diffing, merging, etc. by default its a string + .then(s => { + this.sourcePreParse = s + return this.parse(s) + }) + // prepare the source for writing and diffing, pass in current + // target for merging. errors parsing or preparing targets are ok here + .then(s => + this.applyTarget() + .catch(() => null) + .then(t => this.prepare(s, t)), + ) + .then(s => this.write(s)) + ) + } + + applyTarget() { + return ( + Promise.resolve(this.read(this.target)) + .then(s => this.parse(s)) + // for only preparing the target for diffing + .then(s => this.prepareTarget(s)) + ) + } + + async applyDiff() { // handle if old does not exist const targetError = 'ETARGETERROR' const target = await this.applyTarget().catch(fsOk(targetError)) @@ -148,10 +155,10 @@ class Base { } const source = await Promise.resolve(this.read(this.source)) - .then((s) => this.template(s)) - .then((s) => this.parse(s)) + .then(s => this.template(s)) + .then(s => this.parse(s)) // gets the target to diff against in case it needs to merge, etc - .then((s) => this.prepare(s, target)) + .then(s => this.prepare(s, target)) // if there was a target error then there is no need to diff // so we just show the source with an error message @@ -175,27 +182,27 @@ class Base { class Gitignore extends Base { static types = ['codeowners', '.gitignore', '.prettierignore'] - comment = (c) => `# ${c}` + comment = c => `# ${c}` } class Js extends Base { static types = ['*.js', '*.cjs'] - comment = (c) => `/* ${c} */` + comment = c => `/* ${c} */` } class Ini extends Base { static types = ['*.ini'] - comment = (c) => `; ${c}` + comment = c => `; ${c}` - toString (s) { + toString(s) { return typeof s === 'string' ? s : ini.stringify(s) } - parse (s) { + parse(s) { return typeof s === 'string' ? ini.parse(s) : s } - prepare (s, t) { + prepare(s, t) { let source = s if (typeof this.merge === 'function' && t) { source = this.merge(t, s) @@ -203,7 +210,7 @@ class Ini extends Base { return super.prepare(this.toString(source)) } - diff (t, s) { + diff(t, s) { return jsonDiff(this.parse(t), this.parse(s), this.DELETE) } } @@ -215,14 +222,14 @@ class IniMerge extends Ini { class Markdown extends Base { static types = ['*.md'] - comment = (c) => `` + comment = c => `` } class Yml extends Base { static types = ['*.yml'] - comment = (c) => ` ${c}` + comment = c => ` ${c}` - toString (s) { + toString(s) { try { return s.toString({ lineWidth: 0, indent: 2 }) } catch (err) { @@ -231,22 +238,22 @@ class Yml extends Base { } } - parse (s) { + parse(s) { return yaml.parseDocument(s) } - prepare (s) { + prepare(s) { s.commentBefore = this.header() return this.toString(s) } - prepareTarget (s) { + prepareTarget(s) { return this.toString(s) } } class YmlMerge extends Yml { - prepare (source, t) { + prepare(source, t) { if (t === null) { // If target does not exist or is in an // error state, we cant do anything but write @@ -256,7 +263,7 @@ class YmlMerge extends Yml { const key = [].concat(this.key) - const getId = (node) => { + const getId = node => { const index = node.items.findIndex(p => p.key?.value === this.id) return index !== -1 ? node.items[index].value?.value : node.toJSON() } @@ -284,20 +291,20 @@ class Json extends Base { static types = ['*.json'] // its a json comment! not really but we do add a special key // to json objects - comment = (c) => ({ [`//${this.options.config.__NAME__}`]: c }) + comment = c => ({ [`//${this.options.config.__NAME__}`]: c }) - toString (s) { - return JSON.stringify(s, (_, v) => v === this.DELETE ? undefined : v, 2).trim() + '\n' + toString(s) { + return JSON.stringify(s, (_, v) => (v === this.DELETE ? undefined : v), 2).trim() + '\n' } - parse (s) { + parse(s) { if (Array.isArray(s)) { return s.map(f => this.parse(f)).reduce((a, f) => this.merge(a, f), {}) } return jsonParse(s) } - prepare (s, t) { + prepare(s, t) { let source = s if (typeof this.merge === 'function' && t) { source = this.merge(t, s) @@ -305,7 +312,7 @@ class Json extends Base { return setFirst(this.header(), source) } - diff (t, s) { + diff(t, s) { return jsonDiff(t, s, this.DELETE) } } @@ -322,7 +329,7 @@ class JsonMergeNoComment extends JsonMerge { class PackageJson extends JsonMerge { static types = ['package.json'] - async prepare (s, t) { + async prepare(s, t) { // merge new source with current pkg content const update = super.prepare(s, t) @@ -336,7 +343,7 @@ class PackageJson extends JsonMerge { return update } - async write (s) { + async write(s) { const pkg = await NpmPackageJson.load(dirname(this.target)) pkg.update(s) traverse(pkg.content, (keys, value) => { @@ -378,7 +385,7 @@ for (const parser of Object.values(Parsers)) { } } -const getParser = (file) => { +const getParser = file => { for (const [type, parser] of parserLookup) { if (minimatch(file, type, { nocase: true, dot: true, matchBase: true })) { return parser diff --git a/lib/util/path.js b/lib/util/path.js index e0582f59..3b65b83d 100644 --- a/lib/util/path.js +++ b/lib/util/path.js @@ -1,9 +1,9 @@ const { posix, win32 } = require('path') -const makePosix = (v) => v.split(win32.sep).join(posix.sep) -const deglob = (v) => makePosix(v).replace(/[/*]+$/, '') -const posixDir = (v) => `${v === '.' ? '' : deglob(v).replace(/\/$/, '')}${posix.sep}` -const posixGlob = (str) => `${posixDir(str)}**` +const makePosix = v => v.split(win32.sep).join(posix.sep) +const deglob = v => makePosix(v).replace(/[/*]+$/, '') +const posixDir = v => `${v === '.' ? '' : deglob(v).replace(/\/$/, '')}${posix.sep}` +const posixGlob = str => `${posixDir(str)}**` module.exports = { makePosix, diff --git a/lib/util/template.js b/lib/util/template.js index c7889a23..1413bed6 100644 --- a/lib/util/template.js +++ b/lib/util/template.js @@ -4,12 +4,12 @@ const { Range } = require('semver') const fs = require('fs') const DELETE = '__DELETE__' -const safeValues = (obj) => Object.entries(obj).map(([key, value]) => - [key, new Handlebars.SafeString(value)]) +const safeValues = obj => Object.entries(obj).map(([key, value]) => [key, new Handlebars.SafeString(value)]) -const partialName = (s) => basename(s, extname(s)) // remove extension - .replace(/^_/, '') // remove leading underscore - .replace(/-([a-z])/g, (_, g) => g.toUpperCase()) // camelcase +const partialName = s => + basename(s, extname(s)) // remove extension + .replace(/^_/, '') // remove leading underscore + .replace(/-([a-z])/g, (_, g) => g.toUpperCase()) // camelcase const makePartials = (dir, isBase) => { const partials = fs.readdirSync(dir).reduce((acc, f) => { @@ -32,16 +32,16 @@ const makePartials = (dir, isBase) => { Handlebars.registerPartial(partials) } -const setupHandlebars = (dirs) => { +const setupHandlebars = dirs => { Handlebars.registerHelper('obj', ({ hash }) => Object.fromEntries(safeValues(hash))) Handlebars.registerHelper('extGlob', arr => `{${arr.join(',')}}`) Handlebars.registerHelper('join', (arr, sep) => arr.join(typeof sep === 'string' ? sep : ', ')) Handlebars.registerHelper('pluck', (arr, key) => arr.map(a => a[key])) - Handlebars.registerHelper('quote', (arr) => arr.map(a => `'${a}'`)) - Handlebars.registerHelper('last', (arr) => arr[arr.length - 1]) - Handlebars.registerHelper('json', (c) => JSON.stringify(c)) + Handlebars.registerHelper('quote', arr => arr.map(a => `'${a}'`)) + Handlebars.registerHelper('last', arr => arr[arr.length - 1]) + Handlebars.registerHelper('json', c => JSON.stringify(c)) Handlebars.registerHelper('del', () => JSON.stringify(DELETE)) - Handlebars.registerHelper('semverRangeMajor', (v) => new Range(v).set[0][0].semver.major) + Handlebars.registerHelper('semverRangeMajor', v => new Range(v).set[0][0].semver.major) Handlebars.registerHelper('lte', (a, b) => a <= b) if (Array.isArray(dirs)) { diff --git a/test/apply/allow-paths.js b/test/apply/allow-paths.js index fd272d68..31c7caf7 100644 --- a/test/apply/allow-paths.js +++ b/test/apply/allow-paths.js @@ -1,14 +1,11 @@ const t = require('tap') const setup = require('../setup.js') -t.test('allow paths are merged', async (t) => { +t.test('allow paths are merged', async t => { const s = await setup(t, { package: { templateOSS: { - allowPaths: [ - '/a', - '/b', - ], + allowPaths: ['/a', '/b'], }, }, }) @@ -20,16 +17,13 @@ t.test('allow paths are merged', async (t) => { t.ok(ignore.includes('!/lib/')) }) -t.test('works with custom content', async (t) => { +t.test('works with custom content', async t => { const s = await setup(t, { package: { templateOSS: { content: 'content_dir', defaultContent: false, - allowPaths: [ - '/a', - '/b', - ], + allowPaths: ['/a', '/b'], }, }, testdir: { diff --git a/test/apply/dependabot.js b/test/apply/dependabot.js index c2950b9f..6f44e04e 100644 --- a/test/apply/dependabot.js +++ b/test/apply/dependabot.js @@ -10,7 +10,7 @@ const setupDependabot = async (t, { branches = ['main'], ...config } = {}) => { mocks: { '@npmcli/git': { is: async () => true, - spawn: async (args) => { + spawn: async args => { const command = args.filter(a => typeof a === 'string').join(' ') if (command === 'ls-remote --heads origin') { return { @@ -28,9 +28,9 @@ const setupDependabot = async (t, { branches = ['main'], ...config } = {}) => { }) await s.apply() - const postDependabot = await s.readFile('.github/workflows/post-dependabot.yml') - .catch(() => false) - const dependabot = await s.readFile('.github/dependabot.yml') + const postDependabot = await s.readFile('.github/workflows/post-dependabot.yml').catch(() => false) + const dependabot = await s + .readFile('.github/dependabot.yml') .then(r => yaml.parse(r).updates) .catch(() => false) @@ -41,7 +41,7 @@ const setupDependabot = async (t, { branches = ['main'], ...config } = {}) => { } } -t.test('default', async (t) => { +t.test('default', async t => { const s = await setupDependabot(t) t.equal(s.dependabot.length, 1) @@ -60,7 +60,7 @@ t.test('default', async (t) => { t.ok(s.postDependabot) }) -t.test('change strategy', async (t) => { +t.test('change strategy', async t => { const s = await setupDependabot(t, { dependabot: 'some-other-strategy', }) @@ -68,7 +68,7 @@ t.test('change strategy', async (t) => { t.equal(s.dependabot[0]['versioning-strategy'], 'some-other-strategy') }) -t.test('turn off specific branch', async (t) => { +t.test('turn off specific branch', async t => { const s = await setupDependabot(t, { dependabot: { main: false, @@ -77,24 +77,24 @@ t.test('turn off specific branch', async (t) => { t.equal(s.dependabot, null) }) -t.test('release brancheses', async (t) => { +t.test('release brancheses', async t => { const s = await setupDependabot(t, { - branches: [ - 'release/v10', - ], + branches: ['release/v10'], }) t.match(s.dependabot[0], { 'target-branch': 'release/v10', - allow: [{ - 'dependency-type': 'direct', - 'dependency-name': '@npmcli/template-oss', - }], + allow: [ + { + 'dependency-type': 'direct', + 'dependency-name': '@npmcli/template-oss', + }, + ], labels: ['Dependencies', 'Backport', 'release/v10'], }) }) -t.test('no dependabot', async (t) => { +t.test('no dependabot', async t => { const s = await setupDependabot(t, { dependabot: false, }) diff --git a/test/apply/engines.js b/test/apply/engines.js index 9744a50c..d334d877 100644 --- a/test/apply/engines.js +++ b/test/apply/engines.js @@ -3,7 +3,7 @@ const { join } = require('path') const yaml = require('yaml') const setup = require('../setup.js') -const getCiJobs = async (s) => { +const getCiJobs = async s => { const file = await s.readFile(join('.github', 'workflows', 'ci.yml')) const { jobs } = yaml.parse(file) return { @@ -12,7 +12,7 @@ const getCiJobs = async (s) => { } } -t.test('sets ci versions from engines', async (t) => { +t.test('sets ci versions from engines', async t => { const s = await setup(t, { package: { engines: { node: '>=10' }, @@ -30,18 +30,10 @@ t.test('sets ci versions from engines', async (t) => { const versions = await getCiJobs(s) t.equal(versions.lint, '22.x') - t.strictSame(versions.test, [ - '10.0.0', - '10.x', - '14.x', - '16.x', - '18.x', - '20.x', - '22.x', - ]) + t.strictSame(versions.test, ['10.0.0', '10.x', '14.x', '16.x', '18.x', '20.x', '22.x']) }) -t.test('can set ci to latest plus other versions', async (t) => { +t.test('can set ci to latest plus other versions', async t => { const s = await setup(t, { package: { engines: { node: '*' }, @@ -57,27 +49,16 @@ t.test('can set ci to latest plus other versions', async (t) => { const versions = await getCiJobs(s) t.equal(versions.lint, '22.x') - t.strictSame(versions.test, [ - '6.x', - '8.x', - '22.x', - ]) + t.strictSame(versions.test, ['6.x', '8.x', '22.x']) }) -t.test('sort by major', async (t) => { +t.test('sort by major', async t => { const s = await setup(t, { package: { engines: { node: '*' }, templateOSS: { latestCiVersion: null, - ciVersions: [ - '7.x', - '6.0.0', - '6.x', - '7.0.0', - '8.x', - '8.0.0', - ], + ciVersions: ['7.x', '6.0.0', '6.x', '7.0.0', '8.x', '8.0.0'], }, }, }) @@ -88,17 +69,10 @@ t.test('sort by major', async (t) => { const versions = await getCiJobs(s) t.equal(versions.lint, '8.x') - t.strictSame(versions.test, [ - '6.0.0', - '6.x', - '7.0.0', - '7.x', - '8.0.0', - '8.x', - ]) + t.strictSame(versions.test, ['6.0.0', '6.x', '7.0.0', '7.x', '8.0.0', '8.x']) }) -t.test('latest ci versions', async (t) => { +t.test('latest ci versions', async t => { const s = await setup(t, { package: { templateOSS: { @@ -113,7 +87,5 @@ t.test('latest ci versions', async (t) => { const versions = await getCiJobs(s) t.equal(versions.lint, '22.x') - t.strictSame(versions.test, [ - '22.x', - ]) + t.strictSame(versions.test, ['22.x']) }) diff --git a/test/apply/esm.js b/test/apply/esm.js index 3afc80ca..aeaa9f18 100644 --- a/test/apply/esm.js +++ b/test/apply/esm.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('basic', async (t) => { +t.test('basic', async t => { const s = await setup(t, { package: { type: 'module', diff --git a/test/apply/files-snapshots.js b/test/apply/files-snapshots.js index 79d27bf7..5dd1299e 100644 --- a/test/apply/files-snapshots.js +++ b/test/apply/files-snapshots.js @@ -4,7 +4,7 @@ const setup = require('../setup.js') t.cleanSnapshot = setup.clean t.formatSnapshot = setup.format.readdir -t.test('turn off repo', async (t) => { +t.test('turn off repo', async t => { const s = await setup(t, { package: { templateOSS: { @@ -16,7 +16,7 @@ t.test('turn off repo', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('turn off module', async (t) => { +t.test('turn off module', async t => { const s = await setup(t, { package: { templateOSS: { @@ -28,7 +28,7 @@ t.test('turn off module', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('turn off root', async (t) => { +t.test('turn off root', async t => { const s = await setup(t, { package: { templateOSS: { @@ -41,7 +41,7 @@ t.test('turn off root', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('turn off add/rm types', async (t) => { +t.test('turn off add/rm types', async t => { const s = await setup(t, { package: { templateOSS: { @@ -58,7 +58,7 @@ t.test('turn off add/rm types', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('turn off specific files', async (t) => { +t.test('turn off specific files', async t => { const s = await setup(t, { package: { templateOSS: { @@ -93,7 +93,7 @@ t.test('turn off specific files', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('workspaces with relative content path', async (t) => { +t.test('workspaces with relative content path', async t => { const s = await setup(t, { package: { templateOSS: { @@ -118,7 +118,7 @@ t.test('workspaces with relative content path', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('workspaces', async (t) => { +t.test('workspaces', async t => { const s = await setup(t, { package: { templateOSS: { @@ -149,7 +149,7 @@ t.test('workspaces', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('workspaces only (like npm/cli)', async (t) => { +t.test('workspaces only (like npm/cli)', async t => { const s = await setup(t, { package: { templateOSS: { @@ -163,7 +163,7 @@ t.test('workspaces only (like npm/cli)', async (t) => { await t.resolveMatchSnapshot(s.readdir()) }) -t.test('private workspace', async (t) => { +t.test('private workspace', async t => { const s = await setup(t, { package: { name: 'root-pkg', diff --git a/test/apply/index.js b/test/apply/index.js index 3be5f2a5..a968fe92 100644 --- a/test/apply/index.js +++ b/test/apply/index.js @@ -2,7 +2,7 @@ const t = require('tap') const { join } = require('path') const setup = require('../setup.js') -t.test('turn off root files', async (t) => { +t.test('turn off root files', async t => { const s = await setup(t, { package: { templateOSS: { @@ -26,7 +26,7 @@ t.test('turn off root files', async (t) => { t.ok(await s.exists('.eslintrc.yml')) }) -t.test('turn off root rm only', async (t) => { +t.test('turn off root rm only', async t => { const s = await setup(t, { package: { templateOSS: { @@ -54,7 +54,7 @@ t.test('turn off root rm only', async (t) => { t.ok(await s.exists('.eslintrc.yml')) }) -t.test('turn off root add only', async (t) => { +t.test('turn off root add only', async t => { const s = await setup(t, { package: { templateOSS: { @@ -82,7 +82,7 @@ t.test('turn off root add only', async (t) => { t.notOk(await s.exists('.eslintrc.yml')) }) -t.test('turn off specific files', async (t) => { +t.test('turn off specific files', async t => { const s = await setup(t, { package: { templateOSS: { @@ -120,7 +120,7 @@ t.test('turn off specific files', async (t) => { t.ok(await s.exists('.eslintrc.yml')) }) -t.test('root can set workspace files', async (t) => { +t.test('root can set workspace files', async t => { const s = await setup(t, { package: { templateOSS: { @@ -146,7 +146,7 @@ t.test('root can set workspace files', async (t) => { t.ok(await s.exists(s.workspaces.a, '.npmrc')) }) -t.test('workspace config can override root', async (t) => { +t.test('workspace config can override root', async t => { const s = await setup(t, { package: { templateOSS: { @@ -179,7 +179,7 @@ t.test('workspace config can override root', async (t) => { t.notOk(await s.exists(s.workspaces.a, '.npmrc')) }) -t.test('workspaces can override content', async (t) => { +t.test('workspaces can override content', async t => { const s = await setup(t, { package: { templateOSS: { @@ -209,7 +209,7 @@ t.test('workspaces can override content', async (t) => { t.ok(await s.exists('x.js')) }) -t.test('content can override partials', async (t) => { +t.test('content can override partials', async t => { const s = await setup(t, { package: { templateOSS: { @@ -239,7 +239,7 @@ t.test('content can override partials', async (t) => { t.ok(release.includes('job: 1')) }) -t.test('content can extend files', async (t) => { +t.test('content can extend files', async t => { const s = await setup(t, { package: { templateOSS: { @@ -259,7 +259,7 @@ t.test('content can extend files', async (t) => { t.ok(release.includes('smoke-publish')) }) -t.test('config via multiple locations', async (t) => { +t.test('config via multiple locations', async t => { const s = await setup(t, { package: { templateOSS: { @@ -301,7 +301,7 @@ t.test('config via multiple locations', async (t) => { t.equal(ws.split('\n').slice(-1)[0], 'npm-ws-a-ws-b-ws-c') }) -t.test('private workspace', async (t) => { +t.test('private workspace', async t => { const s = await setup(t, { package: { name: 'root-pkg', diff --git a/test/apply/lint.js b/test/apply/lint.js index a1b8d94b..88914d92 100644 --- a/test/apply/lint.js +++ b/test/apply/lint.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('can disable eslint', async (t) => { +t.test('can disable eslint', async t => { const s = await setup(t, { package: { templateOSS: { @@ -23,7 +23,7 @@ t.test('can disable eslint', async (t) => { t.notMatch(checks[0].solution, 'eslint') }) -t.test('can enable prettier', async (t) => { +t.test('can enable prettier', async t => { const s = await setup(t, { ok: true, package: { @@ -41,11 +41,7 @@ t.test('can enable prettier', async (t) => { const checks = await s.check() t.equal(checks.length, 1) - t.match(checks[0].body, [ - 'prettier', - 'eslint-config-prettier', - '@github/prettier-config', - ]) + t.match(checks[0].body, ['prettier', 'eslint-config-prettier', '@github/prettier-config']) await s.writeJson('package.json', { ...pkg, diff --git a/test/apply/lockfile.js b/test/apply/lockfile.js index 3ffeba99..ee7321c3 100644 --- a/test/apply/lockfile.js +++ b/test/apply/lockfile.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('lockfile', async (t) => { +t.test('lockfile', async t => { const s = await setup(t, { package: { templateOSS: { @@ -17,7 +17,7 @@ t.test('lockfile', async (t) => { t.ok(npmrc.includes('package-lock=true')) }) -t.test('no lockfile by default', async (t) => { +t.test('no lockfile by default', async t => { const s = await setup(t) await s.apply() const gitignore = await s.readFile('.gitignore') diff --git a/test/apply/merge-yml.js b/test/apply/merge-yml.js index d80e50f7..2dbdad92 100644 --- a/test/apply/merge-yml.js +++ b/test/apply/merge-yml.js @@ -2,9 +2,9 @@ const t = require('tap') const yaml = require('yaml') const setup = require('../setup.js') -const toYml = (data) => new yaml.Document(data).toString() +const toYml = data => new yaml.Document(data).toString() -t.test('json merge', async (t) => { +t.test('json merge', async t => { const s = await setup(t, { package: { templateOSS: { @@ -15,19 +15,11 @@ t.test('json merge', async (t) => { testdir: { 'target.yml': toYml({ existing: 'header', - key: [ - { id: 1, a: 1 }, - { id: 2, a: 2 }, - { noid: 1 }, - ], + key: [{ id: 1, a: 1 }, { id: 2, a: 2 }, { noid: 1 }], }), 'clean-target.yml': toYml({ existing: 'header', - key: [ - { id: 1, a: 1 }, - { id: 2, a: 2 }, - { noid: 1 }, - ], + key: [{ id: 1, a: 1 }, { id: 2, a: 2 }, { noid: 1 }], }), content: { 'index.js': await setup.fixture('yml-merge.js'), @@ -47,12 +39,7 @@ t.test('json merge', async (t) => { t.strictSame(yaml.parse(await s.readFile('target.yml')), { existing: 'header', - key: [ - { id: 1, b: 1 }, - { id: 2, b: 2 }, - { noid: 1 }, - { id: 3, b: 3 }, - ], + key: [{ id: 1, b: 1 }, { id: 2, b: 2 }, { noid: 1 }, { id: 3, b: 3 }], }) t.strictSame(yaml.parse(await s.readFile('clean-target.yml')), { new: 'header', diff --git a/test/apply/npm-bin.js b/test/apply/npm-bin.js index c61f6ab3..8cab4153 100644 --- a/test/apply/npm-bin.js +++ b/test/apply/npm-bin.js @@ -2,7 +2,7 @@ const t = require('tap') const { join } = require('path') const setup = require('../setup.js') -t.test('custom npm path', async (t) => { +t.test('custom npm path', async t => { const s = await setup(t, { ok: true, package: { @@ -16,7 +16,7 @@ t.test('custom npm path', async (t) => { t.equal(scripts.posttest, 'node /path/to/npm run lint') }) -t.test('relative npm bin with workspaces', async (t) => { +t.test('relative npm bin with workspaces', async t => { const s = await setup(t, { ok: true, package: { @@ -38,7 +38,7 @@ t.test('relative npm bin with workspaces', async (t) => { }) await s.apply() - const readScripts = (p) => s.readJson(join(p, 'package.json')).then(r => r.scripts) + const readScripts = p => s.readJson(join(p, 'package.json')).then(r => r.scripts) const ws = s.workspaces const pkgs = ['', ws.a, ws.b, ws.c, ws.d, ws.e] diff --git a/test/apply/overwrite-false.js b/test/apply/overwrite-false.js index 260d7f7f..efc513b6 100644 --- a/test/apply/overwrite-false.js +++ b/test/apply/overwrite-false.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('json merge', async (t) => { +t.test('json merge', async t => { const s = await setup(t, { ok: true, package: { diff --git a/test/apply/release-config.js b/test/apply/release-config.js index 13e187cf..16ab3598 100644 --- a/test/apply/release-config.js +++ b/test/apply/release-config.js @@ -1,20 +1,23 @@ const t = require('tap') const setup = require('../setup.js') -const PLUGINS = [ - 'node-workspace', - 'node-workspace-format', -] +const PLUGINS = ['node-workspace', 'node-workspace-format'] -t.test('root only', async (t) => { +t.test('root only', async t => { const prvt = { private: true } const cases = [ [{}, { plugins: false, pr: true }], [{ workspaces: { a: 'a' } }, { plugins: true, pr: true }], [{ workspaces: { a: prvt } }, { plugins: false, pr: true }], [{ package: prvt }, { plugins: false, pr: false }], - [{ package: prvt, workspaces: { a: 'a' } }, { plugins: true, pr: true }], - [{ package: prvt, workspaces: { a: prvt } }, { plugins: false, pr: false }], + [ + { package: prvt, workspaces: { a: 'a' } }, + { plugins: true, pr: true }, + ], + [ + { package: prvt, workspaces: { a: prvt } }, + { plugins: false, pr: false }, + ], ] for (const [config, expected] of cases) { diff --git a/test/apply/release.js b/test/apply/release.js index dcc5762a..3009d7fe 100644 --- a/test/apply/release.js +++ b/test/apply/release.js @@ -2,7 +2,7 @@ const t = require('tap') const { join } = require('path') const setup = require('../setup.js') -t.test('no workspace flags in commands', async (t) => { +t.test('no workspace flags in commands', async t => { const s = await setup(t, { package: { templateOSS: { @@ -22,7 +22,7 @@ t.test('no workspace flags in commands', async (t) => { t.match(release, '--backport=""') }) -t.test('uses workspace flags in commands', async (t) => { +t.test('uses workspace flags in commands', async t => { const s = await setup(t, { workspaces: { a: 'a', @@ -36,7 +36,7 @@ t.test('uses workspace flags in commands', async (t) => { t.match(ciRelease, '--ignore-scripts -ws -iwr --if-present\n') }) -t.test('backport', async (t) => { +t.test('backport', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/apply/source-snapshots.js b/test/apply/source-snapshots.js index f1ec9901..6ceae1fa 100644 --- a/test/apply/source-snapshots.js +++ b/test/apply/source-snapshots.js @@ -4,13 +4,13 @@ const setup = require('../setup.js') t.cleanSnapshot = setup.clean t.formatSnapshot = setup.format.readdirSource -t.test('root only', async (t) => { +t.test('root only', async t => { const s = await setup(t) await s.apply() await t.resolveMatchSnapshot(s.readdirSource()) }) -t.test('with workspaces', async (t) => { +t.test('with workspaces', async t => { const s = await setup(t, { workspaces: { a: 'a', b: 'b' }, }) @@ -18,7 +18,7 @@ t.test('with workspaces', async (t) => { await t.resolveMatchSnapshot(s.readdirSource()) }) -t.test('workspaces only', async (t) => { +t.test('workspaces only', async t => { const s = await setup(t, { package: { templateOSS: { @@ -32,7 +32,7 @@ t.test('workspaces only', async (t) => { await t.resolveMatchSnapshot(s.readdirSource()) }) -t.test('with content path', async (t) => { +t.test('with content path', async t => { const s = await setup(t, { package: { templateOSS: { @@ -50,7 +50,7 @@ t.test('with content path', async (t) => { await t.resolveMatchSnapshot(s.readdirSource()) }) -t.test('workspaces with nested content path', async (t) => { +t.test('workspaces with nested content path', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/apply/tap.js b/test/apply/tap.js index 2a204877..7dbf076c 100644 --- a/test/apply/tap.js +++ b/test/apply/tap.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('tap@18', async (t) => { +t.test('tap@18', async t => { const s = await setup(t, { ok: true, package: { @@ -16,7 +16,7 @@ t.test('tap@18', async (t) => { t.strictSame(pkg.tap, {}) }) -t.test('tap@16', async (t) => { +t.test('tap@16', async t => { const s = await setup(t, { ok: true, package: { @@ -29,9 +29,6 @@ t.test('tap@16', async (t) => { await s.apply() const pkg = await s.readJson('package.json') t.strictSame(pkg.tap, { - 'nyc-arg': [ - '--exclude', - 'tap-snapshots/**', - ], + 'nyc-arg': ['--exclude', 'tap-snapshots/**'], }) }) diff --git a/test/apply/typescript.js b/test/apply/typescript.js index 7bf5f458..42f09b1a 100644 --- a/test/apply/typescript.js +++ b/test/apply/typescript.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('basic', async (t) => { +t.test('basic', async t => { const s = await setup(t, { ok: true, package: { @@ -33,7 +33,7 @@ t.test('basic', async (t) => { t.ok(await s.exists('.commitlintrc.cjs')) }) -t.test('no default content', async (t) => { +t.test('no default content', async t => { const s = await setup(t, { ok: true, package: { @@ -56,7 +56,7 @@ t.test('no default content', async (t) => { t.strictSame(checks[0].body, ['typescript', 'tshy', '@typescript-eslint/parser']) }) -t.test('with tap 16', async (t) => { +t.test('with tap 16', async t => { const s = await setup(t, { ok: true, package: { diff --git a/test/apply/version.js b/test/apply/version.js index 83e9607d..10286273 100644 --- a/test/apply/version.js +++ b/test/apply/version.js @@ -2,7 +2,7 @@ const t = require('tap') const { join } = require('path') const setup = require('../setup.js') -t.test('applies version', async (t) => { +t.test('applies version', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/bin/apply.js b/test/bin/apply.js index 9c80e2f9..c4a32c39 100644 --- a/test/bin/apply.js +++ b/test/bin/apply.js @@ -1,8 +1,12 @@ const t = require('tap') -const templateApply = (mocks) => t.mock('../../bin/apply.js', mocks && { - '../../lib/apply/index.js': async () => mocks(), -}) +const templateApply = mocks => + t.mock( + '../../bin/apply.js', + mocks && { + '../../lib/apply/index.js': async () => mocks(), + }, + ) const _console = console const _global = process.env.npm_config_global @@ -27,26 +31,26 @@ t.afterEach(() => { } }) -t.test('when npm_config_local_prefix is unset, does nothing', async (t) => { +t.test('when npm_config_local_prefix is unset, does nothing', async t => { await templateApply() t.notOk(process.exitCode, 'exitCode is unset') }) -t.test('when npm_config_global is true, does nothing', async (t) => { +t.test('when npm_config_global is true, does nothing', async t => { process.env.npm_config_global = 'true' await templateApply() t.notOk(process.exitCode, 'exitCode is unset') }) -t.test('with mocks', async (t) => { +t.test('with mocks', async t => { process.env.npm_config_local_prefix = 'heynow' await templateApply(() => {}) t.notOk(process.exitCode, 'exitCode is unset') }) -t.test('error', async (t) => { +t.test('error', async t => { process.env.npm_config_local_prefix = 'heynow' await templateApply(() => { diff --git a/test/bin/check.js b/test/bin/check.js index 40b3704b..b6a4654b 100644 --- a/test/bin/check.js +++ b/test/bin/check.js @@ -1,8 +1,12 @@ const t = require('tap') -const templateCheck = (mocks) => t.mock('../../bin/check.js', mocks && { - '../../lib/check/index.js': async () => mocks(), -}) +const templateCheck = mocks => + t.mock( + '../../bin/check.js', + mocks && { + '../../lib/check/index.js': async () => mocks(), + }, + ) const _console = console const _prefix = process.env.npm_config_local_prefix @@ -25,7 +29,7 @@ t.afterEach(() => { } }) -t.test('no local prefix', async (t) => { +t.test('no local prefix', async t => { await templateCheck() t.equal(process.exitCode, 1, 'exit code') @@ -33,24 +37,27 @@ t.test('no local prefix', async (t) => { t.equal(errors.length, 1) }) -t.test('problems', async (t) => { +t.test('problems', async t => { process.env.npm_config_local_prefix = t.testdir() - await templateCheck(() => [{ - title: 'message1', - body: ['a', 'b'], - solution: 'solution1', - }, { - title: 'message2', - body: ['c'], - solution: 'solution2', - }]) + await templateCheck(() => [ + { + title: 'message1', + body: ['a', 'b'], + solution: 'solution1', + }, + { + title: 'message2', + body: ['c'], + solution: 'solution2', + }, + ]) t.ok(process.exitCode, 'exit code') t.matchSnapshot(errors.join('\n')) }) -t.test('no problems', async (t) => { +t.test('no problems', async t => { process.env.npm_config_local_prefix = t.testdir() await templateCheck(() => []) diff --git a/test/check/diff-snapshots.js b/test/check/diff-snapshots.js index 569b362d..36f3a61a 100644 --- a/test/check/diff-snapshots.js +++ b/test/check/diff-snapshots.js @@ -5,7 +5,7 @@ const setup = require('../setup.js') t.cleanSnapshot = setup.clean t.formatSnapshot = setup.format.checks -t.test('update and remove errors', async (t) => { +t.test('update and remove errors', async t => { const s = await setup(t, { ok: true }) await s.apply() @@ -16,17 +16,14 @@ t.test('update and remove errors', async (t) => { const ci = await s.readFile(ciPath) await s.writeFile(ciPath, ci.split('\n').slice(0, -21).join('\n')) - await s.appendFile( - join('.github', 'workflows', 'audit.yml'), - '>>>>I HOPE THIS IS NOT VALID YAML<<<<<<<<<<<' - ) + await s.appendFile(join('.github', 'workflows', 'audit.yml'), '>>>>I HOPE THIS IS NOT VALID YAML<<<<<<<<<<<') await s.writeFile('.eslintrc.json', 'this has to be deleted') await t.resolveMatchSnapshot(s.check()) }) -t.test('will diff json', async (t) => { +t.test('will diff json', async t => { const s = await setup(t, { ok: true }) await s.apply() @@ -44,7 +41,7 @@ t.test('will diff json', async (t) => { await t.resolveMatchSnapshot(s.check()) }) -t.test('json overwrite', async (t) => { +t.test('json overwrite', async t => { const s = await setup(t, { package: { templateOSS: { @@ -66,7 +63,7 @@ t.test('json overwrite', async (t) => { t.strictSame(await s.check(), []) }) -t.test('json merge', async (t) => { +t.test('json merge', async t => { const s = await setup(t, { package: { templateOSS: { @@ -88,7 +85,7 @@ t.test('json merge', async (t) => { t.strictSame(await s.check(), []) }) -t.test('json delete', async (t) => { +t.test('json delete', async t => { const s = await setup(t, { package: { templateOSS: { @@ -110,7 +107,7 @@ t.test('json delete', async (t) => { t.strictSame(await s.check(), []) }) -t.test('different headers', async (t) => { +t.test('different headers', async t => { const s = await setup(t, { package: { templateOSS: { @@ -131,7 +128,7 @@ t.test('different headers', async (t) => { t.strictSame(await s.check(), []) }) -t.test('unknown file type', async (t) => { +t.test('unknown file type', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/check/dogfood.js b/test/check/dogfood.js index 152997b6..aefd89b1 100644 --- a/test/check/dogfood.js +++ b/test/check/dogfood.js @@ -2,7 +2,7 @@ const t = require('tap') const { resolve } = require('path') const check = require('../../lib/check/index.js') -t.test('this repo passes all checks', async (t) => { +t.test('this repo passes all checks', async t => { const root = resolve(__dirname, '..', '..') const res = await check(root) t.equal(res.length, 0) diff --git a/test/check/engines.js b/test/check/engines.js index 7e5741c1..f9c51dcf 100644 --- a/test/check/engines.js +++ b/test/check/engines.js @@ -1,68 +1,69 @@ const t = require('tap') const setup = require('../setup.js') -const setupEngines = ({ engines, omitEngines }) => setup(t, { - ok: true, - package: { - engines: { node: engines }, - templateOSS: { - omitEngines, - }, - dependencies: { - eighteen: '1.0.0', - sixteen: '1.0.0', - nothing: '1.0.0', - anything: '1.0.0', - ohdoteight: '1.0.0', - }, - }, - testdir: { - node_modules: { - nothing: { - 'package.json': JSON.stringify({ - name: 'nothing', - version: '1.0.0', - }), - }, - anything: { - 'package.json': JSON.stringify({ - name: 'anything', - version: '1.0.0', - engines: { - node: '*', - }, - }), +const setupEngines = ({ engines, omitEngines }) => + setup(t, { + ok: true, + package: { + engines: { node: engines }, + templateOSS: { + omitEngines, }, - ohdoteight: { - 'package.json': JSON.stringify({ - name: 'ohdoteight', - version: '1.0.0', - engines: { - node: '>=0.8', - }, - }), + dependencies: { + eighteen: '1.0.0', + sixteen: '1.0.0', + nothing: '1.0.0', + anything: '1.0.0', + ohdoteight: '1.0.0', }, - eighteen: { - 'package.json': JSON.stringify({ - name: 'eighteen', - version: '1.0.0', - engines: { - node: '>=18', - }, - }), - }, - sixteen: { - 'package.json': JSON.stringify({ - name: 'sixteen', - version: '1.0.0', - engines: { - node: '>=16', - }, - }), + }, + testdir: { + node_modules: { + nothing: { + 'package.json': JSON.stringify({ + name: 'nothing', + version: '1.0.0', + }), + }, + anything: { + 'package.json': JSON.stringify({ + name: 'anything', + version: '1.0.0', + engines: { + node: '*', + }, + }), + }, + ohdoteight: { + 'package.json': JSON.stringify({ + name: 'ohdoteight', + version: '1.0.0', + engines: { + node: '>=0.8', + }, + }), + }, + eighteen: { + 'package.json': JSON.stringify({ + name: 'eighteen', + version: '1.0.0', + engines: { + node: '>=18', + }, + }), + }, + sixteen: { + 'package.json': JSON.stringify({ + name: 'sixteen', + version: '1.0.0', + engines: { + node: '>=16', + }, + }), + }, }, }, - }, -}) + }) const cases = [ [['^14 || ^16 || >=18'], ['eighteen', 'sixteen']], diff --git a/test/check/gitignore.js b/test/check/gitignore.js index 614de7dc..b2cb9778 100644 --- a/test/check/gitignore.js +++ b/test/check/gitignore.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('allow package-lock', async (t) => { +t.test('allow package-lock', async t => { const s = await setup.git(t, { ok: true, package: { diff --git a/test/check/index.js b/test/check/index.js index d0205c9a..d3cf0912 100644 --- a/test/check/index.js +++ b/test/check/index.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('empty content is ok', async (t) => { +t.test('empty content is ok', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/check/required.js b/test/check/required.js index b94cfd3d..cc3615c4 100644 --- a/test/check/required.js +++ b/test/check/required.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('ok with required', async (t) => { +t.test('ok with required', async t => { const s = await setup(t, { ok: true, }) @@ -9,7 +9,7 @@ t.test('ok with required', async (t) => { t.strictSame(await s.check(), []) }) -t.test('required in each location', async (t) => { +t.test('required in each location', async t => { const s = await setup(t, { package: { dependencies: { @@ -44,18 +44,16 @@ t.test('required in each location', async (t) => { t.strictSame(await s.check(), []) }) -t.test('can be pinned', async (t) => { +t.test('can be pinned', async t => { const config = { templateOSS: { requiredPackages: { - devDependencies: [ - 'a@1.0.0', - ], + devDependencies: ['a@1.0.0'], }, }, } - await t.test('ok', async (t) => { + await t.test('ok', async t => { const s = await setup(t, { package: { devDependencies: { @@ -69,7 +67,7 @@ t.test('can be pinned', async (t) => { t.strictSame(await s.check(), []) }) - await t.test('not ok', async (t) => { + await t.test('not ok', async t => { const s = await setup(t, { package: { devDependencies: { diff --git a/test/check/snapshots.js b/test/check/snapshots.js index 07fd3c38..fa812e1b 100644 --- a/test/check/snapshots.js +++ b/test/check/snapshots.js @@ -5,25 +5,25 @@ const setup = require('../setup.js') t.cleanSnapshot = setup.clean t.formatSnapshot = setup.format.checks -t.test('check empty dir', async (t) => { +t.test('check empty dir', async t => { const s = await setup(t) await t.resolveMatchSnapshot(s.check()) }) -t.test('workspaces with empty dir', async (t) => { +t.test('workspaces with empty dir', async t => { const s = await setup(t, { workspaces: { a: '@name/aaaa', b: 'bbb' }, }) await t.resolveMatchSnapshot(s.check()) }) -t.test('not ok without required', async (t) => { +t.test('not ok without required', async t => { const s = await setup(t) await s.apply() await t.resolveMatchSnapshot(s.check()) }) -t.test('changelog', async (t) => { +t.test('changelog', async t => { const s = await setup(t, { ok: true, testdir: { @@ -34,7 +34,7 @@ t.test('changelog', async (t) => { await t.resolveMatchSnapshot(s.check()) }) -t.test('gitignore', async (t) => { +t.test('gitignore', async t => { const s = await setup.git(t, { ok: true }) await s.writeFile('ignorethis', 'empty') @@ -45,7 +45,7 @@ t.test('gitignore', async (t) => { await t.resolveMatchSnapshot(s.check()) }) -t.test('gitignore with workspaces workspace', async (t) => { +t.test('gitignore with workspaces workspace', async t => { const s = await setup.git(t, { ok: true, workspaces: { @@ -63,7 +63,7 @@ t.test('gitignore with workspaces workspace', async (t) => { await t.resolveMatchSnapshot(s.check()) }) -t.test('unwanted', async (t) => { +t.test('unwanted', async t => { const s = await setup(t, { ok: true, package: { diff --git a/test/check/unwanted.js b/test/check/unwanted.js index 1d49912c..d50487e1 100644 --- a/test/check/unwanted.js +++ b/test/check/unwanted.js @@ -1,7 +1,7 @@ const t = require('tap') const setup = require('../setup.js') -t.test('unwanted can be overriden with allow', async (t) => { +t.test('unwanted can be overriden with allow', async t => { const s = await setup(t, { ok: true, package: { @@ -9,9 +9,7 @@ t.test('unwanted can be overriden with allow', async (t) => { eslint: '^8.0.0', }, templateOSS: { - allowedPackages: [ - 'eslint', - ], + allowedPackages: ['eslint'], }, }, }) diff --git a/test/fixtures/header.js b/test/fixtures/header.js index 317dc4f2..c85f15b4 100644 --- a/test/fixtures/header.js +++ b/test/fixtures/header.js @@ -3,21 +3,24 @@ module.exports = { add: { 'header.txt': { file: 'source.txt', - parser: (p) => class extends p.Base { - static header = 'Different header' - }, + parser: p => + class extends p.Base { + static header = 'Different header' + }, }, 'noheader.txt': { file: 'source.txt', - parser: (p) => class extends p.Base { - static header = null - }, + parser: p => + class extends p.Base { + static header = null + }, }, 'nocomment.txt': { file: 'source.txt', - parser: (p) => class extends p.Base { - comment = null - }, + parser: p => + class extends p.Base { + comment = null + }, }, }, }, diff --git a/test/fixtures/json-delete.js b/test/fixtures/json-delete.js index d35a2408..a8c5b12c 100644 --- a/test/fixtures/json-delete.js +++ b/test/fixtures/json-delete.js @@ -3,7 +3,7 @@ module.exports = { add: { 'target.json': { file: 'source.json', - parser: (p) => p.Json, + parser: p => p.Json, }, }, }, diff --git a/test/fixtures/json-merge.js b/test/fixtures/json-merge.js index 69d78c27..54435256 100644 --- a/test/fixtures/json-merge.js +++ b/test/fixtures/json-merge.js @@ -3,7 +3,7 @@ module.exports = { add: { 'target.json': { file: 'source.json', - parser: (p) => p.JsonMerge, + parser: p => p.JsonMerge, }, }, }, diff --git a/test/fixtures/mock-release.js b/test/fixtures/mock-release.js index 0c308a62..9df552d8 100644 --- a/test/fixtures/mock-release.js +++ b/test/fixtures/mock-release.js @@ -11,7 +11,7 @@ const RECORD = 'NOCK_RECORD' in process.env ? true : undefined const REPO = 'npm/npm-cli-release-please' const BRANCH = 'template-oss-mock-testing-branch-do-not-delete' -const getPath = (t) => { +const getPath = t => { const fixtureName = relative(CWD, t.testdirName).split(`${sep}tap-testdir-`)[1] return { fixtureName: basename(fixtureName), @@ -19,7 +19,7 @@ const getPath = (t) => { } } -const setup = (t) => { +const setup = t => { const { fixtureName, fixturePath } = getPath(t) // name snapshots by the fixture name so they are all in separate files. this @@ -80,10 +80,7 @@ const releasePlease = async (t, { setup: s, ...opts } = {}) => { } } -const releaseManager = (t, { - cwd = t.testdir({ 'package.json': '{"name":"pkg"}' }), - ...opts -} = {}) => { +const releaseManager = (t, { cwd = t.testdir({ 'package.json': '{"name":"pkg"}' }), ...opts } = {}) => { const s = setup(t) const ReleaseManager = t.mock('../../lib/release/release-manager.js') return ReleaseManager.run({ diff --git a/test/fixtures/yml-merge.js b/test/fixtures/yml-merge.js index 26e891bd..adee0014 100644 --- a/test/fixtures/yml-merge.js +++ b/test/fixtures/yml-merge.js @@ -3,18 +3,20 @@ module.exports = { add: { 'target.yml': { file: 'source.yml', - parser: (p) => class extends p.YmlMerge { - key = 'key' - id = 'id' - }, + parser: p => + class extends p.YmlMerge { + key = 'key' + id = 'id' + }, }, 'clean-target.yml': { file: 'source.yml', clean: () => true, - parser: (p) => class extends p.YmlMerge { - key = 'key' - id = 'id' - }, + parser: p => + class extends p.YmlMerge { + key = 'key' + id = 'id' + }, }, }, }, diff --git a/test/index.js b/test/index.js index 5563ad00..e4098f0f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,18 +1,18 @@ const t = require('tap') const setup = require('./setup.js') -t.test('apply and check is ok', async (t) => { +t.test('apply and check is ok', async t => { const s = await setup(t, { ok: true }) t.same(await s.runAll(), []) }) -t.test('apply and check multiple is ok', async (t) => { +t.test('apply and check multiple is ok', async t => { const s = await setup(t, { ok: true }) t.same(await s.runAll(), []) t.same(await s.runAll(), []) }) -t.test('apply and check workspaces are ok', async (t) => { +t.test('apply and check workspaces are ok', async t => { const s = await setup(t, { ok: true, workspaces: { a: 'a', b: 'b', c: 'c' }, @@ -21,7 +21,7 @@ t.test('apply and check workspaces are ok', async (t) => { t.same(await s.runAll(), []) }) -t.test('empty content is ok', async (t) => { +t.test('empty content is ok', async t => { const s = await setup(t, { package: { templateOSS: { diff --git a/test/release/changelog.js b/test/release/changelog.js index 06030bca..e0083130 100644 --- a/test/release/changelog.js +++ b/test/release/changelog.js @@ -10,9 +10,7 @@ const mockGitHub = ({ commits, authors }) => ({ // simulate a bad sha passed in that doesnt return a commit acc[`_${c.sha}`] = null } else { - const author = i % 2 - ? { user: { login: 'username' } } - : { name: 'Name' } + const author = i % 2 ? { user: { login: 'username' } } : { name: 'Name' } acc[`_${c.sha}`] = { authors: { nodes: authors ? [author] : [] } } } } @@ -22,12 +20,14 @@ const mockGitHub = ({ commits, authors }) => ({ octokit: { rest: { repos: { - listPullRequestsAssociatedWithCommit: async (commit) => { + listPullRequestsAssociatedWithCommit: async commit => { if (commit.commit_sha === 'd') { return { - data: [{ - number: 50, - }], + data: [ + { + number: 50, + }, + ], } } }, @@ -40,32 +40,37 @@ const mockChangelog = async ({ shas = true, authors = true, previousTag = true, - commits: rawCommits = [{ - sha: 'a', - type: 'feat', - bareMessage: 'Hey now', - scope: 'bin', - }, { - sha: 'b', - type: 'feat', - notes: [{ title: 'BREAKING CHANGE', text: 'breaking' }], - bareMessage: 'b', - pullRequest: { - number: '100', + commits: rawCommits = [ + { + sha: 'a', + type: 'feat', + bareMessage: 'Hey now', + scope: 'bin', + }, + { + sha: 'b', + type: 'feat', + notes: [{ title: 'BREAKING CHANGE', text: 'breaking' }], + bareMessage: 'b', + pullRequest: { + number: '100', + }, + }, + { + sha: 'c', + type: 'deps', + bareMessage: 'test@1.2.3', }, - }, { - sha: 'c', - type: 'deps', - bareMessage: 'test@1.2.3', - }, { - sha: 'd', - type: 'fix', - bareMessage: 'this fixes it', - }], + { + sha: 'd', + type: 'fix', + bareMessage: 'this fixes it', + }, + ], } = {}) => { const commits = rawCommits .map(({ notes = [], ...rest }) => ({ notes, ...rest })) - .map(({ sha, ...rest }) => shas ? { sha, ...rest } : { ...rest }) + .map(({ sha, ...rest }) => (shas ? { sha, ...rest } : { ...rest })) const github = mockGitHub({ commits, authors }) const changelog = new ChangelogNotes(github) @@ -79,7 +84,7 @@ const mockChangelog = async ({ return notes .split('\n') - .map((l) => l.replace(/\d{4}-\d{2}-\d{2}/g, 'DATE')) + .map(l => l.replace(/\d{4}-\d{2}-\d{2}/g, 'DATE')) .filter(Boolean) } @@ -120,39 +125,45 @@ t.test('no tag/authors/shas', async t => { t.test('filters out multiple template oss commits', async t => { const changelog = await mockChangelog({ authors: false, - commits: [{ - sha: 'z', - type: 'fix', - bareMessage: 'just a fix', - }, { - sha: 'a', - type: 'chore', - bareMessage: 'postinstall for dependabot template-oss PR', - pullRequest: { - number: '100', + commits: [ + { + sha: 'z', + type: 'fix', + bareMessage: 'just a fix', }, - }, { - sha: 'b', - type: 'chore', - bareMessage: 'postinstall for dependabot template-oss PR', - pullRequest: { - number: '101', + { + sha: 'a', + type: 'chore', + bareMessage: 'postinstall for dependabot template-oss PR', + pullRequest: { + number: '100', + }, }, - }, { - sha: 'c', - type: 'chore', - bareMessage: 'bump @npmcli/template-oss from 1 to 2', - pullRequest: { - number: '101', + { + sha: 'b', + type: 'chore', + bareMessage: 'postinstall for dependabot template-oss PR', + pullRequest: { + number: '101', + }, }, - }, { - sha: 'd', - type: 'chore', - bareMessage: 'bump @npmcli/template-oss from 0 to 1', - pullRequest: { - number: '100', + { + sha: 'c', + type: 'chore', + bareMessage: 'bump @npmcli/template-oss from 1 to 2', + pullRequest: { + number: '101', + }, + }, + { + sha: 'd', + type: 'chore', + bareMessage: 'bump @npmcli/template-oss from 0 to 1', + pullRequest: { + number: '100', + }, }, - }], + ], }) t.strictSame(changelog, [ '## [1.0.0](https://github.com/npm/cli/compare/v0.1.0...v1.0.0) (DATE)', @@ -169,15 +180,18 @@ t.test('filters out multiple template oss commits', async t => { t.test('empty change log with only chore commits', async t => { const changelog = await mockChangelog({ authors: false, - commits: [{ - sha: 'a', - type: 'chore', - bareMessage: 'some chore', - }, { - sha: 'a', - type: 'chore', - bareMessage: 'another chore', - }], + commits: [ + { + sha: 'a', + type: 'chore', + bareMessage: 'some chore', + }, + { + sha: 'a', + type: 'chore', + bareMessage: 'another chore', + }, + ], }) t.strictSame(changelog, []) }) diff --git a/test/release/release-manager.js b/test/release/release-manager.js index 1da2a306..142fb591 100644 --- a/test/release/release-manager.js +++ b/test/release/release-manager.js @@ -8,13 +8,16 @@ t.test('init', async t => { t.rejects(ReleaseManager.run({})) t.rejects(ReleaseManager.run({ token: 'ok' })) t.rejects(ReleaseManager.run({ token: 'ok', repo: 'ok' })) - t.doesNotThrow(() => new ReleaseManager({ - token: 'ok', - repo: 'ok', - pr: 'ok', - silent: false, - defaultTag: 'latest', - })) + t.doesNotThrow( + () => + new ReleaseManager({ + token: 'ok', + repo: 'ok', + pr: 'ok', + silent: false, + defaultTag: 'latest', + }), + ) }) t.test('mock release manager', async t => { diff --git a/test/release/release-please.js b/test/release/release-please.js index c33431c1..1111dc00 100644 --- a/test/release/release-please.js +++ b/test/release/release-please.js @@ -10,17 +10,18 @@ t.test('init', async t => { await t.rejects(ReleasePlease.run({})) await t.rejects(ReleasePlease.run({ token: 'ok' })) await t.rejects(ReleasePlease.run({ token: 'ok', repo: 'ok' })) - await t.rejects(new ReleasePlease({ - token: 'ok', - repo: 'ok', - branch: 'ok', - defaultTag: 'ok', - }).init()) + await t.rejects( + new ReleasePlease({ + token: 'ok', + repo: 'ok', + branch: 'ok', + defaultTag: 'ok', + }).init(), + ) }) t.todo('cases', async t => { - const execRepo = (cmd, opts) => - execSync(cmd, { cwd: REPO_DIR, encoding: 'utf-8', ...opts }).trim() + const execRepo = (cmd, opts) => execSync(cmd, { cwd: REPO_DIR, encoding: 'utf-8', ...opts }).trim() const updateJSON = (p, fn) => { const file = resolve(REPO_DIR, p) @@ -29,7 +30,7 @@ t.todo('cases', async t => { } let init = false - const before = (s) => { + const before = s => { if (s.record) { execRepo('git pull') execRepo(`git reset --hard origin/${BRANCH}`) @@ -46,7 +47,7 @@ t.todo('cases', async t => { const matchPr = async (t, s, { flags, msg, prerelease }) => { if (s.record) { - updateJSON(join(REPO_DIR, 'release-please-config.json'), (d) => ({ + updateJSON(join(REPO_DIR, 'release-please-config.json'), d => ({ ...d, 'last-release-sha': execRepo('git log --grep="chore: release" --format=format:%H -n1'), 'release-search-depth': 7, diff --git a/test/setup.js b/test/setup.js index 33305b6f..dec4bf2d 100644 --- a/test/setup.js +++ b/test/setup.js @@ -9,7 +9,7 @@ const output = require('../lib/util/output.js') const CONTENT = require('..') const { name: NAME, version: VERSION } = require('../package.json') -const createPackageJson = (pkg) => ({ +const createPackageJson = pkg => ({ 'package.json': JSON.stringify(pkg, null, 2), }) @@ -25,37 +25,41 @@ const pkgWithName = (name, defName) => { } // minimum package.json for no errors -const okPackage = () => Object.entries(CONTENT.requiredPackages) - .reduce((acc, [location, deps]) => { - acc[location] = Object.fromEntries(deps.map((name) => { - const arg = npa(name) - return [arg.name, arg.fetchSpec === 'latest' ? '*' : arg.fetchSpec] - })) - return acc - }, { - engines: { - node: '^14.17.0 || ^16.13.0 || >=18.0.0', +const okPackage = () => + Object.entries(CONTENT.requiredPackages).reduce( + (acc, [location, deps]) => { + acc[location] = Object.fromEntries( + deps.map(name => { + const arg = npa(name) + return [arg.name, arg.fetchSpec === 'latest' ? '*' : arg.fetchSpec] + }), + ) + return acc }, - tap: { - 'nyc-arg': [ - '--exclude', - 'tap-snapshots/**', - ], + { + engines: { + node: '^14.17.0 || ^16.13.0 || >=18.0.0', + }, + tap: { + 'nyc-arg': ['--exclude', 'tap-snapshots/**'], + }, }, - }) + ) const setupRoot = async (t, root, mocks) => { const rootPath = (...p) => join(root, ...p) // fs methods for reading from the root - const rootFs = Object.fromEntries(Object.entries({ - readdir: fs.readdir, - readFile: (p) => fs.readFile(p, { encoding: 'utf-8' }), - writeFile: (p, d) => fs.writeFile(p, d, { encoding: 'utf-8' }), - appendFile: fs.appendFile, - stat: fs.stat, - unlink: fs.unlink, - }).map(([k, fn]) => [k, (p, ...rest) => fn(rootPath(p), ...rest)])) + const rootFs = Object.fromEntries( + Object.entries({ + readdir: fs.readdir, + readFile: p => fs.readFile(p, { encoding: 'utf-8' }), + writeFile: (p, d) => fs.writeFile(p, d, { encoding: 'utf-8' }), + appendFile: fs.appendFile, + stat: fs.stat, + unlink: fs.unlink, + }).map(([k, fn]) => [k, (p, ...rest) => fn(rootPath(p), ...rest)]), + ) // Returns a recurisve list of relative file // paths in the testdir root @@ -68,7 +72,7 @@ const setupRoot = async (t, root, mocks) => { continue } if ((await rootFs.stat(nextPath)).isDirectory()) { - paths.push(...await readdir(nextPath)) + paths.push(...(await readdir(nextPath))) } else { paths.push(nextPath) } @@ -80,7 +84,7 @@ const setupRoot = async (t, root, mocks) => { // paths and the values are the full contents const readdirSource = async (p = '') => { const files = await readdir(p) - const contents = await Promise.all(files.map((f) => rootFs.readFile(f))) + const contents = await Promise.all(files.map(f => rootFs.readFile(f))) return Object.fromEntries(files.map((f, i) => [f, contents[i]])) } @@ -92,9 +96,13 @@ const setupRoot = async (t, root, mocks) => { ...rootFs, readdirSource, readdir, - readJson: async (f) => JSON.parse(await rootFs.readFile(f)), + readJson: async f => JSON.parse(await rootFs.readFile(f)), writeJson: (p, d) => rootFs.writeFile(p, JSON.stringify(d, null, 2)), - exists: (...p) => fs.access(rootPath(...p)).then(() => true).catch(() => false), + exists: (...p) => + fs + .access(rootPath(...p)) + .then(() => true) + .catch(() => false), join: rootPath, apply: () => apply(root), check: () => check(root), @@ -102,18 +110,9 @@ const setupRoot = async (t, root, mocks) => { } } -const setup = async (t, { - package = {}, - workspaces = {}, - testdir = {}, - mocks = {}, - ok = false, -} = {}) => { +const setup = async (t, { package = {}, workspaces = {}, testdir = {}, mocks = {}, ok = false } = {}) => { const wsLookup = {} - const pkg = merge( - ok ? okPackage() : {}, - pkgWithName(package, 'testpkg') - ) + const pkg = merge(ok ? okPackage() : {}, pkgWithName(package, 'testpkg')) // convenience for passing in workspaces as an object // and getting those converted to a proper workspaces array @@ -125,10 +124,7 @@ const setup = async (t, { merge(testdir, { [wsDir]: {} }) for (const [wsBase, wsPkgName] of wsEntries) { - const wsPkg = merge( - pkgWithName(wsPkgName, wsBase), - ok ? okPackage() : {} - ) + const wsPkg = merge(pkgWithName(wsPkgName, wsBase), ok ? okPackage() : {}) const wsPath = posix.join(wsDir, wsBase) // obj to lookup workspaces by path in tests wsLookup[wsBase] = wsPath @@ -139,10 +135,7 @@ const setup = async (t, { // creates dir with a root package.json and // package.json files for each workspace - const root = t.testdir(merge( - createPackageJson(pkg), - testdir - )) + const root = t.testdir(merge(createPackageJson(pkg), testdir)) return { ...(await setupRoot(t, root, mocks)), @@ -152,7 +145,7 @@ const setup = async (t, { const setupGit = async (...args) => { const s = await setup(...args) - const git = (arg) => Git.spawn(arg.split(' '), { cwd: s.root }) + const git = arg => Git.spawn(arg.split(' '), { cwd: s.root }) const gca = async () => { await git('add -A .') @@ -170,19 +163,21 @@ const setupGit = async (...args) => { } } -const cleanSnapshot = (str) => str - .replace(resolve(), '{{ROOT}}') - .replace(/\\+/g, '/') - .replace(/\r\n/g, '\n') - .replace(new RegExp(`("version": "|${esc(NAME)}@)${esc(VERSION)}`, 'g'), '$1{{VERSION}}') +const cleanSnapshot = str => + str + .replace(resolve(), '{{ROOT}}') + .replace(/\\+/g, '/') + .replace(/\r\n/g, '\n') + .replace(new RegExp(`("version": "|${esc(NAME)}@)${esc(VERSION)}`, 'g'), '$1{{VERSION}}') const formatSnapshots = { - checks: (arr) => output(arr).trim(), - readdir: (arr) => arr.sort(localeCompare).join('\n').trim(), - readdirSource: (obj) => Object.entries(obj) - .sort((a, b) => localeCompare(a[0], b[0])) - .map(([file, content]) => [file, '='.repeat(40), content].join('\n').trim()) - .join('\n\n') - .trim(), + checks: arr => output(arr).trim(), + readdir: arr => arr.sort(localeCompare).join('\n').trim(), + readdirSource: obj => + Object.entries(obj) + .sort((a, b) => localeCompare(a[0], b[0])) + .map(([file, content]) => [file, '='.repeat(40), content].join('\n').trim()) + .join('\n\n') + .trim(), } module.exports = setup @@ -192,7 +187,7 @@ module.exports.pkgVersion = VERSION module.exports.clean = cleanSnapshot module.exports.format = formatSnapshots module.exports.okPackage = okPackage -module.exports.fixture = (f) => fs.readFile(resolve(__dirname, 'fixtures', f), 'utf-8') +module.exports.fixture = f => fs.readFile(resolve(__dirname, 'fixtures', f), 'utf-8') module.exports.log = (t, f = () => true) => { const cb = (...args) => f(...args) && console.error(...args) process.on('log', cb) diff --git a/test/util/has-package.js b/test/util/has-package.js index 08921091..df95ee80 100644 --- a/test/util/has-package.js +++ b/test/util/has-package.js @@ -27,13 +27,13 @@ const checks = [ [{ a: '^1.0.0' }, 'a@sometag', false], ] -checks.forEach((args) => { +checks.forEach(args => { const res = args.pop() const [pkg, spec, ...rest] = args t.equal(hasPackage({ dependencies: pkg }, spec, ...rest), res, `${JSON.stringify(pkg)}-${spec}`) }) -t.test('works with file urls', async (t) => { +t.test('works with file urls', async t => { const root = t.testdir({ nested: { 'package.json': JSON.stringify({ @@ -50,7 +50,6 @@ t.test('works with file urls', async (t) => { version: '5.0.1', }), }, - }, })