Current version: 0.1.2
Changelog
0.1.2
Patch release: new installer and release tooling around the existing binary, with no change to any crate's code, the library API, the CLI, the migration file format, or the ledger.
The installer release. migratr now has a one-line install: curl -fsSL https://raw.githubusercontent.com/rafters-studio/migratr/main/install.sh | bash downloads the newest published binary for the machine, verifies it against the release's checksums, and puts it on the PATH, with no version written into the script, so each release updates the installer without anyone editing it. Alongside it, migratr is now released by one agent run with no operator step, following a written procedure that bumps the version, writes this changelog, merges the release PR, tags it, and publishes the changelog to smugglr.dev.
New
install.shinstalls the latest migratr release (PR #34, #32): run ascurl -fsSL <url> | bash, the installer at the repo root detects the platform (linuxormacos) and architecture (x64orarm64, preferring the native arm64 build when a macOS shell runs under Rosetta 2), resolves the version, downloadsmigratr-<os>-<arch>.tar.gzandchecksums.txtfrom that GitHub release, and refuses to install unless the archive's SHA-256 matches its line inchecksums.txt. The version comes from the first argument (bash -s v0.1.1), thenMIGRATR_VERSION, then the tag thereleases/latestredirect points at. It installs toMIGRATR_INSTALL_DIR(default~/.local/bin) and, when that directory is not on the PATH, appends a PATH line to.bashrc,.zshrc, or fish'sconfig.fish, only if it is not already there. It usescurlor falls back towget. Platforms with no published build (Windows, linux-arm64) are refused before any download with a pointer tocargo install migratr-cli. The install ends by runningmigratr --version; a binary that fails to run is reported as an install error, not a success.scripts/test-install.shruns the installer against real published releases, and CI runs it on Linux and macOS.- Releases run with no operator step (PR #36, PR #37, PR #38, #33):
RELEASING.mdis the procedure an agent follows to release migratr from a cleanmainto a live smugglr.dev page, stopping and reporting on the first failure.release.tomldeclares the version file (workspace.package.versioninCargo.toml), this changelog, the tag formatv{version}, the preflight commands (fmt, clippy, tests, and the release-script tests), and the shingle docs branch.scripts/release.shandscripts/sync-version.share copied from legion with two patches: the version bump also moves theversionpin on everypath = "..."dependency between the workspace crates, and--activateis refused. The bump level is read from the first line of the new changelog entry (for this entry,Patch release:). Afterrelease.ymlpublishes the GitHub release, polled withghrather thancurlso legion's network hook cannot stall the run, the procedure copiesCHANGELOG.mdinto shingle and merges a docs PR so https://smugglr.dev/migratr/changelog/ shows the new entry.scripts/test-release.shcovers the scripts, skips its legion-backed cases when legion is not installed, and runs in CI.
0.1.1
The release-pipeline release. Pushing a v* tag now builds the migratr binary for four platforms, attaches them to a GitHub release with checksums, and publishes the four workspace crates to crates.io, so a release needs no manual step. Alongside it, the refusal for an edited applied migration now tells the user what to do instead of only what went wrong. Patch release: a message rewording within an existing error (the checksum_mismatch code is unchanged) and new release automation, no API change, no change to the migration file format or the ledger.
New
- A pushed tag releases migratr (PR #29, #28):
.github/workflows/release.ymlruns on anyv*tag. It buildsmigratr-cliin release mode forx86_64-unknown-linux-gnu,x86_64-apple-darwin,aarch64-apple-darwin, andx86_64-pc-windows-msvc, packages each asmigratr-<os>-<arch>.tar.gz(or.zipon Windows), and creates a GitHub release carrying the archives, achecksums.txtof their SHA-256 sums, and generated release notes. A parallel job publishes to crates.io through trusted publishing (rust-lang/crates-io-auth-action, no stored token). Before publishing anything it refuses unless the tag equalsvplus theversionin[workspace.package]ofCargo.toml. It then publishes in dependency order (migratr-format,migratr-macros,migratr,migratr-cli), skipping any crate whose version is already in the crates.io index and treating cargo's "already exists" as success, so a run that failed partway can be re-run and publishes only what is missing.
Fixed
- The checksum-mismatch refusal says how to recover (PR #27, #24): when an applied migration's file has been edited,
upanddown(andMigrator::status) refuse withMigrateError::ChecksumMismatch. The message used to say only that the checksum no longer matched the ledger. It now reads "migration<version>_<name>was edited after it was applied. Applied migrations are not edited: restore the file to what was applied, then write a new migration for the change". The same text reaches the CLI's--jsonerror document under the unchangedchecksum_mismatchcode, and tests in both the library and the CLI pin it.
0.1.0
The first release. migratr manages SQLite schema migrations written as JSON files, applies them atomically against a ledger, rebuilds tables safely where SQLite cannot alter in place, reverses only what has an exact inverse, and snapshots the database before any destructive step. It ships as a library (migratr, with an embed! macro and Migrator for migrations compiled into a program) and as a CLI (migratr) with machine-readable --json output.
New
- Migrations as JSON files (PR #12, #2): each migration is a JSON file of typed operations named by version and name. The parser reports the exact JSON path of a bad field, lists every file that shares a version, and computes a checksum per file so an edit after apply is detected.
- Ledger and
up(PR #13, #3): applied migrations are recorded in a ledger table.upapplies each pending migration and its ledger row in one atomic run; a failure rolls it back and names the failing statement and operation.uprefuses to run when an applied file was edited or a ledger row has no file. - Safe table rebuilds (PR #14, #4): an operation SQLite cannot do in place, such as dropping a column it refuses to drop, rebuilds the table by SQLite's 12-step procedure, editing the stored
CREATE TABLEtext with a comment- and quote-aware scanner. Indexes, triggers, and dependent views are recreated after the row copy, rowids andsqlite_sequencecarry over, andforeign_key_checkruns before commit. A rebuild is refused before anything runs when the table'sCREATE TABLEdoes not parse, when another object uses the dropped column or the table's columns by position, or when the rebuild is not the first operation in its migration. The rebuild is checked against a hazard oracle covering nine SQLite rebuild hazards (PR #16, #5). downreverses only exact inverses (PR #15, #6):downreverses the newest N applied migrations, newest first, each with its ledger delete in one atomic run. Following the Rails rule, an operation with no exact inverse makes the whole range refuse withirreversiblebefore anything runs.downreverses structure only, and says that data in dropped objects is not restored.- Snapshots and restore (PR #17, #7): before a destructive step in
upordown, migratr copies the database into.migratr/snapshots/next to it and keeps the newest snapshot; a snapshot that cannot be written stops the step.restorereplaces the database with the latest snapshot, or a named one, and changes nothing without--yes. schema.jsonandnew(PR #18, #8): after every successfulupanddown, migratr writesschema.jsonin the migrations directory describing the resulting schema.newscaffolds a migration file from a Rails-style name and column specs (such ascreate_users id:integer:pk), checked againstschema.json.embed!andMigrator(PR #21, #10):migratr::embed!("migrations")embeds a migrations directory in the program and parses it at compile time with the library's own parser, so a malformed file stops the build.Migratoroffersup,down,status, andplanover the embedded set.- The CLI, with
--json(PR #20, #9):migratr [--db PATH] [--dir PATH] [--json] <new|up|down|status|plan|restore>.planprints the statements a run would execute, which steps are destructive, and the snapshot each would take, changing nothing. With--json, each command writes one JSON document to stdout carryingcommandandstatus; a failure adds a stable errorcodeandmessageand exits non-zero (2 for usage errors, 1 otherwise). - Published to crates.io (PR #26, #25): the workspace publishes as
migratr-format,migratr-macros,migratr, andmigratr-cliunder the MIT license, with CI verifying each crate builds from its own package.