How to shard Cypress specs on GitHub Actions


This post goes over how to shard Cypress specs on GitHub Actions:

Parallel

If you have a Cypress Cloud account, you can spin multiple containers running in parallel using strategy: matrix:

# .github/workflows/cypress.yml
name: Parallel Cypress Tests
on: push

jobs:
  test:
    name: Cypress run
    runs-on: ubuntu-latest
    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 repository
        uses: actions/checkout@v4

      # because of "record" and "parallel" parameters
      # these containers will load balance all found tests among themselves
      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          record: true
          parallel: true
          group: 'Actions example'
        env:
          # pass the Cypress Cloud record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_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 }}

See the Cypress docs for more information on parallelization.

Shard

You can shard the Cypress specs with Bash using GitHub Actions:

# .github/workflows/cypress.yml
name: Shard Cypress Tests
on: push

jobs:
  cypress:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        # shard is zero-based since we're using the `split` command
        shard: [0, 1, 2]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Split specs
        id: specs
        run: |
          # find and save all spec paths to a file
          SPECS=specs.txt
          find cypress/e2e -type f -name '*.cy.*' > $SPECS

          # count the total number of spec files
          SPECS_COUNT=$(wc -l < $SPECS)

          # calculate the number of lines to split (rounded up)
          LINES=$(( ($SPECS_COUNT + 1) / ${{ strategy.job-total }} ))

          # split the spec files
          split -d -l $LINES $SPECS spec

          # save the current shard of spec files to an output parameter
          echo "SPECS<<EOF" >> $GITHUB_OUTPUT
          cat spec0${{ matrix.shard }} >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          browser: chrome
          spec: |
            # pass specs from the previous step
            ${{ steps.specs.outputs.SPECS }}

You can see that the Cypress specs were split into 3 shards and passed into the GitHub Action via an output parameter. Alternatively, you can store the specs in an environment variable.

See example remarkablemark/cypress-cucumber-steps#979.



Please support this site and join our Discord!