ci: enforce PR policy (tests-present + app type-check) and PR template
All changes now land via PR. New .forgejo/workflows/pr-checks.yml runs on every PR to master and (1) fails code PRs that lack a test change, (2) blocks new app-code type errors. Unit tests are advisory until the baseline is green; lint is omitted (it needs an interactive ESLint migration). PR template carries the docs/tests checklist. Also makes the autofix watcher require a test (issue-12 style) + doc updates in every fix, so its PRs satisfy the new gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
859be8c8d0
commit
debac55a8a
4 changed files with 124 additions and 6 deletions
17
.forgejo/PULL_REQUEST_TEMPLATE.md
Normal file
17
.forgejo/PULL_REQUEST_TEMPLATE.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!-- All changes land via PR — no direct pushes to master. -->
|
||||
|
||||
## What & why
|
||||
|
||||
<!-- Brief summary of the change and the motivation / linked issue (e.g. Closes #NN). -->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] **Tests** added or updated for this change — or it is a docs/config/automation-only PR (tests not applicable). Model: the integration test on `claude/issue-12` (prod-mirror DB, raw-SQL inserts, prefix-isolated, cleans up after itself).
|
||||
- [ ] **Docs** updated where relevant (App/README.md, App/CLAUDE.md, Docs/, automation/README.md, CHANGELOG.md).
|
||||
- [ ] `pnpm type-check` shows no new errors in application code.
|
||||
- [ ] Verified the change (how: unit/integration tests, or a dev server on port 3100 against the test DB).
|
||||
|
||||
<!--
|
||||
The "PR checks" workflow enforces the test-presence rule automatically:
|
||||
a PR that touches App/app|lib|components|hooks without any test change will fail.
|
||||
-->
|
||||
66
.forgejo/workflows/pr-checks.yml
Normal file
66
.forgejo/workflows/pr-checks.yml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
name: PR checks
|
||||
|
||||
# Enforces the contribution policy on every PR into master:
|
||||
# - code changes must ship with tests (docs/config/automation are exempt)
|
||||
# - no new type errors in application code
|
||||
# - unit tests are reported (advisory until the baseline is green)
|
||||
# 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: No new type errors in application code
|
||||
run: |
|
||||
set -uo pipefail
|
||||
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
|
||||
cd App
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm db:generate # prisma client types (no DB needed)
|
||||
pnpm type-check > /tmp/tc.txt 2>&1 || true
|
||||
# Gate on application-code errors only; the test suite has a known
|
||||
# pre-existing type-mismatch baseline that is tracked separately.
|
||||
app_errors=$(grep -E 'error TS' /tmp/tc.txt | grep -vE '/tests/|\.test\.|\.spec\.' || true)
|
||||
if [ -n "$app_errors" ]; then
|
||||
echo "::error::Type errors in application code:"; printf '%s\n' "$app_errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK — no type errors in application code."
|
||||
|
||||
- name: Unit tests (advisory)
|
||||
continue-on-error: true
|
||||
run: |
|
||||
export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"
|
||||
cd App && pnpm test
|
||||
|
|
@ -32,6 +32,34 @@ Claude in a steered session). The triage breakdown comment is plain (no bot
|
|||
marker) so, for `claude-queue` issues, the fix stage reads it back as refined
|
||||
requirements.
|
||||
|
||||
## Contribution policy (all changes via PR)
|
||||
|
||||
**Every change lands through a pull request — no direct pushes to `master`.** This applies
|
||||
to humans and to the automated pipeline alike (the watcher already opens PRs).
|
||||
|
||||
Each PR must include:
|
||||
|
||||
- **Tests** for any code change. Model: the integration test on `claude/issue-12` —
|
||||
it targets the prod-mirror test DB, anchors on existing rows, inserts fixtures via
|
||||
raw SQL (schema-tolerant), isolates them with a unique prefix, and cleans up in
|
||||
`afterEach`. Docs/config/automation-only PRs are exempt.
|
||||
- **Docs** updates where relevant (`App/README.md`, `App/CLAUDE.md`, `Docs/`,
|
||||
this file, `CHANGELOG.md`).
|
||||
|
||||
**Enforcement** — [`.forgejo/workflows/pr-checks.yml`](../.forgejo/workflows/pr-checks.yml)
|
||||
runs on every PR into `master`:
|
||||
|
||||
1. **Test-presence gate (hard):** a PR touching `App/app|lib|components|hooks` with no
|
||||
test change fails. Justify genuine exceptions in the PR body for a reviewer to override.
|
||||
2. **App-code type-check (hard):** no new `tsc` errors in application code. (The test
|
||||
suite has a known pre-existing type-mismatch baseline, tracked separately, so it is
|
||||
filtered out of this gate.)
|
||||
3. **Unit tests (advisory):** reported but non-blocking until the unit baseline is green
|
||||
(2 known failures on `master`). `pnpm lint` is intentionally not run — it currently
|
||||
requires an interactive ESLint migration.
|
||||
|
||||
A [`PULL_REQUEST_TEMPLATE.md`](../.forgejo/PULL_REQUEST_TEMPLATE.md) carries the checklist.
|
||||
|
||||
## Components
|
||||
|
||||
| Piece | Where | Notes |
|
||||
|
|
|
|||
|
|
@ -282,13 +282,20 @@ while [ "$f" -lt "$n_fix" ]; do
|
|||
printf '%s\n' " NEVER use a broad 'pkill -f next' -- it would kill the production app."
|
||||
printf '%s\n' "- Never connect to or modify the production database or the production app."
|
||||
printf '%s\n' ""
|
||||
printf '%s\n' "## Your job"
|
||||
printf '%s\n' "## Your job (PR policy: every code change ships with tests + docs)"
|
||||
printf '%s\n' "1. Investigate the issue and implement a focused, minimal fix in this repository."
|
||||
printf '%s\n' "2. Verify: run 'pnpm type-check' and 'pnpm lint' in App/. If behaviour is covered by unit"
|
||||
printf '%s\n' " tests, run them; for DB-backed behaviour, run integration tests against the test DB above."
|
||||
printf '%s\n' "3. Add or adjust tests when it makes sense."
|
||||
printf '%s\n' "4. Commit ALL changes to the current branch with a conventional message ending: Fixes #$num"
|
||||
printf '%s\n' "5. Do NOT push, do NOT create tags, do NOT switch branches. The supervisor handles push and PR."
|
||||
printf '%s\n' "2. REQUIRED: add or update a test that fails before your fix and passes after. Model it on"
|
||||
printf '%s\n' " App/tests/integration/dashboard-approved-this-month.test.ts (from issue #12): target the"
|
||||
printf '%s\n' " prod-mirror test DB, anchor on existing rows (findFirstOrThrow), insert fixtures via raw"
|
||||
printf '%s\n' " SQL with a unique prefix, and clean them up in afterEach. The PR check REJECTS code"
|
||||
printf '%s\n' " changes under App/app|lib|components|hooks with no test change."
|
||||
printf '%s\n' "3. Verify: 'pnpm type-check' (no new app-code errors) and run your test against the test DB:"
|
||||
printf '%s\n' " cd App && set -a && . ./.env && set +a && pnpm test:integration"
|
||||
printf '%s\n' "4. REQUIRED: update any docs the change affects (App/README.md, App/CLAUDE.md, Docs/,"
|
||||
printf '%s\n' " CHANGELOG.md) — skip only if nothing documented is affected."
|
||||
printf '%s\n' "5. Commit ALL changes (fix + test + docs) to the current branch with a conventional message"
|
||||
printf '%s\n' " ending: Fixes #$num"
|
||||
printf '%s\n' "6. Do NOT push, do NOT create tags, do NOT switch branches. The supervisor handles push and PR."
|
||||
printf '%s\n' "If the issue is unclear, too risky (migrations, payments, permissions), or you cannot verify"
|
||||
printf '%s\n' "the fix, make NO commits and write a short explanation to CLAUDE_RESULT.md in the repo root."
|
||||
} > "$prompt_file"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue