<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rafa Garcia.net - Blog &#187; multistage</title>
	<atom:link href="http://blog.rafagarcia.net/tag/multistage/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rafagarcia.net</link>
	<description>Desvaríos varios sobre ruby, rails, linux, capistrano, ... y muchas cosas más!</description>
	<lastBuildDate>Sun, 22 Aug 2010 13:35:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Capistrano y multistaging</title>
		<link>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/</link>
		<comments>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 02:16:16 +0000</pubDate>
		<dc:creator>Rafa García</dc:creator>
				<category><![CDATA[capistrano]]></category>
		<category><![CDATA[multistage]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.rafagarcia.net/?p=82</guid>
		<description><![CDATA[Mientras veía caer los copos de nieve por la ventana, observando como cuajaban en el patio, me vino a la mente que este &#8220;viernes de Capistrano&#8221; tenía que ser diferente, no estaba/estoy lo suficiente inspirado para corregir bugs. Entonces he recordado que tengo una deuda pendiente con la gente que vino al taller de Capistrano [...]]]></description>
			<content:encoded><![CDATA[<p>Mientras veía caer los copos de nieve por la ventana, observando como cuajaban en el patio, me vino a la mente que este &#8220;viernes de Capistrano&#8221; tenía que ser diferente, no estaba/estoy lo suficiente inspirado para corregir bugs. Entonces he recordado que tengo una deuda pendiente con la gente que vino al taller de Capistrano en la Conferencia Rails. Hubo varios temas que quería haber tocado pero que tuve que eliminar por falta de tiempo. Así que vamos a por uno de esos temas, el multistaging.</p>
<p><span id="more-82"></span>Un ejemplo de entorno multistage podría ser el siguiente:</p>
<ul>
<li> mi máquina de desarrollo </li>
<li> un servidor de aceptación </li>
<li> un servidor de producción </li>
</ul>
<p>Supongamos que mi máquina de desarrollo la actualizo a mano y los otros dos stages los quiero hacer con Capistrano. Capistrano por defecto solo sabe &#8220;deployar&#8221; y no es capaz de diferenciar entre aceptación y producción. Para ayudarle a diferenciar entre los diferentes stages podemos seguir varias estrategias.</p>
<p>Vamos a empezar por el mas simple de los casos, supongamos que entre aceptación y producción lo único que cambian son los datos de los roles. Una solución muy simple podría ser añadir a nuestro deploy.rb lo siguiente:</p>
<pre>  if ENV['DEPLOY'].upcase == 'PRODUCTION'
    puts "*** Deployando en producción"
    role :web, "www.production.com"
    role :app, "app.production.com"
    role :db,  "db.production.com", :primary =&gt; true
  else
    puts "*** Deployando en staging"
    role :web, "www.staging.com"
    role :app, "app.staging.com"
    role :db,  "db.staging.com", :primary =&gt; true
  end
</pre>
<p>El código añadido es bastante simple, si la variable de entorno DEPLOY tiene el string &#8216;PRODUCTION&#8217; ejecutaremos el deploy en la máquina de producción, sino se irá a staging. La ejecución se haría de la siguiente manera:</p>
<pre>  $ DEPLOY=production cap deploy
</pre>
<p>Para probarlo sin tener que subir toda una aplicación a nuestros servidores podemos crear una tarea simple y estúpida como esta:</p>
<pre>  task :foo do
    run "uptime"
  end
</pre>
<p>Entonces ahora lo podemos probar de nuevo:</p>
<pre>  $ DEPLOY=production cap foo
  *** Deployando en producción
  ...

  $ cap foo
  *** Deployando en staging
  ...
</pre>
<p>Vale, funciona pero me chirría un poco, ¿no sería mejor hacerlo en el idioma de Capistrano? -aquí es donde todos al unísono debéis decir: SÍIIIIIIII. Entonces vamos a hacer algo parecido encadenando las tareas.</p>
<p>Si recordáis el día del taller os expliqué que con Capistrano podíamos definir varias tareas y llamarlas una detrás de otra, eso es lo que vamos a hacer. Vamos a considerar la configuración de cada stage una tarea diferente:</p>
<pre>  task :production do
    puts "*** Deployando en producción"
    role :web, "www.production.com"
    role :app, "app.production.com"
    role :db,  "db.production.com", :primary =&gt; true
  end

  task :staging do
    puts "*** Deployando en staging"
    role :web, "www.staging.com"
    role :app, "app.staging.com"
    role :db,  "db.staging.com", :primary =&gt; true
  end
</pre>
<p>Utilizando este método el deploy o la ejecución de tareas en un stage u otro se hace de manera mas natural(sin usar variables de entorno):</p>
<pre>  $ cap staging foo
  * executing `staging'
*** Deployando en staging
  * executing `foo'
  * executing "uptime"
    servers: ["localhost"]
Password:
    [localhost] executing command
 ** [out :: localhost] 01:39:08 up  2:25,  5 users,  load average: 0.01, 0.07, 0.05
    command finished
</pre>
<p>Si nos fijamos en el log de Capistrano vemos que primero ejecuta la tarea &#8220;staging&#8221; y luego ejecuta la tarea &#8220;foo&#8221;, que es lo que comentaba del encadenamiento de tareas.</p>
<p>Esta estrategia a mi me parece muy útil cuando los cambios que se necesitan para desplegar en producción y staging son mínimos. Considerando un cambio mínimo el cambio de variables.</p>
<p>Sin embarbo, esta estrategia no me parece limpia si ya se cambian tareas,callbacks, etc. entre stages. En tal caso cambiaría la estrategía y usaría la gema/plugin <a href="http://github.com/jamis/capistrano-ext" target="_blank">capistrano-ext</a>. Esta gema por dentro usa el mismo método que acabamos de utilizar pero llega un poco mas lejos.</p>
<p>Para usar este plugin solo hay que hacer 4 cosillas y una de ellas opcional <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<blockquote><ol>
<li>Hacer un require de capistrano-ext</li>
<li>Definir los stages que vamos a usar</li>
<li>Definir el stage por defecto **OPCIONAL**</li>
<li>Escribir nuestras recetas por cada stage dentro de config/deploy/&lt;stage&gt;.rb</li>
</ol>
</blockquote>
<p>Vamos a hacer el require y definir los stages, escribimos en el inicio de nuestro deploy.rb:</p>
<pre>  require 'capistrano/ext/multistage'
  set :stages, %w(staging production)
</pre>
<p>No ha sido tan dificil ¿verdad?</p>
<p>Ahora siguiendo nuestro sencillo ejemplo vamos a escribir la receta de cada stage. En config/deploy/staging.rb escribimos:</p>
<pre>  puts "*** Deployando en staging"
  role :web, "localhost"
  role :app, "localhost"
  role :db,  "localhost", :primary =&gt; true
</pre>
<p>Y en config/deploy/production.rb:</p>
<pre>  puts "*** Deployando en producción"
  role :web, "localhost"
  role :app, "localhost"
  role :db,  "localhost", :primary =&gt; true
</pre>
<p>Lo probamos y vemos que funciona:</p>
<pre>  $ cap production foo
  * executing `production'
*** Deployando en producción
    triggering start callbacks for `foo'
  * executing `multistage:ensure'
  * executing `foo'
  * executing "uptime"
    servers: ["localhost"]
Password:
    [localhost] executing command
 ** [out :: localhost] 02:22:19 up  3:08,  5 users,  load average: 0.11, 0.10, 0.07
    command finished
</pre>
<p>Si no le pongo stage falla miserablemente:</p>
<pre>  $ cap foo
    triggering start callbacks for `foo'
  * executing `multistage:ensure'
No stage specified. Please specify one of: staging, production (e.g. `cap staging foo')
</pre>
<p>Para definir un stage por defecto entonces añadimos a nuestro deploy.rb:</p>
<pre>  require 'capistrano/ext/multistage'
  set :stages, %w(staging production)
  set :default_stage, 'staging'
</pre>
<p>Y ahora comprobamos que usamos staging por defecto:</p>
<pre>  $ cap foo
      triggering start callbacks for `foo'
    * executing `multistage:ensure'
  *** Defaulting to `staging'
    * executing `staging'
  *** Deployando en staging
    * executing `foo'
    * executing "uptime"
      servers: ["localhost"]
  Password:
      [localhost] executing command
   ** [out :: localhost] 02:29:17 up  3:15,  5 users,  load average: 0.03, 0.08, 0.08
      command finished
</pre>
<p>Esta última estrategia la recomiendo si hay demasiada diferencia a la hora de hacer un deploy entre los diferentes stages, por ej. si en staging tenéis montado el stack con mongrel y en producción con passenger. Otra situación podría ser cuando el deploy tiene muchas variables(además diferentes entre stages) y hace que se pierda la legibilidad de nuestro deploy.rb</p>
<p>Al usar esta estregia siempre procuro que las variables y tareas comunes se queden en el deploy.rb, y el resto vaya al fichero de configuración del stage. Si tuviésemos demasiadas tareas comunes las movería a otro fichero, todo sea por mantener la legibilidad. De todos modos cada cual lo puede hacer como le vaya bien <img src='http://blog.rafagarcia.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Nota:</strong> El deploy.rb que he usado para escribir este post solo contenía lo que os he ido indicado, para las pruebas que hemos hecho no es necesario definir la aplicación, el repositorio, tipo de scm,&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rafagarcia.net/2010/01/09/capistrano-y-multistaging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
