mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
The hero-geometry check has never measured anything in CI. It launches Chromium in a hook, catches the launch failure, and every case then returns early — green. The quality job installs no browsers, so every run of it since the file landed printed [hero geometry] SKIPPED — no Chromium build available (Error: browserType.launch: Executable doesn't exist at /home/runner/.cache/ms-playwright/chromium_headless_shell-1234/ch) and passed. The file's own header warned about exactly this trap and then fell into it. Both ends move. The quality job installs the headless shell before the unit suite — `--only-shell chromium`, because that is the build `chromium.launch()` resolves to and the one the failing runs named, with a cache on the lockfile hash so the download is paid once. And the check now refuses to be optional: with CI set, a launch failure throws out of the hook and fails the suite with the step to restore. Without CI it still skips, through the test context so the skip and its reason land in the report rather than in a console line nobody reads. No panel number changed. The measurements the check reads back are the same ones the reserve was set against: panels of 400 / 428 / 456 / 484 px for three to six rows, 420 px for three rows plus the basis line, against a 448 px reserve.
150 lines
5.8 KiB
YAML
150 lines
5.8 KiB
YAML
name: Security & Quality
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
quality:
|
|
name: Lint, Typecheck & Test
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
|
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
with:
|
|
node-version: 22
|
|
cache: "pnpm"
|
|
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- run: pnpm db:generate
|
|
|
|
# The hero-geometry check in the unit suite renders the real panel in a
|
|
# real browser and measures the boxes. Without a browser here it caught
|
|
# its own launch failure and passed anyway, so from its first day until
|
|
# v1.38 it measured nothing on any run of this job. The browser is part
|
|
# of the gate now; the test refuses to skip when CI is set.
|
|
#
|
|
# Headless shell only: `chromium.launch()` resolves to
|
|
# chromium_headless_shell, which is what the failing runs named, and the
|
|
# full headed build is several times the download for nothing this job
|
|
# uses. The e2e job keeps `--with-deps chromium` — it drives a real app.
|
|
- name: Cache Playwright headless shell
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-shell-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
playwright-shell-${{ runner.os }}-
|
|
|
|
- run: pnpm exec playwright install --only-shell chromium
|
|
|
|
# Blocking since v1.15.20 — the settings-split refactor that kept
|
|
# this warn-only is long done and the tree lints clean.
|
|
- name: ESLint
|
|
run: pnpm lint
|
|
|
|
# Prettier formatting gate. The format pass excludes generator-owned
|
|
# artifacts via .prettierignore (notably docs/api/openapi.yaml, which
|
|
# the OpenAPI drift check below enforces byte-for-byte).
|
|
- name: Prettier format check
|
|
run: pnpm format:check
|
|
|
|
- name: TypeScript strict check
|
|
run: pnpm typecheck
|
|
|
|
- name: Unit tests
|
|
run: pnpm test
|
|
|
|
# OpenAPI spec drift gate — hard-fail (flipped from warn-only in v1.4.25).
|
|
#
|
|
# The Zod registry is the source of truth for the public API contract.
|
|
# Any route signature change must be reflected in `docs/api/openapi.yaml`
|
|
# so downstream consumers (notably the v1.5 iOS Swift codegen) stay in
|
|
# lockstep. If this step fails, run `pnpm openapi:generate` locally and
|
|
# commit the regenerated spec.
|
|
- name: OpenAPI spec drift check
|
|
run: |
|
|
pnpm openapi:generate
|
|
if ! git diff --exit-code docs/api/openapi.yaml; then
|
|
echo "::error::OpenAPI drift detected — regenerate the spec via 'pnpm openapi:generate' and commit the result. The Zod registry under src/lib/openapi/ is the source of truth for the public API contract."
|
|
exit 1
|
|
fi
|
|
echo "::notice::OpenAPI spec in sync with Zod source schemas."
|
|
|
|
dependency-audit:
|
|
name: Dependency Audit
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
|
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
with:
|
|
node-version: 22
|
|
cache: "pnpm"
|
|
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
# Blocking since v1.15.20 — a HIGH/CRITICAL advisory against a
|
|
# production dependency fails the build. If an advisory has no
|
|
# upstream fix yet, pin an `auditConfig.ignoreCves` entry in
|
|
# package.json (pnpm's documented suppression mechanism) with a
|
|
# comment referencing the tracking issue, rather than flipping
|
|
# this step back to warn-only.
|
|
- name: Audit for known vulnerabilities
|
|
run: pnpm audit --prod --audit-level=high
|
|
|
|
secret-scan:
|
|
name: Secret Scanning
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Gitleaks secret scan
|
|
uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
docker-security:
|
|
name: Container Security
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
|
|
- name: Build Docker image
|
|
run: docker build -t healthlog:scan .
|
|
|
|
- name: Install Trivy
|
|
run: |
|
|
sudo apt-get install -y wget apt-transport-https gnupg
|
|
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
|
|
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee /etc/apt/sources.list.d/trivy.list
|
|
sudo apt-get update && sudo apt-get install -y trivy
|
|
|
|
# Blocking since v1.15.20 — a HIGH/CRITICAL finding in the built
|
|
# image fails the job. For a finding without an upstream fix
|
|
# (e.g. a base-image CVE Alpine has not patched yet), add the CVE
|
|
# id to a `.trivyignore` file at the repository root — Trivy reads
|
|
# it automatically — one CVE per line, each with a comment naming
|
|
# the tracking issue and the re-check condition. Never suppress a
|
|
# finding that has a fixed version available; bump instead.
|
|
- name: Trivy container scan
|
|
run: trivy image --format table --severity CRITICAL,HIGH --exit-code 1 healthlog:scan
|