@npmcli/template-oss 4.17.0 → 4.18.1
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.
- package/lib/config.js +18 -2
- package/lib/content/_on-ci.yml +1 -1
- package/lib/content/_step-node.yml +38 -12
- package/lib/content/ci-release.yml +1 -1
- package/lib/content/codeql-analysis.yml +2 -2
- package/lib/content/dependabot.yml +11 -2
- package/lib/content/index.js +6 -11
- package/lib/content/pull-request.yml +1 -1
- package/lib/content/release.yml +1 -1
- package/lib/content/settings.yml +1 -0
- package/lib/util/dependabot.js +27 -0
- package/lib/util/git.js +82 -0
- package/package.json +1 -1
- package/lib/util/get-git-url.js +0 -26
package/lib/config.js
CHANGED
|
@@ -2,7 +2,8 @@ const { relative, dirname, join, extname, posix, win32 } = require('path')
|
|
|
2
2
|
const { defaults, pick, omit, uniq } = require('lodash')
|
|
3
3
|
const semver = require('semver')
|
|
4
4
|
const parseCIVersions = require('./util/parse-ci-versions.js')
|
|
5
|
-
const
|
|
5
|
+
const parseDependabot = require('./util/dependabot.js')
|
|
6
|
+
const git = require('./util/git.js')
|
|
6
7
|
const gitignore = require('./util/gitignore.js')
|
|
7
8
|
const { mergeWithArrays } = require('./util/merge.js')
|
|
8
9
|
const { FILE_KEYS, parseConfig: parseFiles, getAddedFiles, mergeFiles } = require('./util/files.js')
|
|
@@ -11,6 +12,7 @@ const CONFIG_KEY = 'templateOSS'
|
|
|
11
12
|
const getPkgConfig = (pkg) => pkg[CONFIG_KEY] || {}
|
|
12
13
|
|
|
13
14
|
const { name: NAME, version: LATEST_VERSION } = require('../package.json')
|
|
15
|
+
const { minimatch } = require('minimatch')
|
|
14
16
|
const MERGE_KEYS = [...FILE_KEYS, 'defaultContent', 'content']
|
|
15
17
|
const DEFAULT_CONTENT = require.resolve(NAME)
|
|
16
18
|
|
|
@@ -153,6 +155,12 @@ const getFullConfig = async ({
|
|
|
153
155
|
const publicPkgs = pkgs.filter(p => !p.pkgJson.private)
|
|
154
156
|
const allPrivate = pkgs.every(p => p.pkgJson.private)
|
|
155
157
|
|
|
158
|
+
const branches = uniq([...pkgConfig.branches ?? [], pkgConfig.releaseBranch]).filter(Boolean)
|
|
159
|
+
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
|
+
const defaultBranch = await git.defaultBranch(rootPkg.path) ?? 'main'
|
|
163
|
+
|
|
156
164
|
// all derived keys
|
|
157
165
|
const derived = {
|
|
158
166
|
isRoot,
|
|
@@ -170,6 +178,14 @@ const getFullConfig = async ({
|
|
|
170
178
|
allPrivate,
|
|
171
179
|
// controls whether we are in a monorepo with any public workspaces
|
|
172
180
|
isMonoPublic: isMono && !!publicPkgs.filter(p => p.path !== rootPkg.path).length,
|
|
181
|
+
// git
|
|
182
|
+
defaultBranch,
|
|
183
|
+
baseBranch: isReleaseBranch ? currentBranch : defaultBranch,
|
|
184
|
+
branches: gitBranches.branches,
|
|
185
|
+
branchPatterns: gitBranches.patterns,
|
|
186
|
+
isReleaseBranch,
|
|
187
|
+
// dependabot
|
|
188
|
+
dependabot: parseDependabot(pkgConfig, defaultConfig, gitBranches.branches),
|
|
173
189
|
// repo
|
|
174
190
|
repoDir: rootPkg.path,
|
|
175
191
|
repoFiles,
|
|
@@ -261,7 +277,7 @@ const getFullConfig = async ({
|
|
|
261
277
|
}
|
|
262
278
|
}
|
|
263
279
|
|
|
264
|
-
const gitUrl = await
|
|
280
|
+
const gitUrl = await git.getUrl(rootPkg.path)
|
|
265
281
|
if (gitUrl) {
|
|
266
282
|
derived.repository = {
|
|
267
283
|
type: 'git',
|
package/lib/content/_on-ci.yml
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
- name: Setup Node
|
|
2
2
|
uses: actions/setup-node@v3
|
|
3
|
+
id: node
|
|
3
4
|
with:
|
|
4
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')
|
|
5
7
|
{{#if lockfile}}
|
|
6
8
|
cache: npm
|
|
7
9
|
{{/if}}
|
|
10
|
+
|
|
8
11
|
{{#if updateNpm}}
|
|
9
|
-
|
|
12
|
+
# node 10/12/14 ship with npm@6, which is known to fail when updating itself in windows
|
|
10
13
|
- name: Update Windows npm
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
if: |
|
|
15
|
+
matrix.platform.os == 'windows-latest' && (
|
|
16
|
+
startsWith(steps.node.outputs.node-version, 'v10.') || startsWith(steps.node.outputs.node-version, 'v12.') || startsWith(steps.node.outputs.node-version, 'v14.')
|
|
17
|
+
)
|
|
13
18
|
run: |
|
|
14
19
|
curl -sO https://registry.npmjs.org/npm/-/npm-7.5.4.tgz
|
|
15
20
|
tar xf npm-7.5.4.tgz
|
|
@@ -17,15 +22,36 @@
|
|
|
17
22
|
node lib/npm.js install --no-fund --no-audit -g ..\npm-7.5.4.tgz
|
|
18
23
|
cd ..
|
|
19
24
|
rmdir /s /q package
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
|
|
26
|
+
# Start on Node 10 because we dont test on anything lower
|
|
27
|
+
- name: Install npm@7 on Node 10
|
|
28
|
+
shell: bash
|
|
29
|
+
if: startsWith(steps.node.outputs.node-version, 'v10.')
|
|
30
|
+
id: npm-7
|
|
31
|
+
run: |
|
|
32
|
+
npm i --prefer-online --no-fund --no-audit -g npm@7
|
|
33
|
+
echo "updated=true" >> "$GITHUB_OUTPUT"
|
|
34
|
+
|
|
35
|
+
- name: Install npm@8 on Node 12
|
|
36
|
+
shell: bash
|
|
37
|
+
if: startsWith(steps.node.outputs.node-version, 'v12.')
|
|
38
|
+
id: npm-8
|
|
39
|
+
run: |
|
|
40
|
+
npm i --prefer-online --no-fund --no-audit -g npm@8
|
|
41
|
+
echo "updated=true" >> "$GITHUB_OUTPUT"
|
|
42
|
+
|
|
43
|
+
- name: Install npm@9 on Node 14/16/18.0
|
|
44
|
+
shell: bash
|
|
45
|
+
if: startsWith(steps.node.outputs.node-version, 'v14.') || startsWith(steps.node.outputs.node-version, 'v16.') || startsWith(steps.node.outputs.node-version, 'v18.0.')
|
|
46
|
+
id: npm-9
|
|
47
|
+
run: |
|
|
48
|
+
npm i --prefer-online --no-fund --no-audit -g npm@9
|
|
49
|
+
echo "updated=true" >> "$GITHUB_OUTPUT"
|
|
50
|
+
|
|
51
|
+
- name: Install npm@latest on Node
|
|
52
|
+
if: $\{{ !(steps.npm-7.outputs.updated || steps.npm-8.outputs.updated || steps.npm-9.outputs.updated) }}
|
|
53
|
+
run: npm i --prefer-online --no-fund --no-audit -g npm@latest
|
|
54
|
+
|
|
29
55
|
- name: npm Version
|
|
30
56
|
run: npm -v
|
|
31
57
|
{{/if}}
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
version: 2
|
|
2
2
|
|
|
3
3
|
updates:
|
|
4
|
+
{{#each dependabot}}
|
|
4
5
|
- package-ecosystem: npm
|
|
5
|
-
directory:
|
|
6
|
+
directory: /
|
|
6
7
|
schedule:
|
|
7
8
|
interval: daily
|
|
9
|
+
target-branch: "{{ branch }}"
|
|
8
10
|
allow:
|
|
9
11
|
- dependency-type: direct
|
|
10
|
-
|
|
12
|
+
{{#each allowNames }}
|
|
13
|
+
dependency-name: "{{ . }}"
|
|
14
|
+
{{/each}}
|
|
15
|
+
versioning-strategy: {{ strategy }}
|
|
11
16
|
commit-message:
|
|
12
17
|
prefix: deps
|
|
13
18
|
prefix-development: chore
|
|
14
19
|
labels:
|
|
15
20
|
- "Dependencies"
|
|
21
|
+
{{#each labels }}
|
|
22
|
+
- "{{ . }}"
|
|
23
|
+
{{/each}}
|
|
24
|
+
{{/each}}
|
package/lib/content/index.js
CHANGED
|
@@ -38,14 +38,6 @@ const sharedRootAdd = (name) => ({
|
|
|
38
38
|
'.github/dependabot.yml': {
|
|
39
39
|
file: 'dependabot.yml',
|
|
40
40
|
filter: (p) => p.config.dependabot,
|
|
41
|
-
clean: (p) => p.config.isRoot,
|
|
42
|
-
// dependabot takes a single top level config file. this parser
|
|
43
|
-
// will run for all configured packages and each one will have
|
|
44
|
-
// its item replaced in the updates array based on the directory
|
|
45
|
-
parser: (p) => class extends p.YmlMerge {
|
|
46
|
-
key = 'updates'
|
|
47
|
-
id = 'directory'
|
|
48
|
-
},
|
|
49
41
|
},
|
|
50
42
|
'.github/workflows/post-dependabot.yml': {
|
|
51
43
|
file: 'post-dependabot.yml',
|
|
@@ -53,6 +45,7 @@ const sharedRootAdd = (name) => ({
|
|
|
53
45
|
},
|
|
54
46
|
'.github/settings.yml': {
|
|
55
47
|
file: 'settings.yml',
|
|
48
|
+
filter: (p) => !p.config.isReleaseBranch,
|
|
56
49
|
},
|
|
57
50
|
})
|
|
58
51
|
|
|
@@ -60,6 +53,9 @@ const sharedRootRm = () => ({
|
|
|
60
53
|
'.github/workflows/pull-request.yml': {
|
|
61
54
|
filter: (p) => p.config.allPrivate,
|
|
62
55
|
},
|
|
56
|
+
'.github/settings.yml': {
|
|
57
|
+
filter: (p) => p.config.isReleaseBranch,
|
|
58
|
+
},
|
|
63
59
|
})
|
|
64
60
|
|
|
65
61
|
// Changes applied to the root of the repo
|
|
@@ -139,8 +135,8 @@ module.exports = {
|
|
|
139
135
|
workspaceModule,
|
|
140
136
|
windowsCI: true,
|
|
141
137
|
macCI: true,
|
|
142
|
-
branches: ['main', 'latest'
|
|
143
|
-
|
|
138
|
+
branches: ['main', 'latest'],
|
|
139
|
+
releaseBranch: 'release/v*',
|
|
144
140
|
distPaths: [
|
|
145
141
|
'bin/',
|
|
146
142
|
'lib/',
|
|
@@ -167,7 +163,6 @@ module.exports = {
|
|
|
167
163
|
publish: false,
|
|
168
164
|
npm: 'npm',
|
|
169
165
|
npx: 'npx',
|
|
170
|
-
npmSpec: 'latest',
|
|
171
166
|
updateNpm: true,
|
|
172
167
|
dependabot: 'increase-if-necessary',
|
|
173
168
|
unwantedPackages: [
|
package/lib/content/release.yml
CHANGED
package/lib/content/settings.yml
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { name: NAME } = require('../../package.json')
|
|
2
|
+
const { minimatch } = require('minimatch')
|
|
3
|
+
|
|
4
|
+
const parseDependabotConfig = (v) => typeof v === 'string' ? { strategy: v } : (v ?? {})
|
|
5
|
+
|
|
6
|
+
module.exports = (config, defaultConfig, branches) => {
|
|
7
|
+
const { dependabot } = config
|
|
8
|
+
const { dependabot: defaultDependabot } = defaultConfig
|
|
9
|
+
|
|
10
|
+
if (!dependabot) {
|
|
11
|
+
return false
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return branches
|
|
15
|
+
.filter((b) => dependabot[b] !== false)
|
|
16
|
+
.map(branch => {
|
|
17
|
+
const isReleaseBranch = minimatch(branch, config.releaseBranch)
|
|
18
|
+
return {
|
|
19
|
+
branch,
|
|
20
|
+
allowNames: isReleaseBranch ? [NAME] : [],
|
|
21
|
+
labels: isReleaseBranch ? ['Backport', branch] : [],
|
|
22
|
+
...parseDependabotConfig(defaultDependabot),
|
|
23
|
+
...parseDependabotConfig(dependabot),
|
|
24
|
+
...parseDependabotConfig(dependabot[branch]),
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}
|
package/lib/util/git.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const hgi = require('hosted-git-info')
|
|
2
|
+
const git = require('@npmcli/git')
|
|
3
|
+
const { minimatch } = require('minimatch')
|
|
4
|
+
|
|
5
|
+
const cache = new Map()
|
|
6
|
+
|
|
7
|
+
const tryGit = async (path, ...args) => {
|
|
8
|
+
if (!await git.is({ cwd: path })) {
|
|
9
|
+
throw new Error('no git')
|
|
10
|
+
}
|
|
11
|
+
const key = [path, ...args].join(',')
|
|
12
|
+
if (cache.has(key)) {
|
|
13
|
+
return cache.get(key)
|
|
14
|
+
}
|
|
15
|
+
const res = git.spawn(args, { cwd: path }).then(r => r.stdout.trim())
|
|
16
|
+
cache.set(key, res)
|
|
17
|
+
return res
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// parse a repo from a git origin into a format
|
|
21
|
+
// for a package.json#repository object
|
|
22
|
+
const getUrl = async (path) => {
|
|
23
|
+
try {
|
|
24
|
+
const urlStr = await tryGit(path, 'remote', 'get-url', 'origin')
|
|
25
|
+
const { domain, user, project } = hgi.fromUrl(urlStr)
|
|
26
|
+
const url = new URL(`https://${domain}`)
|
|
27
|
+
url.pathname = `/${user}/${project}.git`
|
|
28
|
+
return url.toString()
|
|
29
|
+
} catch {
|
|
30
|
+
// errors are ignored
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const getBranches = async (path, branchPatterns) => {
|
|
35
|
+
let matchingBranches = new Set()
|
|
36
|
+
let matchingPatterns = new Set()
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const res = await tryGit(path, 'ls-remote', '--heads', 'origin').then(r => r.split('\n'))
|
|
40
|
+
const remotes = res.map((h) => h.match(/refs\/heads\/(.*)$/)).filter(Boolean).map(h => h[1])
|
|
41
|
+
for (const branch of remotes) {
|
|
42
|
+
for (const pattern of branchPatterns) {
|
|
43
|
+
if (minimatch(branch, pattern)) {
|
|
44
|
+
matchingBranches.add(branch)
|
|
45
|
+
matchingPatterns.add(pattern)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
matchingBranches = new Set(branchPatterns.filter(b => !b.includes('*')))
|
|
51
|
+
matchingPatterns = new Set(branchPatterns)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
branches: [...matchingBranches],
|
|
56
|
+
patterns: [...matchingPatterns],
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const defaultBranch = async (path) => {
|
|
61
|
+
try {
|
|
62
|
+
const remotes = await tryGit(path, 'remote', 'show', 'origin')
|
|
63
|
+
return remotes.match(/HEAD branch: (.*)$/m)?.[1]
|
|
64
|
+
} catch {
|
|
65
|
+
// ignore errors
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const currentBranch = async (path) => {
|
|
70
|
+
try {
|
|
71
|
+
return await tryGit(path, 'rev-parse', '--abbrev-ref', 'HEAD')
|
|
72
|
+
} catch {
|
|
73
|
+
// ignore errors
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
getUrl,
|
|
79
|
+
getBranches,
|
|
80
|
+
defaultBranch,
|
|
81
|
+
currentBranch,
|
|
82
|
+
}
|
package/package.json
CHANGED
package/lib/util/get-git-url.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const hgi = require('hosted-git-info')
|
|
2
|
-
const git = require('@npmcli/git')
|
|
3
|
-
|
|
4
|
-
// parse a repo from a git origin into a format
|
|
5
|
-
// for a package.json#repository object
|
|
6
|
-
const getRepo = async (path) => {
|
|
7
|
-
if (!await git.is({ cwd: path })) {
|
|
8
|
-
return
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const res = await git.spawn([
|
|
13
|
-
'remote',
|
|
14
|
-
'get-url',
|
|
15
|
-
'origin',
|
|
16
|
-
], { cwd: path })
|
|
17
|
-
const { domain, user, project } = hgi.fromUrl(res.stdout.trim())
|
|
18
|
-
const url = new URL(`https://${domain}`)
|
|
19
|
-
url.pathname = `/${user}/${project}.git`
|
|
20
|
-
return url.toString()
|
|
21
|
-
} catch {
|
|
22
|
-
// errors are ignored
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = getRepo
|