programación

Cómo usar Git para hacer deploy de nuestro website

No hay duda de las ventajas de un sistema de version control en nuestro flujo de trabajo. Servicios como Github y Bitbucket son eco de cómo ha evolucionado la manera en que escribimos y compartimos código entre colegas. Inclusive si eres un desarrollador solitario estos servicios son de gran ayuda a la hora de crear nuestros proyectos.

De eso se trata precisamente esta nota, vamos a configurar un ambiente de desarrollo en donde podamos utilizar Git para realizar el deployment de nuestro proyecto. Antes de comenzar a presionar teclas a diestra y siniestra vamos a detenernos a pensar en lo que vamos a configurar.

Vamos a crear un repositorio vacío en nuestro web hosting. Luego crearemos un repositorio en nuestro ambiente local y lo sincronizaremos al repositorio remoto. Por último crearemos la lógica para que cada vez que publiquemos un cambio, el mismo se actualice automáticamente en nuestro repositorio principal y a su vez en el folder público de nuestro website. La siguiente gráfica nos presenta un panorama de lo que acabamos de describir.

website-workflow-using-git

Para poder simplificar el proceso hay algunas cosas que vamos a asumir.

  1. Voy asumir que ya tenemos instalado Git y Git Bash en nuestro ambiente local. Git Bash lo vamos a utilizar para realizar los comandos de SSH.
  2. Voy asumir que tenemos acceso a nuestro provedor de hosting a través de SSH. Para este tutorial voy a utilizar Dreamhost como hosting. Antes de proseguir te recomiendo que verifiques y te empapes sobre como accesar tu hosting server usando SSH.
  3. Voy asumir que ya tenemos instalado Git en nuestro hosting server. Aunque para estar 100% seguros vamos a verificarlo.

Vamos a realizar una conexión SSH a nuestro servidor. Para eso vamos a usar el Git Bash.
Normalmente podemos hacer una conexión SSH usando el siguiente comando:

ssh <tu-username>@<tu-domain-name>

Una vez autentiquemos con el hosting server procedamos a verificar si Git está instalado.

$ git --version
git version 1.7.9.5

Si puedes ver el número de versión estamos más que seguro que tenemos instalado Git. De no tenerlo te recomiendo que visites el siguiente tutorial antes de proseguir con los pasos aquí mencionaos.

Vamos a comenzar creando el repositorio en nuestro hosting server. Este repositorio fungirá como repositorio principal. Para tener cierto control sobre los cambios que ocurrirán en este repositorio vamos a utilizar el flag –bare junto al comando git init. Admás, por conveniencia vamos a terminar el nombre del repositorio usando .git.

$ git init --bare website.git

Está instrucción va a devolver el siguiente mensaje:

Initialized empty Git repository in /home/<tu-username>/website.git/

Hemos utilizado website como nombre para el repositorio. O sea que el repositorio se llamará webiste.git. Cabe destacar que este repositorio debe ser creado en el directorio home y no en el public folder. La intención de esto es mantener segura y privada la configuración de nuestro repositorio. Hasta el momento hemos creado un repositorio en el home folder de nuestro hosting.
Para verificar que todo está en orden vamos a entrar a nuestro repositorio y verificar el status.

$ cd website.git/
$ git status

Si vemos la siguiente línea, no te asuste, es lo que debemos ver ya que el repositorio esta vacio y es tipo bare.

fatal: This operation must be run in a work tree

Antes de continuar con nuestro repositorio local vamos a configurar un server-side hook como parte de nuestro repositorio remoto para configurar la actualización de nuestro public-folder. Aquí es donde técnicamente ocurre toda la magia. Los hooks son rutinas que se ejecutan automáticamente cada vez que ocurre un evento particular en el repositorio. A través de estas rutinas podemos extender las funcionalidades de Git y adaptarlas a nuestro ambiente de desarrollo. En este caso vamos a configurar un hook para que cada vez que ocurra un git push a nuestro repositorio remoto se publiquen los cambios al public-folder. Para lograr eso vamos utilizar el siguiente comando:

$ nano > hooks/post-receive

Y escribimos el siguiente script la ventana de nano:

#!/bin/sh
GIT_WORK_TREE=/home/<tu-username>/<tu-dominio.com>/public-folder git checkout -f

Para terminar presionamos Ctrl+X y guardamos el archivo. Ahora aplicamos el siguiente permiso al archivo del script que acabamos de crear:

$ chmod +x hooks/post-receive

Ahora pasamos a trabajar en nuestro repositorio local. Te recomiendo que abras otra ventana de Git Bash para trabajar localmente. Lo primero que vamos hacer es ir a nuestro working folder. En mi caso mi working folder se llama code y se encuentra dentro de Documents.

$ cd /c/users/<tu-username>/Documents/code

Ahora aprovechando que tenemos Git vamos a utiliza la función de git init para crear un proyecto a nuestro folder local. Para este tutorial voy a crear un folder llamado website-project.

$ git init website-project

Atención, si ya tienes un proyecto que deseas utilizar como para este tutorial, lo único que tienes que hacer es utilizar el comando de git init en tu folder de tu proyecto. Por el momento vamos a seguir trabajando dentro del folder website-project.

$ cd website-project

Como estamos usando Git vamos a clonar un repositorio localizado en Github. Vamos a usar el template de HTML 5 Boilerplate como base para nuestro website.

$ git clone https://github.com/h5bp/html5-boilerplate.git

Vamos a mover el código que nos interesa al working folder o sea al folder website-project. Como estamos en el Git Bash hagámoslo usando el siguiente comando:

$ mv html5-boilerplate/dist/* ./

El resto del código que no vamos a utilizar lo vamos a borrar.

$ rm -r -f html5-boilerplate/

Ahora nuestro repositorio local está casi listo para hacer commits. Actualmente nuestros archivos están listos para ser añadidos al version control. Si ejecutamos el comando git status vamos a ver que el siguiente mensaje:

Untracked files:
  (use "git add ..." to include in what will be committed)… etc
        404.html
        apple-touch-icon.png
        browserconfig.xml
        crossdomain.xml
        css/
        doc/
        favicon.ico
        humans.txt
        img/
        index.html
        js/
        robots.txt
        tile-wide.png
        tile.png

nothing added to commit but untracked files present (use "git add" to track)

Vamos bien. Procedamos a añadir los files al version control del repositorio. Para esto vamos a realizar la siguiente instrucción:

$ git add *

Ahora cuando hagamos git status vamos a ver que nuestros files están en la fase staged, o sea listos para commit. Para realizar nuestro commit vamos a utilizar el siguiente comando:

$ git commit -m “Configuración inicial.”

Si revisamos el repositorio usando git status veremos lo siguiente:

On branch master
nothing to commit, working directory clean

Ahora vamos a añadir la conexión de nuestro repositorio remoto al repositorio local. Pasemos a crear la conexión usando el siguiente comando:

$ git remote add <nombre-creativo> ssh://<tu-username>@<tu-domain-name>/home/<tu-username>/website.git

El nombre creativo puede ser algo tan sencillo como deploy. Ya con esta configuración podemos hacer nuestro primer push. Este push será el responsable de sincronizar el repositorio local con el remoto.

$ git push <nombre-creativo> +master:refs/heads/master

Listo!
Ahora cada vez que hagamos un cambio a nuestro projecto lo único que tenemos que hacer es utilizar la instrucción de push usando el nombre que hayamos asignado:

$ git push <nombre-creativo>

Recuerda que antes de hacer el push debe hacer commit del cambio. Una atajo para añadir el cambio y hacer el commit es a través del siguiente comando:

$ git commit -a -m “<descripción-del-commit>”

Esto es todo por el momento. Cabe destacar que el 80% de los problemas que puedas encontrar siguiente el tutorial probablemente sea relacionado a SSH y a la configuración de tu hosting server. Recuerda que para este tutorial se utilizó como hosting provider Dreamhost y es muy probable que tu proveedor tenga otra configuración similiar a la que aquí se mencionó.

Gran parte de este tutorial está inspirado en el trabajo de Abhijit Menon-Sen, Using Git to manage a web site. Si deseas profundizar en el tema de Git te recomiendo la guía Getting Git Right muy elegantemente mantenida por Atlassian que es la compañía detrás de Bitbucket.

  • Nico TheRock

    Buenos dias, queria saber que significaba hacer un push de esta forma +master:refs/heads/master
    y no como se hace habitualmente indicando solo master.

    Gracias

  • Albert

    Hola muy bueno el articulo, el unico que me funciono y explican todo en detalles, una sugerencia por favor utilizar otro color para el code highlighting ya que no se puede apreciar a simple vista los comandos

  • Alejandro Stendelis

    Hola, muy bueno y claro el artículo. Tengo una pregunta yo en el public_html ya tengo los archivos, como los agrego al .git inicialmente, así de ahí en mas trabajo desde mi copia local.

    • Jaime

      Si entiendo bien tu pregunta, voy a dar por sentado que ya tienes configurado Git en el server. En ese caso es solo cuestión de hacer un “pull” de ese repositorio. Si no tienes configurado Git en el server puedes copiar los archivos al tu ambiente de desarrollo local y entonces inicializas el repositorio localmente. Espero haber entendido bien la duda.

  • vagostep

    Hola Jaime, un saludo. Excelente el artículo, estuve buscando por varios días como hacer un auto deploy y cada respuesta que encontraba era mas complicada que otra. Permiteme decirte que, usando este articulo como base, me anime a llevarlo mas allá, y hacer un auto deploy directamente en un gitlab instalado en el servidor de la empresa donde trabajo. No comprendo mucho como realizar un webhook basado en mis necesidades asi que, me fui a la “Fontaneria de Git”. Siguiendo tu principio, el repositorio bare remoto, en mi caso, es el repositorio de GitLab del servidor, mi Repo local está en mi pc y la carpeta publica se encuentra en WWW del servidor. Segui todos los pasos que comentas pero, al momento de colocar el hook en el lado del servidor fue donde me las ingenié un poco.

    GitLab, en los repositorios .git le coloca 2 carpetas dentro, una llamada hooks.old, que asumo se refiere a los hooks del lado del cliente que se copian aca (solo lo asumo, basándome que en esta carpeta están todos los .samples que vemos en nuestro repositorio); y otra carpeta llamada hooks, que en realidad es un symlink que apunta a gitlab-shell/hooks, aqui, se encuentran unos hooks comunes a todos los proyectos (post-receive y update). Debia colocar el post-receive dentro de esta carpeta hooks pero sin modificar los hooks comunes a los demas proyectos, por que, el post-receive que se realiza aquí es personalizado para cada uno. Asi que, cree una nueva carpeta Hooks, y le agregué el post-receive personalizado, y el mismo update común. Y funciona perfectamente, aunque se que no es lo mas optimo, cumple con su tarea, de realizar un auto-deploy desde el repositorio de GitLab, a la carpeta publica.

    • http://www.jaimeolmo.com Jaime Olmo

      ¡Excelente! Gracias por compartirlo por aquí.

  • Alvaro Mendoza

    Hola Jaime,

    Muy interesante el artîculo. Sabes si es posible configurar un auto deploy a mi sitio web pero a partir de un repositorio alojado en Bitbucket ?

    Gracias.

    • Jaime

      La contestación corta a tu pregunta es si claro que es posible. No tengo exactamente la solución pero estoy experimentando con el servicio de http://dploy.io/. Te recomiendo que le eches una mirada. Saludos.

      • Fabrizio

        Hola Jaime,

        Que tal te fue con http://dploy.io/? Vale la pena como para pagarlo?

        Saludos

        • Jaime

          Hasta el momento dploy.io ha resultado ser un buen servicio. Automatiza el proceso realizar un deployment a diferentes servicios (incluyendo FTP) de manera sencilla. Claro, luego de haber realizado la configuración que dicho proceso requiere. Para poder responder si merece la pena la suscripción de pago el servicio ofrece una suscripción gratis en donde puedes utilizar cada una de las opciones sin ningún tipo de limitación. Trátala y si entiendes que añade valor a tu proceso de desarrollo deberías considerar la opción de pago.