# Cypress Monorepo CI/CD Setup: How CircleCI Powers the Build Pipeline

> Learn how the Cypress monorepo leverages CircleCI for a powerful CI/CD setup. Explore its modular configuration for Linux, macOS, and Windows builds with automated publishing.

- Repository: [Cypress.io/cypress](https://github.com/cypress-io/cypress)
- Tags: how-to-guide
- Published: 2026-08-06

---

**The Cypress monorepo uses a modular CircleCI configuration split between source files (`.circleci/src/`) and a packed pipeline ([`.circleci/packed/pipeline.yml`](https://github.com/cypress-io/cypress/blob/main/.circleci/packed/pipeline.yml)), enabling builds across Linux, macOS, and Windows with automated binary publishing.**

Understanding the CI/CD setup for the `cypress-io/cypress` monorepo reveals how one of the most popular end-to-end testing frameworks maintains code quality at scale. The repository's continuous integration system is built entirely on **CircleCI**, with a sophisticated two-layer configuration that separates readable source YAML from the flattened pipeline that CircleCI actually executes.

## Modular Configuration Architecture

Rather than maintaining a single unwieldy YAML file, Cypress engineers structured the CI/CD setup as a **source-and-pack system**. This design keeps individual jobs, commands, and workflows organized while still delivering CircleCI's required single-file format.

### Source Directory Structure

The `.circleci/src/` directory contains the human-readable configuration:

- **`.circleci/src/pipeline/@pipeline.yml`** — Master orchestration file declaring all jobs, executors, and workflows. It imports shared orbs like `browser-tools` and defines the cross-platform test matrix.

- **`.circleci/src/pipeline/workflows/@main.yml`** — Full workflow for the `develop` branch, running the complete Linux, macOS, and Windows test suite plus binary publishing.

- **[`.circleci/src/pipeline/workflows/pull-request.yml`](https://github.com/cypress-io/cypress/blob/main/.circleci/src/pipeline/workflows/pull-request.yml)** — Lightweight workflow for PRs, focusing on unit tests, linting, and limited platform coverage.

The entry point at [`.circleci/config.yml`](https://github.com/cypress-io/cypress/blob/main/.circleci/config.yml) is minimal—it simply references the packed pipeline:

```yaml

# .circleci/config.yml

setup: true
jobs: [...]

```

## Packing Pipeline: scripts/pack-ci.sh

The transformation from modular source to executable pipeline happens through **[`scripts/pack-ci.sh`](https://github.com/cypress-io/cypress/blob/main/scripts/pack-ci.sh)**. This script concatenates all source YAML files, resolves anchors, and writes the final [`pipeline.yml`](https://github.com/cypress-io/cypress/blob/main/pipeline.yml) to `.circleci/packed/`.

Key operations in [`pack-ci.sh`](https://github.com/cypress-io/cypress/blob/main/pack-ci.sh) (lines 27–61):

1. Detects changes to `.circleci/src/` files
2. Runs `circleci config pack` to flatten the configuration
3. Validates the output with `circleci config validate`
4. Caches a version hash in [`.circleci/cache-version.txt`](https://github.com/cypress-io/cypress/blob/main/.circleci/cache-version.txt) for Docker layer reuse

```bash

# Pack the modular config locally

$ ./scripts/pack-ci.sh

# Validate without packing

$ circleci config validate .circleci/config.yml

```

A **pre-commit hook** (`.husky/pre-commit`) automatically triggers this packing when CI configuration files change, ensuring the packed pipeline never drifts from source.

## Cross-Platform Executor Matrix

The packed pipeline defines multiple **executor types** to verify Cypress works across environments:

| Executor | Purpose | Base Image |
|----------|---------|------------|
| Linux Docker | Unit tests, component tests, most CI workloads | `cypress/base-internal:22.19.0-trixie` |
| macOS | Darwin-specific integration tests, binary builds | macOS VM (version specified in pipeline) |
| Windows | Windows-specific integration tests, `.exe` binary builds | Windows VM |

The **`browser-tools` orb** (`circleci/browser-tools@2.4.1`) installs Chrome, Firefox, Edge, and WebKit on each executor, ensuring consistent browser environments.

## Test Distribution and Caching

### Parallel Test Splitting

For large test suites, the CI/CD setup leverages CircleCI's built-in `circleci tests split` utility. In `@pipeline.yml` (line 862), the pipeline globbles spec files and distributes them across parallel nodes:

```bash
TESTFILES=$(circleci tests glob "cypress/e2e/**/*.cy.*" | circleci tests split)

```

This distributes end-to-end tests across `CIRCLE_NODE_TOTAL` parallel containers based on test timing data.

### Multi-Layer Caching Strategy

The pipeline uses **composite cache keys** to maximize build artifact reuse:

```yaml
key: v{{ checksum ".circleci/cache-version.txt" }}-{{ checksum "platform_key" }}-{{ checksum "yarn.lock" }}

```

Cached assets include:
- Node modules and Yarn cache
- Compiled V8 snapshot artifacts
- Electron binary downloads

The [`cache-version.txt`](https://github.com/cypress-io/cypress/blob/main/cache-version.txt) file ensures cache invalidation when the CI environment itself changes.

## Conditional Execution and Branch Logic

Not every job runs on every branch. The pipeline uses **`circleci-agent step halt`** to short-circuit unnecessary work—for example, skipping Windows builds on branches that don't require platform-specific validation.

Runtime CI detection lives in **[`packages/server/lib/util/ci_provider.ts`](https://github.com/cypress-io/cypress/blob/main/packages/server/lib/util/ci_provider.ts)**, which exposes CircleCI-specific variables like `CIRCLE_WORKFLOW_ID` to the Cypress runtime for debugging and metadata collection.

## Binary Publishing Workflow

After successful builds, the CI/CD setup triggers an external **binary publishing pipeline** in the separate `cypress-publish-binary` repository.

From `@pipeline.yml` (lines 62–70):

```yaml
- run:
    name: Trigger publish binary pipeline
    command: |
      curl -X POST \
        -H "Circle-Token: $CIRCLE_TOKEN" \
        -d '{"branch":"develop","parameters":{"trigger_repo":"cypress"}}' \
        https://circleci.com/api/v2/project/github/cypress-io/cypress-publish-binary/pipeline

```

Manual trigger via CLI:

```bash
curl -X POST \
  -H "Circle-Token: $CIRCLE_TOKEN" \
  -d '{"branch":"develop"}' \
  https://circleci.com/api/v2/project/github/cypress-io/cypress-publish-binary/pipeline

```

## System Tests Against Real Projects

The **`system-test`** jobs validate Cypress against real-world example projects. These jobs:

1. Spin up Docker containers with the freshly built Cypress binary
2. Pull down representative test projects
3. Execute comprehensive end-to-end scenarios

This catches integration failures that unit tests miss, particularly around browser launching, screenshot capture, and video recording.

## Workflow Triggers

| Trigger | Workflow File | Behavior |
|---------|-------------|----------|
| Push to `develop` | `@main.yml` | Full test matrix, binary publishing |
| Pull request | [`pull-request.yml`](https://github.com/cypress-io/cypress/blob/main/pull-request.yml) | Lint, unit tests, reduced platform coverage |
| Manual API call | Variable | Custom pipeline parameters |

## Summary

- **CircleCI** is the sole CI/CD platform for the Cypress monorepo, with configuration managed through a source-and-pack architecture.
- **`.circleci/src/`** holds modular YAML source files; **[`scripts/pack-ci.sh`](https://github.com/cypress-io/cypress/blob/main/scripts/pack-ci.sh)** flattens them into the executable pipeline.
- **Cross-platform testing** runs on Linux Docker, macOS, and Windows executors using the `browser-tools` orb for browser installation.
- **Parallel test splitting** and multi-layer caching optimize build performance across large test suites.
- **Binary publishing** triggers an external pipeline via CircleCI API after successful `develop` branch builds.
- **Pre-commit hooks** ensure the packed pipeline stays synchronized with source configuration changes.

## Frequently Asked Questions

### How is the Cypress monorepo CI/CD configuration organized?

The configuration uses a **two-layer system**: human-readable source files in `.circleci/src/` and a machine-generated packed pipeline in [`.circleci/packed/pipeline.yml`](https://github.com/cypress-io/cypress/blob/main/.circleci/packed/pipeline.yml). The [`scripts/pack-ci.sh`](https://github.com/cypress-io/cypress/blob/main/scripts/pack-ci.sh) script handles the transformation, and a pre-commit hook automatically repacks when source files change.

### What platforms does Cypress test against in CI?

The CI/CD setup tests against **Linux** (Docker with `cypress/base-internal:22.19.0-trixie`), **macOS**, and **Windows**. The `develop` branch runs the full matrix, while pull requests use a lighter subset to reduce feedback time.

### How does Cypress handle large test suites in CircleCI?

The pipeline uses **`circleci tests split`** to distribute spec files across parallel containers based on historical timing data. This maximizes throughput for the extensive end-to-end test suite while maintaining balanced job durations.

### What triggers the Cypress binary publishing process?

After successful builds on the `develop` branch, the pipeline makes an authenticated API call to trigger the **`cypress-publish-binary`** pipeline in a separate repository. This decouples the open-source build from the proprietary binary distribution system.

### Can I validate the CircleCI configuration locally?

Yes—run `circleci config validate .circleci/config.yml` to check the packed configuration, or execute [`./scripts/pack-ci.sh`](https://github.com/cypress-io/cypress/blob/main/./scripts/pack-ci.sh) to regenerate and validate the pipeline from source files.