6 releases

0.2.3 Jul 4, 2023
0.2.2 Mar 29, 2023
0.1.1 Feb 28, 2023
0.1.0 Nov 19, 2022

#1132 in Database interfaces

ISC license

46KB
880 lines

Salmo

A database migration system.

Currently it's not proof of concept stage. It's usable for experimentation, but I'd recommend waiting before using in production.

Motivation

Everyone and their mother has written a database migration system. A simple one is not hard. However they tend to have one of 2 issues: either they have no good development story (they are immutable and only intended for production deployment), or have a good development story but they are have a number of traps that can be problematic in production. Salmo is intended specifically to be usable during local development, but then the local changes are commited into an immutable form for production deployment.

It is currently only targeting postgres, but if it's successful there's no reason other databases cannot be supported. It can be used with any framework, and is intended to be easy to install and use in a wide variety of environments.

Migration format

salmo will search for a directory with a Salmo.toml file to use as the base for all commands. This Salmo file has a number of configuration values, including the directory that the migrations are in.

The default file structure is

dir/
  Salmo.toml
  migrations/
    committed.toml
    create-users/
      migrate.sql
      revert.sql

Usage

salmo init: create a Salmo.toml in the current directory, if one does not exist

salmo new [migration-id]: create a new migration directory with the given id

salmo migrate: execute all pending (committed, but not executed) migrations against the current database

salmo status: will show which migrations are what state. The states are:

  • uncommitted: This migration is in development and will not be executed in salmo migrate.
  • tried: This migration is uncommitted, but is being tested locally with salmo try
  • pending: This migration has been committed, but not executed against the current database.
  • complete: This migration has been commited and executed.

by default only uncommitted or pending migrations are shown.

salmo commit [migration-id]: commit the migration. The hash of the migration will be calculated so it can't be changed any more. The migration id can be omitted if only one uncommitted migration exists

salmo try [migration-id]: execute an uncommitted migration. If only one uncommitted migration exists, then that will be executed.toml

salmo retry [migration-id]: revert and re-execute a tried migration

salmo untry [migration-id]: revert a tried migration

salmo reset: revert all tried migrations

A note on evironments

Salmo requires (possibly multiple) environments to be configured (though it can defer the actual connection params to environment variables). Each environment has a is_production flag. If the environment is production, then salmo will not execute salmo try or salmo reset (since especially reset can be dangerous since salmo will undo execute schema changes).

Configuring salmo

Salmo is configured via the Salmo.toml file.

migrations_directory: [optional] the directory which contains the migration files envrionments: [required] an array of different environments with their connection parameters environments.name: [required] the name of the environment. This must be unique between all environments environments.connection_params: [optional] a table of connection params. Each one can be either a string or a table of the form {env: 'ENV_VAR_NAME' environments.connection_url: [optional] the string url to connect to the database with. It can be either a string or a table of the form {env: 'ENV_VAR_NAME'} environments.is_production: a boolean, if the environment is considered to be production default_environments: [optional] an array of active environment names. These environments will be active if no others are specified.

The active environment(s) can be set via the param --environments (or -e), or the SALMO_ENV environment variable. If multiple environments are active, commands will be executed in each. This makes keeping development and testing databases in sync easy.

committed.toml

Committed.toml does not need be manually edited, but it can be inspected if needed. It lists the execution order of migrations with their hash.

  • create a migration with salmo new
  • edit the newly created file
  • salmo try to try to execute the migration
  • if the migration fails, fix it and salmo try again
  • develop code that uses the migration
  • possibly realize that something is missing from the migration, or it could be better. In this case do a salmo reset, edit the migration and salmo try again
  • possibly get code review
  • possibly even test in a staging environment
  • once the whole feature is ready to be deployed, run salmo commit
  • when the new feature is deployed, salmo migrate to run the migration.

Dependencies

~5–15MB
~199K SLoC