This page documents the automated CI pipelines that run on pull requests and the master branch: what jobs they contain, how conditional execution is determined by the ci-filter action, and how the required-checks job enforces branch protection. For the release publishing pipeline see 9.3, and for Docker image builds see 9.4. For an overview of the build system itself (Turborepo, setup-nodejs action) see 9.1.
| File | Trigger | Primary Purpose |
|---|---|---|
.github/workflows/ci-pull-requests.yml | pull_request, merge_group | Full CI gate for PRs |
.github/workflows/ci-master.yml | push to master, 1.x | Post-merge CI, multi-node matrix |
.github/workflows/test-unit-reusable.yml | workflow_call | Reusable unit test runner |
.github/workflows/test-linting-reusable.yml | workflow_call | Reusable lint runner |
.github/workflows/test-e2e-ci-reusable.yml | workflow_call | Reusable E2E runner (Playwright) |
.github/workflows/test-db-reusable.yml | workflow_call | Reusable DB/integration test runner |
.github/workflows/sec-ci-reusable.yml | workflow_call | Reusable security checks |
.github/workflows/test-visual-chromatic.yml | workflow_call | Reusable Chromatic visual tests |
.github/actions/ci-filter | composite action | Determines which jobs run; validates results |
Sources: .github/workflows/ci-pull-requests.yml1-175 .github/workflows/ci-master.yml1-61
ci-pull-requests.yml ā PR CI Workflow.github/workflows/ci-pull-requests.yml1-9
The concurrency block ensures that when a new commit is pushed to an open PR, any in-progress CI run for that PR is cancelled and replaced by the new run. This applies to both ordinary pull requests and GitHub merge queue entries.
PR CI Workflow Job Dependency Graph
Sources: .github/workflows/ci-pull-requests.yml11-174
install-and-build Job.github/workflows/ci-pull-requests.yml12-85
This job does three things:
ci-filter action in filter mode to determine, based on which files changed, which downstream job categories need to run..github/actions/setup-nodejs) and runs pnpm format:check ā only if the ci filter is active.The job exports the filter results as outputs:
| Output | Meaning |
|---|---|
ci | General CI jobs should run (typecheck, lint, unit, e2e) |
unit | Unit test job should run |
e2e | E2E-specific job should run |
workflows | Security/workflow checks should run |
db | DB integration tests should run |
design_system | Chromatic visual tests should run |
commit_sha | Resolved commit SHA for cache consistency |
ci-filter ActionThe ci-filter composite action lives at .github/actions/ci-filter and operates in two modes:
mode: filter ā examines the changed files in the PR/merge group and computes a JSON object indicating which test categories need to run.mode: validate ā takes the needs JSON of all upstream jobs and asserts that no required job failed (used by required-checks).Filter Category to File Pattern Mapping
Sources: .github/workflows/ci-pull-requests.yml39-76
Downstream Job to Reusable Workflow Mapping
Sources: .github/workflows/ci-pull-requests.yml86-156
Notable details per job:
unit-test: passes collectCoverage: true and the CODECOV_TOKEN secret to the reusable workflow.typecheck: runs inline (not a reusable workflow), on a 4-vCPU Blacksmith runner. Calls setup-nodejs with build-command: pnpm typecheck.e2e-tests: additionally guarded by github.repository == 'n8n-io/n8n' to prevent forks from running E2E tests, which require internal secrets.security-checks: triggered only when .github/** files changed (workflows filter), since this checks the workflow files themselves.required-checks ā Branch Protection Gate.github/workflows/ci-pull-requests.yml158-174
This job:
if: always()).ci-filter action in validate mode, passing the full needs context.validate mode logic determines whether any required job actually ran and failed, vs. jobs that were intentionally skipped due to the filter.db-tests, e2e-tests) to be skipped without blocking merges, while still failing the gate if a job that did run returns a failure.ci-master.yml ā Master Branch CI.github/workflows/ci-master.yml1-61
Runs after merges to master or the 1.x maintenance branch. Changes to packages/@n8n/task-runner-python/** are excluded (that package has its own pipeline). There is no concurrency cancellation here ā every push runs to completion.
| Job | Description |
|---|---|
build-github | Full build via setup-nodejs; populates the GitHub Actions cache for downstream jobs |
unit-test | Calls test-unit-reusable.yml; runs in a matrix across Node.js versions |
lint | Calls test-linting-reusable.yml |
notify-on-failure | Sends a Slack message to #alerts-build on any job failure |
.github/workflows/ci-master.yml26-40
fail-fast: false ensures all three matrix legs complete even if one fails, giving visibility into which Node.js versions broke.24.13.1 (collectCoverage: ${{ matrix.node-version == '24.13.1' }}).Master CI Job Flow
Sources: .github/workflows/ci-master.yml11-61
Note that build-github does not feed into unit-test as a needs dependency; both start immediately. The build-github job's purpose is to populate the runner cache so that subsequent runs of unit tests (which call setup-nodejs) benefit from pre-cached node_modules and build artifacts.
| Aspect | ci-pull-requests.yml | ci-master.yml |
|---|---|---|
| Trigger | pull_request, merge_group | push to master, 1.x |
| Concurrency | cancel-in-progress per PR | no cancellation |
| Conditional execution | ci-filter action skips unnecessary jobs | all jobs always run |
| Typecheck | Yes (inline job) | No |
| E2E tests | Yes (conditional) | No |
| DB tests | Yes (conditional) | No |
| Security checks | Yes (conditional) | No |
| Chromatic | Yes (conditional) | No |
| Node.js matrix | Single version (default) | 22.x, 24.13.1, 25.x |
| Branch protection gate | required-checks job | Slack failure notification |
| Coverage upload | collectCoverage: true (always) | Only for node 24.13.1 |
Both workflows support a RUNNER_PROVIDER variable to switch between GitHub-hosted and Blacksmith runners:
The typecheck job uses a 4-vCPU Blacksmith runner (blacksmith-4vcpu-ubuntu-2204) when not on GitHub-hosted runners, reflecting the memory requirements of running tsc across the full monorepo.
Sources: .github/workflows/ci-pull-requests.yml14 .github/workflows/ci-pull-requests.yml103-104
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.