GitHub Action for running Cypress end-to-end and component tests
npm install @cypress/github-action> Cypress based cypress-io/github-action runs End-to-End or Component tests in GitHub Actions Continuous Integration (CI) workflows, optionally recording to Cypress Cloud
In addition to running Cypress tests, the action includes dependency installation, caching and more:
| Function | Benefits |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Single-line call | Simplified use by installing dependencies and running Cypress in one line of workflow code |
| Build app, Start server and Wait for server options | Convenience of app, server and test coordination |
| cypress run CLI type options | Improved readability with vertically listed workflow options |
| Dependency installation based on npm, pnpm and Yarn Classic lock files | Reduced command complexity |
| Caching of Cypress binary and dependencies for npm and Yarn Classic installations | Reduced download bandwidth requirements |
| Job summary | Fast access to results overview |
| Docker compatibility | Improved independence from GitHub-hosted runner image version changes. Fixed Docker environments can be used. |
| Recording to Cypress Cloud compatibility including parallel execution | Improved interpretation of test results through Cypress Cloud |
| Live examples | Speeds up introduction and troubleshooting |
| Yarn Modern usage and cache examples | Extends usage beyond Yarn Classic |
| pnpm cache examples | Reduced download bandwidth requirements for pnpm |
| Debug enabled | Improved workflow troubleshooting |
| Ping utility | Improved server reachability troubleshooting |
The following examples demonstrate the actions' functions.
- End-to-End testing
- Component testing
- Select action version
- Run tests in a given browser
- using Chrome
- using Chrome for Testing
- using Firefox
- using Edge
- using headed mode
- Using Docker image
- Specify environment variables
- Run only some spec files
- Test project in subfolder
- Record results on Cypress Cloud
- Getting Git information environment variables
- Getting PR and URL automatically
- Overwriting Merge SHA into SHA message
- Tag recordings
- Specify auto cancel after failures
- Store test artifacts on GitHub
- Quiet output
- Set Cypress config values
- Use specific config file
- Run tests in parallel
- Combine Component and E2E testing
- Build app before running the tests
- Start server before running the tests
- Start multiple servers before running the tests
- Wait for server to respond before running the tests
- Use custom install command
- Use command prefix
- Use custom test command
- Pass custom build id when recording to Cypress Cloud
- Generate a robust custom build id to allow re-running the workflow
- Use different working-directory
- Use subfolders
- Use pnpm
- Use pnpm workspaces
- Use Yarn Classic
- Use Yarn Modern
- Use Yarn Plug'n'Play
- Use Yarn workspaces
- Disable package manager cache
- Use custom cache key
- Run tests on multiple Node versions
- Split install and tests into separate jobs
- Split install and tests with artifacts
- Use custom install commands
- Install only Cypress to avoid installing all dependencies
- Use timeouts to avoid hanging CI jobs
- Print Cypress info like detected browsers
- Run tests nightly or on any schedule
- Specify job summary title
- Suppress job summary
- More examples
Examples contained in this repository, based on current Cypress versions, can be found in the examples directory.
Live examples, such as example-basic.yml are shown together with a status badge. Click on the status badge to read the source code of the workflow, for example

Note: this package assumes that cypress is declared as a development dependency in the package.json file. The cypress npm module is required to run Cypress via its Module API.
``yml`
name: End-to-end tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
# Install dependencies with caching
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v7

The workflow file example-basic.yml shows how Cypress runs on GH Actions using Ubuntu (22.04 and 24.04), Windows, and macOS without additional OS dependencies necessary.
This workflow uses the default test type of End-to-End (E2E) Testing. Alternatively, Component Testing can be utilized by referencing the Component Testing section below.
To use Cypress Component Testing add component: true
`yml`
name: Component tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
component: true

See the example project component-tests and the example-component-test.yml workflow for more details.
Best practice:
Our examples specify using branch v7 which is the action's recommended major version:
`yml`
- name: Cypress run
uses: cypress-io/github-action@v7
When using cypress-io/github-action@v7 from your workflow file, you will automatically use the latest tag from branch v7.
Alternatively, to mitigate unforeseen breaks, bind to a specific tag, for example:
`yml`
- name: Cypress run
uses: cypress-io/github-action@v7.0.0
The changes associated with each tag are shown under GitHub's releases list. Refer also to the CHANGELOG for an overview of major changes.
The workflows in the examples directory use the latest commit from the repo's current branch. This allows all tests to run in CI before release. If you copy any of the examples to your own repo, you should replace ./ and specify instead the action and version as described above.
`yml`
- uses: ./ # replace with cypress-io/github-action@v7
Specify the browser name or path with the browser parameter. The default browser, if none is specified, is the built-in Electron browser.
`yml`
name: Chrome
on: push
jobs:
chrome:
runs-on: ubuntu-24.04
name: E2E on Chrome
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: chrome

To install Google Chrome for Testing, specify a partial or full numerical Chrome for Testing version using browser-actions/setup-chrome. Refer to Chrome for Testing availability for current versions or JSON API endpoints for all available versions.
`yml`
name: Chrome for Testing
on: push
jobs:
chrome:
runs-on: ubuntu-24.04
name: E2E on Chrome for Testing
steps:
- uses: actions/checkout@v6
- uses: browser-actions/setup-chrome@v2
with:
chrome-version: 140
- uses: cypress-io/github-action@v7
with:
browser: chrome-for-testing

`yml`
name: Firefox
on: push
jobs:
firefox:
runs-on: ubuntu-24.04
name: E2E on Firefox
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: firefox

`yml`
name: Edge
on: push
jobs:
edge:
runs-on: ubuntu-24.04
name: E2E on Edge
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: edge

Run the browser in headed mode - as of Cypress v8.0 the cypress run command executes tests in headless mode by default
`yml`
name: Chrome headed
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: chrome
headed: true
You can run the action in a Docker container.
`yml`
name: Test in Docker
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
# Cypress Docker image from https://hub.docker.com/r/cypress
# with browsers pre-installed
container:
image: cypress/browsers:latest
options: --user 1001
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: chrome
Replace the latest tag with a specific version image tag from cypress/browsers on Docker Hub to avoid breaking changes when new images are released (especially when they include new major versions of Node.js).
Include options: --user 1001 to avoid permissions issues.
When using cypress/included Docker images, set the environment variable CYPRESS_INSTALL_BINARY=0 to suppress saving the Cypress binary cache, otherwise cache restore errors may occur. The example below shows how to do this:
`yml`
name: Test with Docker cypress/included
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
container:
# Cypress Docker image from https://hub.docker.com/r/cypress/included
# with Cypress globally pre-installed
image: cypress/included:latest
options: --user 1001
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
browser: chrome
env:
CYPRESS_INSTALL_BINARY: 0
Refer to cypress-io/cypress-docker-images for further information about using Cypress Docker images. Cypress offers the Cypress Docker Factory to generate additional Docker images with selected components and versions.

Specify the env argument with env parameter
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run with env
uses: cypress-io/github-action@v7
with:
env: host=api.dev.local,port=4222
`
When passing the environment variables this way, unfortunately due to GitHub Actions syntax, the variables should be listed in a single line, which can be hard to read. As an alternative, you can use the step's env block where every variable can be set on its own line. In this case, you should prefix every variable with CYPRESS_ because such variables are loaded by Cypress automatically. The above code example is equivalent to:
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run with env
uses: cypress-io/github-action@v7
env:
CYPRESS_host: api.dev.local
CYPRESS_port: 4222
`
For more examples, see the workflows below, using environment variables for recording.

Specify the spec files to run with spec parameter
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
spec: cypress/e2e/spec1.cy.js
`
You can pass multiple specs and wild card patterns using multi-line parameter, see example-config.yml:
`yml`
spec: |
cypress/e2e/spec-a.cy.js
cypress/*/-b.cy.js
For more information, visit the Cypress command-line docs.
Specify the project to run with the project parameter
`yml`
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
project: ./test-subdirectory
The project parameter may be used to pass on the location of a sub-directory containing a Cypress configuration file and Cypress tests specs. For more information, visit the Cypress command-line docs.
A package manager lock file, including Cypress, must be provided in the root of the repository so that the action is able to install Cypress.
If the parameter working-directory is also defined, then this is the location to place the package manager lock file, and the project directory would be a subdirectory of the working-directory. The project parameter location may not be above the level of a specified working-directory in the file hierarchy.
By setting the parameter record to true, you can record your test results into Cypress Cloud. Read the Cypress Cloud setup documentation to learn how to sign up to Cypress Cloud, to create and set up a Cloud project to get the required projectId and record key for recording.
- The projectId can either be stored in the Cypress Configuration File or passed to the action as an environment variable CYPRESS_PROJECT_ID. In the example below, it is retrieved from a GitHub secret variable.
- The record key is passed to the action as an environment variable CYPRESS_RECORD_KEY. We recommend you treat this value as sensitive and store it as a GitHub secret variable, so that access is restricted.
- We recommend passing the GITHUB_TOKEN secret (created by the GH Action automatically) as an environment variable. This will allow correctly identifying every build and avoid confusion when re-running a build.
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
env:
# pass the Cypress Cloud project ID as an environment variable or store it in the Cypress configuration file
CYPRESS_PROJECT_ID: ${{ secrets.EXAMPLE_PROJECT_ID }}
# pass the Cypress Cloud record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
# pass GitHub token to allow accurately detecting a build vs a re-run build
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
`

Cypress uses the @cypress/commit-info package to associate Git details (branch, commit message, author) with each run. It typically uses Git commands, expecting a .git folder. In Docker or similar environments where .git is absent, or if you need different data in the Cypress Cloud, Git information can be passed via custom environment variables.
`yml`
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
env:
# Get the short ref name of the branch that triggered the workflow run
COMMIT_INFO_BRANCH: ${{ github.ref_name }}
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
Please refer to the Cypress Cloud Git information environment variables section in our documentation for more examples.
Please refer to the default GitHub environment variables for additional GitHub examples.
When recording runs to Cypress Cloud, the PR number and URL can be automatically detected if you pass GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}env
via the workflow . When set, this value enables the Action to perform additional logic that grabs the related PR number and URL (if theyCYPRESS_PULL_REQUEST_ID
exist) and sets them in the environment variables and CYPRESS_PULL_REQUEST_URL, respectively.
- See Cypress' documentation on CI Build Information
Example workflow using the variables:
`yml`
name: Example echo PR number and URL
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
- run: echo "PR number is $CYPRESS_PULL_REQUEST_ID"
- run: echo "PR URL is $CYPRESS_PULL_REQUEST_URL"
env:
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#### Triggering event: pull_request/pull_request_target
For either of these events, we set CYPRESS_PULL_REQUEST_ID and CYPRESS_PULL_REQUEST_URL to that of the PR number and URL, respectively, of the
PR that triggered the workflow.
#### Triggering event: push
When a commit on a branch without a PR is made, the Cypress GitHub Action checks to see if the commit that triggered the workflow has a
related PR. If the commit exists in any other PRs, it's considered a related PR. When there are related PRs, we grab the first related PR
and use that PR's number and URL for CYPRESS_PULL_REQUEST_ID and CYPRESS_PULL_REQUEST_URL, respectively.
If no related PR is detected, CYPRESS_PULL_REQUEST_ID and CYPRESS_PULL_REQUEST_URL will be undefined.
We recommend using the action with on: push rather than on: pull_request or on: merge_group for more accurate commit information in Cypress Cloud. When running on pull_request or merge_group, the commit message defaults to "merge SHA into SHA". You can overwrite the commit message sent to Cypress Cloud by setting an environment variable.
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
env:
# overwrite commit message sent to Cypress Cloud
COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}}
# re-enable PR comment bot
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}}
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
`
See issue 124 for details.
You can pass a single or multiple tags when recording a run. For example
`yml
name: tags
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
# let's make sure our "app" works on several versions of Node
strategy:
matrix:
node: [20, 22, 24, 25]
name: E2E on Node v${{ matrix.node }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
- run: node -v
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
tag: node-${{ matrix.node }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
`
The recording will have tags as labels on the run.
!Tags
You can pass multiple tags using commas like tag: node-22,nightly,staging.
Specify the number of failed tests that will cancel a run when using the Cypress Cloud Auto Cancellation feature.
This feature requires Cypress 12.6.0 or later and a Cypress Cloud Business or Enterprise account.
`yml
name: Cypress E2E Tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
name: E2E
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
# Cancel the run after 2 failed tests
auto-cancel-after-failures: 2
env:
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
`
See Auto Cancellation for more information.
If you don't record the test run on Cypress Cloud, you can still store generated videos and screenshots as CI artifacts. See the workflow example below.
`ymlwarn
name: Artifacts
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
name: Artifacts
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
# after the test run completes store videos and any screenshots
- uses: actions/upload-artifact@v6
# add the line below to store screenshots only on failures
# if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to warn
- uses: actions/upload-artifact@v6
with:
name: cypress-videos
path: cypress/videos
if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to `
You can provide quiet flag for cypress run to silence any Cypress specific output from stdout
`ymlquiet
name: example-quiet
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
# Install dependencies with caching
# and run all Cypress tests with parameter`
- name: Cypress run
uses: cypress-io/github-action@v7
with:
working-directory: examples/quiet
quiet: true

Specify configuration values with config parameter
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
config: pageLoadTimeout=100000,baseUrl=http://localhost:3000
`

Specify the path to your Configuration File with config-file parameter
`yml
name: Cypress tests
on: push
jobs:
cypress-run:
name: Cypress run
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
config-file: cypress.config-alternate.js
`

Note: Cypress parallelization requires a Cypress Cloud account.
You can spin multiple containers running in parallel using strategy: matrix argument. Just add more dummy items to the containers: [1, 2, ...] array to spin more free or paid containers. Then use record and parallel parameters to load balance tests.
`yml
name: Parallel Cypress Tests
on: push
jobs:
test:
name: Cypress run
runs-on: ubuntu-24.04
strategy:
# when one test fails, DO NOT cancel the other
# containers, because this will kill Cypress processes
# leaving Cypress Cloud hanging ...
# https://github.com/cypress-io/github-action/issues/48
fail-fast: false
matrix:
# run 3 copies of the current job in parallel
containers: [1, 2, 3]
steps:
- name: Checkout
uses: actions/checkout@v6
# because of "record" and "parallel" parameters
# these containers will load balance all found tests among themselves
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
parallel: true
group: 'Actions example'
env:
# pass the Cypress Cloud record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
# Recommended: pass the GitHub token lets this action correctly
# determine the unique run id necessary to re-run the checks
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
`
The Cypress GH Action does not spawn or create any additional containers - it only links the multiple containers spawned using the matrix strategy into a single logical Cypress Cloud run where it splits the specs amongst the machines. See the Cypress Cloud Smart Orchestration guide for a detailed explanation.
If you use the GitHub Actions facility for Re-running workflows and jobs, note that Re-running failed jobs in a workflow is not suited for use with parallel recording into Cypress Cloud. Re-running failed jobs in this situation does not simply re-run failed Cypress tests. Instead it re-runs all Cypress tests, load-balanced over the containers with failed jobs.
To optimize runs when there are failing tests present, refer to optional Cypress Cloud Smart Orchestration Premium features:
- Spec Prioritization
- Auto Cancellation. See also Auto cancel after failures for details of how to set this option in a Cypress GitHub Action workflow.
During staged rollout of a new GitHub-hosted runner version, GitHub may provide a mixture of current and new image versions used by the container matrix. It is recommended to use a Docker image in the parallel job run which avoids any Cypress Cloud errors due to browser major version mismatch from the two different image versions. A Docker image is not necessary if testing against the default built-in Electron browser because this browser version is fixed by the Cypress version in use and it is unaffected by any GitHub runner image rollout.
Component Testing and End-to-End (E2E) Testing types can be combined in the same job using separate steps
`yml
- name: Run E2E tests
uses: cypress-io/github-action@v7
- name: Run Component Testing
uses: cypress-io/github-action@v7
with:
# we have already installed everything
install: false
component: true
`
See the example project component-test and the example-component-test.yml workflow for more details.
You can run a build step before starting tests
`yml`
name: Build
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
build: npm run build
If your tests run against a local server, use the start parameter to start your server. The server will run in the background.
`yml`
name: With server
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
start: npm start
Caution: use the start parameter only to start a server, not to run Cypress, otherwise tests may be run twice. The action runs Cypress tests by default, unless the parameter runTests is set to false.
Note: sometimes on Windows you need to run a different start command. You can use the start-windows parameter for this.
`yml`
name: With server
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
# Linux and macOS
start: npm start
# Takes precedences on Windows
start-windows: npm run start:windows:server

Note: A server continues to run until the end of the GitHub workflow job that started it. At the end of the job the GitHub workflow runner executes a "Complete job" phase automatically where it terminates any server processes which are still running.
You can start multiple server processes. For example, if you have an API to start using npm run api and the web server to start using npm run web you can put those commands in start using comma separation.
`yml`
name: With servers
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
start: npm run api, npm run web
You can place the start commands in separate lines
`yml`
with:
start: |
npm run api
npm run web

If you are starting a local server and it takes a while to start, you can add a parameter wait-on and pass url to wait for the server to respond.
`yml`
name: After server responds
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
start: npm start
# quote the url to be safe against YML parsing surprises
wait-on: 'http://localhost:8080'

 (also uses wait-on)
By default, wait-on will retry for 60 seconds. You can pass a custom timeout in seconds using wait-on-timeout.
`yml`
- uses: cypress-io/github-action@v7
with:
start: npm start
wait-on: 'http://localhost:8080/status'
# wait for 2 minutes for the server to respond
wait-on-timeout: 120
You can wait for multiple URLs to respond by separating urls with a comma
`yml`
- uses: cypress-io/github-action@v7
with:
# API runs on port 3050
# Web server runs on port 8080
start: npm run api, npm run web
# wait for all services to respond
wait-on: 'http://localhost:3050, http://localhost:8080'
The action will wait for the first url to respond, then will check the second url, and so on.
You can even use your own command (usually by using npm, yarn, npx) to wait for the server to respond. For example, if you want to use the wait-on utility to ping the server and run the Cypress tests after the server responds:
`yml`
- uses: cypress-io/github-action@v7
with:
start: npm start
wait-on: 'npx wait-on --timeout 60000 http://localhost:3000'
See example-wait-on.yml workflow file.
If this action times out waiting for the server to respond, please see Debugging section in this README file.
The action installs dependencies based on a package manager lock file using default commands described in the Installation section below. If you want to overwrite the default install command you can use the install-command option:
`yml`
- uses: cypress-io/github-action@v7
with:
install-command: yarn --frozen-lockfile --silent
See example-install-command.yml workflow file.
If you do not commit a lock file to the repository, you cannot use the action to install dependencies. In this case you must ensure that dependencies are installed before using the action, and you must use the action option setting install: false.
You can prefix a test command using the command-prefix parameter. This is useful, for example, when running BrowserStack Percy, which requires the test command to be prefixed with percy exec --. When this parameter is used, the action constructs and executes a CLI command using npx in the following form:
`shell`
npx
where the is the literal string value from the command-prefix parameter and are put together from action parameters such as the value of the browser parameter. The complete constructed command is shown in the logs. For the example below, this is shown as:
`text`
Cypress test command: npx percy exec -- npx cypress run --browser chrome
Since command-prefix is run using npx, it is compatible with npm and Yarn Classic. It may also be used with pnpm and Yarn Modern when they are configured for nodeLinker compatibility with the node_modules directory structure of npm. An alternative to using command-prefix is to pass a complete command parameter instead, including the exact command to be passed to the CLI.
`yml`
name: Visual
on: push
jobs:
e2e:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
command-prefix: 'percy exec -- npx'
browser: chrome
If command-prefix is used, then no job summary is produced, since it runs Cypress with a CLI cypress run command instead of using the Cypress Module API. The command parameter overrides the command-prefix parameter, preventing these two parameters from being used together.
The command parameter executes a CLI command using the GitHub @actions/exec action.
This parameter is useful for special test cases, for example:
- in the project examples/custom-command, a JavaScript examples/custom-command/index.js is run with node . through command: npm run custom-testcommand: yarn run --binaries-only cypress run
- in the workflow example-yarn-modern-pnp.yml Yarn Modern with Plug'n'Play is run with since Yarn Plug'n'Play is not natively supported by the action.
If you don't have a special case and you just need to convert a cypress run CLI command to use the Cypress GitHub Action, refer to the section Migrating from CLI command which explains how to map CLI options to equivalent action parameters, avoiding the need for the command parameter in most cases.
There are some parameters that cannot be used together with the command parameter, and these are ignored. The parameters include action input parameters listed in the table CLI Run Option / Action Parameter, the publish-summary, summary-title and command-prefix. If any such parameters are passed to the action, a warning message appears in the logs that the parameters have been ignored.
Correct example snippet:
`yml`
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
command: npm run custom-test

You can overwrite ci-build-id used to link separate machines running tests into a single parallel run.
`yml`
name: Parallel
on: push
jobs:
test:
runs-on: ubuntu-24.04
strategy:
matrix:
# run 3 copies of the current job in parallel
containers: [1, 2, 3]
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
record: true
parallel: true
group: 'Actions example'
ci-build-id: '${{ github.sha }}-${{ github.workflow }}-${{ github.event_name }}'
env:
# pass the Cypress Cloud record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Tip: see Learn GitHub Actions, with sections on Expressions, Contexts and Environment variables.
If you re-run the GitHub workflow, if you use the same custom build id during recording, Cypress Cloud will cancel the run with "Build already finished" error. To avoid this, you need to generate a _new_ custom build id on every workflow re-run. A good solution showing in the example-custom-ci-build-id.yml file is to run a common job first that just generates a new random ID. This ID can be used by the testing jobs to tie the build together. If the user re-runs the workflow a new unique build id is generated, allowing recording the new Cypress Cloud run.
`yml`
jobs:
# single job that generates and outputs a common id
prepare:
outputs:
uuid: ${{ steps.uuid.outputs.value }}
steps:
- name: Generate unique ID 💎
id: uuid
# take the current commit + timestamp together
# the typical value would be something like
# "sha-5d3fe...35d3-time-1620841214"
run: echo "value=sha-$GITHUB_SHA-time-$(date +"%s")" >> $GITHUB_OUTPUT
smoke-tests:
needs: ['prepare']
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
record: true
parallel: true
ci-build-id: ${{ needs.prepare.outputs.uuid }}
env:
# pass the Cypress Cloud record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
See the example-custom-ci-build-id.yml for the full workflow.
In a monorepo, the end-to-end or component test might be placed in a different sub-folder from the application itself. This sub-folder is the Cypress "working directory" which you can specify using the working-directory parameter.
In the following example of a directory layout for end-to-end testing, the Cypress working directory is app-test. The working directory contains the Cypress tests and a package manager lock file:
`text`
repo/
app/
app-test/
cypress/
e2e/
fixtures/
support/
cypress.config.js
package.json
package-lock.json
We use working-directory: app-test to match the above example directory structure:
`yml`
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
start: npm start
working-directory: app-test
See the Cypress documentation Folder structure section for examples of standard directory layouts, covering end-to-end testing and component testing with both JavaScript and TypeScript options.
Each of the examples in this monorepo is separated from other examples by using different working directories. See example-basic.yml for one end-to-end test example using the parameter working-directory and example-component-test.yml for a component test example.
Sometimes the application under test and the Cypress end-to-end tests may have separately defined dependencies. In the example below, Cypress has its own package.json file in a subfolder:
`text
root/
e2e/
(code for installing and running Cypress tests)
package.json
package-lock.json
cypress.config.js
cypress/
(code for running the "app" with "npm start")
package.json
package-lock.json
`
In this case you can first install the dependencies for the application (npm ci), then start the application server (npm start) before calling cypress-io/github-action to install the dependencies for Cypress and to run Cypress. You may also need to use the wait-on parameter to make sure that the app server is fully available.
`yml
name: E2E
on: push
jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Install root dependencies
run: npm ci
- name: Start server in the background
run: npm start &
# Cypress has its own package.json in folder "e2e"
- name: Install Cypress and run tests
uses: cypress-io/github-action@v7
with:
working-directory: e2e
`
The package manager pnpm is not pre-installed in GitHub Actions runner imagespnpm-lock.yaml
(unlike npm and Yarn Classic) and so it must be installed in a separate workflow step (see below).
If the action finds a file, it uses the pnpm command pnpm install --frozen-lockfile by default to install dependencies.
The example below follows pnpm recommendations for installing pnpm and caching the
pnpm store.
Follow the Cypress pnpm configuration instructions
and apply them to your project, to enable pnpm to install the Cypress binary.
`yaml`
name: example-basic-pnpm
on: push
jobs:
basic-pnpm:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
cache-dependency-path: examples/basic-pnpm/pnpm-lock.yaml
- name: Cypress run
uses: cypress-io/github-action@v7
with:
package-manager-cache: false
working-directory: examples/basic-pnpm

The action does not directly support using pnpm workspaces
(see feature request #1144).
As a workaround, you can install dependencies and run Cypress tests in a workspace in separate steps.
The snippet below shows this principle.
`yml
...
- name: Install dependencies
uses: cypress-io/github-action@v7
with:
package-manager-cache: false
runTests: false
working-directory: examples/start-and-pnpm-workspaces
- name: Cypress test
uses: cypress-io/github-action@v7
with:
install: false
working-directory: examples/start-and-pnpm-workspaces/packages/workspace-1
...
`

See the example project start-and-pnpm-workspaces and the example-start-and-pnpm-workspaces.yml workflow for a full working example.
If a yarn.lock file is found, the action uses the Yarn 1 (Classic) command yarn --frozen-lockfile by default to install dependencies.
`yaml`
name: example-yarn-classic
on: push
jobs:
yarn-classic:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
working-directory: examples/yarn-classic

To install dependencies using a yarn.lock file from Yarn Modern (Yarn 2 and later) you need to override the default Yarn 1 (Classic) installation command yarn --frozen-lockfile. You can do this by using the install-command parameter and specifying yarn install as in the example below.
The action supports built-in caching of Yarn Classic dependencies only. To cache Yarn Modern dependencies additionally use actions/setup-node and specify cache: yarn.
`yaml`
name: example-yarn-modern
on: push
jobs:
yarn-modern:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- run: corepack enable # (experimental and optional)
- name: Set up Yarn cache
uses: actions/setup-node@v6
with:
node-version: 24
cache: yarn
cache-dependency-path: examples/yarn-modern/yarn.lock
- name: Cypress run
uses: cypress-io/github-action@v7
with:
working-directory: examples/yarn-modern
install-command: yarn install
This example covers the .yarnrc.yml configuration nodeLinker: node-modules which Yarn uses by default for projects updated from Yarn Classic. For nodeLinker: pnp see Yarn Plug'n'Play below.github-action
(Note that is not compatible with the nodeLinker: pnpm setting.)

When using Yarn Modern (Yarn 2 and later) with Plug'n'Play enabled, you will need to use the command parameter to run yarn instead of npx.
See the above Yarn Modern section for information on caching Yarn Modern dependencies.
`yaml`
name: example-yarn-modern-pnp
on: push
jobs:
yarn-classic:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Cypress run
uses: cypress-io/github-action@v7
with:
working-directory: examples/yarn-modern-pnp
install-command: yarn install
command: yarn run --binaries-only cypress run
This example covers the .yarnrc.yml configuration when nodeLinker is undefined or set to nodeLinker: pnp corresponding to Yarn Plug'n'Play. Yarn uses this by default for projects newly created with Yarn Modern.

Caution: using the action parameter command causes multiple other parameters to be ignored. See command section for more information.
This action should discover the Yarn workspaces correctly. For example, see folder examples/start-and-yarn-workspaces and workflow file example-start-and-yarn-workspaces.yml
`yaml`
name: example-start-and-yarn-workspaces
on: push
jobs:
single:
# the example has Yarn workspace in its "root" folder
# examples/start-and-yarn-workspaces
# and tests in a subfolder like "workspace-1"
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: cypress-io/github-action@v7
with:
working-directory: examples/start-and-yarn-workspaces/workspace-1
build: yarn run build
start: yarn start
wait-on: 'http://localhost:5000'

When the action installs dependencies,
it caches the package manager cache from npm or from Yarn 1 (Classic) by default,
based on the lockfile it discovers.
If package manager caching is implemented separately from the action,
for example to work with Yarn Modern or pnpm,
then disable the actions' package manager caching by setting the parameter
package-manager-cache to false.
GitHub's actions/setup-node offers a convenient way to install a chosen version of Node.js
and to set up caching of package manager caches in one step.
`yml`
name: Package manager caching
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
name:
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts
cache: 'pnpm'
cache-dependency-path: pnpm-lock.yaml
- uses: cypress-io/github-action@v7
with:
package-manager-cache: false
Sometimes the default cache key does not work. For example, if you cannot share the Node modules across Node versions due to native extensions. In that case pass your own cache-key parameter.
`yml`
name: End-to-end tests
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
# let's make sure our "app" works on several versions of Node
strategy:
matrix:
node: [20, 22, 24, 25]
name: E2E on Node v${{ matrix.node }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
# run Cypress tests and record them under the same run
# associated with commit SHA and just give a different group name
- name: Cypress run
uses: cypress-io/github-action@v7
with:
record: true
group: Tests on Node v${{ matrix.node }}
cache-key: node-v${{ matrix.node }}-on-${{ runner.os }}-hash-${{ hashFiles('yarn.lock') }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
You can run your tests across multiple Node versions.
`yml`
name: Node versions
on: push
jobs:
cypress-run:
runs-on: ubuntu-24.04
strategy:
matrix:
node: [20, 22, 24, 25]
name: E2E on Node v${{ matrix.node }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
- uses: cypress-io/github-action@v7
See the Node.js section for information about supported versions and usage of Node.js.

Sometimes you may want to run additional commands between installation and tests. To enable this use the install and runTests parameters.
`yml``
name: E2E
on: push
jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Install dependencies
uses: cypress-io/github-action@v7
with:
# just perform install
runTests: false
- run: yarn lint
- name: Run e2e tests
uses: cypress-io/github-action@v7
with:
# we have already installed all dependencies above
install: false
# Cypress tests and config file are in "e2e" folder
working-directory: e2e
See cypress-gh-action-monorepo for a working example.
If your test job(s) first need a build step, you can split the jobs into a separate build job followed by test jobs. You pass the build results to any subsequent jobs using [GitHub Actions artifacts](http