h1

Volver atras una migración automáticamente con capistrano

5 May, 2009

Hace 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:

Por un lado tenemos db:migrate VERSION=XX. Según las guías de rails esta tarea ejecuta todas las migraciones hacia arriba o hacia abajo hasta llegar a la versión dada, esta es la razón por la que hay que ejecutar esta tarea antes de hacer rollback del código. Por otro lado calculamos el número de versión a la que hay que bajar con el ‘path’ de la release anterior variable de entorno de capistrano previous_release. Apañando el numero de ‘release’ con un estupendo hack de shell:

ls -1 [0-9]*_*.rb | tail -1 | sed -e s/_.*$//

Aqui dejo el código en github.


One comment

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



Leave a Comment