Trigger Selected Cypress Specs Using GitHub Actions

How to quickly run selected Cypress specs via GitHub manual dispatch workflow.

Imagine you have multiple specs, and a test run fails. You see the names of the specs that failed. How do you proceed? For example in the repo bahmutov/cypress-grep-example the recorded CI run had 3 failed specs.

Three specs failed according to Cypress Dashboard

Hmm, I think this is a temporary problem. Maybe I should run these specs by themselves again to see if they still fail. I could use the new Cypress Debug tab 📺, but it would mean running the specs locally. I just want to trigger a new CI run and only have the specs "app-spec.js", "persistence-spec.js", and "routing-spec.js" take part.

Here is how to do this easily. Create a new manual dispatch GitHub workflow.

.github/workflows/trigger-specs.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
name: Trigger specs
on:
workflow_dispatch:
inputs:
specs:
description: Comma-separates spec filenames without spaces
required: true
jobs:
specs:
runs-on: ubuntu-20.04
steps:
- name: Print specs 🖨️
env:
SPECS: ${{ toJson(github.event.inputs.specs) }}
run: echo "$SPECS"

- name: Checkout 🛎
uses: actions/checkout@v3

- name: Run selected specs 🏃
# https://github.com/cypress-io/github-action
uses: cypress-io/github-action@v5
with:
start: npm run start:ci
wait-on: 'http://localhost:8888'
spec: '${{ github.event.inputs.specs }}'
record: true
tag: Trigger specs
group: Selected specs
# each workflow execution should have its own recorded run
ci-build-id: '${{ github.workflow }} - ${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempts }}'
env:
# pass the Dashboard record key as an environment variable
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

We grab the user input from the event and pass it to the Cypress GH action via spec: '${{ github.event.inputs.specs }}' parameter.

⚠️ Watch out: the list of specs cannot have any spaces, foo.js,bar.js is going to run both specs, while foo.js, bar.js will only execute the first spec foo.js

🎓 Not sure how to use GitHub Actions? Read my blog post Trying GitHub Actions and check out presentation Is there anything GitHub Actions cannot do?!.

Let's trigger an example test run. From GitHub Actions tab pick the Trigger specs workflow. Enter the comma-separated relative spec filenames into the input field: cypress/e2e/app-spec.js,cypress/e2e/persistence-spec.js,cypress/e2e/routing-spec.js.

Enter three specs to execute

The test run shows only 3 specs are being executed by Cypress

Only three selected specs execute

Custom recording tag

Let's tag the recorded run in the Cypress Dashboard. Add one more parameter to the workflow inputs and pass it to the Cypress GH action:

1
2
3
4
5
6
7
8
9
10
on:
workflow_dispatch:
inputs:
specs:
description: Comma-separates spec filenames without spaces
required: true
recordingTag:
description: Cypress Dashboard recording tag
required: false
default: Trigger specs

Pass the recordingTag to the action as its input

1
2
3
4
5
6
7
8
uses: cypress-io/github-action@v5
with:
start: npm run start:ci
wait-on: 'http://localhost:8888'
spec: '${{ github.event.inputs.specs }}'
record: true
tag: '${{ github.event.inputs.recordingTag }}'
group: Selected specs

Let's run one spec

Trigger a single routing spec

The dashboard recording shows the custom tag "routing"

Routing tag

Parallel machines

Let's add one more parameter to allow the user to specify the number of machines to run the picked specs in parallel. It is nice to let the user run a lot of specs really quickly, right. Unfortunately, you would need to fiddle with GH workflow to make it dynamic. Luckily, I prepared reusable Cypress workflows that you can use. Let's create another manual dispatch workflow. We will pass the machines input to the parallel workflow's n input by casting it as a number

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
name: Trigger parallel specs
on:
workflow_dispatch:
inputs:
specs:
description: Comma-separates spec filenames without spaces
required: true
recordingTag:
description: Cypress Dashboard recording tag
required: false
default: Trigger specs
machines:
description: Number of machines to use to run these specs
required: false
type: number
default: 1

jobs:
print:
runs-on: ubuntu-20.04
steps:
- name: Print inputs 🖨️
env:
INPUTS: ${{ toJson(github.event.inputs) }}
run: echo "$INPUTS"

specs:
# https://github.com/bahmutov/cypress-workflows
uses: bahmutov/cypress-workflows/.github/workflows/parallel.yml@v1
with:
n: ${{ fromJson(github.event.inputs.machines) }}
spec: '${{ github.event.inputs.specs }}'
tag: '${{ github.event.inputs.recordingTag }}'
group: Selected specs
start: npm run start:ci
wait-on: 'http://localhost:8888'
# each workflow execution should have its own recorded run
ci-build-id: '${{ github.workflow }} - ${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempts }}'
secrets:
recordKey: ${{ secrets.CYPRESS_RECORD_KEY }}

Trigger this new parallel workflow from GitHub Actions tab. Let's use the same three specs and run it across 3 machines

Trigger the parallel workflow

The GH workflow shows the 3 jobs running in parallel, created by the parallel reusable workflow.

Parallel test jobs

The dashboard recording tagged "three" shows all selected specs running in parallel, one spec per machine

Parallel test jobs

Tip: If you want to run selected specs in parallel without using Cypress Dashboard, try cypress-split plugin. There is even a reusable "split" workflow in the cypress-workflows already.

Tip 2: if you use CircleCI to run Cypress tests, you can still trigger the tests using the manual dispatch workflow and passing the specs to the bahmutov/trigger-circleci-pipeline command.

See also