Spaß mit Gitlab, Tags und Releases
« | 12 Dec 2020 | »Eine Entwicklungsrichtlinie in meiner Firma verlangt, dass man nach dem offiziellen Release einer Komponente unter deren Version keinen weiteren Check-in mehr machen darf.
Und ich durfte das umsetzen … und zwar mit
Gitlab CI-YAMLs,
GIT
Tags und Shellscripts unter
[Linux].
Was für ein Spaß … W-T-F …
Da uns GIT keine stabile Versionierung nach dem MAJOR.MINOR.PATCH
Schema
bereitstellt, mussten wir tricksen.
In den .gitlab-ci.yml
Dateien wo die Build-Jobs definiert sind, wird
eine “globale” Versions-Variable geführt, die bei Änderungen inkrementell
hochgezählt werden muss.
Während der aktiven Entwicklung ist das eigentlich egal, doch wenn ein Feature fertig gestellt und getestet ist, soll eine eigene Release-Stage dafür sorgen, dass das Ergebnis in ein Release-Repository hochgeladen wird, woraus dann die produktiven Installationen generiert werden.
Mit dem “Release” soll die Software-Version eingefroren werden und es darf mit eben dieser “Version” keinen weiteren Check-In mehr geben.
Das Konzept sieht vor, dass beim Release in GIT ein Tag angelegt wird, das der Version gleicht. Parallel darf kein Build-Job Code mit einer Version bauen, für die es schon ein solches Release-Tag gibt.
Aber wie setzt man das “billig” um? Denn dort wo ich dieses Schema einsetzen sollte, sind komplexe Scriptabhängigkeiten eher störend.
Meine Lösung sieht daher wie folgt aus:
Im Gitlab-CI Job wird per before-script
vor der Ausführung der
Build-Stage das gute alte Tool curl
aufgerufen, um den GitLab
Server zu fragen, ob ein Tag mit der aktuellen Version schon existiert.
Fall ja (curl Exitcode == 0) ist das ein Fehler und wir brechen ab.
Andernfalls darf der Build durchlaufen.
Beim Durchlauf der Release-Stage kommt ebenso wieder curl
zum Einsatz,
welches die aktuelle Version per REST
POST den aktuellen Commit mit einem GIT-Tag verknüpft.
Das sieht dann etwa so aus:
1variables: 2- GITLAB_API_TOKEN: "my-secret-access-token" 3- VERSION: "1.2.3" 4- TAGS_URL_BASE: "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/tags" 5before_script: 6- "export CHECK_TAG_EXISTS_COMMAND=\"curl -f --header 7 PRIVATE-TOKEN:$GITLAB_API_TOKEN -L $TAGS_URL_BASE/$VERSION\"" 8- "if [[ `$CHECK_TAG_EXISTS_COMMAND` ]]; then exit 1; fi" 9 10after_script: 11- "curl -f --header \"PRIVATE-TOKEN: $GITLAB_API_TOKEN\" --request POST 12 \"$TAGS_URL_BASE?tag_name=$VERSION&ref=$CI_COMMIT_SHA&message=$VERSION\""
Fazit
Ach wie tief bin ich gesunken …
Wenn mich als Entwickler etwas überhaupt nicht interessiert, dann sind das
solche organisatorischen Quick-and-Dirty Ekelskriptereien … aber was soll
man machen.
Es ist ein schlechter Trost, dass ich sagen kann:
Egal wo ich bisher gearbeitet habe, die anderen haben noch schlechtere Workarounds fabriziert.
Aber genau das ist das Problem von “Scripting”. Jeder macht irgendetwas irgendwie. Möglichst schnell und scheinbar einfach … und dann hat man Gigabytes an Ansammlungen von solchen Codes, die keiner mehr richtig nachvollziehen kann.
However, zumindest weiß ich wieder ein bisschen mehr über Gitlab-YAMLs Bescheid.