Jekyll CI/CD mit Azure DevOps
Der Artikel zeigt, wie Sie mithilfe einer Azure DevOps CI/CD Pipeline, einen mittels Jekyll erstellten Webauftritt, builden und automatisiert auf ein GitHub Pages Repository deployen können.
GitHub stellt dem technisch versierten Anwender mit seinen Github Pages ein sehr effizientes Werkzeug zur Verfügung, um schnell und einfach einen Internetauftritt erstellen zu können. Die zugrundeliegende Technologie ist ein auf Ruby basierender “static site generator” namens Jekyll. Das spezielle Setup, welches Github verwendet, bringt allerdings einige Limitierungen mit sich.
Eine der problematischeren Limitierungen ist, dass nur eine sehr eingeschränkte Liste an Jekyll Plugins unterstützt werden. Benötigt man ein Plugin, das nicht aufgelistet ist, wie z.B. das relativ verbreitete jekyll-paginate-v2 Modul, muss man im Gegenzug dafür auf die automatisierte Deployment Pipeline von Github Pages verzichten. Mehr oder weniger nativ lässt sich z.B. TravisCI als individuelle CI Pipeline in das Github Pages Repository integrieren. Mein Lösungsansatz, da ich bereits über einen Azure DevOps account verfüge und auch mit dem CI/CD System vertraut bin, ist, das Jekyll Projekt in einem DevOps repository zu verwalten und durch eine Build Pipeline den generierten Output auf Github Pages zu pushen.
Lokale Entwicklungsumgebung
Für die lokale Entwicklungsumgebung verwende ich einen Docker Container der von Jekyll direkt zur Verfügung gestellt wird. Durch das Einfügen des folgenden docker-componse.yml
files im root Verzeichnis der Jekyll Anwendung kann anschließend mittels der docker compose CLI docker-compose up
ein fertiger konfigurierter Jekyll Container gestartet werden.
version: '3'
services:
jekyll:
image: jekyll/jekyll:4.2.0
command: jekyll serve --watch --force_polling
ports:
- 4000:4000
volumes:
- .:/srv/jekyll
Der erste Start kann ein paar Minuten dauern, da das passende Docker image noch geladen werden muss. Wenn der Container erfolgreich gestartet wurde, sollten die Ausgaben in etwa so aussehen.
Die generierte Seite sollte nun mittels http://localhost:4000 erreichbar sein.
Build Pipeline
Um das Projekt nun automatisiert erstellen zu können, müssen wir im Root Verzeichnis noch eine weitere Yaml datei für die CI/CD Pipeline erstellen. Wir nennen diese azure-pipeline.yml
.
# Jekyll site
# Package your Jekyll site using the jekyll/builder Docker container image.
# Add steps that build, test, save build artifacts, deploy, and more:
# https://aka.ms/yaml
trigger:
- master
pool:
vmImage: 'Ubuntu-latest'
steps:
- task: Docker@0
displayName: 'Run Jekyll'
inputs:
containerRegistryType: 'Container Registry'
action: 'Run an image'
imageName: 'jekyll/builder:4.2.0'
volumes: |
$(build.sourcesDirectory):/srv/jekyll
$(build.sourcesDirectory)/.jekyll-cache:/srv/jekyll/.jekyll-cache
$(build.binariesDirectory):/srv/jekyll/_site
containerCommand: 'jekyll build'
detached: false
- task: PublishBuildArtifacts@1
inputs:
artifactName: 'drop'
pathtoPublish: '$(build.binariesDirectory)'
publishLocation: 'Container'
Auch hier verwenden wir wieder einen Docker Container jekyll/builder:4.2.0
, um ein korrektes Jekyll Setup zu erhalten.
Der Build Prozess hat zwei Teilschritte.
- jekyll build im Container ausführen.
- build Output als Build Artifact an den Buildvorgang anfügen.
Die gerade erstelle Build Definition kann nun im DevOps Portal selektiert werden. Erstellen Sie dazu eine neue Build Pipeline.
Selektieren Sie nun das verwendete Repository und wählen im nächsten Schritt “Existing Azure Pipeline YAML file”.
Anschließend können Sie aus der Liste die zuvor erstellte azure-pipeline.yml
Datei auswählen.
Wurde der Build erfolgreich ausgeführt, sollten Sie im Ergebnis die erzeugten Build Artefakte, sprich die generierte Website, sehen.
Release Pipeline
Um die erstellten Dateien nun in das eigentliche GitHub Pages repository zu laden, wird eine Release Pipeline auf Basis der zuvor erstellten Build Outputs angelegt. Als Synchronisations Task fiel meine Wahl auf eine frei verfügbare Extension GitHub Pages Publish. Alternativ kann man natürlich auch selbst ein kleines Script schreiben, um diese Aufgabe zu erledigen.
"Learning never exhausts the mind."