Utilizing Github actions, to run multiple Cypress specs in parallel

Starting at the route of your project create a .github/workflows/ directory. This is where you will be defining and creating your different workflows. Each workflow will be responsible for running their own set of jobs and steps.

Workflow Name

name: Cypress Automation

Workflow Schedule

I like to set both a cron schedule as well as a workflow dispatch. The dispatch will allow for manually triggering these jobs if you ever find it necessary to.

on:
  schedule:
    - cron '0 14 * * *'
  workflow_dispatch:

Environment Variables

Usually this is where you would read in any defined secrets you already have stored in your github repository secrets. Note that Cypress environment variables should be prefixed with CYPRESS_

env:
   GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
   CYPRESS_TEST_ENV: 'staging'

Workflow Jobs

Note that jobs run in parallel and there are a couple variations you can do to write these more efficiently.

The most basic way I would define my jobs is as follow:

jobs:
 e2e_can_chrome:
    name: Canada End-To-End Suite(Chrome)
    runs-on: ubuntu-latest
    timeout-minutes: 50
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      # Install NPM dependencies, cache them correctly
      # and run all Cypress tests
      - name: Setup Report
        run: yarn clean:reports
      - name: Clean Cache
        run: yarn cache clean
      - name: Install Dependencies
        run: yarn install
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - name: Canada E2E on Chrome
        uses: cypress-io/github-action@v2
        with:
          browser: chrome
          spec: cypress/integration/web-client/canada/end.to.end.spec.ts
        env:
          # pass the Dashboard 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 }}
          CYPRESS_COUNTRY_HEADER: 'ca'
          CYPRESS_COUNTRY_SHORT_CODE: 'CAN'
          CYPRESS_STORE_ID: '3001'
      - name: Copy Screenshots
        run: yarn copy:screenshots
        if: failure()
      - name: Notify Slack
        run: yarn alert:slack
        if: failure()
      - name: generate report
        if: always()
        run: yarn generate:report
      - name: Upload Report
        uses: actions/upload-artifact@v2
        if: always()
        with:
          name: Canada Chrome End-To-End Report
          path: cypress/reports/mochareports/

Some things to note from above:

The if conditions that can be seen above will allow me to control when to run certain steps. I utilize this in order to run a yarn command to send slack alerts on when a job is not successful

The env noted above allows you to override any defined env variables defined on the higher upper scope of you workflow file. This can be useful when trying to define env variables that are specific for just one specific test run. Example of this would maybe you want to run the same script for two different countries.

The artifact upload is useful to save or upload reports or html files to an artifact making it available for download on Github

Optimizations

The downside to structuring your workflow files as I outlined above is eventually you end up with too many jobs that your workflow file becomes far too big. As you would be creating a single job for every spec file you have.

One better way to handle this limitation is to utilize the strategy matrix expansion. This would essentially spin up multiple containers to run test in.

jobs:
   setup:
     name: Run 3 test in parallel
     runs-on: ubuntu-20.04
     strategy:
       fail-fast: false
       matrix:
         # run 3 copies of the current job or set of specs in parallel
         containers: [1, 2, 3]

However this method comes with a heavy cost. It requires setting up recording to the Cypress Dashboard. A paid subscription with the utilization of the cypress dashboard is needed.