diff --git a/README.md b/README.md index c05ea287..4ab53d5a 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ These fields will be set in the project's `package.json`: lint: `eslint '**/*.js'`, postlint: 'npm-template-check', lintfix: 'npm run lint -- --fix', + 'template-copy': 'npm-template-copy --force', preversion: 'npm test', postversion: 'npm publish', prepublishOnly: 'git push origin --follow-tags', @@ -99,6 +100,11 @@ your new file. The object keys are destination paths, and values are source. `npm-template-check` is run by `postlint` and will error if the `package.json` is not configured properly, with steps to run to correct any problems. +### Manual copy + +Template files will be copied automatically when `template-oss` is updated. +You can force an update with `npm run template-copy`. + #### Extending Add any unwanted packages to `unwantedPackages` in `lib/check.js`. Currently diff --git a/lib/config.js b/lib/config.js index cf6e8478..d378ec2e 100644 --- a/lib/config.js +++ b/lib/config.js @@ -7,6 +7,7 @@ const defaultConfig = { applyRootModuleFiles: true, workspaces: [], paths: [], + force: false, } module.exports = async (root) => { @@ -44,5 +45,7 @@ module.exports = async (root) => { config.paths.push(root) + config.force = process.argv.indexOf('--force') !== -1 + return config } diff --git a/lib/postinstall/update-package.js b/lib/postinstall/update-package.js index cf04eff4..7e222166 100644 --- a/lib/postinstall/update-package.js +++ b/lib/postinstall/update-package.js @@ -11,6 +11,7 @@ const changes = { scripts: { lint: `eslint '**/*.js'`, postlint: 'npm-template-check', + 'template-copy': 'npm-template-copy --force', lintfix: 'npm run lint -- --fix', preversion: 'npm test', postversion: 'npm publish', @@ -26,6 +27,7 @@ const changes = { const patchPackage = async (path, root, config) => { const pkg = await PackageJson.load(path) + config = config || {} // If we are running this on itself, we always run the script. // We also don't set templateVersion in package.json because @@ -38,7 +40,9 @@ const patchPackage = async (path, root, config) => { // if the target package.json has a templateVersion field matching our own // current version, we return false here so the postinstall script knows to // exit early instead of running everything again - if (currentVersion === TEMPLATE_VERSION && !isDogfood) { + if (!config.force + && currentVersion === TEMPLATE_VERSION + && !isDogfood) { return false } diff --git a/package.json b/package.json index 62d8e210..3c13f13c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "templated files used in npm CLI team oss projects", "main": "lib/index.js", "bin": { - "npm-template-check": "bin/npm-template-check.js" + "npm-template-check": "bin/npm-template-check.js", + "npm-template-copy": "bin/postinstall.js" }, "scripts": { "lint": "eslint '**/*.js'", @@ -16,7 +17,8 @@ "prepublishOnly": "git push origin --follow-tags", "preversion": "npm test", "snap": "tap", - "test": "tap" + "test": "tap", + "template-copy": "npm-template-copy --force" }, "repository": { "type": "git", diff --git a/tap-snapshots/test/postlint/check-package.js.test.cjs b/tap-snapshots/test/postlint/check-package.js.test.cjs index 4243e0b5..b130d542 100644 --- a/tap-snapshots/test/postlint/check-package.js.test.cjs +++ b/tap-snapshots/test/postlint/check-package.js.test.cjs @@ -12,7 +12,7 @@ Array [ The following package.json fields are incorrect: Field: "author" Expected: "GitHub Inc." Found: "Bob" Field: "files" Expected: ["bin","lib"] Found: undefined - Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined + Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","template-copy":"npm-template-copy --force","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined Field: "engines" Expected: {"node":"^12.13.0 || ^14.15.0 || >=16"} Found: undefined ), "solution": "npm rm @npmcli/template-oss && npm i -D @npmcli/template-oss", @@ -29,6 +29,7 @@ Array [ Field: "files" Expected: ["bin","lib"] Found: undefined Field: "scripts.lint" Expected: "eslint '**/*.js'" Found: undefined Field: "scripts.postlint" Expected: "npm-template-check" Found: undefined + Field: "scripts.template-copy" Expected: "npm-template-copy --force" Found: undefined Field: "scripts.lintfix" Expected: "npm run lint -- --fix" Found: undefined Field: "scripts.preversion" Expected: "npm test" Found: undefined Field: "scripts.postversion" Expected: "npm publish" Found: undefined @@ -50,7 +51,7 @@ Array [ The following package.json fields are incorrect: Field: "author" Expected: "GitHub Inc." Found: undefined Field: "files" Expected: ["bin","lib"] Found: undefined - Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined + Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","template-copy":"npm-template-copy --force","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined Field: "engines" Expected: {"node":"^12.13.0 || ^14.15.0 || >=16"} Found: undefined ), "solution": "npm rm @npmcli/template-oss && npm i -D @npmcli/template-oss", @@ -65,7 +66,7 @@ Array [ The following package.json fields are incorrect: Field: "author" Expected: "GitHub Inc." Found: undefined Field: "files" Expected: ["bin","lib"] Found: undefined - Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined + Field: "scripts" Expected: {"lint":"eslint '**/*.js'","postlint":"npm-template-check","template-copy":"npm-template-copy --force","lintfix":"npm run lint -- --fix","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","snap":"tap","test":"tap","posttest":"npm run lint"} Found: undefined Field: "engines" Expected: {"node":"^12.13.0 || ^14.15.0 || >=16"} Found: undefined ), "solution": "npm rm @npmcli/template-oss && npm i -D @npmcli/template-oss", diff --git a/test/postinstall/update-package.js b/test/postinstall/update-package.js index 1268cb0b..68d73409 100644 --- a/test/postinstall/update-package.js +++ b/test/postinstall/update-package.js @@ -61,6 +61,32 @@ t.test('returns false when templateVersion matches own version', async (t) => { t.notMatch(JSON.parse(contents), patchPackage.changes, 'changes were NOT applied') }) +t.test('returns true when templateVersion matches own version when forced', async (t) => { + const pkg = { + name: '@npmcli/foo', + templateOSS: { + version: TEMPLATE_VERSION, + }, + version: '1.0.0', + author: 'someone else', + files: [], + license: 'MIT', + } + + const project = t.testdir({ + 'package.json': JSON.stringify(pkg, null, 2), + }) + + const needsAction = await patchPackage(project, undefined, { force: true }) + t.equal(needsAction, true, 'returned true') + + const contents = await fs.readFile(join(project, 'package.json'), { + encoding: 'utf8', + }) + const parsed = JSON.parse(contents) + t.match(parsed, patchPackage.changes, 'all changes were applied') +}) + t.test('doesnt set templateVersion on own repo', async (t) => { const pkg = { name: TEMPLATE_NAME,