Skip to content

Commit

Permalink
feat: add dependabot configuration for workspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys committed Sep 18, 2022
1 parent e43ee70 commit caf393c
Show file tree
Hide file tree
Showing 30 changed files with 659 additions and 192 deletions.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version: 2

updates:
- package-ecosystem: npm
directory: "/"
directory: /
schedule:
interval: daily
allow:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ name: CI
on:
workflow_dispatch:
pull_request:
branches:
- '*'
push:
branches:
- main
Expand Down
47 changes: 41 additions & 6 deletions .github/workflows/post-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ name: Post Dependabot Actions

on: pull_request

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

Expand All @@ -29,15 +28,51 @@ jobs:
- run: npm i --ignore-scripts --no-audit --no-fund
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v1.1.1
uses: dependabot/fetch-metadata@v1
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Apply @npmcli/template-oss changes and lint
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Get command flags
if: contains(steps.metadata.outputs.dependency-names, '@npmcli/template-oss')
id: flags
run: |
if [[ "${{steps.metadata.outputs.directory}}" == "/" ]]; then
echo "::set-output name=workspace::-iwr"
else
echo "::set-output name=workspace::-w ${{ steps.metadata.outputs.directory }}"
fi
- name: Apply changes
if: steps.flags.outputs.workspace
id: apply
run: |
npm run template-oss-apply ${{steps.flags.outputs.workspace}}
if [[ `git status --porcelain` ]]; then
echo "::set-output name=changes::true"
fi
- name: Push all changes
if: steps.apply.outputs.changes
id: push
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npm run template-oss-apply
git commit -am "chore: postinstall for dependabot template-oss PR"
git push
npm run lint
- name: Push all except workflows
if: steps.push.outcome == 'failure'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git reset HEAD~
git checkout HEAD -- .github/workflows/
git clean -fd .github/workflows/
git commit -am "chore: postinstall for dependabot template-oss PR"
git push
- name: Verify changes
if: steps.apply.outputs.changes
run: |
npm exec --offline ${{steps.flags.outputs.workspace}} -- template-oss-check
68 changes: 42 additions & 26 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ const DEFAULT_CONTENT = require.resolve(NAME)

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

const makePosix = (str) => str.split(win32.sep).join(posix.sep)
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 getCmdPath = (key, { rootConfig, defaultConfig, isRoot, path, root }) => {
// Make a path relative from a workspace to the root if we are in a workspace
Expand Down Expand Up @@ -78,27 +81,27 @@ const getFiles = (path, rawConfig) => {
}

const getFullConfig = async ({
// the path to the root of the repo
root,
// the path to the package being operated on
// this is the same as root when operating on the root
path,
pkg,
// the full contents of the package.json for this package
pkgJson,
// an array of all package info {pkgJson,path,config}[]
pkgs,
// an array of all workspaces in this repo
workspaces,
// the config from the package.json in the root
rootConfig: _rootConfig,
// the config from the package.json being operated on
pkgConfig: _pkgConfig,
}) => {
const isRoot = root === path
const isRootMono = isRoot && workspaces.length > 0
const isLatest = _pkgConfig.version === LATEST_VERSION
const isDogFood = pkg.name === NAME
const isDogFood = pkgJson.name === NAME
const isForce = process.argv.includes('--force')

// this is written to ci yml files so it needs to always use posix
const pkgRelPath = makePosix(relative(root, path))

const workspacePkgs = pkgs.filter((p) => p.path !== path)
const workspaceDirs = isRootMono && workspaces.map((p) => makePosix(relative(root, p)))
const workspaceGlobs = isRootMono && pkg.workspaces.map(p => p.replace(/[/*]+$/, ''))

// These config items are merged betweent the root and child workspaces and only come from
// the package.json because they can be used to read configs from other the content directories
const mergedConfig = mergeConfigs(_rootConfig, _pkgConfig)
Expand All @@ -112,6 +115,7 @@ const getFullConfig = async ({

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

Expand All @@ -128,16 +132,24 @@ const getFullConfig = async ({
...isRoot ? [
// in the root allow all repo files
...getAddedFiles(repoFiles),
// and allow all workspace repo level files
...workspacePkgs.filter(p => p.config.workspaceRepo !== false).flatMap((p) =>
getAddedFiles(files.workspaceRepo)
),
// and allow all workspace repo level files in the root
...pkgs
.filter(p => p.path !== root && p.config.workspaceRepo !== false)
.flatMap(() => getAddedFiles(files.workspaceRepo)),
] : [],
]

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

// these are written to ci yml files so it needs to always use posix
const pkgPath = makePosix(relative(root, path)) || '.'

// we use the raw paths from the package.json workspaces as ignore patterns in
// some cases. the workspaces passed in have already been run through map workspaces
const workspacePaths = (pkgJson.workspaces || []).map(deglob)

// all derived keys
const derived = {
isRoot,
Expand All @@ -147,8 +159,8 @@ const getFullConfig = async ({
// For these cases it is helpful to know if we are in a
// monorepo since template-oss might be used only for
// workspaces and not the root or vice versa.
isRootMono,
isMono: isRootMono || !isRoot,
isRootMono: isRoot && !!workspaces.length,
isMono: !!workspaces.length,
// repo
repoDir: root,
repoFiles,
Expand All @@ -158,13 +170,14 @@ const getFullConfig = async ({
moduleFiles,
applyModule: !!moduleFiles,
// package
pkgName: pkg.name,
pkgNameFs: pkg.name.replace(/\//g, '-').replace(/@/g, ''),
pkgRelPath: pkgRelPath,
pkgPrivate: !!pkg.private,
pkgPublic: !pkg.private,
workspaces: workspaceDirs,
workspaceGlobs,
pkgName: pkgJson.name,
pkgNameFs: pkgJson.name.replace(/\//g, '-').replace(/@/g, ''),
// paths
pkgPath,
pkgDir: posixDir(pkgPath),
pkgGlob: posixGlob(pkgPath),
workspacePaths,
workspaceGlobs: workspacePaths.map(posixGlob),
// booleans to control application of updates
isForce,
isDogFood,
Expand All @@ -175,6 +188,9 @@ const getFullConfig = async ({
rootNpmPath: npmPath.root,
localNpmPath: npmPath.local,
rootNpxPath: npxPath.root,
// lockfiles are only present at the root, so this only should be set for
// all workspaces based on the root
lockfile: rootPkgConfig.lockfile,
// gitignore
ignorePaths: [
...gitignore.sort([
Expand All @@ -185,7 +201,7 @@ const getFullConfig = async ({
]),
// these cant be sorted since they rely on order
// to allow a previously ignored directoy
...gitignore.allowDir(workspaceDirs || []),
...isRoot ? gitignore.allowDir(workspaces.map((p) => makePosix(relative(root, p)))) : [],
],
// needs update if we are dogfooding this repo, with force argv, or its
// behind the current version
Expand All @@ -210,7 +226,7 @@ const getFullConfig = async ({
derived.repository = {
type: 'git',
url: gitUrl,
...(pkgRelPath ? { directory: pkgRelPath } : {}),
...(!isRoot ? { directory: pkgPath } : {}),
}
}

Expand Down
18 changes: 8 additions & 10 deletions lib/content/_setup-ci-on.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
workflow_dispatch:
pull_request:
branches:
- '*'
{{#if pkgRelPath}}
{{#if isWorkspace}}
paths:
- {{pkgRelPath}}/**
- {{pkgGlob}}
{{/if}}
{{#if workspaceGlobs}}
{{#if isRootMono}}
paths-ignore:
{{#each workspaceGlobs}}
- {{.}}/**
- {{.}}
{{/each}}
{{/if}}
push:
branches:
{{#each branches}}
- {{.}}
{{/each}}
{{#if pkgRelPath}}
{{#if isWorkspace}}
paths:
- {{pkgRelPath}}/**
- {{pkgGlob}}
{{/if}}
{{#if workspaceGlobs}}
{{# if isRootMono}}
paths-ignore:
{{#each workspaceGlobs}}
- {{.}}/**
- {{.}}
{{/each}}
{{/if}}
schedule:
Expand Down
3 changes: 2 additions & 1 deletion lib/content/_setup-deps.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- run: {{rootNpmPath}} i --ignore-scripts --no-audit --no-fund {{~#if flags}} {{flags}}{{/if}}
- name: Install Dependencies
run: {{rootNpmPath}} i --ignore-scripts --no-audit --no-fund {{~#if flags}} {{flags}}{{/if}}
3 changes: 2 additions & 1 deletion lib/content/_setup-git.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- uses: actions/checkout@v3
- name: Checkout
uses: actions/checkout@v3
{{#if checkout}}
with:
{{#each checkout}}
Expand Down
12 changes: 7 additions & 5 deletions lib/content/_setup-node.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
- name: Setup Node {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{last ciVersions}}{{/if}}
- uses: actions/setup-node@v3
with:
node-version: {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{#each ciVersions}}{{#if @last}}{{.}}{{/if}}{{/each}}{{/if}}
node-version: {{#if useMatrix}}$\{{ matrix.node-version }}{{else}}{{last ciVersions}}{{/if}}
{{#if lockfile}}
cache: npm
{{/if}}
Expand All @@ -16,15 +17,16 @@
node lib/npm.js install --no-fund --no-audit -g ..\npm-7.5.4.tgz
cd ..
rmdir /s /q package
- name: Update npm to 7
- name: npm@7
# If we do test on npm 10 it needs npm7
if: startsWith(matrix.node-version, '10.')
run: npm i --prefer-online --no-fund --no-audit -g npm@7
- name: Update npm to latest
- name: npm@latest
if: $\{{ !startsWith(matrix.node-version, '10.') }}
{{else}}
- name: Update npm to latest
- name: npm@latest
{{/if}}
run: npm i --prefer-online --no-fund --no-audit -g npm@latest
- run: npm -v
- name: npm Version
run: npm -v
{{/if}}
4 changes: 3 additions & 1 deletion lib/content/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ on:

jobs:
audit:
name: Audit
{{> setupJob flags="--package-lock"}}
- run: {{rootNpmPath}} audit
- name: npm audit
run: {{rootNpmPath}} audit
12 changes: 9 additions & 3 deletions lib/content/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ on:

jobs:
lint:
name: Lint
{{> setupJob }}
- run: {{rootNpmPath}} run lint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
- name: npm run lint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
run: {{rootNpmPath}} run lint --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
- name: npm run postlint {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
run: {{rootNpmPath}} run postlint --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}

test:
name: Test
{{> setupJobMatrix }}
- name: add tap problem matcher
- name: Add tap Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- run: {{rootNpmPath}} test --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
- name: npm test {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
run: {{rootNpmPath}} test --ignore-scripts {{~#if isWorkspace}} -w {{pkgName}}{{/if}}
2 changes: 1 addition & 1 deletion lib/content/commitlintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [{{#each changelogTypes}}'{{type}}'{{#unless @last}}, {{/unless}}{{/each}}]],
'type-enum': [2, 'always', [{{{join (quote (pluck changelogTypes "type"))}}}]],
'header-max-length': [2, 'always', 80],
'subject-case': [0, 'always', ['lower-case', 'sentence-case', 'start-case']],
},
Expand Down
22 changes: 2 additions & 20 deletions lib/content/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,14 @@ version: 2

updates:
- package-ecosystem: npm
directory: "/"
directory: {{pkgDir}}
schedule:
interval: daily
allow:
- dependency-type: direct
versioning-strategy: increase-if-necessary
versioning-strategy: {{dependabot}}
commit-message:
prefix: deps
prefix-development: chore
labels:
- "Dependencies"

{{#if workspaces}}
{{#each workspaces}}
- package-ecosystem: npm
directory: "{{.}}/"
schedule:
interval: daily
allow:
- dependency-type: direct
versioning-strategy: increase-if-necessary
commit-message:
prefix: deps
prefix-development: chore
labels:
- "Dependencies"

{{/each}}
{{/if}}
4 changes: 2 additions & 2 deletions lib/content/eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ const localConfigs = readdir(__dirname)

module.exports = {
root: true,
{{#if isRootMono}}
{{#if workspaceGlobs}}
ignorePatterns: [
{{#each workspaces}}
{{#each workspaceGlobs}}
'{{.}}',
{{/each}}
],
Expand Down
Loading

0 comments on commit caf393c

Please # to comment.