
Volver atras una migración automáticamente con capistrano
5 May, 2009Hace un par de semanas Xavi me pidió la funcionalidad que da título a este post en el deploy de uno de nuestros proyectos, me pareció extraño no encontrarlo por defecto en el código de capistrano, pero así es. Hurgando un poco en la lista encontré el siguiente fragmento de código que realiza lo requerido:
before "deploy:rollback:revision", "deploy:rollback_database"
desc "Rolls back database to migration level of the previously deployed release"
task :rollback_database, :roles => :db, :only => { :primary => true } do
if releases.length < 2
abort "could not rollback the code because there is no prior release"
else
rake = fetch(:rake, "rake")
rails_env = fetch(:rails_env, "production")
migrate_env = fetch(:migrate_env, "")
migrate_target = fetch(:migrate_target, :latest)
run "cd #{current_path}; #{rake} RAILS_ENV=#{rails_env} #{migrate_env} db:migrate VERSION=`cd #{File.join(previous_release, 'db', 'migrate')} && ls -1 [0-9]*_*.rb | tail -1 | sed -e s/_.*$//`"
end
end
Voy a comentar un poquito como funciona la cosa:
La primera línea añade un ‘hook’ a la tarea rollback:revision, es necesario ejecutar la tarea antes de volver a la versión anterior de código por la manera que utilizamos para calcular las migraciones hacia atrás que tenemos que volver, pensad que en un sólo commit se pueden incluir varias migracione.
A continuación comprobamos que haya al menos una versión anterior del código a la que volver, y las siguientes lineas sirven para establecer las variables de entorno y rutas necesarias para ejecutar este ‘rollback’.
Lo importante viene en el comando que se ejecuta, como veis es la tarea de rake que lanza la migración. Voy a comentar los puntos dificiles de la linea:
ls -1 [0-9]*_*.rb | tail -1 | sed -e s/_.*$//
Aqui dejo el código en github.


[...] Fundiendo capistrano y migrations, por parte de Jacobo. [...]