Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 172 additions & 1 deletion .github/workflows/frontend-pr-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,50 @@ on:
type: boolean
default: false

# Cypress configuration
run-cypress-functional:
description: 'Run Cypress functional tests'
type: boolean
default: false
cypress-functional-command:
description: 'Cypress functional test command'
type: string
default: 'yarn test:functional'
cypress-functional-start:
description: 'Command to start server for functional tests'
type: string
default: 'yarn start:ci'
cypress-functional-wait-on:
description: 'URL to wait for before running functional tests'
type: string
default: 'http://localhost:9000'

run-cypress-visual:
description: 'Run Cypress visual regression tests'
type: boolean
default: false
cypress-visual-command:
description: 'Cypress visual test command'
type: string
default: 'yarn test:visual'
cypress-visual-start:
description: 'Command to start server for visual tests'
type: string
default: 'yarn start:ci'
cypress-visual-wait-on:
description: 'URL to wait for before running visual tests'
type: string
default: 'http://localhost:9000'

cypress-runner:
description: 'Runner for Cypress tests (defaults to e2e-runner)'
type: string
default: ''
cypress-timeout:
description: 'Cypress test timeout (minutes)'
type: number
default: 20

# Deployment configuration
deploy-preview:
description: 'Deploy preview environment'
Expand Down Expand Up @@ -174,6 +218,14 @@ on:
required: false
JENKINS_USER_TOKEN:
required: false
CYPRESS_RECORD_KEY:
required: false
VRT_APIURL:
required: false
VRT_APIKEY:
required: false
VRT_PROJECT:
required: false

permissions:
id-token: write
Expand Down Expand Up @@ -439,4 +491,123 @@ jobs:
app: ${{ inputs.app-name }}
secrets:
JENKINS_OKTA_USERNAME: ${{ secrets.JENKINS_OKTA_USERNAME }}
JENKINS_USER_TOKEN: ${{ secrets.JENKINS_USER_TOKEN }}
JENKINS_USER_TOKEN: ${{ secrets.JENKINS_USER_TOKEN }}

# Job 8: Cypress Functional Tests
cypress-functional:
name: ⚙️ Cypress Functional
if: inputs.run-cypress-functional
needs: build
runs-on: ${{ fromJSON(inputs.cypress-runner != '' && inputs.cypress-runner || inputs.e2e-runner) }}
timeout-minutes: ${{ inputs.cypress-timeout }}

steps:
- name: Check out Git repository
uses: actions/checkout@v4

- name: Setup Node with Cache
uses: Typeform/.github/shared-actions/setup-node-with-cache@v1
with:
node-version: ${{ inputs.node-version }}
use-asdf: ${{ inputs.use-asdf }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Setup Jarvis
uses: Typeform/.github/shared-actions/setup-jarvis@v1
with:
jarvis-branch: ${{ inputs.jarvis-branch }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Setup Cypress
uses: Typeform/.github/shared-actions/setup-cypress@PLT-2912-add-cypress-support-for-workflows

- name: Run pre-test command
if: inputs.pre-test-command != ''
run: ${{ inputs.pre-test-command }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Cypress functional tests
uses: cypress-io/github-action@v6
timeout-minutes: 15
with:
install: false
start: ${{ inputs.cypress-functional-start }}
wait-on: ${{ inputs.cypress-functional-wait-on }}
command: ${{ inputs.cypress-functional-command }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
CYPRESS_PORT: 8080

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: cypress-functional-results-${{ github.run_id }}
path: |
cypress/screenshots/
cypress/videos/
retention-days: 7

# Job 9: Cypress Visual Tests
cypress-visual:
name: 🎨 Cypress Visual
if: inputs.run-cypress-visual
needs: build
runs-on: ${{ fromJSON(inputs.cypress-runner != '' && inputs.cypress-runner || inputs.e2e-runner) }}
timeout-minutes: ${{ inputs.cypress-timeout }}

steps:
- name: Check out Git repository
uses: actions/checkout@v4

- name: Setup Node with Cache
uses: Typeform/.github/shared-actions/setup-node-with-cache@v1
with:
node-version: ${{ inputs.node-version }}
use-asdf: ${{ inputs.use-asdf }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Setup Jarvis
uses: Typeform/.github/shared-actions/setup-jarvis@v1
with:
jarvis-branch: ${{ inputs.jarvis-branch }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Setup Cypress
uses: Typeform/.github/shared-actions/setup-cypress@PLT-2912-add-cypress-support-for-workflows

- name: Run pre-test command
if: inputs.pre-test-command != ''
run: ${{ inputs.pre-test-command }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Cypress visual tests
uses: cypress-io/github-action@v6
timeout-minutes: 15
with:
install: false
start: ${{ inputs.cypress-visual-start }}
wait-on: ${{ inputs.cypress-visual-wait-on }}
command: ${{ inputs.cypress-visual-command }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
CYPRESS_PORT: 8080
VRT_APIURL: ${{ secrets.VRT_APIURL }}
VRT_APIKEY: ${{ secrets.VRT_APIKEY }}
VRT_PROJECT: ${{ secrets.VRT_PROJECT }}
VRT_BRANCHNAME: ${{ github.head_ref || github.ref_name }}
VRT_CIBUILDID: ${{ github.sha }}

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: cypress-visual-results-${{ github.run_id }}
path: |
cypress/screenshots/
cypress/videos/
retention-days: 7
151 changes: 151 additions & 0 deletions shared-actions/setup-cypress/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Setup Cypress with Caching

A reusable GitHub Action for installing and caching Cypress binary to speed up CI workflows.

## Features

- 🚀 **Automatic Version Detection**: Detects Cypress version from `node_modules` or `package.json`
- 💾 **Intelligent Caching**: Caches Cypress binary with version-specific keys
- 🔄 **Fallback Cache Keys**: Uses progressive cache restoration for faster setup
- ⚙️ **Flexible Installation**: Supports yarn installation
- ✅ **Verification**: Validates Cypress installation after setup

## Usage

### Basic Usage

```yaml
- name: Setup Cypress
uses: Typeform/.github/shared-actions/setup-cypress@v1
```

### Complete Example

```yaml
name: Cypress Tests
on: [pull_request]

jobs:
test:
runs-on: [self-hosted, ci-e2e]
steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: Typeform/.github/shared-actions/setup-node-with-cache@v1
with:
use-asdf: true
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Setup Cypress
uses: Typeform/.github/shared-actions/setup-cypress@v1

- name: Run Cypress Tests
uses: cypress-io/github-action@v6
with:
install: false
start: yarn start:ci
wait-on: 'http://localhost:9000'
command: yarn test:functional
```

## What It Does

1. **Detects Cypress Version**
- First tries to read from `node_modules/cypress/package.json`
- Falls back to reading from `package.json` dependencies
- Uses `unknown` if version cannot be detected

2. **Caches Cypress Binary**
- Primary key: `{os}-{arch}-cypress-{version}`
- Fallback keys for partial matches
- Caches `~/.cache/Cypress` directory

3. **Installs Cypress Binary**
- Skipped if cache hit
- Runs `yarn cypress install`
- Verifies installation success

## Cache Strategy

### Primary Cache Key
```
Linux-X64-cypress-13.6.2
```

### Restore Keys (Fallback)
```
Linux-X64-cypress-
```

This allows:
- Exact version match (fastest)
- Same OS/architecture, different version (fast)

## Performance Impact

| Scenario | Time Saved | Notes |
|----------|------------|-------|
| Cache Hit | ~30-60s | No download or installation needed |
| Cache Miss | 0s | Must download and install binary |
| Partial Match | ~15-30s | May reuse some cached data |

## Prerequisites

- Node.js and yarn must be installed
- Cypress must be listed in `package.json` dependencies or devDependencies
- `node_modules` should be installed before running this action

## Troubleshooting

### Cypress binary not found

**Problem**: Tests fail with "Cypress binary not found"

**Solution**:
1. Ensure `node_modules` is installed before this action
2. Verify Cypress is in `package.json` dependencies
3. Try clearing cache and re-running

### Cache not working

**Problem**: Cache is not being hit

**Solution**:
1. Check Cypress version is being detected correctly
2. Verify cache key format
3. Ensure runner OS/architecture matches
4. Check cache storage limits haven't been exceeded

### Version detection fails

**Problem**: Version shows as "unknown"

**Solution**:
1. Ensure `package.json` exists in working directory
2. Verify Cypress is listed in dependencies or devDependencies
3. Install `node_modules` before running this action

## Compatibility

### Cypress Versions
- ✅ Cypress 9.x
- ✅ Cypress 10.x
- ✅ Cypress 12.x
- ✅ Cypress 13.x

## Reusable By

This action is used by:
- [`frontend-pr-workflow.yml`](../../.github/workflows/frontend-pr-workflow.yml) - Centralized PR workflow
- Individual project workflows for Cypress testing


## Best Practices

1. **Always install node_modules first**: This action requires Cypress to be in node_modules
2. **Use with cypress-io/github-action**: Set `install: false` to skip redundant installation
3. **Monitor cache hit rates**: Check workflow logs to ensure caching is effective
4. **Version pin Cypress**: Use exact versions in package.json for consistent caching


Loading