Skip to content

feat(ci): run db migrations from github ci with environment-scoped secrets#4957

Merged
TheodoreSpeaks merged 7 commits into
stagingfrom
feat/migrate-db-github-ci
Jun 11, 2026
Merged

feat(ci): run db migrations from github ci with environment-scoped secrets#4957
TheodoreSpeaks merged 7 commits into
stagingfrom
feat/migrate-db-github-ci

Conversation

@TheodoreSpeaks

@TheodoreSpeaks TheodoreSpeaks commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • replaces the removed ECS migration sidecar (infra: feat/decouple-migration): migrations now run as a GitHub CI job that gates the ECR image push, so the schema is migrated before CodePipeline deploys the new app version
  • migrations.yml is now a reusable workflow taking an explicit environment input (production / staging / dev) that maps to exactly one of the existing repo secrets (DATABASE_URL / STAGING_DATABASE_URL / DEV_DATABASE_URL) — the job never holds another environment's URL, and an unresolved value fails fast instead of falling through
  • dev keeps db:push --force only (matching previous sidecar/CI behavior); staging/main apply versioned migrations; dev/staging/main image builds all depend on their migrate job
  • manual workflow_dispatch now takes an explicit environment choice instead of inferring from the dispatching ref
  • uses existing repo secrets — no settings changes needed before merge. Note: the *DATABASE_URL secrets must be direct (port 5432) connections, not pooled (PgBouncer 6432) — the advisory lock, SET statement_timeout, and CREATE INDEX CONCURRENTLY are all session-scoped

Type of Change

  • New feature

Testing

bun run lint and bun run check:api-validation:strict pass; workflow YAML validated with actionlint. First real run happens on merge to staging.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jun 10, 2026 11:59pm

Request Review

@cursor

cursor Bot commented Jun 10, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Applies schema changes directly against production/staging/dev databases from CI and gates deploys on success; misconfigured secrets or pooled DB URLs could block deploys or run migrations against the wrong target.

Overview
Database migrations now run in GitHub Actions before ECR image pushes, replacing the ECS migration sidecar so schema changes land before CodePipeline deploys new app images.

CI adds migrate (main/staging after test-build) and migrate-dev (dev), and build-amd64 / build-dev wait on those jobs instead of migrating after the build. The post-build migrate-dev job is removed.

migrations.yml is reusable with a required environment input (production / staging / dev) that selects a single DATABASE_URL secret, fails if none resolves, and keeps dev on db:push --force vs versioned migrate.ts elsewhere. Manual workflow_dispatch picks the target environment explicitly instead of inferring from the branch ref.

Reviewed by Cursor Bugbot for commit e141ff1. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the removed ECS migration sidecar by running database migrations as GitHub CI jobs that gate ECR image pushes, ensuring the schema is migrated before CodePipeline deploys the new app version. The migrations.yml workflow is refactored into a reusable, environment-aware workflow with input-based secret selection and guards for missing URLs and PgBouncer connections.

  • Migration ordering fixed for dev: the old migrate-dev job ran after build-dev (post-image push); it now runs before, blocking build-dev on a successful schema push.
  • Environment-scoped secrets: DATABASE_URL is now resolved from an explicit environment input (production/staging/dev) rather than inferred from github.ref, so the job can never hold multiple environments' credentials simultaneously.
  • Notable outstanding issue (flagged in a prior review, not yet addressed): build-ghcr-arm64 still only depends on detect-version — it publishes :latest-arm64 to GHCR in parallel with migrations on main, so self-hosted ARM64 users pulling from GHCR can still encounter a schema mismatch if the migrate job fails or is slow.

Confidence Score: 4/5

Safe to merge for ECR/CodePipeline consumers; GHCR ARM64 self-hosted users can still pull a pre-migration image on main because build-ghcr-arm64 does not wait for the migrate job.

The migration-before-ECR-push ordering is correctly implemented for both amd64 (ECR + GHCR) and dev paths. However, build-ghcr-arm64 only depends on detect-version, so on a main push it races against the migrate job and can publish :latest-arm64 to GHCR before the schema is updated — leaving anyone who deploys self-hosted ARM64 from GHCR exposed to a schema mismatch. This issue was flagged in a prior review but has not been addressed.

ci.yml — the build-ghcr-arm64 job's needs list should include migrate to close the ARM64/GHCR race.

Important Files Changed

Filename Overview
.github/workflows/ci.yml Adds migrate and migrate-dev jobs that gate image builds; build-amd64 correctly blocks on migrate, but build-ghcr-arm64 (line 238) still only needs detect-version, leaving ARM64 GHCR images published before migrations complete on main.
.github/workflows/migrations.yml Refactored into a reusable workflow with explicit environment input, input-based secret selection, empty-URL guard, and PgBouncer port (6432) guard; logic is sound and handles invalid inputs gracefully.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    push[Push to main/staging/dev]

    push --> test_build
    push --> detect_version
    push --> migrate_dev_check{ref == dev?}

    test_build[test-build]
    detect_version[detect-version]

    test_build --> migrate_check{ref == main/staging?}
    migrate_check -->|yes| migrate[migrate\nenvironment=production/staging]

    migrate_dev_check -->|yes| migrate_dev[migrate-dev\nenvironment=dev]

    migrate --> build_amd64[build-amd64\nECR + GHCR amd64]
    detect_version --> build_amd64
    test_build --> build_amd64

    detect_version --> build_ghcr_arm64[build-ghcr-arm64\nGHCR arm64 only]:::warning

    migrate_dev --> build_dev[build-dev\nECR only]
    detect_version --> build_dev

    build_amd64 --> create_manifests[create-ghcr-manifests]
    build_ghcr_arm64 --> create_manifests

    classDef warning fill:#ffcccc,stroke:#cc0000,color:#000
Loading

Reviews (5): Last reviewed commit: "Revert "improvement(ci): reject pooled (..." | Re-trigger Greptile

Comment thread .github/workflows/migrations.yml
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks TheodoreSpeaks merged commit 0252984 into staging Jun 11, 2026
15 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/migrate-db-github-ci branch June 11, 2026 01:37
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.

1 participant