test: add PostgreSQL migration integration coverage
This commit is contained in:
@@ -122,10 +122,14 @@ messages, machine-specific paths, causes, stacks, or partial execution results.
|
||||
are reported without hiding the primary failure and without copying underlying exception text.
|
||||
|
||||
The developer commands read `DATABASE_URL` from the environment. A local uncommitted `.env` may
|
||||
supply it, but commands never print it. This slice verifies database behavior through a narrow
|
||||
in-memory database port and unit tests. A real PostgreSQL integration suite for lock contention,
|
||||
DDL rollback, history creation, and driver behavior is deliberately deferred rather than claimed
|
||||
by the current verification gate.
|
||||
supply it, but commands never print it. This decision's implementation slice verified database
|
||||
behavior through a narrow in-memory database port and unit tests; it deliberately deferred live
|
||||
PostgreSQL evidence to a follow-up slice rather than claiming it at acceptance time.
|
||||
|
||||
Implementation follow-up (2026-07-21): `pnpm test:migrations:integration` now runs the production
|
||||
adapter and migration services against disposable PostgreSQL for lock contention, DDL rollback,
|
||||
history creation, approvals, and sanitized driver failures. The Docker-backed command remains
|
||||
separate from the code-only `pnpm verify` gate.
|
||||
|
||||
The transaction and single-client choices follow node-postgres's
|
||||
[transaction guidance](https://node-postgres.com/features/transactions). The non-blocking lock and
|
||||
@@ -162,6 +166,6 @@ that invocation's schema or history changes committed. Destructive migrations ar
|
||||
a trusted approval provider is composed, by design.
|
||||
|
||||
The all-or-nothing batch can hold locks for longer than per-migration transactions and excludes
|
||||
operations PostgreSQL forbids in a transaction. The current unit-tested database port gives fast,
|
||||
deterministic coverage but cannot prove real server behavior. The next infrastructure-focused
|
||||
slice must add live PostgreSQL tests before production operation is considered complete.
|
||||
operations PostgreSQL forbids in a transaction. The narrow database port continues to provide fast,
|
||||
deterministic unit coverage; the dated implementation follow-up above records the separate live
|
||||
PostgreSQL evidence added after this decision was accepted.
|
||||
|
||||
@@ -69,8 +69,9 @@ validated metadata, explicit destructive-change declarations, and exact SHA-256
|
||||
now compare that inventory with its fixed PostgreSQL history table, produce a read-only plan, and
|
||||
apply the complete pending batch under a session advisory lock and one transaction. Destructive
|
||||
migrations require an exact externally supplied approval bound to module, identity, and checksum.
|
||||
Hermetic integration coverage now exercises those contracts through the production adapter against
|
||||
the pinned PostgreSQL container, including real DDL rollback and advisory-lock concurrency.
|
||||
|
||||
Target architecture, not yet implemented: production approval-provider composition, live
|
||||
PostgreSQL migration-runner integration coverage, Better Auth,
|
||||
Target architecture, not yet implemented: production approval-provider composition, Better Auth,
|
||||
permission enforcement, physical storage-bucket provisioning, Surface SDK, richer public resource
|
||||
and action contracts, API server, dashboard, Builder, and reference feature modules.
|
||||
|
||||
@@ -24,6 +24,7 @@ pnpm migrations:plan # read-only comparison with PostgreSQL applied history
|
||||
pnpm migrations:apply # locked, transactional application of the pending batch
|
||||
pnpm typecheck # strict TypeScript
|
||||
pnpm test # Vitest
|
||||
pnpm test:migrations:integration # production runner against disposable PostgreSQL
|
||||
pnpm build # Turborepo package build graph
|
||||
pnpm verify # every code-only gate; never plan or apply
|
||||
```
|
||||
@@ -63,13 +64,24 @@ The default command composition supplies no destructive approvals. There is no `
|
||||
or source-controlled approval escape hatch; deployments must later compose a trusted external
|
||||
provider that supplies an exact module ID, migration identity, and checksum triple.
|
||||
|
||||
The migration runner currently has comprehensive unit coverage through its narrow database port.
|
||||
Live PostgreSQL tests for real DDL rollback, advisory-lock contention, history-table behavior, and
|
||||
driver cleanup are deliberately deferred and are not part of `pnpm verify` or CI yet.
|
||||
Migration-runner unit tests cover orchestration through its narrow database port. Run the separate
|
||||
live suite when changing migration behavior:
|
||||
|
||||
CI runs `pnpm ci:verify`, which adds Compose configuration validation to `pnpm verify`. A separate
|
||||
CI job runs the live infrastructure smoke test so code-only local verification does not require
|
||||
Docker. The explicit suffix avoids pnpm's built-in `ci` install command.
|
||||
```bash
|
||||
pnpm test:migrations:integration
|
||||
```
|
||||
|
||||
It requires Docker with Compose, starts the pinned PostgreSQL image with a generated throwaway
|
||||
credential and a Docker-assigned loopback port, creates an isolated database for each scenario,
|
||||
and removes its containers, network, databases, and volume afterward. It exercises the production
|
||||
adapter and real PostgreSQL transactions, history, advisory locks, approvals, and sanitized errors.
|
||||
It remains outside the Docker-free `pnpm verify` command.
|
||||
|
||||
CI runs `pnpm ci:verify`, which adds Compose configuration validation to `pnpm verify`. Separate
|
||||
`infrastructure-smoke` and `migration-smoke` jobs run the live service and migration suites. The
|
||||
exact pull-request context to add to `main` branch protection after merge is
|
||||
`CI / migration-smoke (pull_request)`. The explicit `ci:verify` suffix avoids pnpm's built-in `ci`
|
||||
install command.
|
||||
|
||||
## Development infrastructure
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Testing
|
||||
|
||||
Ekklesia separates fast code-level evidence from live infrastructure evidence.
|
||||
|
||||
## Unit and repository verification
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
pnpm verify
|
||||
```
|
||||
|
||||
These commands exercise package tests, repository boundaries, type checking, offline module and
|
||||
migration discovery, formatting, linting, and builds. Migration-runner unit tests use a narrow
|
||||
database/session port to prove deterministic planning, approval, transaction orchestration,
|
||||
cleanup, and sanitized errors. They do not claim to prove PostgreSQL behavior.
|
||||
|
||||
`pnpm verify` is intentionally Docker-free. It never plans or applies migrations against a live
|
||||
database.
|
||||
|
||||
## Live PostgreSQL migration evidence
|
||||
|
||||
Docker and the Docker Compose plugin are required for the live suite:
|
||||
|
||||
```bash
|
||||
pnpm test:migrations:integration
|
||||
```
|
||||
|
||||
The command starts the repository's pinned PostgreSQL image in a unique Compose project, waits for
|
||||
bounded health readiness, runs the production PostgreSQL adapter and migration services, and then
|
||||
removes the container, network, and volume. Each scenario also receives a safely named disposable
|
||||
database. Direct host runs use a Docker-assigned random port bound only to `127.0.0.1`; a
|
||||
containerized Gitea job joins the isolated Compose network and uses the PostgreSQL service name.
|
||||
|
||||
The live suite proves fresh read-only planning, initial and incremental application, genuine
|
||||
no-op behavior, exact applied checksums and history, edited or corrupt history rejection,
|
||||
whole-batch DDL rollback, Drizzle breakpoint execution, real advisory-lock concurrency and
|
||||
timeouts, lock release after failure, exact destructive approvals, and public-error sanitization.
|
||||
It does not make migrations automatic during Core startup.
|
||||
|
||||
CI runs the same command in the dedicated `migration-smoke` job. After this change is merged, add
|
||||
the following pull-request status context to `main` branch protection:
|
||||
|
||||
```text
|
||||
CI / migration-smoke (pull_request)
|
||||
```
|
||||
|
||||
## Safe troubleshooting
|
||||
|
||||
Confirm the prerequisites without printing configuration:
|
||||
|
||||
```bash
|
||||
docker info
|
||||
docker compose version
|
||||
```
|
||||
|
||||
Then rerun `pnpm test:migrations:integration`. The harness emits fixed failure messages and does
|
||||
not dump PostgreSQL logs, SQL, container inspection output, or the generated database URL. Do not
|
||||
enable query logging, print the test environment, run `docker compose config` without redaction,
|
||||
or paste Docker inspection output into an issue. If the Docker daemon itself stopped during
|
||||
cleanup, restore it before rerunning so the harness can create a fresh uniquely named project.
|
||||
@@ -275,9 +275,11 @@ ID, exact identity, and exact checksum. Module metadata cannot grant approval, a
|
||||
wildcard, force, or approve-all option. The default developer command supplies no approvals and
|
||||
therefore refuses destructive pending migrations.
|
||||
|
||||
Runner behavior is unit-tested through a narrow database port. Live PostgreSQL coverage of DDL
|
||||
rollback, advisory-lock contention, and driver behavior is a deferred infrastructure slice; the
|
||||
current verification suite does not claim that coverage.
|
||||
Runner behavior is unit-tested through a narrow database port. The separate
|
||||
`pnpm test:migrations:integration` command now exercises the production adapter against disposable
|
||||
PostgreSQL, including DDL rollback, advisory-lock contention, history behavior, approvals, and
|
||||
sanitized failures. It remains outside the Docker-free `pnpm verify` gate; see the
|
||||
[testing guide](../development/testing.md).
|
||||
|
||||
Core completes discovery before importing any server entrypoint. It then loads and verifies every
|
||||
runtime definition before running hooks, registers all modules dependency-first into an unpublished
|
||||
|
||||
Reference in New Issue
Block a user