Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,42 @@ jobs:
# Run database migrations before images are pushed: the ECR push triggers
# CodePipeline, so migrating first guarantees the schema is in place before
# the new app version deploys (replaces the removed ECS migration sidecar)
# Detect whether this push actually changed any migration files, so the
# migrate job below can skip connecting to the production/staging database on
# merges that touch no schema (a no-op db:migrate otherwise dials the DB and
# fails any time it is at its connection limit).
detect-migrations:
name: Detect Migration Changes
runs-on: blacksmith-4vcpu-ubuntu-2404
if: >-
github.event_name == 'push' &&
(github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging')
outputs:
migrations_changed: ${{ steps.filter.outputs.migrations }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
fetch-depth: 2 # Need the previous commit to diff migration paths
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: filter
with:
filters: |
migrations:
- 'packages/db/migrations/**'

# The job always runs on push to main/staging so downstream build/deploy jobs
# that `need` it are never skipped; the actual db:migrate step is gated on
# detect-migrations inside the reusable workflow.
migrate:
name: Migrate DB
needs: [test-build]
needs: [test-build, detect-migrations]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Filter Failure Blocks Deploys

When detect-migrations fails before producing an output, the new needs edge cancels migrate, and build-amd64 cannot run because it needs migrate. That makes a checkout or paths-filter infrastructure failure block the whole main/staging deploy path, even though the safe fallback should be to run migrations rather than skip the deploy.

if: >-
github.event_name == 'push' &&
(github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging')
uses: ./.github/workflows/migrations.yml
with:
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
migrations_changed: ${{ needs.detect-migrations.outputs.migrations_changed }}
secrets: inherit

# Same ordering for dev (schema push before the dev image lands in ECR)
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/migrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ on:
description: Target environment (production, staging, or dev)
required: true
type: string
migrations_changed:
description: >-
Whether this push changed migration files. When 'false' the versioned
apply step is skipped. Defaults to 'true' so manual dispatch and any
omitted/unknown value always applies migrations (never silently skip).
required: false
type: string
default: 'true'
workflow_dispatch:
inputs:
environment:
Expand Down Expand Up @@ -61,6 +69,7 @@ jobs:
DATABASE_URL: ${{ inputs.environment == 'production' && secrets.DATABASE_URL || inputs.environment == 'staging' && secrets.STAGING_DATABASE_URL || inputs.environment == 'dev' && secrets.DEV_DATABASE_URL || '' }}
MIGRATION_DATABASE_URL: ${{ inputs.environment == 'production' && secrets.MIGRATION_DATABASE_URL || inputs.environment == 'staging' && secrets.STAGING_MIGRATION_DATABASE_URL || '' }}
ENVIRONMENT: ${{ inputs.environment }}
MIGRATIONS_CHANGED: ${{ inputs.migrations_changed }}
run: |
if [ -z "$DATABASE_URL" ]; then
echo "ERROR: no database URL secret resolved for environment '${ENVIRONMENT}'" >&2
Expand All @@ -70,6 +79,8 @@ jobs:
if [ "${ENVIRONMENT}" = "dev" ]; then
echo "Dev environment — pushing schema directly (db:push)"
bun run db:push --force
elif [ "${MIGRATIONS_CHANGED}" = "false" ]; then
echo "No migration files changed in this push — skipping db:migrate (nothing to apply)."
else
echo "Applying versioned migrations (db:migrate)"
bun run ./scripts/migrate.ts
Expand Down
Loading