Skip to content

ci(#265): wire pnpm test:rls into CI — RLS + dual-provider conformance gate#324

Merged
TortoiseWolfe merged 2 commits into
mainfrom
ci/265-conformance-gate
Jul 18, 2026
Merged

ci(#265): wire pnpm test:rls into CI — RLS + dual-provider conformance gate#324
TortoiseWolfe merged 2 commits into
mainfrom
ci/265-conformance-gate

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What & why

pnpm test:rls ran in zero workflows. ci.yml's pnpm test --run uses the default vitest.config.ts, which excludes tests/rls/** and both messaging-provider.*.test.ts contract runners — so until now neither the Supabase RLS policies nor the .NET/Supabase messaging providers were gated in CI. The #265 scoping called this out as core Phase-1 work: the anti-drift alarm was off.

This adds a Conformance workflow that closes the gap.

How it works

It stands up a local, ephemeral dual-provider stack (local Supabase + the .NET messaging server) and runs the full test:rls config against it:

Verified 107/107 green locally before wiring.

Design notes

  • No e2e-supabase mutex. e2e.yml needs a repo-wide mutex because every E2E run shares one cloud Supabase project and races the others' cleanup hooks. This job spins up its own per-runner ephemeral Postgres, so concurrent runs cannot race — a per-ref cancel-in-progress group is all that's warranted.
  • test:rls runs on the runner (CI-native, like ci.yml); the compose stack provides backends on localhost. Only the services the suite needs start (db/kong/auth/rest + dotnet-messaging) — not scripthammer/studio/mail/etc.
  • Uses the public Supabase self-hosting demo keys (already committed in docker-compose.yml's x-supabase-env anchor). The .NET server boots in Development, so the fix(#265): .NET messaging conformance 12/12 + JWT hardening + C11 doc-truth #322 fail-closed demo-secret guard correctly permits it.
  • Path-filtered on PRs (migrations / messaging / dotnet / tests / compose); full run on push to main.

Self-validating

This PR edits conformance.yml, which is in the workflow's own path filter — so the Conformance check runs on this PR. Its green (or red) result is the proof the wiring works end-to-end in real CI.

Follow-ups (not this PR)

Refs #265, #280.

🤖 Generated with Claude Code

TurtleWolfe and others added 2 commits July 18, 2026 18:53
… gate)

pnpm test:rls ran in ZERO workflows: ci.yml's `pnpm test --run` excludes
tests/rls/** and both messaging-provider contract runners (vitest.config.ts),
so neither the Supabase RLS policies nor the .NET/Supabase providers were gated
in CI. The new `Conformance` workflow closes that gap.

It stands up a LOCAL, ephemeral dual-provider stack (local Supabase + the .NET
messaging server) and runs the full test:rls config against it:
  - tests/rls/**                         (9 suites — the RLS policies)
  - messaging-provider.supabase.test.ts  (C7-C14 [supabase])
  - messaging-provider.dotnet.test.ts    (C7-C14 [dotnet], live ASP.NET)
Verified 107/107 green locally before wiring.

Design notes:
- No e2e-supabase mutex: unlike e2e.yml (one shared cloud project that
  concurrent runs race), each run owns its own ephemeral Postgres, so runs
  can't race. Per-ref cancel-in-progress is all that's warranted.
- test:rls runs on the runner (CI-native, like ci.yml); the compose stack
  provides backends on localhost. Only the services test:rls needs are started
  (db/kong/auth/rest + dotnet), not scripthammer/studio/mail/etc.
- Uses the public Supabase self-hosting demo keys (already in docker-compose.yml).
- Path-filtered on PRs (migrations/messaging/dotnet/tests/compose); full run on
  push to main.

Not yet a required check — prove it stable across a few runs first, then add it
to branch protection.

Refs #265, #280.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GitHub Actions runs `run:` steps with `bash -eo pipefail`. The wait loop's
`rest=$(curl ...)` probes exit non-zero while the services are still starting,
and under set -e that aborted the whole step on iteration 1 (~6s in) instead of
retrying — the run read as a 5-min timeout but the loop never actually ran. (The
supabase-db "FATAL: terminating background worker TimescaleDB" line is just the
image's normal init restart, unrelated.)

Add `set +e` in the wait step so the probes fail-and-retry as designed, and read
the anon key directly from process env. Validated the probe codes (db=ok,
rest/auth/dotnet=200) against a live local stack before pushing.

Refs #265.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe
TortoiseWolfe merged commit 08320e2 into main Jul 18, 2026
3 checks passed
@TortoiseWolfe
TortoiseWolfe deleted the ci/265-conformance-gate branch July 18, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants