Skip to content

Commit caf393c

Browse files
committed
feat: add dependabot configuration for workspaces
1 parent e43ee70 commit caf393c

30 files changed

+659
-192
lines changed

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version: 2
44

55
updates:
66
- package-ecosystem: npm
7-
directory: "/"
7+
directory: /
88
schedule:
99
interval: daily
1010
allow:

.github/workflows/ci.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ name: CI
55
on:
66
workflow_dispatch:
77
pull_request:
8-
branches:
9-
- '*'
108
push:
119
branches:
1210
- main

.github/workflows/post-dependabot.yml

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ name: Post Dependabot Actions
44

55
on: pull_request
66

7-
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
87
permissions:
98
contents: write
109

@@ -29,15 +28,51 @@ jobs:
2928
- run: npm i --ignore-scripts --no-audit --no-fund
3029
- name: Dependabot metadata
3130
id: metadata
32-
uses: dependabot/fetch-metadata@v1.1.1
31+
uses: dependabot/fetch-metadata@v1
3332
with:
34-
github-token: "${{ secrets.GITHUB_TOKEN }}"
35-
- name: Apply @npmcli/template-oss changes and lint
33+
github-token: ${{ secrets.GITHUB_TOKEN }}
34+
35+
- name: Get command flags
3636
if: contains(steps.metadata.outputs.dependency-names, '@npmcli/template-oss')
37+
id: flags
38+
run: |
39+
if [[ "${{steps.metadata.outputs.directory}}" == "/" ]]; then
40+
echo "::set-output name=workspace::-iwr"
41+
else
42+
echo "::set-output name=workspace::-w ${{ steps.metadata.outputs.directory }}"
43+
fi
44+
45+
- name: Apply changes
46+
if: steps.flags.outputs.workspace
47+
id: apply
48+
run: |
49+
npm run template-oss-apply ${{steps.flags.outputs.workspace}}
50+
if [[ `git status --porcelain` ]]; then
51+
echo "::set-output name=changes::true"
52+
fi
53+
54+
- name: Push all changes
55+
if: steps.apply.outputs.changes
56+
id: push
57+
continue-on-error: true
3758
env:
3859
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3960
run: |
40-
npm run template-oss-apply
4161
git commit -am "chore: postinstall for dependabot template-oss PR"
4262
git push
43-
npm run lint
63+
64+
- name: Push all except workflows
65+
if: steps.push.outcome == 'failure'
66+
env:
67+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68+
run: |
69+
git reset HEAD~
70+
git checkout HEAD -- .github/workflows/
71+
git clean -fd .github/workflows/
72+
git commit -am "chore: postinstall for dependabot template-oss PR"
73+
git push
74+
75+
- name: Verify changes
76+
if: steps.apply.outputs.changes
77+
run: |
78+
npm exec --offline ${{steps.flags.outputs.workspace}} -- template-oss-check

lib/config.js

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ const DEFAULT_CONTENT = require.resolve(NAME)
1515

1616
const merge = withArrays('branches', 'distPaths', 'allowPaths', 'ignorePaths')
1717

18-
const makePosix = (str) => str.split(win32.sep).join(posix.sep)
18+
const makePosix = (v) => v.split(win32.sep).join(posix.sep)
19+
const deglob = (v) => makePosix(v).replace(/[/*]+$/, '')
20+
const posixDir = (v) => `${v === '.' ? '' : deglob(v).replace(/\/$/, '')}${posix.sep}`
21+
const posixGlob = (str) => `${posixDir(str)}**`
1922

2023
const getCmdPath = (key, { rootConfig, defaultConfig, isRoot, path, root }) => {
2124
// Make a path relative from a workspace to the root if we are in a workspace
@@ -78,27 +81,27 @@ const getFiles = (path, rawConfig) => {
7881
}
7982

8083
const getFullConfig = async ({
84+
// the path to the root of the repo
8185
root,
86+
// the path to the package being operated on
87+
// this is the same as root when operating on the root
8288
path,
83-
pkg,
89+
// the full contents of the package.json for this package
90+
pkgJson,
91+
// an array of all package info {pkgJson,path,config}[]
8492
pkgs,
93+
// an array of all workspaces in this repo
8594
workspaces,
95+
// the config from the package.json in the root
8696
rootConfig: _rootConfig,
97+
// the config from the package.json being operated on
8798
pkgConfig: _pkgConfig,
8899
}) => {
89100
const isRoot = root === path
90-
const isRootMono = isRoot && workspaces.length > 0
91101
const isLatest = _pkgConfig.version === LATEST_VERSION
92-
const isDogFood = pkg.name === NAME
102+
const isDogFood = pkgJson.name === NAME
93103
const isForce = process.argv.includes('--force')
94104

95-
// this is written to ci yml files so it needs to always use posix
96-
const pkgRelPath = makePosix(relative(root, path))
97-
98-
const workspacePkgs = pkgs.filter((p) => p.path !== path)
99-
const workspaceDirs = isRootMono && workspaces.map((p) => makePosix(relative(root, p)))
100-
const workspaceGlobs = isRootMono && pkg.workspaces.map(p => p.replace(/[/*]+$/, ''))
101-
102105
// These config items are merged betweent the root and child workspaces and only come from
103106
// the package.json because they can be used to read configs from other the content directories
104107
const mergedConfig = mergeConfigs(_rootConfig, _pkgConfig)
@@ -112,6 +115,7 @@ const getFullConfig = async ({
112115

113116
// The content config only gets set from the package we are in, it doesn't inherit
114117
// anything from the root
118+
const rootPkgConfig = merge(useDefault, rootConfig)
115119
const pkgConfig = merge(useDefault, getConfig(_pkgConfig.content, _pkgConfig))
116120
const [pkgFiles, pkgDir] = getFiles(mergedConfig.content, mergedConfig)
117121

@@ -128,16 +132,24 @@ const getFullConfig = async ({
128132
...isRoot ? [
129133
// in the root allow all repo files
130134
...getAddedFiles(repoFiles),
131-
// and allow all workspace repo level files
132-
...workspacePkgs.filter(p => p.config.workspaceRepo !== false).flatMap((p) =>
133-
getAddedFiles(files.workspaceRepo)
134-
),
135+
// and allow all workspace repo level files in the root
136+
...pkgs
137+
.filter(p => p.path !== root && p.config.workspaceRepo !== false)
138+
.flatMap(() => getAddedFiles(files.workspaceRepo)),
135139
] : [],
136140
]
137141

142+
// root only configs
138143
const npmPath = getCmdPath('npm', { rootConfig, defaultConfig, isRoot, path, root })
139144
const npxPath = getCmdPath('npx', { rootConfig, defaultConfig, isRoot, path, root })
140145

146+
// these are written to ci yml files so it needs to always use posix
147+
const pkgPath = makePosix(relative(root, path)) || '.'
148+
149+
// we use the raw paths from the package.json workspaces as ignore patterns in
150+
// some cases. the workspaces passed in have already been run through map workspaces
151+
const workspacePaths = (pkgJson.workspaces || []).map(deglob)
152+
141153
// all derived keys
142154
const derived = {
143155
isRoot,
@@ -147,8 +159,8 @@ const getFullConfig = async ({
147159
// For these cases it is helpful to know if we are in a
148160
// monorepo since template-oss might be used only for
149161
// workspaces and not the root or vice versa.
150-
isRootMono,
151-
isMono: isRootMono || !isRoot,
162+
isRootMono: isRoot && !!workspaces.length,
163+
isMono: !!workspaces.length,
152164
// repo
153165
repoDir: root,
154166
repoFiles,
@@ -158,13 +170,14 @@ const getFullConfig = async ({
158170
moduleFiles,
159171
applyModule: !!moduleFiles,
160172
// package
161-
pkgName: pkg.name,
162-
pkgNameFs: pkg.name.replace(/\//g, '-').replace(/@/g, ''),
163-
pkgRelPath: pkgRelPath,
164-
pkgPrivate: !!pkg.private,
165-
pkgPublic: !pkg.private,
166-
workspaces: workspaceDirs,
167-
workspaceGlobs,
173+
pkgName: pkgJson.name,
174+
pkgNameFs: pkgJson.name.replace(/\//g, '-').replace(/@/g, ''),
175+
// paths
176+
pkgPath,
177+
pkgDir: posixDir(pkgPath),
178+
pkgGlob: posixGlob(pkgPath),
179+
workspacePaths,
180+
workspaceGlobs: workspacePaths.map(posixGlob),
168181
// booleans to control application of updates
169182
isForce,
170183
isDogFood,
@@ -175,6 +188,9 @@ const getFullConfig = async ({
175188
rootNpmPath: npmPath.root,
176189
localNpmPath: npmPath.local,
177190
rootNpxPath: npxPath.root,
191+
// lockfiles are only present at the root, so this only should be set for
192+
// all workspaces based on the root
193+
lockfile: rootPkgConfig.lockfile,
178194
// gitignore
179195
ignorePaths: [
180196
...gitignore.sort([
@@ -185,7 +201,7 @@ const getFullConfig = async ({
185201
]),
186202
// these cant be sorted since they rely on order
187203
// to allow a previously ignored directoy
188-
...gitignore.allowDir(workspaceDirs || []),
204+
...isRoot ? gitignore.allowDir(workspaces.map((p) => makePosix(relative(root, p)))) : [],
189205
],
190206
// needs update if we are dogfooding this repo, with force argv, or its
191207
// behind the current version
@@ -210,7 +226,7 @@ const getFullConfig = async ({
210226
derived.repository = {
211227
type: 'git',
212228
url: gitUrl,
213-
...(pkgRelPath ? { directory: pkgRelPath } : {}),
229+
...(!isRoot ? { directory: pkgPath } : {}),
214230
}
215231
}
216232

lib/content/_setup-ci-on.yml

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
11
workflow_dispatch:
22
pull_request:
3-
branches:
4-
- '*'
5-
{{#if pkgRelPath}}
3+
{{#if isWorkspace}}
64
paths:
7-
- {{pkgRelPath}}/**
5+
- {{pkgGlob}}
86
{{/if}}
9-
{{#if workspaceGlobs}}
7+
{{#if isRootMono}}
108
paths-ignore:
119
{{#each workspaceGlobs}}
12-
- {{.}}/**
10+
- {{.}}
1311
{{/each}}
1412
{{/if}}
1513
push:
1614
branches:
1715
{{#each branches}}
1816
- {{.}}
1917
{{/each}}
20-
{{#if pkgRelPath}}
18+
{{#if isWorkspace}}
2119
paths:
22-
- {{pkgRelPath}}/**
20+
- {{pkgGlob}}
2321
{{/if}}
24-
{{#if workspaceGlobs}}
22+
{{# if isRootMono}}
2523
paths-ignore:
2624
{{#each workspaceGlobs}}
27-
- {{.}}/**
25+
- {{.}}
2826
{{/each}}
2927
{{/if}}
3028
schedule:

lib/content/_setup-deps.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
- run: {{rootNpmPath}} i --ignore-scripts --no-audit --no-fund {{~#if flags}} {{flags}}{{/if}}
1+
- name: Install Dependencies
2+
run: {{rootNpmPath}} i --ignore-scripts --no-audit --no-fund {{~#if flags}} {{flags}}{{/if}}

lib/content/_setup-git.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
- uses: actions/checkout@v3
1+
- name: Checkout
2+
uses: actions/checkout@v3
23
{{#if checkout}}
34
with:
45
{{#each checkout}}

lib/content/_setup-node.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
- name: Setup Node {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{last ciVersions}}{{/if}}
12
- uses: actions/setup-node@v3
23
with:
3-
node-version: {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{#each ciVersions}}{{#if @last}}{{.}}{{/if}}{{/each}}{{/if}}
4+
node-version: {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{last ciVersions}}{{/if}}
45
{{#if lockfile}}
56
cache: npm
67
{{/if}}
@@ -16,15 +17,16 @@
1617
node lib/npm.js install --no-fund --no-audit -g ..\npm-7.5.4.tgz
1718
cd ..
1819
rmdir /s /q package
19-
- name: Update npm to 7
20+
- name: npm@7
2021
# If we do test on npm 10 it needs npm7
2122
if: startsWith(matrix.node-version, '10.')
2223
run: npm i --prefer-online --no-fund --no-audit -g npm@7
23-
- name: Update npm to latest
24+
- name: npm@latest
2425
if: $\{{ !startsWith(matrix.node-version, '10.') }}
2526
{{else}}
26-
- name: Update npm to latest
27+
- name: npm@latest
2728
{{/if}}
2829
run: npm i --prefer-online --no-fund --no-audit -g npm@latest
29-
- run: npm -v
30+
- name: npm Version
31+
run: npm -v
3032
{{/if}}

lib/content/audit.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ on:
88

99
jobs:
1010
audit:
11+
name: Audit
1112
{{> setupJob flags="--package-lock"}}
12-
- run: {{rootNpmPath}} audit
13+
- name: npm audit
14+
run: {{rootNpmPath}} audit

lib/content/ci.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ on:
55

66
jobs:
77
lint:
8+
name: Lint
89
{{> setupJob }}
9-
- run: {{rootNpmPath}} run lint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
10+
- name: npm run lint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
11+
run: {{rootNpmPath}} run lint --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
12+
- name: npm run postlint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
13+
run: {{rootNpmPath}} run postlint --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
1014

1115
test:
16+
name: Test
1217
{{> setupJobMatrix }}
13-
- name: add tap problem matcher
18+
- name: Add tap Problem Matcher
1419
run: echo "::add-matcher::.github/matchers/tap.json"
15-
- run: {{rootNpmPath}} test --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
20+
- name: npm test {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
21+
run: {{rootNpmPath}} test --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}

lib/content/commitlintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
22
extends: ['@commitlint/config-conventional'],
33
rules: {
4-
'type-enum': [2, 'always', [{{#each changelogTypes}}'{{type}}'{{#unless @last}}, {{/unless}}{{/each}}]],
4+
'type-enum': [2, 'always', [{{{join (quote (pluck changelogTypes "type"))}}}]],
55
'header-max-length': [2, 'always', 80],
66
'subject-case': [0, 'always', ['lower-case', 'sentence-case', 'start-case']],
77
},

lib/content/dependabot.yml

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,14 @@ version: 2
22

33
updates:
44
- package-ecosystem: npm
5-
directory: "/"
5+
directory: {{pkgDir}}
66
schedule:
77
interval: daily
88
allow:
99
- dependency-type: direct
10-
versioning-strategy: increase-if-necessary
10+
versioning-strategy: {{dependabot}}
1111
commit-message:
1212
prefix: deps
1313
prefix-development: chore
1414
labels:
1515
- "Dependencies"
16-
17-
{{#if workspaces}}
18-
{{#each workspaces}}
19-
- package-ecosystem: npm
20-
directory: "{{.}}/"
21-
schedule:
22-
interval: daily
23-
allow:
24-
- dependency-type: direct
25-
versioning-strategy: increase-if-necessary
26-
commit-message:
27-
prefix: deps
28-
prefix-development: chore
29-
labels:
30-
- "Dependencies"
31-
32-
{{/each}}
33-
{{/if}}

lib/content/eslintrc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ const localConfigs = readdir(__dirname)
88

99
module.exports = {
1010
root: true,
11-
{{#if isRootMono}}
11+
{{#if workspaceGlobs}}
1212
ignorePatterns: [
13-
{{#each workspaces}}
13+
{{#each workspaceGlobs}}
1414
'{{.}}',
1515
{{/each}}
1616
],

0 commit comments

Comments
 (0)