Integración continua con Drupal 10, OVH Cloud y Github

Para montar este site contrate un hosting, si no el más barato, el siguiente más baráto que encontre. Tiene sus limitaciones, por supuesto, pero nos va a permitir montar un sistema de integración continua con pocas cosas.

Tenemos que tener en cuenta que no vamos a tener ni el vendor ni los contrib de modules o themes en el repositorio por lo que vamos a usar composer. En cada deploy se va a instalar lo que tengamos en composer.json y en caso de tener parches definidos en composer, aplicarlos.

Nuestra primera tarea es instalar composer en nuestro alojamiento y para eso accedemos con las credenciales ssh que nos dan y creamos un directorio llamado bin donde vamos a instalar las aplicaciones que necesitemos.

$ mkdir bin

Voy a asumir ciertas cosas como que hemos elegido php 8.1 para nuestro alojamiento. Dicho esto procedemos a descargarnos e installar composer en nuestro hosting.

$ curl -sS https://getcomposer.org/installer | php -- --install-dir=./bin --filename=composer

Uno de los problemas con el que nos topamos a la hora de implementar este sistema de integración continua es que el deploy (lo veremos un poco más adelante) va a eliminar todo el documment root y lo va a crear de nuevo clonando la rama de github que nosotros le indiquemos. 

Lo ideal para realizar esto sería hacerlo en un directorio fuera del document root usando un timestamp como nombre y una vez completado el deploy sin errores crear un symlink al document root. Para esta ocasión no nos vamos a complicar mucho y lo vamos a realizar todo sobre el document root directamente.

El siguiente problema es el directorio de ficheros públicos de Drupal. Por lo comentado anteriormente, tiene que quedar fuera del document root para evitar que se borre en cada deploy. En el fichero settings que estemos usando es conveniente comentar o eliminar la configuración del public files que viene.

$ mkdir -p shared/example.com/files

Para terminar con la preparación de Drupal, esta parte es opcional y por eso no la voy a explicar aquí, configuramos el sites.php para poder tener nuestros directorios de configuración de drupal separados para poder trabajar en local, desarrollo y prod. Hay mas configuraciones como thrusted hosts, proxies, etc... que tampoco corresponde que se expliquen aquí.

Bien, ya tenemos nuestro código subido a Github y el entorno de hosting preparado para empezar a trabajar. 

Lo primero es crear, dentro de nuestro proyecto de Github el siguiente directorio:

$ mkdir -p .github/workflows

Dentro de este directorio el fichero main.yaml (He elegido ese nombre por que coincide con la rama que quiero usar para producción).

name: Deploy to OVHcloud Power
on:
  push:
    branches: [ main ]
  workflow_dispatch:
jobs:
  deploy:    
    runs-on: ubuntu-20.04
    env:
        OVH_SSH_HOST: ${{ secrets.OVH_SSH_HOST }}
        OVH_SSH_PORT: ${{ secrets.OVH_SSH_PORT }}
        OVH_SSH_USERNAME: ${{ secrets.OVH_HOSTING_USER }}
        OVH_SSH_PASSWORD: ${{ secrets.OVH_HOSTING_PASSWORD }}
        OVH_WEBSITE_URL: ${{ secrets.OVH_WEBSITE_URL }}    
        DRUPAL_USER: ${{ secrets.DRUPAL_USER }}    
    steps:
      - name: Install prerequisites
        run: |
          sudo apt-get update
          sudo apt-get install -y curl jq sshpass openssh-client

      - name: WakeUp website           
        run: curl --silent --insecure --location --write-out "%{http_code}" -o /dev/null ${OVH_WEBSITE_URL}

      - name: Clone over SSH
        run: sshpass -p ${OVH_SSH_PASSWORD} ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet ${OVH_SSH_USERNAME}@${OVH_SSH_HOST} -p ${OVH_SSH_PORT} -- 'chmod -R 777 www/sites/ && rm -rf  www && git clone '${GITHUB_SERVER_URL}'/'${GITHUB_REPOSITORY}'.git --single-branch --branch '${GITHUB_REF##*/}' www'

      - name: Composer install
        run: sshpass -p ${OVH_SSH_PASSWORD} ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet ${OVH_SSH_USERNAME}@${OVH_SSH_HOST} -p ${OVH_SSH_PORT} -- 'php ./bin/composer install -d www'

      - name: Create sym links
        run: sshpass -p ${OVH_SSH_PASSWORD} ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet ${OVH_SSH_USERNAME}@${OVH_SSH_HOST} -p ${OVH_SSH_PORT} -- 'cd www/sites/gelr.es && ln -s ../../../shared/gelr.es/files files'

      - name: Drupal credentials
        run: sshpass -p ${OVH_SSH_PASSWORD} ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet ${OVH_SSH_USERNAME}@${OVH_SSH_HOST} -p ${OVH_SSH_PORT} -- 'php bin/envs.php www/sites/gelr.es/settings.php'

      - name: Rebuild drupal
        run: sshpass -p ${OVH_SSH_PASSWORD} ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet ${OVH_SSH_USERNAME}@${OVH_SSH_HOST} -p ${OVH_SSH_PORT} -- 'cd www/sites/gelr.es && ../../vendor/bin/drush rebuild'

      - name: WakeUp website
        run: curl --silent --fail --insecure --location --write-out "%{http_code}" -o /dev/null ${OVH_WEBSITE_URL}

Si tenemos que resumir lo que hace este fichero en unas pocas palabras podríamos decir que Github crea un container de docker con linux y alguna aplicacion para poder conectarse a nuestro hosting y ejecutar comandos sobre el:

Clone Over SSH

Realiza dos acciones principales. Cambiar los permisos del directorio site. Esto es por que drupal, de forma automática y así está definido en su settings cambia los permisos cuando accedemos a el y quita el permiso de escritura (lo mas normal del mundo). Los siguiente es borrar el document root y por último clonar nuestra rama en el nuevo document root.

Composer install

Ya habíamos instalado nuestro composer en el hosting. En este paso del deploy se ejecuta el install para que genere el vendor y los contrib que estamos usando y tenemos definidos en nuestro composer.json|lock.

php ./bin/composer install -d www

Create Sym links

Como sacamos nuestro directorio de files public de Drupal fuera del document root necesitamos enlazar el files dentro del document root a nuestro shared fuera del document root. La mejor forma que he encontrado es hacerlo de forma relativa al document root por eso que lo haga de esta manera:

cd www/sites/example.com && ln -s ../../../shared/example.com/files files

Drupal credentials

Al tener el proyecto en un repositorio público y las bases de datos de ovh son de acceso público con phpmyadmin. Se usan tokens para las credenciales de base de datos en el settings.php y se reemplazan en este punto del deploy con un script alojado en el servidor.

Rebuild drupal

En este paso simplemente hacemos un rebuild del site drupal para que renere todas las caches y aplique bien los cambios que pudieramos haber hecho en templates, css y demás.

WakeUp Website

Por último solo nos queda comprobar que el site está funcionando y no está dando errores tipo 500.

Quizás me dejo por comentar como se crear los secrets en Github. En cualquier, caso dentro de settings del projecto de Github, en security, se pueden crear las secrets y variables.

Con todo esto, ya solo tenemos que hacer nuestros push a la rama y automáticamente nos hará el deploy a nuestro hosting.

También te puede interesar: