Last active
August 16, 2023 03:25
-
-
Save thlorenz/5c044652333031c82886551be8f3b637 to your computer and use it in GitHub Desktop.
script: Dorny path filter generator (derived from deps of the provided package)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import path from 'path' | |
// 1. Define root of project from which to resolve all packages | |
const ROOT = path.resolve(__dirname, '..') | |
// 2. Define the relative path of the package that we generate the dorny filters for | |
const PACK = process.argv[2] | |
if (PACK == null) { | |
throw new Error( | |
'Need to supply relative path argument for package you want to render dorny filter for' | |
) | |
} | |
const PACKAGE_PATH = path.join(ROOT, PACK) | |
// NOTE: adapt the below to your project | |
const TASK = 'build-test-lint' | |
const LOCAL_PREFIX = '@my-platform/' | |
// 3. Read the package and derive Job labels from its name | |
const pack = require(`${PACKAGE_PATH}/package.json`) | |
const jobLabel = pack.name.replace(LOCAL_PREFIX, '').replace(/-/g, '_') | |
const changesJobLabel = `${jobLabel}_changes` | |
const taskJobLabel = `${jobLabel}_${TASK}` | |
// 4. Extract local deps and sort them and resolve their relative path | |
const deps = Object.keys(pack.dependencies ?? {}).filter((dep) => | |
dep.startsWith(LOCAL_PREFIX) | |
) | |
const devDeps = Object.keys(pack.devDependencies ?? {}).filter((dep) => | |
dep.startsWith(LOCAL_PREFIX) | |
) | |
const allDeps = [...deps, ...devDeps] | |
allDeps.sort() | |
allDeps.unshift(pack.name) | |
const resolvedDeps = allDeps.map((dep) => { | |
const label = dep.replace(LOCAL_PREFIX, '').replace(/-/g, '_') | |
return { label, relPath: path.relative(ROOT, require.resolve(dep)) } | |
}) | |
// 5. Render functions for the different section pieces | |
function dornyOutput({ label }: { label: string }, indent: string) { | |
return `${indent}${label}: \${{ steps.filter.outputs.${label} }}` | |
} | |
function dornyFilter( | |
{ label, relPath }: { label: string; relPath: string }, | |
indent: string = ' ' | |
) { | |
// Simplest (naive) way to find package root (one above first `/src`) | |
// A more sophisticated way, i.e. finding `package.json` could be used | |
const idxOfSrc = relPath.indexOf('/src') | |
const packageRoot = relPath.slice(0, idxOfSrc) | |
return `${indent}${label}:\n` + `${indent} - './${packageRoot}/**'` | |
} | |
function dornyNeeds({ label }: { label: string }, indent: string) { | |
return `${indent}needs.${changesJobLabel}.outputs.${label} == 'true'` | |
} | |
const packOutputs = resolvedDeps.map((x) => dornyOutput(x, ' ')).join('\n') | |
const packFilters = resolvedDeps | |
.map((x) => dornyFilter(x, ' ')) | |
.join('\n') | |
const taskNeeds = resolvedDeps.map((x) => dornyNeeds(x, ' ')).join(' ||\n') | |
// 6. Piece it all together | |
const changesJob = ` | |
jobs: | |
${changesJobLabel}: | |
runs-on: | |
group: Default | |
outputs: | |
${packOutputs} | |
action: \${{ steps.filter.outputs.action }} | |
workflow: \${{ steps.filter.outputs.workflow }} | |
steps: | |
- uses: actions/checkout@master | |
if: github.event_name != 'pull_request' | |
- uses: dorny/paths-filter@v2 | |
id: filter | |
with: | |
filters: | | |
${packFilters} | |
workflow: | |
- '.github/workflows/${jobLabel}.yml' | |
action: | |
- '.github/actions/build-test-lint/action.yml' | |
${taskJobLabel}: | |
needs: ${changesJobLabel} | |
if: \${{ | |
${taskNeeds} || | |
needs.account_runtime_changes.outputs.action == 'true' || | |
needs.account_runtime_changes.outputs.workflow == 'true' | |
}} | |
` | |
console.log(changesJob) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment