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
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ jobs:
run: npm ci

- name: Verify migrations and schema syntax
run: bash scripts/verify-migrations.sh
run: |
chmod +x scripts/verify-migrations.sh
bash scripts/verify-migrations.sh
env:
DATABASE_URL: postgresql://postgres:password@localhost:5432/astroid_test?schema=public
SHADOW_DATABASE_URL: postgresql://postgres:password@localhost:5432/astroid_shadow?schema=public
CI: "true"

- name: Run typecheck
run: npm run typecheck
Expand Down
9 changes: 9 additions & 0 deletions docs/database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Database Guidelines & Migration Verification

All database changes must be managed via Prisma migrations.

## Migration Verification Requirements
- Every migration folder must contain a valid, non-empty `migration.sql` file.
- Migration directories must start with a 14-digit timestamp prefix (`YYYYMMDDHHMMSS`) to ensure strict ordering and avoid conflicts.
- Run `npm run db:verify` locally to execute `scripts/verify-migrations.sh` prior to opening a pull request.
- The CI pipeline automatically runs `scripts/verify-migrations.sh` to validate schema syntax, migration structure, and working tree cleanliness.
64 changes: 56 additions & 8 deletions scripts/verify-migrations.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,72 @@
#!/usr/bin/env bash
set -e
set -euo pipefail

echo "Starting database migration verification..."

# 1. Validate Prisma schema syntax
echo "Validating Prisma schema..."
npx prisma validate

MIGRATIONS_DIR="prisma/migrations"

if [ -d "$MIGRATIONS_DIR" ]; then
COUNT=$(find "$MIGRATIONS_DIR" -mindepth 1 -maxdepth 1 -type d ! -name 'migration_lock.toml' | wc -l)
echo "Found $COUNT migration directory(ies)"
for dir in "$MIGRATIONS_DIR"/*/; do
if [ -d "$dir" ]; then
if [ ! -f "${dir}migration.sql" ]; then
echo "Error: Missing migration.sql in $dir"
echo "Checking migration directories under $MIGRATIONS_DIR..."

declare -A timestamps
migration_count=0

for dir in "$MIGRATIONS_DIR"/*/;
do
# Skip if not a directory or if it's not a migration folder
[ -d "$dir" ] || continue
dirname=$(basename "$dir")

# Skip lock files or other non-migration directories if any
if [ "$dirname" = "migration_lock.toml" ]; then
continue
fi

migration_count=$((migration_count + 1))
echo "Inspecting migration: $dirname"

# Check 2: Verify migration.sql exists and is non-empty
sql_file="${dir}migration.sql"
if [ ! -f "$sql_file" ]; then
echo "Error: Missing migration.sql in migration folder '$dirname'"
exit 1
fi

if [ ! -s "$sql_file" ]; then
echo "Error: migration.sql in '$dirname' is empty"
exit 1
fi

# Check 3: Extract timestamp prefix (expects YYYYMMDDHHMMSS or similar leading numeric prefix)
if [[ "$dirname" =~ ^([0-9]{14}) ]]; then
ts="${BASH_REMATCH[1]}"
if [ -n "${timestamps[$ts]:-}" ]; then
echo "Error: Conflicting migration timestamps detected: '$dirname' shares timestamp prefix with '${timestamps[$ts]}'"
exit 1
fi
timestamps["$ts"]="$dirname"
else
echo "Warning: Migration directory '$dirname' does not start with a standard 14-digit timestamp (YYYYMMDDHHMMSS)"
fi
done

echo "Successfully verified $migration_count migration folder(s)."
else
echo "No migrations directory found."
echo "No migrations directory found at $MIGRATIONS_DIR."
fi

# Check 4: Optionally check git working tree cleanliness if explicitly requested
if [ "${CHECK_GIT_DIRTY:-false}" = "true" ]; then
echo "Checking git working tree state..."
if [ -n "$(git status --porcelain)" ]; then
echo "Error: Git working tree is dirty. Uncommitted migration or schema changes detected."
git status --porcelain
exit 1
fi
fi

echo "Migration verification completed successfully!"
Loading