@npmcli/template-oss 4.18.1 → 4.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +15 -11
  2. package/bin/release-manager.js +6 -0
  3. package/lib/config.js +112 -136
  4. package/lib/content/{_job-matrix.yml → _job-matrix-yml.hbs} +1 -1
  5. package/lib/content/{_job-release-integration.yml → _job-release-integration-yml.hbs} +2 -2
  6. package/lib/content/{_job.yml → _job-yml.hbs} +1 -1
  7. package/lib/content/_step-node-yml.hbs +60 -0
  8. package/lib/content/_steps-setup-yml.hbs +6 -0
  9. package/lib/content/{audit.yml → audit-yml.hbs} +2 -2
  10. package/lib/content/{ci-release.yml → ci-release-yml.hbs} +7 -7
  11. package/lib/content/ci-yml.hbs +13 -0
  12. package/lib/content/{codeql-analysis.yml → codeql-analysis-yml.hbs} +1 -1
  13. package/lib/content/{eslintrc.js → eslintrc-js.hbs} +11 -1
  14. package/lib/content/{gitignore → gitignore.hbs} +2 -0
  15. package/lib/content/index.js +47 -42
  16. package/lib/content/{pkg.json → package-json.hbs} +8 -9
  17. package/lib/content/{post-dependabot.yml → post-dependabot-yml.hbs} +1 -1
  18. package/lib/content/{pull-request.yml → pull-request-yml.hbs} +1 -1
  19. package/lib/content/{release.yml → release-yml.hbs} +10 -10
  20. package/lib/content/tsconfig-json.hbs +17 -0
  21. package/lib/util/ci-versions.js +80 -0
  22. package/lib/util/files.js +29 -20
  23. package/lib/util/get-cmd-path.js +36 -0
  24. package/lib/util/git.js +6 -11
  25. package/lib/util/import-or-require.js +29 -0
  26. package/lib/util/merge.js +0 -1
  27. package/lib/util/parser.js +6 -1
  28. package/lib/util/path.js +13 -0
  29. package/lib/util/template.js +9 -6
  30. package/package.json +10 -10
  31. package/lib/content/_step-node.yml +0 -57
  32. package/lib/content/_steps-setup.yml +0 -6
  33. package/lib/content/ci.yml +0 -13
  34. package/lib/util/parse-ci-versions.js +0 -78
  35. /package/lib/content/{CODEOWNERS → CODEOWNERS.hbs} +0 -0
  36. /package/lib/content/{CODE_OF_CONDUCT.md → CODE_OF_CONDUCT-md.hbs} +0 -0
  37. /package/lib/content/{CONTRIBUTING.md → CONTRIBUTING-md.hbs} +0 -0
  38. /package/lib/content/{LICENSE.md → LICENSE-md.hbs} +0 -0
  39. /package/lib/content/{SECURITY.md → SECURITY-md.hbs} +0 -0
  40. /package/lib/content/{_on-ci.yml → _on-ci-yml.hbs} +0 -0
  41. /package/lib/content/{_step-audit.yml → _step-audit-yml.hbs} +0 -0
  42. /package/lib/content/{_step-checks.yml → _step-checks-yml.hbs} +0 -0
  43. /package/lib/content/{_step-deps.yml → _step-deps-yml.hbs} +0 -0
  44. /package/lib/content/{_step-git.yml → _step-git-yml.hbs} +0 -0
  45. /package/lib/content/{_step-lint.yml → _step-lint-yml.hbs} +0 -0
  46. /package/lib/content/{_step-test.yml → _step-test-yml.hbs} +0 -0
  47. /package/lib/content/{bug.yml → bug-yml.hbs} +0 -0
  48. /package/lib/content/{commitlintrc.js → commitlintrc-js.hbs} +0 -0
  49. /package/lib/content/{config.yml → config-yml.hbs} +0 -0
  50. /package/lib/content/{dependabot.yml → dependabot-yml.hbs} +0 -0
  51. /package/lib/content/{npmrc → npmrc.hbs} +0 -0
  52. /package/lib/content/{release-please-config.json → release-please-config-json.hbs} +0 -0
  53. /package/lib/content/{release-please-manifest.json → release-please-manifest-json.hbs} +0 -0
  54. /package/lib/content/{settings.yml → settings-yml.hbs} +0 -0
  55. /package/lib/content/{tap.json → tap-json.hbs} +0 -0
package/README.md CHANGED
@@ -3,7 +3,11 @@
3
3
  This module bundles the npm CLI team's basics for package development into a
4
4
  single devDependency.
5
5
 
6
- **CAUTION: THESE CHANGES WILL OVERWRITE ANY LOCAL FILES AND SETTINGS**
6
+ > [!WARNING]
7
+ > THESE CHANGES WILL OVERWRITE LOCAL FILES AND SETTINGS
8
+
9
+ > [!IMPORTANT]
10
+ > This package does not follow semantic versioning for its API. This package is designed to be installed with `--save-exact` and therefore will make breaking API changes outside of major versions, including `engines` narrowing. Major versions are reserved for breaking changes to files written to a repo by this package.
7
11
 
8
12
  ### Configuration
9
13
 
@@ -60,21 +64,21 @@ any of the same settings in the root.
60
64
  ### Content
61
65
 
62
66
  All the templated content for this repo lives in
63
- [`lib/content/`](./lib/content/). The `index.js`[./lib/content/index.js] file
67
+ [`lib/content/`](./lib/content/). The [`index.js`](./lib/content/index.js) file
64
68
  controls how and where this content is written.
65
69
 
66
70
  Content files can be overwritten or merged with the existing target file.
67
- Currently mergining is only supported for `package.json` files.
71
+ Merging is only supported for some types of files (ini, yaml, json, package.json)
68
72
 
69
73
  Each content file goes through the following pipeline:
70
74
 
71
75
  1. It is read from its source location
72
- 1. It is are templated using Handlebars with the variables from each packages's
73
- config (with some derived values generated in [`config.js`](./lib/config.js)
74
- 1. It is parsed based on its file extension in
76
+ 2. It is compiled using [Handlebars](https://handlebarsjs.com/) with the variables from each packages's
77
+ config (with some derived values generated in [`config.js`](./lib/config.js))
78
+ 3. It is parsed based on its file extension in
75
79
  [`parser.js`](./lib/util/parser.js)
76
- 1. Additional logic is applied by the parser
77
- 1. It is written to its target location
80
+ 4. Additional logic is applied by the parser
81
+ 5. It is written to its target location
78
82
 
79
83
  ### Usage
80
84
 
@@ -82,7 +86,7 @@ This package provides two bin scripts:
82
86
 
83
87
  #### `template-oss-check`
84
88
 
85
- This will check if any of the applied files different from the target content,
89
+ This will check if any of the applied files differ from the target content,
86
90
  or if any of the other associated checks fail. The diffs of each file or check
87
91
  will be reported with instructions on how to fix it.
88
92
 
@@ -92,7 +96,7 @@ This will write all source files to their target locations in the cwd. It will
92
96
  do nothing if `package.json#templateOSS.version` is the same as the version
93
97
  being run. This can be overridden by `--force`.
94
98
 
95
- This is the script that is run on `postinsall`.
99
+ This is the script that is run on `postinstall`.
96
100
 
97
101
  ### Extending
98
102
 
@@ -100,7 +104,7 @@ This is the script that is run on `postinsall`.
100
104
 
101
105
  This directory is where all the logic for applying files lives. It should be
102
106
  possible to add new files without modifying anything in this directory. To add a
103
- file, add the templated file to `lib/content/$FILENAME` and add entry for it in
107
+ file, add the templated file to `lib/content/$FILENAME` and an entry for it in
104
108
  `lib/content/index.js` depending on where and when it should be written (root vs
105
109
  workspace, repo vs module, add vs remove, etc).
106
110
 
@@ -50,6 +50,12 @@ const MANUAL_PUBLISH_STEPS = `
50
50
  `
51
51
 
52
52
  const AUTO_PUBLISH_STEPS = `
53
+ 1. Approve this PR
54
+
55
+ \`\`\`sh
56
+ gh pr review <PR-NUMBER> -R {NWO} --approve
57
+ \`\`\`
58
+
53
59
  1. Merge release PR :rotating_light: Merging this will auto publish :rotating_light:
54
60
 
55
61
  \`\`\`sh
package/lib/config.js CHANGED
@@ -1,42 +1,31 @@
1
- const { relative, dirname, join, extname, posix, win32 } = require('path')
2
- const { defaults, pick, omit, uniq } = require('lodash')
1
+ const { relative, dirname, join, extname } = require('path')
2
+ const { defaults, defaultsDeep, pick, omit, uniq, isPlainObject } = require('lodash')
3
3
  const semver = require('semver')
4
- const parseCIVersions = require('./util/parse-ci-versions.js')
4
+ const ciVersions = require('./util/ci-versions.js')
5
5
  const parseDependabot = require('./util/dependabot.js')
6
6
  const git = require('./util/git.js')
7
7
  const gitignore = require('./util/gitignore.js')
8
- const { mergeWithArrays } = require('./util/merge.js')
8
+ const { mergeWithCustomizers, customizers } = require('./util/merge.js')
9
9
  const { FILE_KEYS, parseConfig: parseFiles, getAddedFiles, mergeFiles } = require('./util/files.js')
10
+ const template = require('./util/template.js')
11
+ const getCmdPath = require('./util/get-cmd-path.js')
12
+ const importOrRequire = require('./util/import-or-require.js')
13
+ const { makePosix, deglob, posixDir, posixGlob } = require('./util/path.js')
14
+ const { name: NAME, version: LATEST_VERSION } = require('../package.json')
10
15
 
11
16
  const CONFIG_KEY = 'templateOSS'
12
- const getPkgConfig = (pkg) => pkg[CONFIG_KEY] || {}
13
-
14
- const { name: NAME, version: LATEST_VERSION } = require('../package.json')
15
- const { minimatch } = require('minimatch')
16
17
  const MERGE_KEYS = [...FILE_KEYS, 'defaultContent', 'content']
17
18
  const DEFAULT_CONTENT = require.resolve(NAME)
19
+ const getPkgConfig = (pkg) => pkg[CONFIG_KEY] || {}
18
20
 
19
- const merge = mergeWithArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths')
20
-
21
- const makePosix = (v) => v.split(win32.sep).join(posix.sep)
22
- const deglob = (v) => makePosix(v).replace(/[/*]+$/, '')
23
- const posixDir = (v) => `${v === '.' ? '' : deglob(v).replace(/\/$/, '')}${posix.sep}`
24
- const posixGlob = (str) => `${posixDir(str)}**`
25
-
26
- const getCmdPath = (key, { rootConfig, defaultConfig, isRoot, pkg, rootPkg }) => {
27
- // Make a path relative from a workspace to the root if we are in a workspace
28
- const wsToRoot = (p) => isRoot ? p : makePosix(join(relative(pkg.path, rootPkg.path), p))
29
-
30
- const rootPath = rootConfig[key]
31
- const defaultPath = defaultConfig[key]
32
- const isLocal = rootPath && rootPath !== defaultPath
33
-
34
- return {
35
- isLocal,
36
- root: !isLocal ? defaultPath : `node ${rootPath}`,
37
- local: !isLocal ? defaultPath : `node ${wsToRoot(rootPath)}`,
21
+ const merge = mergeWithCustomizers(
22
+ customizers.mergeArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths'),
23
+ (value, srcValue, key) => {
24
+ if (key === 'ciVersions' && (Array.isArray(srcValue) || isPlainObject(srcValue))) {
25
+ return { ...ciVersions.parse(value), ...ciVersions.parse(srcValue) }
26
+ }
38
27
  }
39
- }
28
+ )
40
29
 
41
30
  const mergeConfigs = (...configs) => {
42
31
  const mergedConfig = merge(...configs.map(c => pick(c, MERGE_KEYS)))
@@ -50,37 +39,33 @@ const mergeConfigs = (...configs) => {
50
39
  })
51
40
  }
52
41
 
53
- const readContentPath = (path) => {
42
+ const readContentPath = async (path) => {
54
43
  if (!path) {
55
44
  return {}
56
45
  }
57
46
 
58
- let content = {}
59
47
  const index = extname(path) === '.js' ? path : join(path, 'index.js')
60
48
  const dir = dirname(index)
61
-
62
- try {
63
- content = require(index)
64
- } catch {
65
- // its ok if this fails since the content dir
66
- // might only be to provide other files. the
67
- // index.js is optional
68
- }
49
+ const content = await importOrRequire(index)
69
50
 
70
51
  return { content, dir }
71
52
  }
72
53
 
73
- const getConfig = (path, rawConfig) => {
74
- const config = omit(readContentPath(path).content, FILE_KEYS)
54
+ const getConfig = async (path, rawConfig) => {
55
+ const { content } = await readContentPath(path)
56
+ const config = omit(content, FILE_KEYS)
75
57
  return merge(config, rawConfig ? omit(rawConfig, FILE_KEYS) : {})
76
58
  }
77
59
 
78
- const getFiles = (path, rawConfig) => {
79
- const { content, dir } = readContentPath(path)
60
+ const getFiles = async (path, rawConfig, templateSettings) => {
61
+ const { content, dir } = await readContentPath(path)
80
62
  if (!dir) {
81
63
  return []
82
64
  }
83
- return [parseFiles(pick(content, FILE_KEYS), dir, pick(rawConfig, FILE_KEYS)), dir]
65
+ return [
66
+ parseFiles(pick(content, FILE_KEYS), dir, pick(rawConfig, FILE_KEYS), templateSettings),
67
+ dir,
68
+ ]
84
69
  }
85
70
 
86
71
  const getFullConfig = async ({
@@ -105,43 +90,18 @@ const getFullConfig = async ({
105
90
  // These config items are merged betweent the root and child workspaces and only come from
106
91
  // the package.json because they can be used to read configs from other the content directories
107
92
  const mergedConfig = mergeConfigs(rootPkg.config, pkg.config)
108
-
109
- const defaultConfig = getConfig(DEFAULT_CONTENT)
110
- const [defaultFiles, defaultDir] = getFiles(DEFAULT_CONTENT, mergedConfig)
93
+ const defaultConfig = await getConfig(DEFAULT_CONTENT)
111
94
  const useDefault = mergedConfig.defaultContent && defaultConfig
112
95
 
113
- const rootConfig = getConfig(rootPkg.config.content, rootPkg.config)
114
- const [rootFiles, rootDir] = getFiles(rootPkg.config.content, mergedConfig)
96
+ const rootConfig = await getConfig(rootPkg.config.content, rootPkg.config)
115
97
 
116
98
  // The content config only gets set from the package we are in, it doesn't inherit
117
99
  // anything from the root
118
100
  const rootPkgConfig = merge(useDefault, rootConfig)
119
- const pkgConfig = merge(useDefault, getConfig(pkg.config.content, pkg.config))
120
- const [pkgFiles, pkgDir] = getFiles(mergedConfig.content, mergedConfig)
101
+ const pkgConfig = merge(useDefault, await getConfig(pkg.config.content, pkg.config))
121
102
 
122
- // Files get merged in from the default content (that template-oss provides) as well
123
- // as any content paths provided from the root or the workspace
124
- const fileDirs = uniq([useDefault && defaultDir, rootDir, pkgDir].filter(Boolean))
125
- const files = mergeFiles(useDefault && defaultFiles, rootFiles, pkgFiles)
126
- const repoFiles = isRoot ? files.rootRepo : files.workspaceRepo
127
- const moduleFiles = isRoot ? files.rootModule : files.workspaceModule
128
-
129
- const allowRootDirs = [
130
- // Allways allow module files in root or workspaces
131
- ...getAddedFiles(moduleFiles),
132
- ...isRoot ? [
133
- // in the root allow all repo files
134
- ...getAddedFiles(repoFiles),
135
- // and allow all workspace repo level files in the root
136
- ...pkgs
137
- .filter(p => p.path !== rootPkg.path && p.config.workspaceRepo !== false)
138
- .flatMap(() => getAddedFiles(files.workspaceRepo)),
139
- ] : [],
140
- ]
141
-
142
- // root only configs
143
- const npmPath = getCmdPath('npm', { rootConfig, defaultConfig, isRoot, pkg, rootPkg })
144
- const npxPath = getCmdPath('npx', { rootConfig, defaultConfig, isRoot, pkg, rootPkg })
103
+ const npmPath = getCmdPath('npm', { pkgConfig, rootConfig, isRoot, pkg, rootPkg })
104
+ const npxPath = getCmdPath('npx', { pkgConfig, rootConfig, isRoot, pkg, rootPkg })
145
105
 
146
106
  // these are written to ci yml files so it needs to always use posix
147
107
  const pkgPath = makePosix(relative(rootPkg.path, pkg.path)) || '.'
@@ -157,9 +117,14 @@ const getFullConfig = async ({
157
117
 
158
118
  const branches = uniq([...pkgConfig.branches ?? [], pkgConfig.releaseBranch]).filter(Boolean)
159
119
  const gitBranches = await git.getBranches(rootPkg.path, branches)
160
- const currentBranch = await git.currentBranch(rootPkg.path)
161
- const isReleaseBranch = currentBranch ? minimatch(currentBranch, pkgConfig.releaseBranch) : false
162
120
  const defaultBranch = await git.defaultBranch(rootPkg.path) ?? 'main'
121
+ const isReleaseBranch = !!pkgConfig.backport
122
+ const publishTag = isReleaseBranch ? `next-${pkgConfig.backport}` : 'latest'
123
+ const releaseBranch = isReleaseBranch
124
+ ? pkgConfig.releaseBranch.replace(/\*/g, pkgConfig.backport)
125
+ : defaultBranch
126
+
127
+ const esm = pkg.pkgJson?.type === 'module' || !!pkgConfig.typescript || !!pkgConfig.esm
163
128
 
164
129
  // all derived keys
165
130
  const derived = {
@@ -179,25 +144,17 @@ const getFullConfig = async ({
179
144
  // controls whether we are in a monorepo with any public workspaces
180
145
  isMonoPublic: isMono && !!publicPkgs.filter(p => p.path !== rootPkg.path).length,
181
146
  // git
182
- defaultBranch,
183
- baseBranch: isReleaseBranch ? currentBranch : defaultBranch,
184
147
  branches: gitBranches.branches,
185
148
  branchPatterns: gitBranches.patterns,
186
149
  isReleaseBranch,
187
- // dependabot
150
+ releaseBranch,
151
+ publishTag,
188
152
  dependabot: parseDependabot(pkgConfig, defaultConfig, gitBranches.branches),
189
- // repo
153
+ // paths
190
154
  repoDir: rootPkg.path,
191
- repoFiles,
192
- applyRepo: !!repoFiles,
193
- // module
194
155
  moduleDir: pkg.path,
195
- moduleFiles,
196
- applyModule: !!moduleFiles,
197
- // package
198
156
  pkgName: pkg.pkgJson.name,
199
157
  pkgNameFs: pkg.pkgJson.name.replace(/\//g, '-').replace(/@/g, ''),
200
- // paths
201
158
  pkgPath,
202
159
  pkgDir: posixDir(pkgPath),
203
160
  pkgGlob: posixGlob(pkgPath),
@@ -205,6 +162,12 @@ const getFullConfig = async ({
205
162
  allFlags: isMono ? '-ws -iwr --if-present' : '',
206
163
  workspacePaths,
207
164
  workspaceGlobs: workspacePaths.map(posixGlob),
165
+ // type
166
+ esm,
167
+ cjsExt: esm ? 'cjs' : 'js',
168
+ deleteJsExt: esm ? 'js' : 'cjs',
169
+ // tap
170
+ tap18: semver.coerce(pkg.pkgJson?.devDependencies?.tap)?.major === 18,
208
171
  // booleans to control application of updates
209
172
  isForce,
210
173
  isDogFood,
@@ -218,20 +181,8 @@ const getFullConfig = async ({
218
181
  // lockfiles are only present at the root, so this only should be set for
219
182
  // all workspaces based on the root
220
183
  lockfile: rootPkgConfig.lockfile,
221
- // gitignore
222
- ignorePaths: [
223
- ...gitignore.sort([
224
- ...gitignore.allowRootDir(allowRootDirs),
225
- ...isRoot && pkgConfig.lockfile ? ['!/package-lock.json'] : [],
226
- ...(pkgConfig.allowPaths || []).map((p) => `!${p}`),
227
- ...(pkgConfig.ignorePaths || []),
228
- ]),
229
- // these cant be sorted since they rely on order
230
- // to allow a previously ignored directoy
231
- ...isRoot
232
- ? gitignore.allowDir(wsPkgs.map((p) => makePosix(relative(rootPkg.path, p.path))))
233
- : [],
234
- ],
184
+ // ci versions / engines
185
+ ciVersions: ciVersions.get(pkg.pkgJson.engines?.node, pkgConfig),
235
186
  // needs update if we are dogfooding this repo, with force argv, or its
236
187
  // behind the current version
237
188
  needsUpdate: isForce || isDogFood || !isLatest,
@@ -239,42 +190,22 @@ const getFullConfig = async ({
239
190
  __NAME__: NAME,
240
191
  __CONFIG_KEY__: CONFIG_KEY,
241
192
  __VERSION__: LATEST_VERSION,
242
- __PARTIAL_DIRS__: fileDirs,
243
193
  }
244
194
 
245
- if (pkgConfig.ciVersions) {
246
- let versions = pkgConfig.ciVersions
247
- if (versions === 'latest' || (Array.isArray(versions) && versions.includes('latest'))) {
248
- const { ciVersions } = [isWorkspace ? rootPkgConfig : {}, defaultConfig]
249
- .find(c => Array.isArray(c.ciVersions))
250
- const defaultLatest = ciVersions[ciVersions.length - 1]
251
- versions = [].concat(versions).map(v => v === 'latest' ? defaultLatest : v)
252
- }
253
-
254
- const { targets, engines } = parseCIVersions(versions)
255
-
256
- // get just a list of the target versions (not ranges)
257
- // these are used for the node version when doing engines checks
258
- // since we want to test in the lowest version of each major
259
- let targetVersions = targets.filter(t => semver.valid(t))
260
- // if the versions are all ranges then convert them to the lower bound of each range
261
- if (!targetVersions.length) {
262
- targetVersions = targets.filter(t => semver.validRange(t)).map(t => {
263
- return new semver.Range(t).set[0][0].semver.version
264
- })
265
- }
266
-
267
- derived.ciVersions = targets
268
- derived.baseCiVersions = targetVersions
269
- derived.engines = pkgConfig.engines || engines
195
+ if (!pkgConfig.eslint && Array.isArray(pkgConfig.requiredPackages?.devDependencies)) {
196
+ pkgConfig.requiredPackages.devDependencies =
197
+ pkgConfig.requiredPackages.devDependencies.filter(p => !p.includes('eslint'))
270
198
  }
271
199
 
272
- if (!pkgConfig.eslint) {
273
- derived.ignorePaths = derived.ignorePaths.filter(p => !p.includes('eslint'))
274
- if (Array.isArray(pkgConfig.requiredPackages?.devDependencies)) {
275
- pkgConfig.requiredPackages.devDependencies =
276
- pkgConfig.requiredPackages.devDependencies.filter(p => !p.includes('eslint'))
277
- }
200
+ if (pkgConfig.typescript) {
201
+ defaultsDeep(pkgConfig, { allowPaths: [], requiredPackages: { devDependencies: [] } })
202
+ pkgConfig.distPaths = null
203
+ pkgConfig.allowPaths.push('/src/')
204
+ pkgConfig.requiredPackages.devDependencies.push(
205
+ 'typescript',
206
+ 'tshy',
207
+ '@typescript-eslint/parser'
208
+ )
278
209
  }
279
210
 
280
211
  const gitUrl = await git.getUrl(rootPkg.path)
@@ -286,10 +217,55 @@ const getFullConfig = async ({
286
217
  }
287
218
  }
288
219
 
289
- return {
290
- ...pkgConfig,
291
- ...derived,
292
- }
220
+ const fullConfig = { ...pkgConfig, ...derived }
221
+
222
+ // files, come at the end since file names can be based on config
223
+ const [defaultFiles, defaultDir] = await getFiles(DEFAULT_CONTENT, mergedConfig, fullConfig)
224
+ const [rootFiles, rootDir] = await getFiles(rootPkg.config.content, mergedConfig, fullConfig)
225
+ const [pkgFiles, pkgDir] = await getFiles(mergedConfig.content, mergedConfig, fullConfig)
226
+
227
+ // Files get merged in from the default content (that template-oss provides) as well
228
+ // as any content paths provided from the root or the workspace
229
+ const fileDirs = uniq([useDefault && defaultDir, rootDir, pkgDir].filter(Boolean))
230
+ const files = mergeFiles(useDefault && defaultFiles, rootFiles, pkgFiles)
231
+ const repoFiles = isRoot ? files.rootRepo : files.workspaceRepo
232
+ const moduleFiles = isRoot ? files.rootModule : files.workspaceModule
233
+
234
+ Object.assign(fullConfig, {
235
+ repoFiles,
236
+ moduleFiles,
237
+ applyRepo: !!repoFiles,
238
+ applyModule: !!moduleFiles,
239
+ __PARTIAL_DIRS__: fileDirs,
240
+ // gitignore, these use the full config so need to come at the very end
241
+ ignorePaths: [
242
+ ...gitignore.sort([
243
+ ...gitignore.allowRootDir([
244
+ // Allways allow module files in root or workspaces
245
+ ...getAddedFiles(moduleFiles).map(s => template(s, fullConfig)),
246
+ ...isRoot ? [
247
+ // in the root allow all repo files
248
+ ...getAddedFiles(repoFiles).map(s => template(s, fullConfig)),
249
+ // and allow all workspace repo level files in the root
250
+ ...pkgs
251
+ .filter(p => p.path !== rootPkg.path && p.config.workspaceRepo !== false)
252
+ .flatMap(() => getAddedFiles(files.workspaceRepo)),
253
+ ] : [],
254
+ ]),
255
+ ...isRoot && pkgConfig.lockfile ? ['!/package-lock.json'] : [],
256
+ ...(pkgConfig.allowPaths || []).map((p) => `!${p}`),
257
+ ...(pkgConfig.distPaths || []).map((p) => `!/${p}`),
258
+ ...(pkgConfig.ignorePaths || []),
259
+ ]),
260
+ // these cant be sorted since they rely on order
261
+ // to allow a previously ignored directoy
262
+ ...isRoot
263
+ ? gitignore.allowDir(wsPkgs.map((p) => makePosix(relative(rootPkg.path, p.path))))
264
+ : [],
265
+ ].filter(p => !pkgConfig.eslint ? !p.includes('eslint') : true),
266
+ })
267
+
268
+ return fullConfig
293
269
  }
294
270
 
295
271
  module.exports = getFullConfig
@@ -26,4 +26,4 @@ defaults:
26
26
  run:
27
27
  shell: $\{{ matrix.platform.shell }}
28
28
  steps:
29
- {{> stepsSetup jobIsMatrix=true }}
29
+ {{> stepsSetupYml jobIsMatrix=true }}
@@ -22,14 +22,14 @@ steps:
22
22
  - name: Publish
23
23
  env:
24
24
  PUBLISH_TOKEN: $\{{ secrets.PUBLISH_TOKEN }}
25
- run: npm publish --provenance
25
+ run: npm publish --provenance --tag={{ publishTag }}
26
26
  {{else}}
27
27
  runs-on: ubuntu-latest
28
28
  defaults:
29
29
  run:
30
30
  shell: bash
31
31
  steps:
32
- {{> stepNode lockfile=false }}
32
+ {{> stepNodeYml lockfile=false }}
33
33
  - name: View in Registry
34
34
  run: |
35
35
  EXIT_CODE=0
@@ -5,4 +5,4 @@ defaults:
5
5
  run:
6
6
  shell: bash
7
7
  steps:
8
- {{> stepsSetup }}
8
+ {{> stepsSetupYml }}
@@ -0,0 +1,60 @@
1
+ - name: Setup Node
2
+ uses: actions/setup-node@v3
3
+ id: node
4
+ with:
5
+ node-version: {{#if jobIsMatrix}}$\{{ matrix.node-version }}{{else}}{{ last ciVersions }}{{/if}}
6
+ check-latest: contains({{#if jobIsMatrix}}matrix.node-version{{else}}'{{ last ciVersions }}'{{/if}}, '.x')
7
+ {{#if lockfile}}
8
+ cache: npm
9
+ {{/if}}
10
+
11
+ {{#if updateNpm}}
12
+ {{#if jobIsMatrix}}
13
+ # node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
14
+ - name: Update Windows npm
15
+ if: |
16
+ matrix.platform.os == 'windows-latest' && (
17
+ startsWith(steps.node.outputs.node-version, 'v10.') ||
18
+ startsWith(steps.node.outputs.node-version, 'v12.') ||
19
+ startsWith(steps.node.outputs.node-version, 'v14.')
20
+ )
21
+ run: |
22
+ curl -sO https://registry.npmjs.org/npm/-/npm-7.5.4.tgz
23
+ tar xf npm-7.5.4.tgz
24
+ cd package
25
+ node lib/npm.js install --no-fund --no-audit -g ..\npm-7.5.4.tgz
26
+ cd ..
27
+ rmdir /s /q package
28
+ {{/if}}
29
+
30
+ - name: Install Latest npm
31
+ shell: bash
32
+ env:
33
+ NODE_VERSION: $\{{ steps.node.outputs.node-version }}
34
+ run: |
35
+ MATCH=""
36
+ SPECS=("latest" "next-10" "next-9" "next-8" "next-7" "next-6")
37
+
38
+ echo "node@$NODE_VERSION"
39
+
40
+ for SPEC in ${SPECS[@]}; do
41
+ ENGINES=$(npm view npm@$SPEC --json | jq -r '.engines.node')
42
+ echo "Checking if node@$NODE_VERSION satisfies npm@$SPEC ($ENGINES)"
43
+
44
+ if npx semver -r "$ENGINES" "$NODE_VERSION" > /dev/null; then
45
+ MATCH=$SPEC
46
+ echo "Found compatible version: npm@$MATCH"
47
+ break
48
+ fi
49
+ done
50
+
51
+ if [ -z $MATCH ]; then
52
+ echo "Could not find a compatible version of npm for node@$NODE_VERSION"
53
+ exit 1
54
+ fi
55
+
56
+ npm i --prefer-online --no-fund --no-audit -g npm@$MATCH
57
+
58
+ - name: npm Version
59
+ run: npm -v
60
+ {{/if}}
@@ -0,0 +1,6 @@
1
+ {{~#if jobCheck}}{{> stepChecksYml }}{{/if}}
2
+ {{~#unless jobSkipSetup}}
3
+ {{> stepGitYml }}
4
+ {{> stepNodeYml }}
5
+ {{> stepDepsYml }}
6
+ {{/unless}}
@@ -8,5 +8,5 @@ on:
8
8
 
9
9
  jobs:
10
10
  audit:
11
- {{> job jobName="Audit Dependencies" jobDepFlags="--package-lock" }}
12
- {{> stepAudit }}
11
+ {{> jobYml jobName="Audit Dependencies" jobDepFlags="--package-lock" }}
12
+ {{> stepAuditYml }}
@@ -7,7 +7,7 @@ on:
7
7
  ref:
8
8
  required: true
9
9
  type: string
10
- default: {{ baseBranch }}
10
+ default: {{ releaseBranch }}
11
11
  workflow_call:
12
12
  inputs:
13
13
  ref:
@@ -19,19 +19,19 @@ on:
19
19
 
20
20
  jobs:
21
21
  lint-all:
22
- {{> job
22
+ {{> jobYml
23
23
  jobName="Lint All"
24
24
  jobCheck=(obj sha="inputs.check-sha")
25
25
  jobCheckout=(obj ref="${{ inputs.ref }}")
26
26
  }}
27
- {{> stepLint jobRunFlags=allFlags }}
28
- {{> stepChecks jobCheck=true }}
27
+ {{> stepLintYml jobRunFlags=allFlags }}
28
+ {{> stepChecksYml jobCheck=true }}
29
29
 
30
30
  test-all:
31
- {{> jobMatrix
31
+ {{> jobMatrixYml
32
32
  jobName="Test All"
33
33
  jobCheck=(obj sha="inputs.check-sha")
34
34
  jobCheckout=(obj ref="${{ inputs.ref }}")
35
35
  }}
36
- {{> stepTest jobRunFlags=allFlags }}
37
- {{> stepChecks jobCheck=true }}
36
+ {{> stepTestYml jobRunFlags=allFlags }}
37
+ {{> stepChecksYml jobCheck=true }}
@@ -0,0 +1,13 @@
1
+ name: CI {{~#if isWorkspace}} - {{ pkgName }}{{/if}}
2
+
3
+ on:
4
+ {{> onCiYml }}
5
+
6
+ jobs:
7
+ lint:
8
+ {{> jobYml jobName="Lint" }}
9
+ {{> stepLintYml jobRunFlags=pkgFlags }}
10
+
11
+ test:
12
+ {{> jobMatrixYml jobName="Test" }}
13
+ {{> stepTestYml jobRunFlags=pkgFlags }}
@@ -24,7 +24,7 @@ jobs:
24
24
  contents: read
25
25
  security-events: write
26
26
  steps:
27
- {{> stepGit }}
27
+ {{> stepGitYml }}
28
28
  - name: Initialize CodeQL
29
29
  uses: github/codeql-action/init@v2
30
30
  with:
@@ -8,12 +8,22 @@ const localConfigs = readdir(__dirname)
8
8
 
9
9
  module.exports = {
10
10
  root: true,
11
- {{#if workspaceGlobs}}
12
11
  ignorePatterns: [
12
+ 'tap-testdir*/',
13
13
  {{#each workspaceGlobs}}
14
14
  '{{ . }}',
15
15
  {{/each}}
16
+ {{#if typescript}}
17
+ 'dist/',
18
+ {{/if}}
16
19
  ],
20
+ {{#if typescript}}
21
+ parser: '@typescript-eslint/parser',
22
+ settings: {
23
+ 'import/resolver': {
24
+ typescript: {},
25
+ },
26
+ },
17
27
  {{/if}}
18
28
  extends: [
19
29
  '@npmcli',
@@ -1,5 +1,7 @@
1
1
  # ignore everything in the root
2
2
  /*
3
+ # transient test directories
4
+ tap-testdir*/
3
5
 
4
6
  # keep these
5
7
  {{#each ignorePaths}}