Kontinuierliche Integration mit Gitlab CI

  • Koray Zorluoglu
  • 25.10.2021

Verwaltungsmanagement: Gitlab Continous-Integration Server

GitLab startete als ein webbasierter Git-Repository Verwaltungsmanager und hat sich mittlerweile zu einem umfangreichen Entwicklungskit mit vielen Tools weiterentwickelt, welches auch einen Continuous-Integration-Server enthält.

WAS IST CI/CD?

Der Begriff CI bedeutet Continuous Integration (Kontinuierliche Integration), also der Automatisierungsprozess für Entwickler. Es handelt sich hier um eine Methode, bei der dem Kunden regelmäßig Apps bereitgestellt und alle Phasen der Anwendungsentwicklung automatisiert werden.

In diesem Artikel zeigen wir, wie eine Test- und Deployment-Pipeline (Bereitstellungen in Phasen automatisieren) eingerichtet wird.

Als Beispiel verwenden wir dafür den Chameleon Demo Shop, der mit PHPUnit getestet und auf Staging- bzw. danach auf dem Live-Server deployt wird.

Um das CI-/CD-System von GitLab nutzen zu können, ist ein GitLab Runner notwendig. Dieser ist dafür zuständig, die Aufgaben, welche in der CI-Datei festgelegt sind, abzuarbeiten und die Ergebnisse an GitLab zurückzusenden. Die Anleitung dazu findet sich im GitLab Runner Installation-Handbuch.

GitLab CI verlangt eine .gitlab-ci.yml Datei, in welcher die Schritte bzw. Aufgaben, die von der CI ausgeführt werden. Die Aufgaben werden in einzelne Jobs unterteilt, die wiederum in unterschiedlichen Stages laufen können.

Quelle: Eigene Darstellung

Pipeline mit Gitlab

Hier ist ein Pipeline-Beispiel aus der Gitlab-Dokumentation: Die stages definieren die Reihenfolge der Pipeline, das heißt eine Build-Pipeline in Gitlab besteht aus Stages und Jobs von einzelnen Stages. Ein Job hat genau eine Stage, eine Stage wiederum kann mehrere Jobs enthalten, diese werden dann parallel ausgeführt.

Auf der Suche nach Kompetenz?

Gerne begleiten wir Ihre Softwareprojekte.

Kontakt

Wie bereits erwähnt, muss unsere Pipeline erst den Chameleon Shop builden, dann Tests mit PHPUnit ausführen, danach entscheiden, ob die Dateien auf dem Staging- oder dem Live-Server deployt werden.

image: php:7.4
# Stages
stages:
- build
- test
- stage_deploy
- live_deploy
before_script:
- # Anweisungen #
# Jobs
build_stage:
stage: build
script:
- # Anweisungen #
test_stage:
stage: test
script:
- # Anweisungen #
 deploy_stage:
stage: stage_deploy
script:
- # Anweisungen #
deploy_live:
stage: live_deploy
script:
- # Anweisungen #

Die Datei enthält bereits alle Schritte sowie das Container-Image. Während es möglich ist ein eigenes Image mit benutzerdefinierten PHP-Versionen zu erstellen, verwenden wir der Einfachheit halber ein vorhandenes Standard-PHP-Docker-Image.

WAS IST EIN CONTAINER IMAGE?

Gitlab CI initialisiert einen Docker-Container mit dem eingegebenen Docker-Image. Die Images werden aus dem offiziellen Docker-Repository gezogen, wenn Sie kein lokales Repository haben. Das bedeutet, dass alle Skripte in dieser docker-compose.yml Datei, in diesem Container ausgeführt werden.

Beginnen wir erst mit before_script, danach mit dem script-Teil des Jobs.

image: php:7.4
# Stages
stages:
- build
- test
- stage_deploy
 - live_deploy
before_script:
- apt-get update -yqq #Update
- apt-get install -yqq
# Install php extensions
- docker-php-ext-install mysqli mbstring pdo pdo_mysql curl json intl gd xml zip bz2 opcache pcntl tidy
# Enable php extensions
- docker-php-ext-enable pdo_mysql tidy
#  Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
- chmod +x /usr/local/bin/composer
# Jobs
build_stage:
stage: build
script:
- composer install
test_stage:
stage: test
# script:
#    - 
#deploy_stage:
#  stage: stage_deploy
#  script:
#    - 
#deploy_live:
#  stage: live_deploy
#  script:
#    -

Der before_script-Schritt besteht daraus, Systempakete zu aktualisieren und zu installieren. Um benötigte php-Erweiterungen verfügbar zu machen, führen wir die Befehle docker-php-ext-install und /-enable aus. Im script-Teil des Jobs build_stage führen wir die composer install aus, um alle PHP-Abhängigkeiten zu installieren und zu validieren, ob alle Composer Post-Installatiosschritte erfolgreich beendet wurden. Bei diesen Vorgängen werden alle Dateien in einem Build-Ordner abgelegt, der für den Deploy auf einem Server bereit steht. Vor dem Deployment sollte jedoch der Testprozess gestartet werden. Dazu schreiben wir die test_stage-Skripte und aktualisieren den before_script-Schritt mit den für den Test benötigten Testtools.

image: php:7.4
# Stages
stages:
- build
- test
- stage_deploy
- live_deploy
before_script:
- apt-get update -yqq #Update
- apt-get install -yqq
# Install php extensions
- docker-php-ext-install mysqli mbstring pdo pdo_mysql curl json intl gd xml zip bz2 opcache pcntl tidy
# Enable php extensions
- docker-php-ext-enable pdo_mysql tidy
#  Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
 - chmod +x /usr/local/bin/composer
# Install Codeception Testing Tool
- curl --location --output /usr/local/bin/codecept https://codeception.com/codecept.phar
- chmod +x /usr/local/bin/codecept
# Jobs
build_stage:
stage: build
script:
- composer install
test_stage:
stage: test
- codecept init unit
- codecept init acceptance
#deploy_stage:
#  stage: stage_deploy
#  script:
#    - 
#deploy_live:
#  stage: live_deploy
#  script:
#    -

Unter dem before_script installieren wir das Codecept-Testtool für die Unit- und Acceptance-Tests zur Überprüfung der Software, damit wir vor dem Deployment sicher sein können, dass die Korrekturen oder neuen Features keine Fehler erzeugt haben. Jetzt können wir die Deployment-Stages definieren. Für die Vorbereitung einer SSH-Verbindung müssen wir in Gitlab eine Variable SSH_PRIVATE_KEY anlegen, die den privaten Key des SSH-Schlüssels enthält. Weiterhin muss das rsync-Paket installiert sein.

image: php:7.4
# Stages
stages:
- build
- test
- stage_deploy
- live_deploy
before_script:
- apt-get update -yqq #Update
- apt-get install -yqq
# Install php extensions
- docker-php-ext-install mysqli mbstring pdo pdo_mysql curl json intl gd xml zip bz2 opcache pcntl tidy
# Enable php extensions
- docker-php-ext-enable pdo_mysql tidy
#  Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
- chmod +x /usr/local/bin/composer
# Install Codeception Testing Tool
- curl --location --output /usr/local/bin/codecept https://codeception.com/codecept.phar
- chmod +x /usr/local/bin/codecept
# Install ssh-agent if not already installed, it is required by Docker.
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
# Run ssh-agent (inside the build environment)
- eval $(ssh-agent -s)
# Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
# Create the SSH directory and give it the right permissions
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
# Jobs
build_stage:
stage: build
script:
- composer install
test_stage:
stage: test
- codecept init unit
- codecept init acceptance
deploy_stage:
stage: stage_deploy
script:
- echo "Deploying ${CI_COMMIT_SHA} from ${CI_COMMIT_REF_NAME} to staging server"
- rsync -a --progress --human-readable --delete
--exclude-from '.gitignore'
--exclude .gitignore
--exclude .git
.
root@staging-server.com:/home/httpdocs/
rules:
if: $CI_COMMIT_BRANCH == "develop"

Im diesem Teil des Jobs verbinden wir uns per SSH mit dem Server, danach übertragen wir die Daten per rsync in den Ordner “/home/httpdocs/”. Mit rules können wir einen Branch Name angeben, für den dieser Job gelten soll.

Was sind rules(Regeln)?

Die Regeln werden der Reihe nach bis zur ersten Übereinstimmung ausgewertet. Wenn eine Übereinstimmung gefunden wird, wird der Job je nach Konfiguration entweder in die Pipeline aufgenommen oder ausgeschlossen. Rules akzeptieren diese Definierten Regeln: if, changes, exists, allow_failure, variables und when.

Sie können für komplexe Regeln mehrere vordefinierten Regeln miteinander kombinieren.

Und der letzte Schritt deploy_live-Stage, sieh genauso aus wie von deploy_stage-Stage weiter oben.

image: php:7.4
# Stages
stages:
- build
- test
- stage_deploy
- live_deploy
before_script:
- apt-get update -yqq #Update
- apt-get install -yqq
# Install php extensions
- docker-php-ext-install mysqli mbstring pdo pdo_mysql curl json intl gd xml zip bz2 opcache pcntl tidy
# Enable php extensions
- docker-php-ext-enable pdo_mysql tidy
#  Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
- chmod +x /usr/local/bin/composer
# Install Codeception Testing Tool
- curl --location --output /usr/local/bin/codecept https://codeception.com/codecept.phar
- chmod +x /usr/local/bin/codecept
# Install ssh-agent if not already installed, it is required by Docker.
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
# Run ssh-agent (inside the build environment)
- eval $(ssh-agent -s)
# Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
# Create the SSH directory and give it the right permissions
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
# Jobs
build_stage:
stage: build
script:
- composer install
test_stage:
stage: test
- codecept init unit
- codecept init acceptance
deploy_stage:
stage: stage_deploy
script:
- echo "Deploying ${CI_COMMIT_SHA} from ${CI_COMMIT_REF_NAME} to staging server"
- rsync -a --progress --human-readable --delete
--exclude-from '.gitignore'
--exclude .gitignore
--exclude .git
.
root@staging-server.com:/home/httpdocs/
rules:
if: $CI_COMMIT_BRANCH == "develop"
deploy_live:
stage: live_deploy
script:
- echo "Deploying ${CI_COMMIT_SHA} from ${CI_COMMIT_REF_NAME} to live server"
- rsync -a --progress --human-readable --delete
--exclude-from '.gitignore'
--exclude .gitignore
--exclude .git
.
root@live-server.com:/home/live/httpdocs/
rules:
if: $CI_COMMIT_BRANCH == "main"

Was wir erreicht haben: Zeit sparen + Fehlervermeidung + Flexibilität

Im Detail:

  • Bei jeder Änderung werden die Tests ausgeführt.
  • Verhindert Fehler, die von Hand gemacht werden könnten.
  • Serverwechsel oder Migrationen, können sogar mit einer einzigen Zeile abgewickelt werden.
  • Schnelle Datenübertragung zwischen Git und Zielserver
  • Niemand muss Zeit für diese Prozesse aufwenden.
  • Deklarierter Deployment Prozess für alle

Der Autor Koray Zorluoglu alias d8devs veröffentlicht regelmäßig spannende Blogartikel über Development, 3D-Printing, Docker oder PHP.