Adds an `integration` job to PR checks: spins up a throwaway postgres:16 container on a random host port (isolated from prod / pelagia_test / staging), applies migrations, dev-seeds, and runs `pnpm test:integration` (108 tests). Container is always torn down via an EXIT trap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
101 lines
4.1 KiB
YAML
101 lines
4.1 KiB
YAML
name: PR checks
|
|
|
|
# Enforces the contribution policy on every PR into master (all gates hard):
|
|
# - code changes must ship with tests (docs/config/automation are exempt)
|
|
# - type-check is clean across the whole project (tests included)
|
|
# - unit tests pass
|
|
# - integration tests pass against an ephemeral Postgres (migrate + seed)
|
|
# Runs on the pms1 host runner. See automation/README.md > "Contribution policy".
|
|
|
|
on:
|
|
pull_request:
|
|
branches: [master]
|
|
|
|
jobs:
|
|
checks:
|
|
runs-on: host
|
|
steps:
|
|
- name: Checkout PR
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Policy — code changes must include tests
|
|
run: |
|
|
set -uo pipefail
|
|
base="${GITHUB_BASE_REF:-master}"
|
|
git fetch origin "$base" --depth=200 -q
|
|
changed=$(git diff --name-only "origin/$base...HEAD")
|
|
printf 'Changed files:\n%s\n\n' "$changed"
|
|
|
|
# "Code" = app source (pages, API routes, lib, components, hooks).
|
|
# Tests, prisma, config, docs, automation and .forgejo are exempt.
|
|
code=$(printf '%s\n' "$changed" | grep -E '^App/(app|lib|components|hooks)/' \
|
|
| grep -vE '(\.test\.|\.spec\.|/tests/)' || true)
|
|
tests=$(printf '%s\n' "$changed" | grep -E '(\.test\.|\.spec\.|/tests/)' || true)
|
|
|
|
if [ -n "$code" ] && [ -z "$tests" ]; then
|
|
echo "::error::Code changed but no test files changed."
|
|
echo "Every code PR must add or update tests (model: the claude/issue-12 integration test)."
|
|
echo "If a test is genuinely not applicable, say why in the PR description so a reviewer can override."
|
|
printf '\nCode files without accompanying tests:\n%s\n' "$code"
|
|
exit 1
|
|
fi
|
|
echo "OK — test-presence policy satisfied."
|
|
|
|
- name: Type-check (no errors)
|
|
run: |
|
|
set -e
|
|
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
|
|
cd App
|
|
pnpm install --frozen-lockfile
|
|
pnpm db:generate # prisma client types (no DB connection needed)
|
|
pnpm type-check # whole project, tests included — must be clean
|
|
|
|
- name: Unit tests
|
|
run: |
|
|
set -e
|
|
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
|
|
cd App && pnpm test # jsdom unit tests, no DB — must pass
|
|
|
|
integration:
|
|
runs-on: host
|
|
steps:
|
|
- name: Checkout PR
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Integration tests (ephemeral Postgres)
|
|
run: |
|
|
set -euo pipefail
|
|
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
|
|
|
|
# Throwaway Postgres per run — isolated from prod / pelagia_test / staging.
|
|
# A random host port avoids collisions with the host DB and concurrent runs.
|
|
PG="ci-pg-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT:-1}"
|
|
cleanup() { docker rm -f "$PG" >/dev/null 2>&1 || true; }
|
|
trap cleanup EXIT
|
|
docker rm -f "$PG" >/dev/null 2>&1 || true
|
|
docker run -d --name "$PG" \
|
|
-e POSTGRES_USER=ci -e POSTGRES_PASSWORD=ci -e POSTGRES_DB=pelagia_ci \
|
|
-p 127.0.0.1::5432 postgres:16 >/dev/null
|
|
|
|
for i in $(seq 1 30); do
|
|
docker exec "$PG" pg_isready -U ci -d pelagia_ci >/dev/null 2>&1 && break
|
|
sleep 1
|
|
done
|
|
|
|
PORT=$(docker inspect --format '{{ (index (index .NetworkSettings.Ports "5432/tcp") 0).HostPort }}' "$PG")
|
|
export DATABASE_URL="postgresql://ci:ci@127.0.0.1:${PORT}/pelagia_ci"
|
|
# Non-secret placeholders so auth.ts (reads these at module load) boots in dev mode.
|
|
export NEXTAUTH_SECRET="ci-secret"
|
|
export NEXTAUTH_URL="http://localhost:3000"
|
|
export AZURE_AD_CLIENT_ID="placeholder"
|
|
export AZURE_AD_CLIENT_SECRET="placeholder"
|
|
export AZURE_AD_TENANT_ID="placeholder"
|
|
|
|
cd App
|
|
pnpm install --frozen-lockfile
|
|
pnpm db:generate
|
|
pnpm db:migrate:deploy # apply migrations to the fresh DB
|
|
pnpm db:seed # dev seed — integration tests rely on it
|
|
pnpm test:integration # node + real DB — must pass
|