Skip to content
Closed
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
14 changes: 9 additions & 5 deletions .github/actions/e2e-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ inputs:
e2e_test_token:
description: The authentication token used for E2E test endpoints.
required: true
slack_token:
description: The slack authentication token.
required: true
environment:
description: The value of the ENV environment variable to use for npm run env.
required: true
Expand Down Expand Up @@ -48,6 +45,13 @@ runs:
lsof -ti:3000 | xargs kill -9 || true
env:
E2E_TEST_TOKEN: ${{ inputs.e2e_test_token }}
SLACK_TOKEN: ${{ inputs.slack_token }}
ENV: ${{ inputs.environment == 'production' && 'prod' || inputs.environment }}
GITHUB_ACTION_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

- name: Upload failed test videos
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-failed-test-videos-${{ inputs.environment }}-${{ github.run_attempt }}
path: frontend/reports/screen-captures/*.mp4
if-no-files-found: ignore
retention-days: 30
1 change: 0 additions & 1 deletion .github/workflows/.reusable-deploy-ecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,4 @@ jobs:
uses: ./.github/actions/e2e-tests
with:
e2e_test_token: ${{ secrets.E2E_TEST_TOKEN }}
slack_token: ${{ secrets.SLACK_TOKEN }}
environment: ${{ inputs.environment }}
14 changes: 9 additions & 5 deletions .github/workflows/.reusable-docker-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ on:
GCR_TOKEN:
description: A token to use for logging into Github Container Registry. If not provided, login does not occur.
required: false
SLACK_TOKEN:
description: A token to use uploading test failures to slack.
required: false

jobs:
run-e2e:
Expand Down Expand Up @@ -84,5 +81,12 @@ jobs:
API_IMAGE: ${{ inputs.api-image }}
E2E_IMAGE: ${{ inputs.e2e-image }}
E2E_CONCURRENCY: ${{ inputs.concurrency }}
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
GITHUB_ACTION_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

- name: Upload failed test videos
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-failed-test-videos-docker-${{ github.run_attempt }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate artifact names when matrix jobs fail simultaneously

The artifact name e2e-failed-test-videos-docker-${{ github.run_attempt }} does not include any matrix-distinguishing identifier. This reusable workflow is called with a matrix strategy (e.g., two different runners in platform-pull-request.yml). If multiple matrix jobs fail, they all try to upload artifacts with the same name. With actions/upload-artifact@v4, duplicate artifact names cause an upload error, so only the first failing job's video gets uploaded while subsequent ones fail silently. The name needs to include ${{ inputs.runs-on }} or similar to be unique.

Fix in Cursor Fix in Web

path: frontend/e2e-videos/*.mp4
if-no-files-found: ignore
retention-days: 30
1 change: 0 additions & 1 deletion .github/workflows/frontend-deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ jobs:
uses: ./.github/actions/e2e-tests
with:
e2e_test_token: ${{ secrets.E2E_TEST_TOKEN }}
slack_token: ${{ secrets.SLACK_TOKEN }}
environment: prod

deploy-production:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/frontend-test-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ jobs:
uses: ./.github/actions/e2e-tests
with:
e2e_test_token: ${{ secrets.E2E_TEST_TOKEN }}
slack_token: ${{ secrets.SLACK_TOKEN }}
environment: staging
11 changes: 10 additions & 1 deletion .github/workflows/manual-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
api-url:
description: An API URL to run the E2E tests against
default: 'https://api.flagsmith.com/api/v1/'

jobs:
run-e2e-tests:
runs-on: depot-ubuntu-latest
Expand All @@ -31,3 +31,12 @@ jobs:
npm ci
npm run env
npm run test

- name: Upload failed test videos
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-failed-test-videos-manual-${{ github.run_attempt }}
path: frontend/reports/screen-captures/*.mp4
if-no-files-found: ignore
retention-days: 30
1 change: 0 additions & 1 deletion .github/workflows/platform-docker-build-test-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ jobs:
args: ${{ matrix.args.args }}
secrets:
GCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

strategy:
matrix:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/platform-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ jobs:
args: --meta-filter category=oss
secrets:
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
Expand All @@ -171,7 +170,6 @@ jobs:
args: --meta-filter category=oss,category=enterprise
secrets:
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
Expand Down
6 changes: 4 additions & 2 deletions frontend/.testcaferc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const isDev = process.env.E2E_DEV;
const environment = process.env.ENV || 'dev';
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-');

module.exports = {
"browsers": "firefox:headless",
"port1": 8080,
Expand All @@ -13,7 +15,7 @@ module.exports = {
"videoOptions": {
"singleFile": true,
"failedOnly": true,
"pathPattern": "./test-report-${FILE_INDEX}.mp4"
"pathPattern": environment + "-" + timestamp + "-test-${FILE_INDEX}.mp4"
},
"videoEncodingOptions": {
"r": 20,
Expand Down
11 changes: 8 additions & 3 deletions frontend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ serve:

.PHONY: test
test:
docker compose run frontend \
npx cross-env E2E_CONCURRENCY=${E2E_CONCURRENCY} npm run test -- $(opts) \
|| (docker compose logs flagsmith-api; exit 1)
mkdir -p e2e-videos
docker rm -f e2e-test-runner 2>/dev/null || true
docker compose run --rm=false --name e2e-test-runner frontend \
npx cross-env E2E_CONCURRENCY=${E2E_CONCURRENCY} npm run test -- $(opts); \
TEST_EXIT_CODE=$$?; \
docker cp e2e-test-runner:/srv/flagsmith/reports/screen-captures/. e2e-videos/ 2>/dev/null || true; \
docker rm e2e-test-runner 2>/dev/null || true; \
if [ $$TEST_EXIT_CODE -ne 0 ]; then docker compose logs flagsmith-api; exit $$TEST_EXIT_CODE; fi
31 changes: 0 additions & 31 deletions frontend/bin/upload-file.js

This file was deleted.

3 changes: 0 additions & 3 deletions frontend/docker-compose-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ services:
E2E_TEST_TOKEN_DEV: some-token
DISABLE_ANALYTICS_FEATURES: 'true'
FLAGSMITH_API: flagsmith-api:8000/api/v1/
SLACK_TOKEN: ${SLACK_TOKEN}
GITHUB_ACTION_URL: ${GITHUB_ACTION_URL}
ports:
- 3000:3000
depends_on:
flagsmith-api:
condition: service_healthy

links:
- flagsmith-api:flagsmith-api
command: [npm, run, test]
48 changes: 48 additions & 0 deletions frontend/e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# E2E Test Video Recording

This document explains how to access video recordings of failed E2E tests from GitHub Actions.

## Overview

The E2E tests are configured to automatically record videos of **failed tests only** and upload them as GitHub Actions artifacts.

## How it works

**TestCafe Configuration**: The `.testcaferc.js` file is configured with:
- `failedOnly: true` - Only records videos when tests fail.
- Videos are saved to `reports/screen-captures/`.
- Files are named with environment, timestamp, and test index for easy identification.

**GitHub Actions Artifacts**:
- Videos are automatically uploaded as artifacts when tests fail.
- Artifacts are retained for 30 days.
- Different workflows use different artifact names:
- `e2e-failed-test-videos-{environment}-{run_attempt}` for direct e2e-tests action
- `e2e-failed-test-videos-docker-{run_attempt}` for Docker-based tests
- `e2e-failed-test-videos-manual-{run_attempt}` for manual test runs

## Accessing Video Recordings

1. Go to the failed GitHub Actions run.
2. Scroll down to the "Artifacts" section at the bottom of the run page.
3. Download the video artifact(s) to view the recordings of failed tests.

## Configuration

The video recording behavior is controlled by:
- TestCafe configuration in `.testcaferc.js` - controls video quality, path, and naming
- GitHub Actions workflow files - handle the artifact upload

## Video Settings

- **Format**: MP4
- **Frame rate**: 20 FPS
- **Aspect ratio**: 4:3
- **Recording**: Only when tests fail
- **GitHub Actions Retention**: 30 days

## Troubleshooting

- If no videos appear in artifacts, check that tests actually failed (videos are only recorded on failure).
- For Docker-based tests, ensure the video extraction step completed successfully.
- Check the test logs for any video-related error messages.
12 changes: 3 additions & 9 deletions frontend/e2e/index.cafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const fs = require('fs');
const path = require('path');
const { fork } = require('child_process');
const _options = require("../.testcaferc")
const upload = require('../bin/upload-file');
const minimist = require('minimist');
const options = {
..._options,
Expand Down Expand Up @@ -66,15 +65,10 @@ createTestCafe()
.run(options)
})
.then(async (v) => {
// Upload files
console.log(`Test failures ${v} in ${Date.now().valueOf() - start}ms`);
if (fs.existsSync(dir) && !process.env.E2E_DEV) {
try {
const files = fs.readdirSync(dir);
await Promise.all(files.map(f => upload(path.join(dir, f))));
} catch (e) { console.log('error uploading files', e); }
} else {
console.log('No files to upload');
if (fs.existsSync(dir)) {
const files = fs.readdirSync(dir);
console.log(`${files.length} video file(s) saved for GitHub Actions artifacts`);
}
// Shut down server and testcafe
server.kill('SIGINT');
Expand Down
Loading