mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
Installing WebKit's system packages in every shard stalled one shard for 29 minutes on apt and left another without time for its tests. The bottom-sheet spec now runs in its own job inside Microsoft's Playwright image, whose tag follows the playwright-core version the lockfile resolves; the shards install Chromium only and skip the WebKit project. The e2e gate answers for the shards and the WebKit job.
256 lines
9.6 KiB
YAML
256 lines
9.6 KiB
YAML
name: e2e
|
||
|
||
on:
|
||
pull_request:
|
||
branches: [main]
|
||
push:
|
||
branches: [main]
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
# Cancel in-progress runs when a new commit lands on the same PR.
|
||
concurrency:
|
||
group: e2e-${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
jobs:
|
||
# The suite outgrew the runner the same way the integration suite did: the
|
||
# single job passed at ~18 minutes against a 20-minute cap, and the settings
|
||
# geometry measurements pushed it over. Same remedy, split rather than raise:
|
||
# Playwright shards, each with its own database and production build, and
|
||
# a gate job below that carries the exact name branch protection requires.
|
||
# Two shards grew to 14–19 minutes against the 20-minute cap once the
|
||
# mobile route sweep landed, and a slow runner tipped them over; three
|
||
# shards with a 30-minute cap leave room for both.
|
||
shard:
|
||
runs-on: ubuntu-24.04
|
||
timeout-minutes: 30
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
shard: [1, 2, 3]
|
||
name: e2e shard ${{ matrix.shard }}/3
|
||
services:
|
||
postgres:
|
||
image: postgres:16-alpine
|
||
env:
|
||
POSTGRES_USER: healthlog
|
||
POSTGRES_PASSWORD: healthlog
|
||
POSTGRES_DB: healthlog
|
||
ports:
|
||
- 5432:5432
|
||
options: >-
|
||
--health-cmd "pg_isready -U healthlog"
|
||
--health-interval 5s
|
||
--health-timeout 5s
|
||
--health-retries 10
|
||
|
||
env:
|
||
DATABASE_URL: postgresql://healthlog:healthlog@localhost:5432/healthlog?schema=public
|
||
ENCRYPTION_KEYS: '{"v1":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}'
|
||
ENCRYPTION_ACTIVE_KEY_ID: v1
|
||
API_TOKEN_HMAC_KEY: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||
AUTH_RP_NAME: HealthLog
|
||
AUTH_RP_ID: localhost
|
||
AUTH_RP_ORIGIN: http://localhost:3000
|
||
SESSION_COOKIE_SECURE: "false"
|
||
NODE_ENV: production
|
||
# WebKit runs in the `webkit` job below; installing its ~180 system
|
||
# packages here once stalled a shard past its 30-minute cap.
|
||
E2E_SKIP_WEBKIT: "1"
|
||
|
||
steps:
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
|
||
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||
|
||
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||
with:
|
||
node-version: 22
|
||
cache: pnpm
|
||
|
||
- run: pnpm install --frozen-lockfile
|
||
|
||
- run: pnpm db:generate
|
||
|
||
- run: pnpm db:migrate:deploy
|
||
|
||
- name: Cache Playwright browsers
|
||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||
with:
|
||
path: ~/.cache/ms-playwright
|
||
key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||
restore-keys: |
|
||
playwright-${{ runner.os }}-
|
||
|
||
- run: pnpm exec playwright install --with-deps chromium
|
||
|
||
# `pnpm build` (not bare `next build`): the prebuild hook generates
|
||
# the versioned service-worker stamp AND the static i18n catalog
|
||
# assets (public/i18n/<locale>.js) the client boots from — without
|
||
# them every UI interaction waits on missing catalogs.
|
||
# The repository-wide Next type worker exceeds V8's ~4 GiB default
|
||
# old-space ceiling. Keep the larger heap scoped to this production
|
||
# build only; tests and the runtime retain their normal limits.
|
||
- run: NODE_OPTIONS=--max-old-space-size=8192 pnpm build
|
||
|
||
# Client-bundle budget gate — rides this job because it is the one
|
||
# place CI already has a production build on disk. Catches the
|
||
# regressions the dead webpack-era tooling (ANALYZE=1, the old
|
||
# bundle-report) let through: a statically imported message catalog
|
||
# (~100 KB gz on every route) or a chart import bypassing the shared
|
||
# chart-runtime boundary (a duplicated ~92 KB gz recharts chunk).
|
||
- run: pnpm bundle-check
|
||
|
||
- run: pnpm exec playwright test --shard=${{ matrix.shard }}/3
|
||
env:
|
||
E2E_BASE_URL: http://localhost:3000
|
||
|
||
- name: Upload Playwright HTML report
|
||
if: always()
|
||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||
with:
|
||
name: playwright-report-shard-${{ matrix.shard }}
|
||
path: playwright-report/
|
||
retention-days: 7
|
||
if-no-files-found: ignore
|
||
|
||
# The machine-readable report, for the skipped-spec check in the gate
|
||
# job below. Only uploaded when the shard ran to completion, so a missing
|
||
# artifact there means a shard that did not finish, not an empty suite.
|
||
- name: Upload Playwright JSON report
|
||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||
with:
|
||
name: playwright-json-shard-${{ matrix.shard }}
|
||
path: playwright-json/results.json
|
||
retention-days: 7
|
||
if-no-files-found: error
|
||
|
||
# The Playwright image must carry the browsers of the exact Playwright the
|
||
# lockfile resolves, or the run refuses them. Read the version from the
|
||
# lockfile so a dependency bump moves the image with it.
|
||
playwright-version:
|
||
runs-on: ubuntu-24.04
|
||
timeout-minutes: 5
|
||
outputs:
|
||
version: ${{ steps.read.outputs.version }}
|
||
steps:
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
with:
|
||
sparse-checkout: pnpm-lock.yaml
|
||
sparse-checkout-cone-mode: false
|
||
- id: read
|
||
run: |
|
||
version=$(grep -m1 -E "^ playwright-core@[0-9]" pnpm-lock.yaml | sed -E "s/^ playwright-core@([0-9.]+):.*/\1/")
|
||
if [ -z "$version" ]; then echo "playwright-core not found in pnpm-lock.yaml"; exit 1; fi
|
||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||
|
||
# The WebKit spec (`bottom-sheet.spec.ts`, project `webkit-iphone`) in
|
||
# Microsoft's Playwright image, which ships WebKit with its system
|
||
# libraries, so nothing is installed from apt at run time.
|
||
webkit:
|
||
runs-on: ubuntu-24.04
|
||
needs: playwright-version
|
||
timeout-minutes: 30
|
||
name: e2e webkit
|
||
container:
|
||
image: mcr.microsoft.com/playwright:v${{ needs.playwright-version.outputs.version }}-noble
|
||
services:
|
||
postgres:
|
||
image: postgres:16-alpine
|
||
env:
|
||
POSTGRES_USER: healthlog
|
||
POSTGRES_PASSWORD: healthlog
|
||
POSTGRES_DB: healthlog
|
||
options: >-
|
||
--health-cmd "pg_isready -U healthlog"
|
||
--health-interval 5s
|
||
--health-timeout 5s
|
||
--health-retries 10
|
||
|
||
env:
|
||
# Inside a job container the service is reached by its name.
|
||
DATABASE_URL: postgresql://healthlog:healthlog@postgres:5432/healthlog?schema=public
|
||
ENCRYPTION_KEYS: '{"v1":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}'
|
||
ENCRYPTION_ACTIVE_KEY_ID: v1
|
||
API_TOKEN_HMAC_KEY: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||
AUTH_RP_NAME: HealthLog
|
||
AUTH_RP_ID: localhost
|
||
AUTH_RP_ORIGIN: http://localhost:3000
|
||
SESSION_COOKIE_SECURE: "false"
|
||
NODE_ENV: production
|
||
HOME: /root
|
||
|
||
steps:
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
|
||
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
||
|
||
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||
with:
|
||
node-version: 22
|
||
cache: pnpm
|
||
|
||
- run: pnpm install --frozen-lockfile
|
||
|
||
- run: pnpm db:generate
|
||
|
||
- run: pnpm db:migrate:deploy
|
||
|
||
- run: NODE_OPTIONS=--max-old-space-size=8192 pnpm build
|
||
|
||
- run: pnpm exec playwright test --project=webkit-iphone
|
||
env:
|
||
E2E_BASE_URL: http://localhost:3000
|
||
|
||
- name: Upload Playwright HTML report
|
||
if: always()
|
||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||
with:
|
||
name: playwright-report-webkit
|
||
path: playwright-report/
|
||
retention-days: 7
|
||
if-no-files-found: ignore
|
||
|
||
- name: Upload Playwright JSON report
|
||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||
with:
|
||
name: playwright-json-shard-webkit
|
||
path: playwright-json/results.json
|
||
retention-days: 7
|
||
if-no-files-found: error
|
||
|
||
# Branch protection requires a check named exactly "e2e". This job carries
|
||
# that name and answers for every shard and the WebKit job: it fails when
|
||
# any of them failed or was cancelled, so a half-green run cannot satisfy
|
||
# the gate.
|
||
e2e:
|
||
runs-on: ubuntu-24.04
|
||
needs: [shard, webkit]
|
||
if: always()
|
||
timeout-minutes: 5
|
||
steps:
|
||
- name: Every shard finished green
|
||
run: |
|
||
if [ "${{ needs.shard.result }}" != "success" ] || [ "${{ needs.webkit.result }}" != "success" ]; then
|
||
echo "shard result: ${{ needs.shard.result }}, webkit result: ${{ needs.webkit.result }}"
|
||
exit 1
|
||
fi
|
||
|
||
# A spec file that skipped every one of its tests reports green. The
|
||
# check aggregates both shards' reports, because Playwright splits a
|
||
# file's tests across shards; see the script's header for the allowlist.
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
with:
|
||
sparse-checkout: scripts
|
||
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||
with:
|
||
node-version: 22
|
||
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||
with:
|
||
pattern: playwright-json-shard-*
|
||
path: playwright-json
|
||
- name: No spec file skipped all of its tests
|
||
run: node scripts/check-e2e-skipped-specs.mjs playwright-json/*/results.json
|