Deterministic schema diff, migration planning, and destructive-change gates for MoonBit
Dependencies
# Fail the build when a migration would destroy data.
moon run cmd/main -- verify postgresql \
--before schema/v1.json --after schema/v2.json
# exit 2: migration policy violated: --max-risk is review
# step-5 [destructive] drop column users.legacy_code: drops all values stored in the columnmoon add kath61105/moon_schema_planmoon run cmd/main -- verify postgresql \
--before schema/v1.json \
--after schema/v2.json \
--hints schema/renames.json \
--max-risk review| Exit code | Meaning |
|---|---|
| 0 | The plan satisfies --max-risk. |
| 1 | Usage, file, JSON or schema-validation error. Nothing was planned. |
| 2 | The plan is valid but contains a step above --max-risk. |
moon run cmd/main -- verify postgresql \
--before schema/v1.json --after schema/v2.json \
--format markdown --out migration-plan.md# Blocked: exits 2 and prints the offending steps, with no SQL.
moon run cmd/main -- plan postgresql \
--before examples/schema_v1.json \
--after examples/schema_v2.json \
--hints examples/rename_hints.json
# Approved: renders the migration.
moon run cmd/main -- plan postgresql \
--before examples/schema_v1.json \
--after examples/schema_v2.json \
--hints examples/rename_hints.json \
--allow-destructivemoon run cmd/main -- plan sqlite --before v1.json --after v2.json --allow-destructive --out migration.sql
sqlite3 -bail app.db < migration.sqllet result = @moon_schema_plan.build_plan(before, after, @moon_schema_plan.PostgreSQL)
match result {
// Every invalid path at once, rather than the first one found.
Err(issues) => report(issues)
Ok(plan) =>
if plan.max_risk().severity() > @moon_schema_plan.Review.severity() {
reject(plan.steps_above(@moon_schema_plan.Review))
} else {
match @moon_schema_plan.render_plan(plan) {
Err(blocked) => report(blocked)
Ok(rendered) => println(rendered.sql.join("\n"))
}
}
}moon fmt --check
moon info
moon check --deny-warn
moon test --deny-warn
sh scripts/cli_smoke.sh # every documented CLI invocation and exit code
sh scripts/sqlite_e2e.sh # applies generated SQL to a real sqlite3 database
sh scripts/postgres_e2e.sh # the same against a real PostgreSQL serverdocker build -t moon-schema-plan-dev -f .devcontainer/Dockerfile .
docker run --rm -v "$PWD:/workspace" moon-schema-plan-dev moon test --deny-warnpub(all) enum Change {
AddTable(Table)
DropTable(Table)
RenameTable(String, String)
AddColumn(String, Column)
DropColumn(String, Column)
RenameColumn(String, String, String)
AlterColumn(String, Column, Column)
AddIndex(String, Index)
DropIndex(String, Index)
AddForeignKey(String, ForeignKey)
DropForeignKey(String, ForeignKey)
AddCheck(String, CheckConstraint)
DropCheck(String, CheckConstraint)
AddTrigger(String, Trigger)
DropTrigger(String, Trigger)
AddView(View)
DropView(View)
RebuildTable(Table, Table, Array[(String, String)])
} derive(Eq, ToJson, Debug, FromJson)fn build_plan(before : Schema, after : Schema, dialect : Dialect, hints? : RenameHints) -> Result[Plan, Array[ValidationIssue]]Install
Download zipDeterministic schema diff, migration planning, and destructive-change gates for MoonBit
Dependencies