Skip to content

Add Lighthouse CI with calibrated thresholds and emoji-per-cell PR co… #30

Add Lighthouse CI with calibrated thresholds and emoji-per-cell PR co…

Add Lighthouse CI with calibrated thresholds and emoji-per-cell PR co… #30

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
# Cancel in-flight runs for the same workflow + ref. Including
# `github.workflow` in the key keeps this from colliding with any other
# workflow that happens to share a ref-based group prefix.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Least-privilege: this workflow only reads the repo to lint/build/verify; it
# never writes back. Anything that needs write scopes lives in a separate
# workflow with its own scoped permissions.
permissions:
contents: read
jobs:
ci:
name: Lint, build, verify
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.13
# Bun is the package manager and script runner, but Next.js (and tsc)
# run on Node. ubuntu-latest's default Node version drifts; pin via
# .nvmrc so a future GitHub bump can't break the build silently.
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
# Cache Bun's resolved package store keyed on the lockfile hash. Cuts
# ~10s off `bun install` on a clean runner; the restore-key falls back
# to any prior cache from this OS so partial hits still help.
- name: Cache Bun install cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-
# Cache Next.js's incremental build output. Keyed on lockfile + commit
# SHA so the exact-key match is always per-commit fresh; restore-keys
# fall back to any previous build on the same lockfile, then any build
# on this OS — so most CI runs hit a cache and skip rebuilding
# unchanged webpack modules.
- name: Cache Next.js build cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('bun.lock') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('bun.lock') }}-
${{ runner.os }}-nextjs-
- name: Install
run: bun install --frozen-lockfile
- name: Lint + format check
run: bun run check:ci
# Build BEFORE typecheck: the build runs velite (populating .velite/
# which the `#site/content` path alias resolves to) and produces
# next-env.d.ts. tsc fails without these, so order matters here.
- name: Build
run: bun run build
- name: Type check
run: bun run typecheck
- name: Start server
run: |
bun run start > /tmp/server.log 2>&1 &
echo $! > /tmp/server.pid
for i in $(seq 1 30); do
if curl -sf http://localhost:3000 > /dev/null; then
echo "server ready"
exit 0
fi
sleep 1
done
echo "server failed to start in 30s"
cat /tmp/server.log
exit 1
- name: Verify endpoints
run: bun run verify
- name: Stop server
if: always()
run: |
if [ -f /tmp/server.pid ]; then
kill $(cat /tmp/server.pid) 2>/dev/null || true
fi
- name: Server logs (on failure)
if: failure()
run: cat /tmp/server.log || true
# Hard-gates on vulnerable direct/transitive deps. Two advisories are
# ignored because they're upstream-blocked (both via @lhci/cli@0.15.1
# and resend's transitive svix; both dev-/server-side with no
# exploitable code path) — see CLAUDE.md "Audit advisories" for
# context and removal triggers. Any new advisory fails the job.
- name: Dependency audit
run: bun audit --ignore=GHSA-w5hq-g745-h8pq --ignore=GHSA-52f5-9888-hmc6
# Runs only on PRs (no baseline diff to compute on a push to main).
# Compares the PR's dependency manifest against main and flags
# high-severity advisories or license incompatibilities. Posts a summary
# comment on the PR when it finds something. continue-on-error while we
# establish a baseline of acceptable findings.
dependency-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Dependency Review
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
continue-on-error: true
with:
fail-on-severity: high
comment-summary-in-pr: on-failure