Jekyll-dockerimage: Bundler und Gemfile

2 Minuten Lesezeit

Was ist bundler?

Bundler ist ein Werkzeug, mit dem Abhängigkeiten zwischen Modulen und Bibliotheken in der Programmiersprache Ruby verwaltet und versioniert werden können. Ich benutze Bundler-Kommandos regelmäßig, z.B. um meinen Blog zu bauen und auf dem Server live zu stellen.

Will ich lokal bauen, so tippe ich beispielsweise

bundle exec jekyll serve --incremental --future

in die Konsole. Dieser Befehl sagt Bundler, es soll die Applikation jekyll im Server-Modus ausführen und ihr Parameter mitgeben, welche jekyll nicht bei jeder Dateiänderung komplett neu bauen lässt und noch nicht veröffentlichte Seiten dennoch mit erstellt.

bundler in der CI-Pipeline

Auch für die Veröffentlichung meiner Seite nutze ich Bundler als Teil eines Jekyll-Dockerimages, wie bereits öfters auf meiner Seite verlinkt, z.B. bei der Umstellung auf self-hosted. Seit ich auf eine neue Version der Blog-Software umgestiegen bin, sehe ich in meiner CI-Pipeline rätselhafte Fehler. Lokal baut das System jedoch einwandfrei. Wie man solche Fehler angeht und behebt, habe ich hier festgehalten.

“There was an error while trying to write to /path/to/Gemfile.lock” - CI console output

Keine Schreibrechte

Bundler selbst kann auf meiner CI wie der Jekyll-user auch nur Dateien lesen und nicht schreiben. Was ich für den Jekyll output mit chown beheben kann, möchte ich bundler aber gar nicht erlauben: Ich will ja gerade, dass Gemfile.lock zwischen meiner lokalen Bauumgebung und der CI identisch bleibt, damit ich mögliche Fehler schon vorab beheben kann.

Spezifikationsdatei für bundler

In der Datei Gemfile.lock stehen alle Abhängigkeiten der verwendeten Applikation drin, inkl. Versionsnummer und Bezugsquelle. Wird nur der Quellcode der Anwendung plus diese Datei geliefert, so kann bundler eine konkrete Version aller Abhängigkeiten beim Bauen ziehen, sodass unabhängig von Maschine und Version mit ähnlichen Voraussetzungen gearbeitet werden kann.

Fehlerbehebung

Ein erster Versuch der Behebung durch Angleichung sämtlicher Versionen zwischen lokal und CI schlug fehl. Der zweite Versuch, dem Jekyll-user Schreibrechte auf die Gemfile.lock zu geben, schlug ebenfalls fehl. Der dritte Versuch führte mich zur Bundler-Website, wo ich die Parameter genauer unter die Lupe nahm, Stichwort “frozen”.

Es ist nämlich so, dass man bundler verbieten kann, die Gemfile.lock umzuschreiben. Dafür verwendet man das Kommando

bundle config set frozen true

Laut Dokumentation wird die Verarbeitung abgebrochen, sobald die Datei umgeschrieben werden müsste.

Obwohl ich diesen Befehl meiner yaml-Datei in der CI hinzugefügt hatte, schlug das Bauen erneut fehl. Auslöser war dieselbe Bibliothek nokogiri wie vorher, nur war die Fehlermeldung nun viel hilfreicher:

Image: jekyll build error due to build platform incompatibility between local and remote.

Gemfile.lock für verschiedene Umgebungen optimieren

Also befolge ich den Vorschlag und führe das gewünschte Kommando auf meinem lokalen Rechner aus:

bundle lock --add-platform x86_64_musl # my CI runner's environment

Randnotiz: musl ist eine libc-Implementierung für Linux, sprich mit ihrer Hilfe laufen viele in C geschriebene Programme.

In meiner Lockfile taucht daraufhin folgender Eintrag auf:

nokogiri (1.18.10-x86_64-linux-musl)

Nun läuft meine CI wieder sauber durch und nebenbei habe ich die Portabilität meines Jekll-Setups verbessert.

Image: successful CI run with updated dependencies