A Cypress test suite that only runs on your laptop is a manual verification step. A suite wired into your CI/CD pipeline — triggered on every push, running against every pull request, blocking merges on failure — is an automated quality gate. Running Cypress in CI requires headless execution, browser installation, dependency management, and artifact collection. This lesson covers the complete setup for the three most popular CI platforms: GitHub Actions, GitLab CI, and Jenkins.
Cypress in GitHub Actions, GitLab CI and Jenkins
Each platform requires slightly different configuration, but the core pipeline structure is identical: install dependencies, start the application (if needed), run Cypress headlessly, and upload results.
// ── GITHUB ACTIONS — Complete workflow ──
const GITHUB_ACTIONS = `
# .github/workflows/cypress.yml
name: Cypress Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
cypress-run:
runs-on: ubuntu-22.04
steps:
# Step 1: Check out the code
- name: Checkout
uses: actions/checkout@v4
# Step 2: Use the official Cypress GitHub Action
# It handles: Node install, npm ci, browser install, caching
- name: Cypress run
uses: cypress-io/github-action@v6
with:
browser: chrome
headed: false
# If your app needs to be started first:
# start: npm start
# wait-on: 'http://localhost:3000'
# wait-on-timeout: 120
# Step 3: Upload screenshots and videos on failure
- name: Upload artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-screenshots-videos
path: |
cypress/screenshots
cypress/videos
retention-days: 7
`;
// ── GITLAB CI — .gitlab-ci.yml ──
const GITLAB_CI = `
# .gitlab-ci.yml
cypress:
image: cypress/browsers:latest
stage: test
script:
- npm ci
- npx cypress run --browser chrome
artifacts:
when: on_failure
paths:
- cypress/screenshots/
- cypress/videos/
expire_in: 7 days
cache:
key: cypress-\${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- ~/.cache/Cypress/
`;
// ── JENKINS — Jenkinsfile ──
const JENKINS = `
// Jenkinsfile
pipeline {
agent {
docker {
image 'cypress/browsers:latest'
}
}
stages {
stage('Install') {
steps { sh 'npm ci' }
}
stage('Test') {
steps { sh 'npx cypress run --browser chrome' }
}
}
post {
failure {
archiveArtifacts artifacts: 'cypress/screenshots/**,cypress/videos/**'
}
}
}
`;
// ── Key CI configuration decisions ──
const CI_DECISIONS = [
{
decision: 'Browser selection',
recommendation: 'Chrome for speed; Firefox for cross-browser; Electron as fallback',
command: 'npx cypress run --browser chrome',
},
{
decision: 'Dependency caching',
recommendation: 'Cache node_modules/ and ~/.cache/Cypress/ to skip reinstallation',
command: 'GitHub Action handles this; GitLab/Jenkins: configure cache paths',
},
{
decision: 'Artifact collection',
recommendation: 'Upload screenshots and videos on failure; use if: failure() or when: on_failure',
command: 'Configured in the artifact/post step',
},
{
decision: 'Application startup',
recommendation: 'If testing your own app: start it in CI and wait for it to be ready',
command: 'start: npm start, wait-on: http://localhost:3000',
},
{
decision: 'Timeout configuration',
recommendation: 'Increase defaultCommandTimeout to 10s in CI (slower than local)',
command: 'CYPRESS_DEFAULT_COMMAND_TIMEOUT=10000 npx cypress run',
},
];
console.log('CI/CD Platform Configurations');
console.log('GitHub Actions: cypress-io/github-action@v6 (recommended — handles everything)');
console.log('GitLab CI: cypress/browsers Docker image + npm ci + npx cypress run');
console.log('Jenkins: Dockerfile with cypress/browsers + pipeline stages');
cypress-io/github-action@v6 is the recommended way to run Cypress in GitHub Actions. It handles Node.js installation, npm ci, Cypress binary caching, browser installation, and headless execution in a single step. It eliminates 15-20 lines of manual configuration and is maintained by the Cypress team. For GitLab and Jenkins, use the official cypress/browsers Docker image which includes Chrome, Firefox, Edge, and all system dependencies pre-installed.CYPRESS_DEFAULT_COMMAND_TIMEOUT=10000 as an environment variable in your CI configuration. CI runners are typically slower than developer laptops due to shared CPU, containerisation overhead, and network latency. Increasing the default timeout from 4 seconds to 10 seconds prevents timeout-related flakiness in CI without changing your local development experience. You can also set CYPRESS_VIDEO=false to skip video recording and speed up the pipeline when you only need screenshots on failure.start and wait-on options in the GitHub Action handle this automatically. Without them, Cypress tries to visit your app at localhost:3000 and fails with a connection refused error. Always verify the app is healthy before starting tests.Common Mistakes
Mistake 1 — Not caching Cypress binary and node_modules
❌ Wrong: Every CI run downloads 500MB+ of npm packages and the Cypress binary from scratch — adding 3-5 minutes to every pipeline.
✅ Correct: Configuring dependency caching so npm ci uses the cache and the Cypress binary is restored from a previous run. The GitHub Action handles this automatically; for other CI platforms, cache ~/.cache/Cypress/ and node_modules/.
Mistake 2 — Not uploading failure artifacts
❌ Wrong: The pipeline fails, screenshots and videos are generated, but they are lost when the CI container is destroyed.
✅ Correct: Configuring artifact upload with if: failure() (GitHub) or when: on_failure (GitLab) so diagnostic evidence is preserved for post-failure analysis.