« heh | Main | eval.c »

Subverted Migrations

I got fed up with the lack of best practice for working with Rails migrations across source control branches, so I decided to write a little Rails plugin. Here it is: the first release of Subverted Migrations!

This is a plugin that manages your migration versions across Subversion branches. It has two primary functions:

  • It scans all of your Subversion branches and trunk to find a safe version number when creating migrations.
  • It keeps track (à la svnmerge.py) of which migrations have been applied, and applies new migrations when they are merged back into the branch. (A detailed example exploring this feature is below.)

Warning

Careful, it's alpha! Please back up your schemas and data before trying this. At this time, it is only tested on OS X and PostgreSQL.

Getting It

script/plugin install \
  svn://svn.madriska.com/plugins/subverted_migrations

Example (with Chunky Bacon)

Assume you have trunk and a ChunkyBacon branch (/branches/chunky_bacon). Both
have their latest migration at revision 010.

You create a migration in trunk:

[trunk]$ script/generate migration BoringBacon
    exists  db/migrate
    create  db/migrate/011_boring_bacon.rb

Next, you want to create a migration in branches/chunky_bacon. Without this
plugin, the new migration would have version number 011 and would create a
merge conflict. With the plugin, the version numbers are kept in sync:

[branches/chunky_bacon]$ script/generate migration ExtraCrispy
    exists  db/migrate
    create  db/migrate/012_extra_crispy.rb

The migration scripts should work as usual, but behind the scenes they keep
track of which migrations have been run, à la svnmerge.py. So let's say you
run the migration from the branch:

[branches/chunky_bacon]$ rake db:migrate
Current version: 1-10
Target version: 1-12
== ExtraCrispy: migrating ==================================================
(...)
== ExtraCrispy: migrated (0.0000s) =========================================
Final version: 1-10,12

This indicates that the migrated version contains migrations 1-10 (from
before), as well as the ExtraCrispy revision (12). Once the Rake script detects
that a file matching "db/migrate/011_*" has been added, it will apply that
change as well. So if you merge the BoringBacon change from trunk into the
Chunky Bacon branch, just run "rake db:migrate" and it will pick up the new
change:

[branches/chunky_bacon]$ (svnmerge...)
[branches/chunky_bacon]$ rake db:migrate
Current version: 1-10,12
Target version: 1-12
== BoringBacon: migrating ==================================================
(...)
== BoringBacon: migrated (0.0000s) =========================================
Final version: 1-12

Note that version 11 has been incorporated, and now the version is 1-12.

You may also specify a version string on the command line. It can either be a
series of ranges or numbers separated by commas ("1-6,7,12-42") or a single
number, as before ("12", equivalent to "1-12"). To specify a single revision,
you must express it as a range (to migrate to revision 6 only, specify "6-6").

To back out the BoringBacon change, we would specify the version string that
removes version 11. The plugin includes a Rake task to show the current
version:

[branches/chunky_bacon]$ rake db:version
1-12

We remove 11 from the range and give the new range as an environment variable:

[branches/chunky_bacon]$ rake db:migrate VERSION="1-10,12"
Current version: 1-12
Target version: 1-10,12
== BoringBacon: reverting ==================================================
(...)
== BoringBacon: reverted (0.0000s) =========================================
Final version: 1-10,12

And now the change is backed out.

TrackBack

TrackBack URL for this entry:
http://www.bradediger.com/blog/mt-tb.cgi/5

Comments (3)

David Southwell:

Hi
Just wonder if you know how this would work for those of us using eclipse as an IDE with subclipse as the subversion client.

Have you tried it using eclipse setup with aptana and RadRails.

Thanks for your contribution

David

The plugin modifies Rails's own concept of what a migration number is, so I don't see any reason why it shouldn't work with RadRails. It does shell out to svn, so if you can't call svn from the command line you will have a problem. But you can change that in Madriska::SubvertedMigrations::CommandsBase#svn.

I used to use RadRails, but that was long before I wrote this plugin, so YMMV. Let me know if it works out.

David Southwell:

I have referenced your blog on:
http://www.aptana.com/forums/viewtopic.php?t=2519

Woulod be interested to hyave your reactions and wonder whether you might be willing to consider amending your code to work in the way suggested there.

david

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About

This page contains a single entry from the blog posted on November 30, 2006 8:02 PM.

The previous post in this blog was heh.

The next post in this blog is eval.c.

Many more can be found on the main index page or by looking through the archives.