This episode covers integrating Jest into a CI/CD pipeline: setup in GitHub Actions, GitLab CI, and Jenkins, parallel execution with test splitting, fail fast through selective test runs, and reporting results and coverage badges.

Tests that only run on a developer's laptop aren't enough. Episode 14 covers running Jest in CI/CD — running the suite automatically on every push and pull request. You'll integrate Jest into GitHub Actions, GitLab CI, and Jenkins, take advantage of parallel execution and test splitting, apply fail fast with selective test runs, and publish results and coverage badges.
A good pipeline makes tests an automated quality gate: code that fails tests never reaches production unnoticed.
The simplest workflow for GitHub Actions:
name: test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm testThe npm ci line installs dependencies deterministically using the lockfile — more reliable than npm install in CI. If any test fails, the job stops and the pull request is marked red.
For GitLab CI, write a job in .gitlab-ci.yml with a Node.js image and run npm ci then npm test. Jenkins uses a Jenkinsfile with a test stage that runs the same commands. The principle is identical: a clean environment, deterministic dependencies, and a single command for the entire suite.
Jest already runs in parallel within a single runner. For very large suites, you can split the work across several CI jobs:
npx jest --listTests --json > tests.jsonnpx jest --listTests --json produces a list of test files in JSON. From this list, a CI script can split the files across several jobs — for example the first job handles the first half, the second job the next half.
Some CI providers offer a shard index. A common pattern:
matrix:
shard: [1, 2, 3, 4]
steps:
- run: npx jest --shard=${{ matrix.shard }}/4The --shard=n/m flag uses Jest's built-in support to split tests into m parts and run the n-th part. Each CI job handles its share, and the total pipeline time shrinks dramatically.
For faster feedback, run tests selectively based on changes. In GitHub Actions, use paths in the trigger, or compare changes against the main branch:
on:
pull_request:
paths:
- "src/**"
- "package.json"The paths trigger makes the workflow run only when source code changes — documentation, README, and images don't trigger the full suite. For fail fast, run unit tests first; only proceed to heavy steps like e2e if unit tests pass.
Jest can write results in the JUnit format, understood by almost all CI systems:
npx jest --coverage --reporters=default --reporters=jest-junitThe --reporters=jest-junit flag writes results to the JUnit format after installing the jest-junit package. These reports can be uploaded as artifacts and displayed in the pipeline summary.
From coverage reports, many services like Coveralls or Codecov create badges automatically:
npm install --save-dev @vitest/coverage-v8Don't be confused — for Jest, choose the appropriate provider, such as @vitest/coverage-v8, only if you've already moved to Vitest. For Jest, use collectCoverage and upload the lcov.info report to a badge service. The point: publish coverage reports on every release, and display the badge in the README as a quality trend indicator.
Episode 14 brought Jest into the CI/CD pipeline: setup in GitHub Actions, GitLab CI, and Jenkins, parallel execution with shard-based test splitting, fail fast with selective test runs, and reporting results and coverage badges.
Key takeaways:
npm ci in CI for deterministic dependencies.npm test.--shard=n/m splits tests across several parallel jobs.paths trigger runs the suite only when relevant code changes.--reporters=jest-junit produces uploadable reports.In the next episode, episode 15, we'll cover performance optimization — speeding up execution with watch mode and caching, managing workers with --runInBand and --maxWorkers, reducing setup overhead, and optimizing large test suites.