Skip to content

Full E2E Tests

Full E2E Tests #98

Workflow file for this run

name: Full E2E Tests
on:
schedule:
- cron: "0 6 * * *" # Nightly 6am UTC (full-suite guard on main)
workflow_call:
workflow_dispatch:
concurrency:
group: test-full-${{ github.ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint-unit:
name: lint-unit
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check compose parity
run: bash scripts/check-compose-persist-parity.sh
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version: "22"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run unit tests
run: npm run test:run
e2e:
name: e2e (shard ${{ matrix.shard }}/4)
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version: "22"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Cache Playwright browsers
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-chromium-webkit-${{ hashFiles('package-lock.json') }}
restore-keys: playwright-${{ runner.os }}-chromium-webkit-
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium webkit
- name: Run E2E shard
run: npm run test:e2e -- --shard=${{ matrix.shard }}/4
- name: Upload blob report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() }}
with:
name: blob-report-${{ matrix.shard }}
path: blob-report/
retention-days: 7
merge-reports:
name: merge-reports
needs: e2e
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version: "22"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Download blob reports
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: blob-report-*
path: all-blob-reports
merge-multiple: true
- name: Merge into HTML report
run: npx playwright merge-reports --reporter html ./all-blob-reports
- name: Upload merged Playwright report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report
path: playwright-report/
retention-days: 7
notify-on-failure:
name: notify-on-failure
needs: [lint-unit, e2e, merge-reports]
if: ${{ failure() }}
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Notify on failure
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
TITLE: "Full E2E test suite failing"
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
# Dedup on the exact title so this tracker stays separate from other
# ci-failure issues (e.g. the self-hosted advisory tracker in test.yml,
# which shares the ci-failure label but uses a different title).
EXISTING=$(gh issue list --state open --label ci-failure --limit 100 \
--json number,title \
--jq "map(select(.title == \"$TITLE\")) | first | .number // empty")
if [ -n "$EXISTING" ]; then
gh issue comment "$EXISTING" --body "Full E2E failed again: $RUN_URL ($GITHUB_EVENT_NAME, $(date -u +%Y-%m-%dT%H:%M:%SZ))"
else
gh issue create \
--title "$TITLE" \
--label "automated,ci-failure" \
--body "The nightly full E2E test suite failed.
**Run:** $RUN_URL
**Trigger:** $GITHUB_EVENT_NAME
**Ref:** $GITHUB_REF
Check the Playwright report artifact for details."
fi