Mit Impressum, dem ersten öffentlichen Plugin im WordPress.org-Repository, an dem ich als Teil von Epiphyt mitwirke, war es für uns eine wichtige Möglichkeit, ein automatisches Deployment in selbiges nutzen zu können. Es gibt zwar bereits vorhandene Lösungen (beispielsweise hier), die habe ich im Voraus ehrlicherweise jedoch gar nicht erst gesucht.

Aus diesem und auch aus anderen Gründen (wir hatten bereits ein fertiges Deployment für einen direkten Upload auf Test- und Production-Server inklusive dem Kompilieren unserer Assets) habe ich das Deployment mit unserem eigenen GitLab kurzerhand selbst entwickelt. Ich nutze hierfür das normale GitLab CI/CD und gehe in diesem Beitrag davon aus, dass das bereits funktionierend eingerichtet wurde. Falls das noch nicht der Fall ist, kann hier eine Anleitung eingesehen werden.

Deploy-Skript

Für das Deploy-Skript nutze ich ein eigenes Git-Repository in unserem GitLab. Das hat mehrere Vorteile:

  • Änderungshistorie über das Skript
  • Einfach für mehrere Projekte nutzbar
  • Eine Änderung muss nur an einer Stelle angepasst werden
  • Es wird in jedem Repository die aktuelle Version des Skripts genutzt

Bei mir befindet sich das Skript in einem Repository namens deploy-script in der Datei deploy.sh. Der relevante Inhalt für das Deployment ins WordPress-Respository, welches über SVN läuft, sieht folgendermaßen aus:

#!/bin/bash
# get parameters
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
	--svn)
	SVN=YES
	SVN_URL="$2"
	shift # past argument
	shift # past value
	;;
	*) # unknown option
	POSITIONAL+=("$1") # save it in an array for later
	shift # past argument
	;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
# change directory
cd ..
if [ "$SVN" = YES ]; then
	TAG=$(git describe --tags)
	# remove first character (usually a 'v')
	TAG=${TAG:1:${#TAG}}
	mkdir svn
	svn co $SVN_URL svn
	cp -rv `ls -A | grep -vE "svn|.git|deploy-script|temp"` svn/trunk/
	cd svn
	svn stat
	cd trunk
	# see https://stackoverflow.com/a/20095520/3461955
	svn st | grep '^\?' | sed 's/^\? *//' | xargs -I% svn add %
	cd ..
	svn ci -m "Version ${TAG}"
	svn cp trunk tags/${TAG}
	svn ci -m "Tag ${TAG}"
	cd ..
fi
Code-Sprache: Bash (bash)

Kurz zur Erklärung:

In den Zeilen 4–22 werden sämtliche an das Skript übergebene Parameter verarbeitet. In diesem Fall gibt es nur den Parameter --svn.

In Zeile 25 wird das aktuelle Verzeichnis gewechselt. Beim Deployment wird das Deploy-Skript per Git in ein separates Unterverzeichnis geklont und in dieses gewechselt, bevor das Skript startet. Um aber die eigentlich relevanten Dateien zu deployen, muss man wieder eine Ebene nach oben.

In den Zeilen 28–44 findet dann das eigentliche Deployment via SVN statt. Dabei werden folgende Befehle durchgeführt (aufgeführt nach Zeilennummer):

  • Der aktuelle Git-Tag wird in eine Variable gespeichert (Format: v1.2.3).
  • Vom aktuellen Tag wird das beginnende „v“ entfernt.
  • Für das SVN-Repository wird ein eigenes Verzeichnis erstellt.
  • Die aktuellen Daten des SVN-Repositorys werden in dieses angelegte Verzeichnis heruntergeladen.
  • Alle Dateien aus dem Git-Repository werden ins SVN-Repository ins Verzeichnis trunk/ geladen.
  • Es wird ins angelegte Verzeichnis für das SVN-Repository gewechselt.
  • Zur Sicherheit wird einmal der aktuelle Status der Dateien im SVN-Repository ausgegeben.
  • Es wird ins Verzeichnis trunk/ gewechselt.
  • Alle noch nicht versionierten Dateien werden zum SVN-Repository hinzugefügt.
  • Es wird wieder ins angelegte Verzeichnis für das SVN-Repository gewechselt.
  • Die aktuelle Version wird ins SVN-Repository deployt.
  • Die aktuelle Version wird als SVN-Tag gesichert.
  • Der aktuelle Tag wird ins SVN-Repository übernommen bzw. dort getagt.
  • Es wird wieder aus dem SVN-Repository heraus gewechselt.

Und nun?

Das obere Skript kann also Inhalte aus einem übergeordneten Verzeichnis in ein SVN laden, dessen URL man über einen Parameter angeben kann. Soweit, so gut. Um es jedoch nutzen zu können, benötigt man beim eigentlichen Git-Repository, welches deployt werden soll, ein Deployment via GitLab CI/CD.

GitLab CI/CD

GitLab CI/CD funktioniert immer über eine Datei namens .gitlab-ci.yml. Genauere Informationen sind unter folgendem Link zu finden. Auf die genaue Funktionsweise von GitLab CI/CD werde ich in diesem Beitrag nicht eingehen.

Wichtig für das Deployment, wie ich es verwende, ist das before_script, mit dessen Hilfe ich jedes Mal das Deploy-Skript von oben per Git klone. Das sieht in unserer .gitlab-ci.yml folgendermaßen aus:

before_script:
    - git clone --branch=master --depth=1 --quiet git@git.kittmedia.com:wordpress/deploy-script.git
    - chmod +x deploy-script/*.sh
Code-Sprache: YAML (yaml)

Dabei wird vor dem eigentlichen Deploy-Vorgang das besagte Skript geklont und ausführbar gemacht.

Das eigentliche Deployment sieht dann folgendermaßen aus:

upload_svn:
    stage: production
    script:
        - cd deploy-script
        - ./deploy.sh --svn https://plugins.svn.wordpress.org/impressum
    only:
        - tags
Code-Sprache: YAML (yaml)

Hierbei wird (Zeile 5) erst ins Verzeichnis des Deploy-Skripts gewechselt und dann das Deploy-Skript ausgeführt. Über den bereits genannten Parameter --svn wird die URL zum SVN-Repository – in diesem Falle die zum Impressum – angegeben. Außerdem wird das Deployment nur durchgeführt, wenn ein Tag in Git gesetzt wurde.

Die ganze .gitlab-ci.yml sieht dann bei mir folgendermaßen aus:

variables:
    GIT_SUBMODULE_STRATEGY: recursive
before_script:
    - git clone --branch=master --depth=1 --quiet git@git.kittmedia.com:wordpress/deploy-script.git
    - chmod +x deploy-script/*.sh
stages:
    - test
    - production
upload_svn:
    stage: production
    script:
        - cd deploy-script
        - ./deploy.sh --svn https://plugins.svn.wordpress.org/impressum
    only:
        - tags
Code-Sprache: YAML (yaml)

GitLab-Runner

Das war es dann auch schon – fast. Damit der GitLab-Runner, welcher für das Ausführen des Deploy-Jobs verantwortlich ist, die Zugangsdaten zum SVN-Repository speichern kann, empfehle ich die erstmalige Ausführung des Deploy-Skripts über den manuellen Weg direkt in der Konsole. Dann können diese bereits im System gespeichert werden und müssen nicht bei jedem Deploy-Vorgang wieder angegeben werden.

Fazit

Im Grunde ist es nicht viel, was ein funktionierendes Deployment voraussetzt. Allerdings ist es ein steiniger Weg, weshalb ich hoffe, dass dieser kleine Beitrag auch anderen hilft, damit man sich nicht alles selbst zusammensuchen muss.

Gerne nehme ich auch Feedback an, um unseren Deploy-Vorgang zu verbessern. 🚀

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert