View as Markdown

Implementing a Two⁠-⁠Step CI with Mergify

Run essential tests on every PR and comprehensive tests before merging, optimizing CI time and resources.


Split your CI into fast preliminary checks on every PR and full tests that run only before merging.

Step 1: Preliminary tests run on every PR push: linters, formatters, unit tests, basic compile checks. Fast feedback, cheap to run.

Step 2: Pre-merge tests run only when a PR enters the merge queue: integration tests, end-to-end tests, performance benchmarks. Thorough but expensive.

open 🔄 PR opened or updated preliminary 🧪 Preliminary tests (Unit tests, linting) open->preliminary preliminary_ok ✅ Tests passed (Ready for queue) preliminary->preliminary_ok preliminary_fail ❌ Tests failed (Needs fixes) preliminary->preliminary_fail queue_req 📝 Queue command (@mergifyio queue) preliminary_ok->queue_req queued ⏳ PR queued queue_req->queued premerge 🔬 Pre-merge tests (Integration, performance) queued->premerge premerge_ok ✅ All tests passed (Ready to merge) premerge->premerge_ok premerge_fail ❌ Pre-merge failed (Removed from queue) premerge->premerge_fail merged 🎉 Merged to main premerge_ok->merged

Enable batching to run pre-merge tests once for a group of PRs instead of per PR. For 5 PRs with a 30-minute pre-merge suite, that’s 30 minutes instead of 2.5 hours.

Run pre-merge tests only on merge queue branches. Mergify creates branches prefixed with mergify/merge-queue/ (customizable via queue_branch_prefix in queue_rules).

name: CI
on:
pull_request:
branches:
- main
jobs:
# STEP 1: Preliminary tests (runs on every PR)
preliminary-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run linters
run: make lint
- name: Run unit tests
run: make test-unit
# STEP 2: Pre-merge tests (runs only on merge queue branches)
pre-merge-tests:
if: startsWith(github.head_ref, 'mergify/merge-queue/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run integration tests
run: make test-integration
- name: Run E2E tests
run: make test-e2e
- name: Run performance benchmarks
run: make benchmark
  • CircleCI: Branch filter regex /^mergify\/merge-queue\/.*/
  • Jenkins: Conditional execution on BRANCH_NAME
  • GitLab CI: only: /^mergify\/merge-queue\/.*/
queue_rules:
- name: default
# PRs can enter the queue after preliminary tests pass
queue_conditions:
- check-success=preliminary-tests
# PRs can merge only after pre-merge tests pass
merge_conditions:
- check-success=pre-merge-tests

queue_conditions gates entry into the queue; merge_conditions gates the final merge to main.

Was this page helpful?