---
# System prepended metadata

title: Drupal y Github CI

---

# Drupal y Github CI 

## Índice de acciones a realizar 

1. Después de cada commit, llamamos GitLab CI para que realice diversas acciones.
2. Dejamos que GitLab CI haga login en el servidor que hostea por medio de SSH.
3. En el host correremos distintos comandos como: 
```bash=
git pull
drush config-impot
```

* Si una tarea falla, GitLab CI enviará un e-mail.
* Si una tarea es satisfactoria, los commits más nuevos son desplegados en minutos.


## Pre requisitos 

1. Tener una cuenta de GitLab
2. Haber creado un proyecto en GitLab y pusheado un proyecto de Drupal.
3. Tener acceso SSH al servidor host.
4. En el servidor de hosting está instalado: 
    4.1. Composer
    4.2. Git
    4.3. Drush
5. No puedes ejectuar git pull en tu servidor de hosting (en GitLab debes añadir una "DeployKey" en Ajustos > Repository )

## Paso 1: Crear una key pública y privada

GitLabCI usa SSH para logear en tu servidor de hosting.

* Asumamos que logeas con un un usuario específico 'gitlabuser' y tu dominio es 'example.com'. Ahora debes añadir las claves públicas que GitLabCI usará con 'gilabuser' en el servidor de hosting.
* Puedes elegir entre no crear una nueva cuenta para gitlabuser y en su lugar añadir la clave pública SSH a la lista 'authorized_Keys' de usuarios que existen.
* Do not re-use existing SSH-keys from existing users (for example your own developer-laptop), but create a new keypair.
* No reuses claves SSh que tienen otros usuarios, crea claves nuevas para cada máquina nueva que vaya a trabajar. 

Store and distribute SSH-keys carefully with tools like Lastpass or 1Password.
Guarda y distribuyes las claves SSH con cuidado con herramientas como Lastpass o 1Password.

### Crear la nueva clave SSH localmente
https://docs.gitlab.com/ee/ssh/#generating-a-new-ssh-key-pair

### Añadir la clave pública a la cuenta de usuario en el servidor host 
```bash=
$ cat id_rsa.pub | ssh gitlabuser@example.com 'cat >> .ssh/authorized_keys'
```

### Añadir la clave privada a GitLab
1. Ve a tu repositorio de GitLab
2. En el menú de la izquierda ve a 'Settings', seguido de 'CI / CD' y de nuevo vamos a 'Settings'.
3. Baja hasta 'Variables' y añade una nueva.
4. Input variable: "SSH_PRIVATE_KEY".
5. Input variable value: el valor de la clave privada.
6. Guardar los cambios. 

* No hacer la variable "protected" ya que el runner de GitLab CI no puede acceder a éstas. 
* Solo los miembros del equipo con permisos de dueño o maintainer tienen acceso a la página de settings en GitLab.

### Hacer commit de .gitlab-ci.yml al repositorio

* Fork disponible aquí: https://gitlab.com/dx-experts/drupal-templates-for-gitlab-ci

* Ejemplo del script: 
```bash=
# GitLab CI script for Drupal 8 websites.
# @see https://www.dx-experts.nl/blog/2018/drupal-8-and-gitlab-ci-setup-guide
# @see https://gitlab.com/dx-experts/drupal-templates-for-gitlab-ci
#
# This script deploys a Drupal 8 site on each commit on the master-branch.
#
# Preparation:
# Save $SSH_PRIVATE_KEY first in GitLab CI variables.
variables:
  GIT_ROOT: "/var/www/my-website/"
  SSH_LOGIN: "ssh -p22 -oStrictHostKeyChecking=no gitlabuser@example.com"
  DRUSH: "drush"
  COMPOSER: "composer"
before_script:
# @see https://docs.gitlab.com/ee/ci/ssh_keys/
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d 'r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
deploy_master:
  when: always
  only:
  - master
  script:
  - $SSH_LOGIN "cd $GIT_ROOT && git fetch --tags"
  - $SSH_LOGIN "cd $GIT_ROOT && git pull"
  # Never blindly run composer update on the server: https://blog.martinhujer.cz/17-tips-for-using-composer-efficiently/
  - $SSH_LOGIN "cd $GIT_ROOT && $COMPOSER install"
  # Updates must be run before configuration is imported
  # https://drupal.stackexchange.com/questions/188840/what-order-should-configuration-import-and-module-updates-be-run
  - $SSH_LOGIN "cd $GIT_ROOT && $DRUSH updatedb -y"
  - $SSH_LOGIN "cd $GIT_ROOT && $DRUSH config-import -y"
  # (Additional) sanitizing tasks.
  #- $SSH_LOGIN "cd $GIT_ROOT && $DRUSH locale:check"
  #- $SSH_LOGIN "cd $GIT_ROOT; $DRUSH locale:update"
  - $SSH_LOGIN "cd $GIT_ROOT && $DRUSH core-cron"
  # You should consider fine-grained cache invalidation
  # @see https://www.dx-experts.nl/blog/2017/drupal-8-development-caching
  - $SSH_LOGIN "cd $GIT_ROOT && $DRUSH cache-rebuild -y"
```

### Variables 
* GIT_ROOT: Es la carpeta donde el sitio de Drupal está instalado en el servidor.
* SSH_LOGIN: Es usado como el string de login de SSH.
* -p22: Es el ssh-portnumber (22 es por defecto).
* -oStrictHostKeyChecking=no: Desactiva la pregunta 'confiar en este host' que se muestra por defecto la primera vez que se crea una conexión SSH con el servidor.

### Antes del Script

Échale un vistazo a https://docs.gitlab.com/ee/ci/ssh_keys/.
Básicamente, asegura que el agente de SSH y la SSH_PRIVATE_KEY están disponibles para el runner de Gitlab-CI

## Paso 3: Correr el script de despliegue

Cada vez que pushees a la rama master, el script de arriba correrá: 
* Se llama trabajo (?) y puedes encontrar su progreso en la UI de Gitlab. Barra izquierda -> "CI / CD" > "Jobs"
* El commit más nuevo será pulleado en el servidor de hosting.
* El composer instala lo que el usuario ha declarado.
* Drush actualiza el sitio e importa la nueva configuración.

## Debugging

Su tienes problemas accediendo al servidor de GitLab CI e intenta añadir la flag --verbose a la variable SSH_LOGIN.

* Asegúrate de que puedes hacer login sin contraseña con las claves públicas/privadas.
* Especialmente si no has usado el 'Drupal Composer Project' como plantilla para tu Drupal, deberías revisar la variable GIT_ROOT.
* Cuando logeas en el servidor debes ser capaz de poder correr todos los comandos en el script de deploy_prod manualmente sin errores. Añade --verbose a los comandos que fallan para mayor investigación.
* Cuando uses la línea de comandos Fish, reemplaza && por ; .
* Usa una ruta absoluta para los ejecutables de Drush o Composer.
    * DRUSH : "~/.composer/vendor/bin/drush"
    * COMPOSER: "php ~/.composer/composer.phar" 
    * Echa un vistazo a: https://askubuntu.com/questions/810098/why-doesnt-my-alias-work-over-ssh en caso de errores. 

## Procedimientos avanzados de despliegue
La integración continua puede hacerse tan avanzada como se necesita. El procedimiento de abajo tiene carencias de features avanzadas. 

Ejemplos de features de despliegue avanzado:
* Entorno único por cada rama de git (cada rama tiene su propio enviroment con su propia URL, etc. PLatform.sh tiene esta arquitectura y es genial para proyectos con muchos cambios y ramas de features nuevas.)
* Un procedimiento de despligue rojo/verde (donde una build será testeada primero con PHPUnit o Cypress y solo si estos tests están en verde, la build será desplegada.)
* Un paso de artefacto intermedio (donde los assets son fetched y los runtimes son compilados.)

# Bibliografía
https://nielsdefeyter.nl/en/articles/2018/drupal-8-and-gitlab-ci-setup-guide