Add Alembic migration testing against Postgres in CI #169
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/pal-e-api!169
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "164-migration-testing-ci"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds a
migration-testCI step that runs all Alembic migrations against a real Postgres database before build-and-push. This catches migration failures (syntax errors, missing extensions, bad dependencies) before they reach production. Usespgvector/pgvector:pg17as the service image so the pgvector extension is available for the embedding migrations.Changes
.woodpecker.yaml— Addedservices:block withpgvector/pgvector:pg17container, and amigration-teststep betweentestandbuild-and-pushthat:vectorextension (platform-provides pattern, matching CNPG CRD behavior)alembic upgrade head+alembic checkpushandpull_requesteventsTest Plan
migration-teststep on thepull_requesteventalembic checkpasses (no pending migrations vs. model state)teststep still runs unchanged (SQLite :memory: unit tests)Review Checklist
Related
plan-pal-e-docs— Phase 7 (CI/Infra)PR #169 Review
BLOCKERS
None.
NITS
Double
pip installfor psycopg2-binary -- The readiness check installspsycopg2-binarystandalone (line 43), thenpip install .[dev]installs it again as a project dependency (pyproject.toml line 21). This works but wastes ~5-10 seconds of CI time. A possible optimization would be to install.[dev]first and then run the readiness loop, but this would add app install time to the wait window. Current approach is pragmatic -- keeping it as-is is fine.Hardcoded connection strings repeated 3 times -- The Postgres connection string (
host=postgres dbname=paledocs_test user=postgres password=postgres) appears in thePALDOCS_DATABASE_URLenv var (line 39), the readiness check (line 46), and the extension creation (line 55). If any of the service container env vars change, all three must be updated in sync. Not a blocker for a CI config file, but worth noting for maintainability.No
--no-cache-diron pip installs -- Addingpip install --no-cache-dirwould reduce layer size in the ephemeral CI container. Minor optimization, non-blocking.ANALYSIS
psycopg2 vs psycopg driver concern: Not an issue. The project declares
psycopg2-binary>=2.9inpyproject.toml(line 21). The embedding worker usespsycopg2directly for LISTEN/NOTIFY. Production usespostgresql://(bare scheme in the k8s secret atterraform/main.tf:1563), which defaults to psycopg2 in SQLAlchemy 2.0+. The CI migration-test usespostgresql+psycopg2://explicitly -- these are equivalent drivers. No mismatch.Services block syntax: Correct. Top-level
services:key withname,image, andenvironmentfields matches Woodpecker CI service container spec.Postgres readiness check: Robust. 10 attempts with 2-second intervals (20 seconds total timeout). Uses actual connection attempt via psycopg2 rather than a simple port check, which validates that Postgres is actually accepting connections and the database exists. Exits non-zero on failure with a clear error message.
alembic checkvalidity: Confirmed. The project requiresalembic>=1.14, andalembic checkwas introduced in Alembic 1.9. This command compares SQLAlchemy model metadata against the migration head revision and exits non-zero if models have diverged from migrations -- exactly the right safety net.Extension creation (platform-provides pattern): The
CREATE EXTENSION IF NOT EXISTS vectorcall (line 55) correctly mirrors what the CNPG Cluster CRD does in production viapostInitSQL. The migration filel2g3h4i5j6k7_add_vector_embeddings.pyexplicitly checks for the extension and raises a RuntimeError if absent -- this CI step ensures that check passes.Step ordering: Correct.
test(SQLite unit tests) ->migration-test(Postgres migrations) ->build-and-push->update-deployment-tag->smoke-test. Migration failures will block the build.Security: The hardcoded
postgres/postgrescredentials are for an ephemeral CI service container that exists only for the pipeline run. This is standard CI practice and not a security concern. Real secrets (harbor, forgejo token) usefrom_secretand were present before this PR.SOP COMPLIANCE
164-migration-testing-cireferences issue #164)plan-pal-e-docs-- Phase 7)Closes #164present in Related section.woodpecker.yaml)VERDICT: APPROVED