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.sh installs the latest migratr release (PR #34, #32): run as curl -fsSL <url> | bash, the installer at the repo root detects the platform (linux or macos) and architecture (x64 or arm64, preferring the native arm64 build when a macOS shell runs under Rosetta 2), resolves the version, downloads migratr-<os>-<arch>.tar.gz and checksums.txt from that GitHub release, and refuses to install unless the archive's SHA-256 matches its line in checksums.txt. The version comes from the first argument (bash -s v0.1.1), then MIGRATR_VERSION, then the tag the releases/latest redirect points at. It installs to MIGRATR_INSTALL_DIR (default ~/.local/bin) and, when that directory is not on the PATH, appends a PATH line to .bashrc, .zshrc, or fish's config.fish, only if it is not already there. It uses curl or falls back to wget. Platforms with no published build (Windows, linux-arm64) are refused before any download with a pointer to cargo install migratr-cli. The install ends by running migratr --version; a binary that fails to run is reported as an install error, not a success. scripts/test-install.sh runs 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.md is the procedure an agent follows to release migratr from a clean main to a live smugglr.dev page, stopping and reporting on the first failure. release.toml declares the version file (workspace.package.version in Cargo.toml), this changelog, the tag format v{version}, the preflight commands (fmt, clippy, tests, and the release-script tests), and the shingle docs branch. scripts/release.sh and scripts/sync-version.sh are copied from legion with two patches: the version bump also moves the version pin on every path = "..." dependency between the workspace crates, and --activate is refused. The bump level is read from the first line of the new changelog entry (for this entry, Patch release:). After release.yml publishes the GitHub release, polled with gh rather than curl so legion's network hook cannot stall the run, the procedure copies CHANGELOG.md into shingle and merges a docs PR so https://smugglr.dev/migratr/changelog/ shows the new entry. scripts/test-release.sh covers 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.yml runs on any v* tag. It builds migratr-cli in release mode for x86_64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, and x86_64-pc-windows-msvc, packages each as migratr-<os>-<arch>.tar.gz (or .zip on Windows), and creates a GitHub release carrying the archives, a checksums.txt of 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 equals v plus the version in [workspace.package] of Cargo.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, up and down (and Migrator::status) refuse with MigrateError::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 --json error document under the unchanged checksum_mismatch code, 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. up applies each pending migration and its ledger row in one atomic run; a failure rolls it back and names the failing statement and operation. up refuses 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 TABLE text with a comment- and quote-aware scanner. Indexes, triggers, and dependent views are recreated after the row copy, rowids and sqlite_sequence carry over, and foreign_key_check runs before commit. A rebuild is refused before anything runs when the table's CREATE TABLE does 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).
  • down reverses only exact inverses (PR #15, #6): down reverses 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 with irreversible before anything runs. down reverses structure only, and says that data in dropped objects is not restored.
  • Snapshots and restore (PR #17, #7): before a destructive step in up or down, migratr copies the database into .migratr/snapshots/ next to it and keeps the newest snapshot; a snapshot that cannot be written stops the step. restore replaces the database with the latest snapshot, or a named one, and changes nothing without --yes.
  • schema.json and new (PR #18, #8): after every successful up and down, migratr writes schema.json in the migrations directory describing the resulting schema. new scaffolds a migration file from a Rails-style name and column specs (such as create_users id:integer:pk), checked against schema.json.
  • embed! and Migrator (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. Migrator offers up, down, status, and plan over the embedded set.
  • The CLI, with --json (PR #20, #9): migratr [--db PATH] [--dir PATH] [--json] <new|up|down|status|plan|restore>. plan prints 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 carrying command and status; a failure adds a stable error code and message and 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, and migratr-cli under the MIT license, with CI verifying each crate builds from its own package.