Desplegando Aplicaciones Web con Git

lunes 16 octubre


Utilizando Git Hooks para acelerar nuestro workflow.


Soy un control freak: me gusta tener siempre el control de las cosas. Por eso, la primera vez que descubrí servicios como el de Bitbucket Pipelines o el de Travis CI, no me agradaba mucho la idea de que otro desplegara mi código en una cajita configurada especialmente para mi software. Me gusta tener control absoluto de mi ambiente de desarrollo (por eso desarrollo en Linux) y conozco bien mi ambiente de producción (tengo una VPS propia, configurada a mi gusto) y no quiero esperar en una cola para que mi código sea subido a producción, luego de un git push.

Por mucho tiempo encontré depender de un tercero para esto más un problema que una solución. A veces Bitbucket Pipelines se caía, y Travis CI es demasiado si no trabajas con grandes equipos. Comencé a buscar una forma de siemplemente escribir algo en mi consola y poder pasar mi código automáticamente a producción haciendo algo como git push production master. Fue cuando descubrí dos potentes features de Git: repositorios remotos y hooks.

Los Requisitos

Lo primero que necesitas es tu propia VPS. No importa si tienes Apache, Ngnix u otro servidor web. Pero lo que si es indispensable, es que debes tener instalado git. Si utilizas un derivativo de Debian, como Ubuntu, lo más probable es que tu VPS ya venga con git. En caso de que no, puedes instalarlo utilizando sudo apt install git. Si vives en Chile, puedes conseguir una VPS a un precio decente en OpenCloud. Si no, DigitalOcean sirve también.

Además, se da por sentado que tienes un dominio configurado para funcionar con tu máquina de producción, y su correspondiente VirtualHost (si usas Apache). Si no, entonces no podrías probar que http://tu-sitio-de-produccion.cl funciona.

Recomendación: Siempre debes configurar el acceso a tu máquina VPS a través de una Clave SSH, al menos para la cuenta root. No es obligatorio, pero es mucho mejor, porque cuando quieras desplegar tu código a producción, se hará automáticamente sin preguntar por contraseña.

Configurando la VPS

Lo primero que debes hacer es entrar a tu VPS. Luego, ejecuta lo siguiente:

mkdir /var/repos && cd /var/repos

Esto creará una carpeta repos en el directorio var, e ingresará a ella. Una vez dentro de tu carpeta, repite el procedimiento anterior, esta vez creando la carpeta para tu nuevo repositorio:

mkdir [nombre-de-tu-repo].git && cd [nombre-de-tu-repo].git

Una vez dentro de esta carpeta (que tendrá el nombre de tu repo), debes iniciar un nuevo repositorio git, pero con un flag especial (si tu VPS no tiene git, un simple apt install git soluciona todo).

git init --bare

Lo que hace este comando es crear un repositorio bare, es decir, un repositorio git hecho sólo para recibir pushes, pero no para mantener un working tree.

Luego de esto, entramos a la carpeta hooks:

cd hooks

Alli creamos un archivo llamado post-receive.

nano post-receive

Debemos colocar lo siguiente en el archivo:

#!/bin/sh
git --work-tree=[ubicacion/de/tus/archivos/html/para/servir] --git-dir=/var/repos/[tu-repo].git checkout -f

Lo que hacen estas líneas es que van a forzar un comando git checkout, pero vamos a decirle a git que el working directory está en otro lugar, específicamente, en la ubicación donde vas a servir tus archivos para la web. Bien podría ser /var/www o /home/[usuario]/public_html/. No debes olvidar añadir el directorio del repositorio al final.

Guardamos y no olvidamos hacer ejecutable el archivo:

chmod +x post-receive

Todo lo que acabamos de hacer no es más que lo que se conoce como un git hook. Los hooks son acciones que puedes ejecutar luego de cierto hito. El hook de post-receive se ejecuta cuando el repositorio recibe un push. Entonces, cada vez que hagas un push a ese repositorio, el working tree en tu directorio para ser servido en la web, se actualizará también. ¿Chido no?

Configurando tu Máquina

Ahora que tenemos nuestro repositorio en nuestra VPS, ya podemos comenzar a mandarle pushs. Para ello, simplemente añade el nuevo repositorio que hiciste como un remote al repositorio actual:

git remote add [nombre] ssh://[usuario-vps]@[ip-o-fdqn-vps]/var/repos/[tu-repo].git

Es muy importante que definas el nombre de tu remote. Una buena convención es testing o production, dependiendo del caso. Además, debes incluir las credenciales ssh de tu VPS (el usuario y la dirección de la misma) y luego la ruta al repositorio bare.

Nota: Si el puerto SSH de tu VPS es distinto al 22, incluye el puerto luego de la IP o FDQN del mismo, antecediéndole :. Al final, deberías tener algo como esto: `git remote add production ssh://root@server.com/var/repos/web.git.

Luego, desde tu consola, cada vez que cambies el código y comitees los cambios, debes hacer lo siguiente:

git push [nombre-remote] master

Con esto le decimos a git que haga un push al repositorio remoto (usando el nombre) de la rama master (que se supone contiene los últimos cambios de tu código).

Requisitos extra

Si utilizas un framework o algún package manager como composer, o si has exlcuido ciertos archivos utilizando un gitignore, quizás tengas que hacer un par de tweaks más.

Por ejemplo, utilizo mucho PHP y composer, lo que significa que en mi VPS, debo ir a la carpeta donde tengo los archivos para servir a la web, y realizar un composer install luego del primer push. Si agrego alguna dependencia, debo hacer un composer update en el futuro.

Además, posiblemente en frameworks como Laravel o Codeigniter, debas ajustar algunos permisos de carpetas para que sean leidos por tu servidor.

Sin embargo, estas tareas se pueden realizar de forma automática también. Lo puedes incluso añadir a tu post-receive.

Las Ventajas

Te preguntarás, "¿Para que realizar toda esta complejidad?" Quizás suena complejo al principio, pero luego de hacerlo dos o tres veces ya no lo es. Ahora lo utilizo para cada proyecto que hago, y no dejaré de utilizarlo nunca más, por varias razones:

  1. Tú tienes el control: Puedes actualizar tu ambiente de desarrollo automáticamente, cuando tu quieras. Lo que yo suelo hacer es un script llamado "deploy.sh" que testea mi código con pruebas unitarias y luego hace un push si pasa.

  2. Es seguro: He visto personas que utilizan FTP para hacer este tipo de cosas. La verdad es que FTP es lento e inseguro. SSH es un procotolo extremadamente rápido y muchísimo más seguro. Te sorprenderás lo rápido que pasará tu código a producción.

  3. Es rápido: Sólo debes hacer un simple git push y ya estás en producción. ¿Qué más rápido que eso?