Migratable 2.3.0

dotnet add package Migratable --version 2.3.0                
NuGet\Install-Package Migratable -Version 2.3.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Migratable" Version="2.3.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Migratable --version 2.3.0                
#r "nuget: Migratable, 2.3.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Migratable as a Cake Addin
#addin nuget:?package=Migratable&version=2.3.0

// Install Migratable as a Cake Tool
#tool nuget:?package=Migratable&version=2.3.0                

Migratable

Simple and efficient database migrations supporting multiple database technologies.

Available as both a cross-platform CLI tool suitable for any ecosystem (eg DotNet, Go, Node etc) and a set of nuget packages for inclusion in your own DotNet apps (eg to automate migrations).

Runs on Linux, Mac (Intel/ARM), and Windows. Currently supports PostgreSQL and MySQL.

Contents


About the cross-platform CLI tool

  • It's not dependent on the DotNet platform
  • It fits any ecosystem (eg Go, Python, Node etc)
  • It's easy to configure, needing only:
    • A connection string in an environment variable
    • A folder with named migrations using up/down SQL scripts

Benefits of both the CLI and the Nuget packages

  • Your database structure can be version-controlled
  • Roll your database backwards as well as forwards
  • Seed/pre-populate, update, or remove data
  • Run in transactions for atomic up/down
  • Uses the MIT licence

What's available?

Cross-platform releases (not dependent on DotNet):

Packages available on Nuget for DotNet:

Requirements

These requirements are the same whether you are using the command-line CLI tool or the Nuget packages.

You need a suitable database server installed (either MySQL or PostgreSQL). You also need the following:

A database connection string in an environment variable

You can use any environment variable name you like. Here's an example for Linux/Mac connecting to PostgreSQL:

export MY_CONNSTR="Server=127.0.0.1;Port=5432;Database=my_database;Search Path=my_schema;User Id=my_user;Password=my_password"

(This is an example, not a revealed secret.)

It's similar for Windows, but you'd replace export with set instead. However in Windows it's probably simpler to edit the environment variables from your Control Panel / Settings area.

A folder of SQL migration scripts

A single folder holds all migration scripts. Inside is a subfolder per migration, where the name begins with the migration sequence number (optional leading zeros) followed by a description. Each migration in turn consists of an up.sql file and a down.sql file.

/migrations
  /001 Create account table
    down.sql
    up.sql
  /002 Create news table
    down.sql
    up.sql
  /003 Insert sample data
    down.sql
    up.sql

There's an example folder here.

You must start at version one and you cannot omit a version in the sequence. You may also not have duplicate version numbers.

Using Migratable via the CLI tool

  • Download a release and place it somewhere convenient
  • Add the connection string into your environment
  • Create the folder of SQL migration scripts
  • Run the CLI

On a Mac for example you could do:

# Create a folder and copy the builds into it.
cd <repository_root>
sudo mkdir -p /usr/local/bin/Migratable
sudo cp -r builds/macos-arm64/* /usr/local/bin/Migratable

# Run it.
/usr/local/bin/Migratable/Migratable.CLI postgres my_connstr ~/my-app/migrations --info

In the above example the parameters are:

  • postgres is the database type (postgres or mysql)
  • my_connstr is the name of the environment variable containing your database connection string
  • ~/my-app/migrations is the folder containing all your migrations
  • --info is the Migratable command to run

You can run without any command arguments to get a summary of usage:

MIGRATABLE CLI v1.0.0.0
Built with Net 7.0.9
Uses Migratable v2.2.0.0

Usage:
  migratable <db> <env_name> <migrations> <command>


  db          database; either POSTGRES or MYSQL
              (always converted to uppercase)
  env_name    the name of an environment variable
              with a database connection string
              (always converted to uppercase)
  migrations  folder containing migration scripts
              (https://github.com/kcartlidge/migratable)
  command     migration action to perform
              (always converted to lowercase)

Commands:

  -info        Show migration status
  -list        List known migrations

  -reset       Remove all migrations
  -latest      Apply new migrations
  -next        Roll forward one migration
  -back        Roll backward one migration
  -target=0    Target specific migration

If it fails to run on Linux and Mac one of the following may help:

  • Run chmod +x Migratable.CLI to ensure the CLI tool is executable
  • Open it in Finder/Nemo/whatever first to deal with any security unlocking needed

Using the Migratable Nuget packages

There is an Example project in this solution. It's totally self-contained as it uses an in-memory provider. It also shows the use of a Timeline to show the known migrations and the current status.

Here's some sample code to show the packages in use. SampleProvider is defined in the example project just mentioned. You could also look at the (simple and commented) code for the CLI tool.

// Configure.
var provider = new SampleProvider();
var migrator = new Migratable.Migrator(provider);
var migrations = migrator.LoadMigrations("./migrations");

// Show the known migrations and current database position.
var timeline = new Timeline(provider, migrations, 3);
timeline.Show();

// Confirm the connection.
Console.WriteLine(migrator.Describe());
Console.Write("Press enter/return to continue (or Ctrl+C) ... ");
Console.ReadLine();

// Migrate from the current version to version 5.
Console.WriteLine($"Old version: {migrator.GetVersion()}");
migrator.SetVersion(5);
Console.WriteLine($"New version: {migrator.GetVersion()}");

The Describe() method is designed to give confidence in proceeding. For MySQL/MariaDB it shows the server and database name.

How it works

There are 2 necessary components, with two optional ones:

  • Migrator - what your code should interact with to load/perform migrations
  • Provider - a utility package to support a particular database technology
  • Notifier - an optional class that can be sent progress messages for you to output to the console, log to a file, send via email, or whatever you choose
    • The Notifier 'hook' is there but no delivery mechanism is provided, although the example project shows that a console notifier is just one line of code
  • Timeline - an optional class that can show/return a list of migrations with the current migration position

In brief, you follow this process:

  • Create a Provider instance for your database
  • Create a Migrator and pass in your Provider
  • Optionally create a Notifier and pass that to the Migrator
  • Ask your Migrator to load your migrations
  • Ask your Migrator to perform versioned actions
  • Optionally use the Timeline before and/or after applying actions

That final Migrator step will result in your up/down SQL statements being issued as needed to transition from your current database version to your target one. This is supported by an automatically created/updated migratable_version table.

Timeline Display

The Timeline class has options to either write a timeline to the Console or to return a List<string> containing the equivalent text. If you're writing to the screen a blank separator line is included before and after; this is not present if you request the text.

When creating a new Timeline instance, the 2 is an optional indent for the text to ensure it fits with your own output. You can also provide overrides for the title and the position text.

var timeline = new Timeline(provider, migrations, 2);
...
migrator.SetVersion(2);
timeline.Show();

Depending upon the migrations (this is based on one of the test fixtures) it would give something like this:

  STATUS
  001 Create accounts
  002 Populate accounts
  <-- YOU ARE HERE
  003 Create themes

Note about MySQL

MySQL has a habit of silently committing structural changes (add column, create table etc) mid-transaction. You should therefore avoid using multiple statements in a single migration if any one of them is structural. If you do, and one of the other statements fails, the transaction rollback may fail to undo a structural change that has already been applied in the current migration script.


For developers working on Migratable itself

If you only intend making use of Migratable in your own projects read no further.

Running the tests

cd Migratable.Tests
dotnet test

Creating a new version for Nuget

The Migratable/Migratable.csproj file contains Nuget settings. Within that file, update the version number then create the Nuget package. The version exists twice, in VersionPrefix and Version.

The pack command that follows is done at the solution level not the project.

cd <solution>
dotnet build
dotnet pack -c Release

The pack command will mention issues with other projects in the solution; we are not packing them so it's fine to ignore the suggestions (eg a README for the example). When completed the Successfully created package line says where the .nupkg file is.

If you are changing the CLI that project contains its own version number. It also has its own script for creating new cross-platform builds:

cd <solution>
cd Migratable.CLI
./build.sh

On Windows use build.bat rather than build.sh.

Forcing another project to get the latest from Nuget

It sometimes takes a while for a new version to be available after pushing. You may be able to speed up the process:

cd <other-project>
dotnet restore --no-cache

MIT Licence

Copyright (c) 2019-2024 K Cartlidge. See the included LICENCE file for details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Migratable:

Package Downloads
Migratable.MySqlProvider

Database provider for kcartlidge/migratable adding support for MySql/MariaDB

Migratable.PostgresProvider

Database provider for kcartlidge/migratable adding support for Postgres

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.3.0 87 10/23/2024
2.2.0 649 1/27/2023
2.1.0 1,171 2/1/2019
1.2.0 1,340 5/24/2018