mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
tablet-shell.spec.ts runs on WebKit with an iPad profile (webkit-tablet, in the WebKit job) and on Chromium with an Android tablet profile (chromium-tablet, in the shards), across iPad mini to iPad Pro 13 in both orientations, Safari's bars, Split View and Slide Over. It checks that the shell fills the window and leaves the document nothing to scroll, that every rail destination scrolls into view on top and takes a tap, that the scroll cue follows the overflow, that main reaches its last line clear of the bottom bar, that the page scrolls again after a sheet and a dialog close, and that a tab strip leaves the vertical pan to the page. ui-standards records the shell and rail rules.
259 lines
10 KiB
YAML
259 lines
10 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.
|
||
# Every Playwright job runs inside Microsoft's Playwright image, which ships
|
||
# the browsers with their system libraries: installing them from apt at run
|
||
# time stalled shards for 29 minutes twice, once for WebKit and once for
|
||
# Chromium alone.
|
||
shard:
|
||
runs-on: ubuntu-24.04
|
||
needs: playwright-version
|
||
timeout-minutes: 30
|
||
container:
|
||
image: mcr.microsoft.com/playwright:v${{ needs.playwright-version.outputs.version }}-noble
|
||
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
|
||
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
|
||
# The WebKit specs run in the `webkit` job below.
|
||
E2E_SKIP_WEBKIT: "1"
|
||
|
||
steps:
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
|
||
# The image runs as root while the checkout belongs to the runner user;
|
||
# git refuses such a tree, and the prepare hook calls git.
|
||
- run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||
|
||
- 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
|
||
|
||
# `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. Measures the first
|
||
# load of every page (files deduplicated by content hash) against its
|
||
# baseline, the p95 and max across pages, and the distinct client code
|
||
# (modules deduplicated by id); see the script header. Catches a
|
||
# statically imported message catalog, a duplicated recharts chunk, or
|
||
# a heavy module (Zod) pulled into a page that had none.
|
||
- 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 specs, in the same image as the shards: the bottom sheet on an
|
||
# iPhone (`bottom-sheet.spec.ts`, project `webkit-iphone`) and the app shell
|
||
# on an iPad (`tablet-shell.spec.ts`, project `webkit-tablet`).
|
||
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
|
||
|
||
steps:
|
||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||
|
||
# The image runs as root while the checkout belongs to the runner user;
|
||
# git refuses such a tree, and the prepare hook calls git.
|
||
- run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||
|
||
- 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 --project=webkit-tablet
|
||
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
|