Mercurial: automatizando al máximo

Cuando trabajamos con servidores de versiones seguro que hay muchas razones de peso de por medio, una de ellas -la que veremos- puede ser la replicación de código en diversas máquinas.

Supongamos un montón de máquinas que comparten el mismo código de repositorio, el orden de propagación de un cambio en todas esas máquinas es sencillo:

  1. Programamos dicho cambio en nuestro servidor de desarrollo (devel).
  2. Hacemos un commit local (en sistemas de versionado distribuido -como Mercurial- cada repositorio también es servidor).
  3. Lo siguiente es un push al servidor donde almacenamos el código (repo código).
  4. Ahora tocaría entrar en cada una de esas máquinas en las que queremos propagar el código y ejecutar un hg pull ; hg update.

Tedioso cuando el número de máquinas que se manejan tiene dos cifras. Intentemos automatizar todo el proceso a través de las opciones que nos ofrece Mercurial.

Combinando la confianza entre equipos por ssh y los hooks de mercurial podemos crear un monstruo sencillo de manejar.

Local/Devel

En la copia local lo primero que tenemos que hacer es un clone del repositorio padre y definir los archivos que vamos a ignorar. Por ejemplo los archivos de configuración de base de datos o de peculiaridades locales de cada proyecto en producción (idioma, usuarios, themes, datos de usuario, imágenes...):

[devel] # cat repo/.hgignore
syntax:  glob
.hgignore
config.php
bd.php
.project
uploads*

Nota: una buena práctica sería no agregar esos ficheros que estamos ignorando al repositorio, podemos agregar unos config-example.php o algo así para tener una referencia pero no las configuraciones en sí -imho-.

A la hora de hacer un pull al repositorio del código todos los archivos que concuerden con los patrones escritos en el fichero .hgignore no se agregarán al repositorio. Ojo: el fichero .hgignore debe estar en el raíz del repositorio y debe pertenecer al mismo usuario que vaya a hacer el pull.

Repo código

Aquí es donde viene la chicha. Teóricamente en el repositorio del código no habría demasiado que tocar, sin embargo es aquí donde ejerceremos la mayor automatización del proceso. Para propagar los cambios a las máquinas en producción podemos hacerlo de dos formas:

  1. Como hacíamos antes, entrando en cada máquina en producción y hacer pull del repositorio del código
  2. Desde el repositorio del código hacer push a todas las máquinas en producción


Este punto ha sido el que más me ha costado entender, digamos que dependiendo de la dirección en la que se ejecute el pull/push los resultados son los mismos. Con lo que, si desde el repositorio del código ejecutamos lo siguiente, los cambios se propagarán a las máquinas 1, 2, 3 y 4:

[repo] # hg push ssh://usuario@maquina1/repo
[repo] # hg push ssh://usuario@maquina2/repo
[repo] # hg push ssh://usuario@maquina3/repo
[repo] # hg push ssh://usuario@maquina4/repo

Tuneando un poco el repo/.hg/hgrc del repositorio podemos acortar el comando e intentar automatizarlo un poco más, fijaos:

[repo] # cat repo/.hg/hgrc
[paths]
maquina1 = ssh://user@maquina1/repo
maquina2 = ssh://user@maquina2/repo
maquina3 = ssh://user@maquina3/repo
maquina4 = ssh://user@maquina4/repo

Ojo: el fichero hgrc debe estar dentro del directorio .hg/ del repositorio y debe pertenecer al mismo usuario que vaya a hacer el pull.

De forma que para ejecutar el comando de propagación a todas las máquinas tendremos que hacer un:

[repo] # hg push maquina1 ; hg push maquina2 ; hg push maquina3 ; hg push maquina4

Ya tenemos los push automatizados, ¿y los updates del lado de producción?. Vamos a ello.

Máquina producción

Cada vez que una de estas máquinas recibe un push del repositorio de código, mercurial debe actualizar los datos con un hg update. Para hacerlo automáticamente en cada push -ya lo hemos visto en otro post- en el repositorio de cada una de las máquinas en producción configuramos el repo/.hg/hgrc de forma que:

[hooks]
changegroup = hg update

Ojo: el fichero hgrc debe estar dentro del directorio .hg/ del repositorio y debe pertenecer al mismo usuario que vaya a hacer el pull.

Proceso

 - Programamos en \"devel\" y guardamos cambios.
 - [devel] # hg commit
 - [devel] # hg push
 - [repo] # hg push maquina1 ; hg push maquina2...
pushing to ssh://user@maquina1/repo
searching for changes
pushing to ssh://user@maquina2/repo
searching for changes
...

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.