n8n/.github/workflows/ci-pr-quality.yml
Charlie Kolb c8d3c82b23
ci: Block merge when 'Do Not Merge' label is present (no-changelog) (#33828)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 08:37:42 +00:00

167 lines
5.6 KiB
YAML

name: 'CI: PR Quality Checks'
on:
merge_group:
pull_request:
types:
- opened
- edited
- synchronize
- labeled
- unlabeled
issue_comment:
types:
- created
jobs:
handle-size-override:
name: Handle /size-limit-override
# Re-requests the PR Size Limit check run on the PR's HEAD commit, so it re-runs
# in the original PR context and picks up the override comment.
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/size-limit-override')
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
checks: write
issues: write
pull-requests: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: ./.github/actions/setup-nodejs
with:
build-command: ''
install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace
cache-dependency-path: .github/scripts/pnpm-lock.yaml
- name: Re-request PR Size Limit check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node .github/scripts/quality/handle-size-override.mjs
check-pr-size:
name: PR Size Limit
# Checks that the PR size doesn't exceed the limit (currently 1000 lines)
# Allows for override via '/size-limit-override' comment.
# Skipped for bot-authored PRs — dep bumps from Dependabot/Renovate/Aikido
# routinely exceed the size limit and shouldn't be gated on it.
if: |
github.event_name == 'pull_request' &&
github.event.action != 'labeled' &&
github.event.action != 'unlabeled' &&
github.event.pull_request.head.repo.full_name == github.repository &&
!contains(github.event.pull_request.labels.*.name, 'automation:backport') &&
!contains(github.event.pull_request.title, '(backport to') &&
github.event.pull_request.user.type != 'Bot'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: ./.github/actions/setup-nodejs
with:
build-command: ''
install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace
cache-dependency-path: .github/scripts/pnpm-lock.yaml
- name: Check PR size
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node .github/scripts/quality/check-pr-size.mjs
changes:
name: Detect Changes
if: |
(github.event_name == 'pull_request' &&
github.event.action != 'labeled' &&
github.event.action != 'unlabeled') ||
github.event_name == 'merge_group'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
outputs:
janitor: ${{ fromJSON(steps.filter.outputs.results).janitor == true }}
changed-files: ${{ steps.filter.outputs.changed-files }}
added-files: ${{ steps.filter.outputs.added-files }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Detect changed paths
id: filter
uses: ./.github/actions/ci-filter
with:
mode: filter
filters: |
janitor:
packages/testing/playwright/**
packages/testing/janitor/**
check-static-analysis:
name: Static Analysis
needs: changes
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js
uses: ./.github/actions/setup-nodejs
with:
build-command: pnpm turbo run build --filter=@n8n/code-health --filter=@n8n/playwright-janitor
- name: Run code-health
env:
CODE_HEALTH_CHANGED_FILES: ${{ needs.changes.outputs.changed-files }}
CODE_HEALTH_ADDED_FILES: ${{ needs.changes.outputs.added-files }}
run: pnpm --filter=@n8n/code-health check
- name: Run janitor
if: ${{ !cancelled() && (github.event_name == 'merge_group' || needs.changes.outputs.janitor == 'true') }}
run: pnpm --filter=n8n-playwright janitor
check-do-not-merge:
name: Do Not Merge
# Fails while the 'Do Not Merge' label is present. Re-runs on labeled/unlabeled
# so the gate flips as the label is toggled on the current commit.
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions: {}
steps:
- name: Fail if 'Do Not Merge' label is present
if: contains(github.event.pull_request.labels.*.name, 'Do Not Merge')
run: |
echo "::error::This PR has the 'Do Not Merge' label and cannot be merged."
exit 1
required-pr-quality-checks:
name: Required PR Quality Checks
needs: [check-pr-size, check-static-analysis, check-do-not-merge]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: .github/actions/ci-filter
sparse-checkout-cone-mode: false
- name: Validate required checks
uses: ./.github/actions/ci-filter
with:
mode: validate
job-results: ${{ toJSON(needs) }}