Skip to content
Merged
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
55 changes: 21 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,17 +327,28 @@ jobs:
# dbmate keys migrations by their version filename. Once a migration
# has shipped to main, editing it silently no-ops in any environment
# whose schema_migrations row already lists that version (i.e. prod).
# The fresh-Postgres `dbmate up` below applies the latest text of every
# file and stays green, so edits-after-apply are invisible to that job.
# Fail the PR when a migration file changes (rather than is added)
# relative to main; force authors to ship a new dated file instead.
# relative to main; force authors to ship a new dated migration instead.
#
# Exceptions:
# 1. The baseline at 00000000000000_baseline.sql may be regenerated
# by re-running the squash workflow (always modifiable).
# 2. PRs whose commit message contains the explicit sentinel
# `[squash-baseline]` may delete the forward-delta migration
# files that were collapsed into the baseline. This is a
# one-time-per-squash exception and code review is the gate.
if: github.event_name == 'pull_request'
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
edited=$(git diff --name-only --diff-filter=MRD "$BASE_SHA"...HEAD -- db/migrations/ || true)
if git log "$BASE_SHA"..HEAD --format=%B | grep -qF '[squash-baseline]'; then
echo "[squash-baseline] sentinel present; immutability check is skipped for this PR."
exit 0
fi
edited=$(git diff --name-only --diff-filter=MRD "$BASE_SHA"...HEAD -- db/migrations/ \
| grep -v '^db/migrations/00000000000000_baseline\.sql$' || true)
if [ -n "$edited" ]; then
echo "::error::Migration files were modified or renamed — applied migrations are immutable. Add a new dated migration instead."
echo "::error::Migration files were modified or renamed — applied migrations are immutable (only db/migrations/00000000000000_baseline.sql is excluded). Add a new dated migration instead."
echo "$edited"
exit 1
fi
Expand All @@ -351,10 +362,11 @@ jobs:
- name: Apply all migrations against an empty Postgres
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/lobu_ci?sslmode=disable
# `dbmate up` dumps `db/schema.sql` after running. The drift check below
# diffs that file against the committed version after stripping volatile
# lines (see `scripts/normalize-schema.sh`).
run: dbmate --migrations-dir db/migrations --schema-file db/schema.sql up
# The baseline migration plus any forward deltas must apply cleanly
# to a fresh DB. That's the only schema check left after the squash —
# db/schema.sql + the drift-gate-vs-baseline diff are gone since the
# baseline IS the canonical schema.
run: dbmate --migrations-dir db/migrations up

- name: Verify migrations are listed in the schema_migrations table
env:
Expand All @@ -368,31 +380,6 @@ jobs:
exit 1
fi

- name: Normalize generated schema.sql for comparison
# pg_dump emits non-deterministic / env-dependent lines that vary
# across pg_dump versions and runs: `\restrict <random_token>`,
# `\unrestrict <random_token>`, `-- Dumped from database version ...`,
# `-- Dumped by pg_dump version ...`, and `SET transaction_timeout = 0;`
# (pg17+ only). Strip them so the drift check is purely about the
# actual schema. The committed `db/schema.sql` is in the same stripped
# form; devs reproducing locally should run `scripts/normalize-schema.sh
# db/schema.sql` after `dbmate ... dump`.
run: scripts/normalize-schema.sh db/schema.sql

- name: Schema snapshot drift — db/schema.sql must match `dbmate up` output
# Independent backstop against editing applied migrations. The
# immutability check above looks at the migration file set; this looks
# at the end-state schema. They catch the same class of bug from
# opposite sides — a buggy edit could in principle pass one and trip
# the other (e.g. rename + edit). Failure mode is concrete:
# `make db-schema` locally (requires DATABASE_URL with pgvector) and
# commit the regenerated db/schema.sql.
run: |
if ! git diff --exit-code -- db/schema.sql; then
echo "::error::db/schema.sql is stale. Regenerate locally with \`make db-schema\` (requires DATABASE_URL with pgvector) and commit the result."
exit 1
fi

# Path-filter for the Mac smoke build, isolated to a cheap ubuntu runner
# so skipped PRs don't allocate a macOS runner just to evaluate the diff.
# `github.event.pull_request.changed_files` in the webhook payload is an
Expand Down
17 changes: 1 addition & 16 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Development Makefile for Lobu

.PHONY: help setup build test eval clean dev build-packages ensure-submodule clean-workers test-unit test-integration test-e2e typecheck task-setup task-clean task-use db-schema
.PHONY: help setup build test eval clean dev build-packages ensure-submodule clean-workers test-unit test-integration test-e2e typecheck task-setup task-clean task-use

# Default target
help:
Expand All @@ -18,7 +18,6 @@ help:
@echo " make task-setup NAME=<name> - Create a paired worktree at .claude/worktrees/<name> (lobu + submodule on real branch, .env copied, ports auto-assigned, Lobu context registered)"
@echo " make task-clean NAME=<name> [FORCE=1] - Remove the worktree, both branches, and the Lobu context (refuses if there's uncommitted/unpushed work unless FORCE=1)"
@echo " make task-use NAME=<name|main> - Point Chrome ext / Mac app symlinks at this worktree (or 'main' for the canonical checkout)"
@echo " make db-schema - Run dbmate up + normalize db/schema.sql (after adding a migration; auto-patches the varchar(128) gotcha)"

# Strict typecheck — mirrors the Dockerfile so local matches CI. Catches
# what `build-packages` (relaxed, bundler-only) misses.
Expand Down Expand Up @@ -91,20 +90,6 @@ task-use:
@: $${NAME?Usage: make task-use NAME=<name|main>}
@./scripts/task-use.sh "$(NAME)"

# --- DB schema regen ---------------------------------------------------------
# After adding a file under db/migrations/, regenerate the end-state snapshot
# at db/schema.sql so CI's drift check passes. Mirrors exactly what CI runs,
# then normalizes the output (strips pg18 noise + restores the varchar(128)
# length pg18 silently drops from schema_migrations.version).

db-schema:
@: $${DATABASE_URL?Set DATABASE_URL=postgres://... (with pgvector) before running}
@echo "→ dbmate up (migrations → db/schema.sql)..."
@dbmate --migrations-dir db/migrations --schema-file db/schema.sql up
@echo "→ normalizing db/schema.sql..."
@./scripts/normalize-schema.sh db/schema.sql
@echo "✓ db/schema.sql regenerated and normalized (varchar(128) auto-patched)"

# --- Test pipelines ---------------------------------------------------------
# These mirror what CI runs (.github/workflows/ci.yml) so a passing local run
# is a strong signal CI will pass.
Expand Down
Loading
Loading