Add Kysely database migrations for self-hosting#17
Open
stephen-dahl wants to merge 1 commit intoChurchApps:mainfrom
Open
Add Kysely database migrations for self-hosting#17stephen-dahl wants to merge 1 commit intoChurchApps:mainfrom
stephen-dahl wants to merge 1 commit intoChurchApps:mainfrom
Conversation
bc214d8 to
91d49a2
Compare
Replace the ad-hoc SQL init scripts with a proper migration system using Kysely. Each of the 6 databases (membership, attendance, content, giving, messaging, doing) gets versioned, trackable migrations that can be run forward or rolled back. New commands: npm run migrate — apply all pending migrations npm run migrate:status — see what's applied vs pending npm run migrate:down — roll back the last migration npm run migrate:create — scaffold a new migration file npm run migrate:baseline — mark existing DBs as up-to-date npm run seed — load demo data Existing initdb.ts still works but prints a deprecation notice. Removed unused 01_tables.sql drafts and old ad-hoc migration scripts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91d49a2 to
122507c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Setting up or updating ChurchApps requires running raw SQL scripts through
initdb.ts— a 600-line script that reads ~100.sqlfiles and executes them with no version tracking. There's no way to know what state a database is in, no way to roll back a bad schema change, and no way for self-hosters to apply incremental updates without re-reading the full init script source code.Ad-hoc migration scripts have accumulated in scattered places (
giving/migrations/,content/links_visibility_migration.sql,giving/eventLogs_migration.sql) with no unified way to run them.What this does
Adds Kysely-managed migrations — one command to set up or update all 6 databases:
Each database tracks its own migration history in a
kysely_migrationtable. Kysely is already a MySQL query builder (no ORM overhead), weighs ~50KB, and has zero dependencies.For self-hosters
Before: Read
initdb.ts, understand the module system, hope your DB matches the SQL files.After:
npm run migrate— done. Every future schema change is a numbered migration file that runs exactly once.For us (developers)
Before: Edit a
.sqlfile and hope everyone re-runsinitdb. No rollback. No version tracking.After:
For existing deployments (prod/staging)
What's included
tools/migrations/kysely-config.tsEnvironment.getDatabaseConfig()tools/migrate.ts--module=<name>,--action=up|down|statustools/migrate-create.tstools/migrate-baseline.tstools/seed.tsdemo.sqlfilestools/migrations/<module>/2026-02-06_initial_schema.tsWhat didn't change
dbScripts/are untouched (still the source of truth for reading)initdb.tsstill works, just prints a deprecation noticedemo.sqlfiles untouched (used by the new seed runner)What was cleaned up
01_tables.sqldraft files (had different schema than the actual.sqlfiles)giving/migrations/,eventLogs_migration.sql,links_visibility_migration.sql)npm scripts added
Test results
All tests run against MySQL 8.0 in Docker (
mysql:8.0on port 3307).Fresh database — all 96 tables created across 6 databases
Idempotent — second run is a no-op
Status check
Down/Up roundtrip (attendance module)
Seed data
Baseline (for existing databases)
Test plan
npm run migrateon empty MySQL — all 96 tables creatednpm run migratetwice — second run is a no-opnpm run migrate:down -- --module=attendancethenmigrate:up— tables recreatednpm run migrate:status— shows applied migrationsnpm run migrate:baselinethennpm run migrate— no-opnpm run seedafter migrate — demo data loadsmain— picked upplanItems.labelvarchar(100) +thumbnailUrlcolumn🤖 Generated with Claude Code