diff --git a/.github/workflows/pr-filter.yml b/.github/workflows/pr-filter.yml new file mode 100644 index 0000000..b6bcd00 --- /dev/null +++ b/.github/workflows/pr-filter.yml @@ -0,0 +1,22 @@ +name: Block Invalid PR + +on: + pull_request_target: + types: [opened, reopened, edited] + +jobs: + check-template: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Check PR Content + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('.github/workflows/scripts/pr-filter.js'); + await script({ github, context }); diff --git a/.github/workflows/scripts/pr-filter.js b/.github/workflows/scripts/pr-filter.js new file mode 100644 index 0000000..e720630 --- /dev/null +++ b/.github/workflows/scripts/pr-filter.js @@ -0,0 +1,40 @@ +function noTypes(markdown) { + if (/## Type of change/.test(markdown) && /- \[x\]/i.test(markdown)) { + return false; + } + return true; +} + +function noDescription(markdown) { + return ( + /## Description/.test(markdown) === false || + /## Description\s*\n\s*## \w+/.test(markdown) || + /## Description\s*\n\s*$/.test(markdown) + ); +} + +module.exports = async ({ github, context }) => { + const pr = context.payload.pull_request; + + if (pr.labels.length > 0) { + // Skip if the PR is already labeled (typically created by a deps-bot.) + return; + } + + const body = pr.body === null ? '' : pr.body.trim(); + const markdown = body.replace(//g, ''); + + if (body === '' || noTypes(markdown) || noDescription(markdown)) { + await github.rest.pulls.update({ + ...context.repo, + pull_number: pr.number, + state: 'closed' + }); + + await github.rest.issues.createComment({ + ...context.repo, + issue_number: pr.number, + body: "Oops, it seems you've submitted an invalid pull request. No worries, we'll close it for you." + }); + } +};