From bdaa73486e3568ca1ad0fa8c2e7789b536a92bc1 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Thu, 14 Mar 2024 14:42:41 +0200 Subject: [PATCH] chore: changeset validating github action --- .github/workflows/validate-pr-base.yml | 20 ++++++++++++ scripts/validate-prs.js | 43 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 .github/workflows/validate-pr-base.yml create mode 100644 scripts/validate-prs.js diff --git a/.github/workflows/validate-pr-base.yml b/.github/workflows/validate-pr-base.yml new file mode 100644 index 0000000000..13f535dc94 --- /dev/null +++ b/.github/workflows/validate-pr-base.yml @@ -0,0 +1,20 @@ +name: Validate PRs + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - edited + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/github-script@v7 + with: + script: | + const { validate } = await import('${{ github.workspace }}/scripts/validate-prs.js'); + await validate({ context }); diff --git a/scripts/validate-prs.js b/scripts/validate-prs.js new file mode 100644 index 0000000000..40b3b7e0fd --- /dev/null +++ b/scripts/validate-prs.js @@ -0,0 +1,43 @@ +/* eslint-env node */ +import read from '@changesets/read'; +import conventionalCommitsParser from 'conventional-commits-parser'; + +export async function validate({ context }) { + const { base, title, auto_merge: autoMerge } = context.payload.pull_request; + + if (base.startsWith('staging/')) { + return true; + } + + const { type } = conventionalCommitsParser.sync(title); + + console.log({ type }); + + if (autoMerge?.merge_method === 'rebase') { + throw new Error('Validating auto-rebase PRs is not yet implemented'); + // one approach could be to use `@commitlint/load` to read { from: baseBranch } + // then pipe that array as a stream to conventionalcommitsparser's transform stream + } + + const sets = await read(process.cwd()); + + const release = sets.reduce((greatest, type) => { + switch (greatest) { + case null: + case 'major': + return greatest; + case 'minor': + return type === 'major' ? type : greatest; + case 'patch': + return (type === 'major' || type === 'minor') ? type : greatest; + } + }, null); + + if (!release && type) { + throw new Error(`PR conventional commit title has type (${type}) but no changesets were detected.`); + } + + if (type !== release) { + throw new Error(`PR conventional commit title type (${type}) does not match release type (${release}).`); + } +}