Drupal CI/CD mit GitLab

Nutze alle Facetten des Staging, Building, Testing und Deployments - geeignet für jede Team-Größe

Jürgen Haas - @jurgenhaas

4. März 2021

Agenda

  1. Demo
  2. Komponenten
  3. Pipelines
  4. Performance
  5. Konfiguration
  6. Deployment
  7. Dokumentation

Demo

Drupal 9 Demo Projekt

Aeschbach Quartier

* nicht öffentlich

Komponenten

GitLab

  • Jede GitLab Instanz kann verwendet werden
  • Die kostenlose Lizenz ist bereits ausreichend
  • Öffentliche und private Projekte werden unterstützt
  • Installation

GitLab Runner

  • Läuft irgendwo, nicht notwendigerweise auf GitLab Host
  • Damit skaliert das problemlos
  • Installation

Docker oder Kubernetes

Composer

Theme Building

  • Komponenten:
  • Tasks (exemplarisch):
    • Scss nach CSS Konvertierung
    • Auto-Prefixing
    • Post-Processing
    • Komprimierung

Beliebige Tests

Ansible

Ansible ist optional, wir verwenden Ansible für alle Provisionierungs-Aufgaben über SSH auf remote Hosts. Es können aber beliebige andere Tools für diesen Zweck eingesetzt werden.

Pipelines

  • Pipelines in 6 Stages
  • Grüne Jobs: erforderlich
  • Gelbe Jobs: optional
  • Artefacte für Deploy
    • Prod Site
    • Datenbank
    • Test Site
    • Theme

Zuverlässigkeit

Aufgrund der dargestellten Pipeline-Struktur haben wir die defintive Gewährleistung, dass…

  • Alle Folgeschritte bauen auf dem Prod Site Artefact auf
  • Die Codebase für Tests wird auf genau dieser Basis aufgebaut und erweitert
  • Datenbank wird bei Bedarf von Live-Site geholt (kann sanetized werden)
  • Theme wird produktionstauglich und automatisch erzeugt

  • Alle Aspekte werden getestet
  • Tests basieren auf der Codebase für zukünftige Live-Site
  • Deployment startet nur, wenn vorher ALLES gut gegangen ist

Läuft komplett autonom, egal wie oft, egal wann.

Entwickler:innen machen nur noch eins: Commit und Push.

… und gehen dann Kaffee trinken!

Performance

  • Artefacts
    keine doppelten Tasks erforderlich
  • Caching
    auf Resultat der letzten Pipeline aufsetzen
  • DB und Dateien
    pro Environment vorhalten
  • Mehrere GitLab Runner
    skaliert horizontal

Konfiguration

GitLab Runner

[[runners]]
  name = "Name of runner"
  url = "https://gitlab.lakedrops.com/"
  token = "TOKEN"
  executor = "docker"
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
  [runners.docker]
    tls_verify = false
    image = "registry.lakedrops.com/docker/gitlab-drupal-ci:php-7.4"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
    cache_dir = "/cache"
    shm_size = 0

GitLab Variablen

Drupal Projekt

.gitlab-ci.yml

variables:
  COMPOSE_PROJECT_NAME: myproject_$CI_COMMIT_REF_SLUG
  ENVIRONMENT_NAME: myproject/$CI_COMMIT_REF_NAME
  THEME_CSS_PATH: web/themes/custom/mytheme/css
  HOST_NAME: myhostname
  SITE_NAME: mysiteid

include:
  - project: 'gitlab-ci-cd/drupal'
    ref: master
    file: '/test-and-deploy.yml'

Validate Environment:
  extends: '.prerequisites'

Build Prod Site:
  extends: '.build-prod'

Build Site:
  extends: '.build'

Download DB:
  extends: '.dumpdb'

Import DB:
  extends: '.importdb'

Update DB:
  extends: '.updatedb'

Build Theme:
  extends: '.theme'
  before_script:
    - cd web/themes/custom/mytheme

Test Code Style:
  extends: '.codestyle'

Test PHPUnit:
  extends: '.phpunit'

Test Behat:
  extends: '.behat'

Test Backstop:
  extends: '.backstop'

Deploy:
  extends: '.deploy'

Ansible

Der Einsatz von Ansible ist optional, wird bei uns aber für alle Provisionierungs-Aufgaben eingesetzt, bei denen ein Prozess per SSH auf remote Hosts zugreift.

[[runners]]
  name = "Name of ansible runner"
  url = "https://gitlab.lakedrops.com/"
  token = "TOKEN"
  executor = "docker"
  environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.lakedrops.com\":{\"auth\":\"YOURAUTHTOKEN\"}}}"]
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
  [runners.docker]
    tls_verify = false
    hostname = "Ansible-INVENTORYNAME"
    image = "registry.lakedrops.com/ansible-inventories/INVENTORYNAME:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/home/gitlab-runner/.ssh/id_rsa:/root/.ssh/id_rsa", "/home/gitlab-runner/.a/variables.yml:/root/.ansible/secrets", "/home/gitlab-runner/.a/inventories/INVENTORYNAME:/root
/.ansible", "/etc/ansible.yml:/etc/ansible.yml", "/var/log/ansible:/var/log/ansible"]
    pull_policy = "always"
    shm_size = 0

Deployment

  • Wird oft an den Anfang der Überlegung gestellt - wir empfehlen das Gegenteil
  • Deployment ist nichts anderes als das Kopieren der Artefacte auf einen oder mehrere remote Hosts gefolgt von einigen Maintenance-Tasks
  • Ja OK, bei hochverfügbaren Seiten gibt es Zusatz-Anforderungen und Überlegungen, aber das Prinzip bleibt gleich

  • Wir setzen dafür Ansible ein, aus guten Gründen:
    • modern und extrem umfangreich
    • einzige Voraussetzung: Zugriff per SSH auf remote Hosts
    • sehr viele “Collections”, umfangreiche Dokumentation und große Community
    • Open Source
  • Deshalb lautet die Antwort auf die Frage, welche Hoster wir unterstützen: ALLE !!!

  • Ob AWS, Azure, Google Cloud, Hetzner, Domain Factory, Linode, Digital Ocean oder eigenes Rechenzentrum des Kunden, alles bedienen wir mit dieser Infrastruktur - auch gleichzeitig. Und eine Integration von Acquia, PlatformSH, Pantheon oder anderen stellt gar kein Problem dar - solange SSH-Zugriff gewährleistet ist
  • Aber selbstverständlich kann die vorgestellte CI/CD Infrastruktur für diesen Task auch jedes andere Werkzeug einsetzen, das diese Aufgaben erfüllt
  • Oder sogar Kubernetes?
    Das macht GitLab out-of-the-box order ebenfalls Ansible.

Dokumentation

Danke

… und viel Spaß bei der Diskussion