Auf demselben Cloud-Mac kann fastlane im Terminal eines Entwicklers erfolgreich laufen, während der CI-Job ein fehlendes Gem meldet. Nach der Korrektur des Runners verweist das Anmeldeterminal mitunter wiederum auf eine andere Ruby-Installation. Solche Fehler liegen meist nicht an fastlane selbst, sondern an abweichenden Pfaden, die durch das Zusammenspiel von System-Ruby, Versionsmanager, Bundler-Konfiguration und Job-Umgebung entstehen. Die Lösung besteht nicht darin, Gems wiederholt zu installieren, sondern die gesamte Ruby-Werkzeugkette als Bestandteil des Projekts zu verwalten.
Tatsächlich ausgeführte Ruby-Installation ermitteln
Führen Sie nicht sofort Installationsbefehle aus. Erfassen Sie zunächst im Anmeldeterminal und im CI-Job jeweils die folgenden Ausgaben:
command -v ruby
ruby -v
command -v bundle
bundle -v
gem env home
bundle config list
printf '%s
' "$PATH"
Vergleichen Sie insbesondere, ob ruby und bundle aus demselben Präfix stammen. Befindet sich Ruby im Verzeichnis eines Versionsmanagers, während Bundler aus einem Systemverzeichnis kommt, werden nachfolgende Installationen wahrscheinlich in den falschen Gem-Pfad geschrieben. Prüfen Sie außerdem, ob in der CI GEM_HOME, GEM_PATH oder BUNDLE_PATH gesetzt ist. Veraltete Umgebungsvariablen können die Projektkonfiguration überschreiben.
Dass ein Befehl im interaktiven Terminal funktioniert, bedeutet nicht, dass ein automatisierter Job dieselbe Umgebung verwendet. Die CI sollte auf Grundlage eindeutiger Versionsdateien und Projektkonfigurationen starten, statt darauf zu vertrauen, dass ein Shell-Startskript zufällig den PATH anpasst.
Ein einzelnes Diagnoseartefakt genügt. Geben Sie keine Token, Zertifikatsinhalte oder vollständigen Umgebungsvariablen im Protokoll aus. Pfade und Versionen reichen aus, um die meisten Auflösungsprobleme zu identifizieren.
Ruby, Bundler und fastlane fixieren
Im Stammverzeichnis des Repositorys sollten .ruby-version, Gemfile und Gemfile.lock eingecheckt werden. Die Ruby-Version muss als vollständig installierbare Version angegeben sein, nicht als ungenaue Angabe wie 3.3. Legen Sie die Version zunächst im Team fest und führen Sie anschließend Folgendes aus:
printf '%s
' '3.3.6' > .ruby-version
bundle init
bundle add fastlane --version '~> 2.0'
bundle lock
Das Gemfile beschreibt den zulässigen Versionsbereich, während Gemfile.lock die bei dieser Auflösung ermittelten exakten Versionen festhält. Die CI sollte nicht vor jedem Build bundle update ausführen, da die Sperrdatei dadurch ihre bindende Wirkung verliert. Führen Sie nach der Installation alle Befehle über Bundler aus:
bundle exec fastlane --version
bundle exec fastlane ios ci
Verwenden Sie ein global installiertes fastlane nicht als Abkürzung. Es kann aus einer anderen Ruby-Installation stammen oder sich nach einem Systemupdate beziehungsweise einer manuellen Fehlersuche geändert haben. Benötigt das Projekt eine bestimmte Bundler-Version, lesen Sie diese aus dem Abschnitt BUNDLED WITH in Gemfile.lock, installieren Sie genau diese Version und führen Sie danach bundle install aus.
Installation der Abhängigkeiten auf das Projektverzeichnis beschränken
Die projektspezifische Konfiguration sollte in .bundle/config neben dem Repository gespeichert werden. Ändern Sie nicht die globale Bundler-Konfiguration des gesamten Hosts:
bundle config set --local path vendor/bundle
bundle config set --local clean true
bundle install --jobs 4 --retry 2
vendor/bundle wird üblicherweise nicht in Git eingecheckt, sondern über den CI-Cache verwaltet. Dadurch werden weder die System-Gems verunreinigt noch unterschiedliche Versionen zwischen mehreren Projekten verhindert. Nach der Installation lässt sich mit den folgenden Prüfungen bestätigen, dass die gesamte Auflösungskette intakt ist:
test -f Gemfile.lock
test "$(ruby -e 'print RUBY_VERSION')" = "$(cat .ruby-version)"
bundle check
bundle exec ruby -e 'require "fastlane"; puts Fastlane::VERSION'
Falls der letzte Schritt fehlschlägt, löschen Sie nicht sofort den gesamten Cache. Prüfen Sie zuerst bundle config list und bundle env, um sicherzustellen, dass der Job das Gemfile des aktuellen Repositorys verwendet und nicht eines aus einem übergeordneten Verzeichnis oder eine andere, über BUNDLE_GEMFILE referenzierte Datei.
Saubere nicht interaktive Umgebung simulieren
Vor der endgültigen Einbindung in den Runner können Sie die Konfiguration einmal in einer minimalen Umgebung validieren:
RUBY_BIN="$(dirname "$(command -v ruby)")"
env -i \
HOME="$HOME" \
PATH="$RUBY_BIN:/usr/bin:/bin:/usr/sbin:/sbin" \
BUNDLE_GEMFILE="$PWD/Gemfile" \
bundle exec fastlane --version
Dieser Schritt deckt frühzeitig Pfade, Aliase und Umgebungsvariablen auf, die ausschließlich in einer persönlichen Shell-Konfiguration definiert sind. Schlägt der Befehl fehl, korrigieren Sie die explizite Initialisierung des Runners, statt die CI die gesamte persönliche Konfiguration laden zu lassen.
Cache-Schlüssel ohne unerwünschte Vermischung entwerfen
Für Gems mit nativen Erweiterungen darf der Cache-Schlüssel nicht ausschließlich auf Gemfile.lock basieren. Unterschiede bei der Ruby-Version, der CPU-Architektur oder der Haupt- und Nebenversion von macOS können dazu führen, dass kompilierte Dateien nicht geladen werden können. Der Cache-Schlüssel sollte mindestens die folgenden Felder enthalten:
| Feld | Ermittlung | Zweck |
|---|---|---|
| Ruby-Version | ruby -e 'print RUBY_VERSION' |
ABI-Unterschiede isolieren |
| CPU-Architektur | uname -m |
Unterschiedlichen nativen Code trennen |
| macOS-Version | sw_vers -productVersion |
Unterschiede bei Systembibliotheken vermeiden |
| Prüfsumme der Sperrdatei | shasum -a 256 Gemfile.lock |
Cache bei geänderten Abhängigkeiten verwerfen |
Ein stabiler Fingerabdruck lässt sich wie folgt erzeugen:
RUBY_VERSION_KEY="$(ruby -e 'print RUBY_VERSION')"
ARCH_KEY="$(uname -m)"
OS_KEY="$(sw_vers -productVersion | cut -d. -f1,2)"
LOCK_KEY="$(shasum -a 256 Gemfile.lock | cut -d' ' -f1)"
printf '%s-%s-%s-%s
' "$RUBY_VERSION_KEY" "$ARCH_KEY" "$OS_KEY" "$LOCK_KEY"
Führen Sie auch nach der Wiederherstellung des Caches bundle check aus. Erst wenn diese Prüfung fehlschlägt, sollte bundle install die fehlenden Inhalte ergänzen. Eine erfolgreiche Cache-Extraktion ist kein Nachweis dafür, dass die Abhängigkeiten tatsächlich verwendbar sind.
Fehler mit einem prüfbaren Gate eindeutig lokalisieren
Der endgültige Job sollte in drei Phasen ausgeführt werden: Umgebungsprüfung, Abhängigkeitsprüfung und fachliche Lane. In der ersten Phase werden Versionen und Pfade geprüft, in der zweiten wird bundle check ausgeführt und erst in der dritten fastlane aufgerufen. Schlägt eine Phase fehl, muss der Job sofort beendet werden. So erscheint der ursprüngliche Fehler nicht erst in einem späteren Schritt als schwer verständliches fehlendes Plug-in oder als Fehler beim Laden einer Konstante.
Es empfiehlt sich, die folgenden Punkte in die Merge-Prüfung aufzunehmen:
.ruby-versionstimmt exakt mit der tatsächlich vom Runner verwendeten Ruby-Version überein.Gemfile.lockist eingecheckt und bleibt vor und nach der Job-Ausführung unverändert.- fastlane wird ausschließlich über
bundle execaufgerufen. .bundle/configverwendet ein projektspezifisches Verzeichnis für Abhängigkeiten.- Der Cache-Schlüssel enthält Ruby-Version, Architektur, Systemversion und Prüfsumme der Sperrdatei.
- Die Protokolle enthalten nur Versionen, Pfade und Prüfergebnisse, jedoch keine sensiblen Umgebungswerte.
- Runner und Anmeldeterminal verwenden dieselbe explizite Initialisierungslogik.
Sind diese Vorgaben umgesetzt, wird die Ruby-Werkzeugkette von einer „auf dem Host installierten Sammlung von Befehlen“ zu einer überprüfbaren Build-Eingabe. Bei späteren Upgrades von Ruby oder fastlane können Versions- und Sperrdateien in einem eigenen Commit aktualisiert und die Auswirkungen mit denselben Prüfschritten bestätigt werden. Nach einem Fehler muss dann nicht mehr geraten werden, welche Umgebung der Job tatsächlich verwendet hat.
Häufig gestellte Fragen
Warum kann sich fastlane trotz eingecheckter Gemfile.lock ändern?
Meist wird das globale fastlane direkt aufgerufen oder die Sperrdatei vor dem Lauf neu erzeugt. Verwenden Sie immer bundle exec fastlane und behandeln Sie Gemfile.lock als unveränderliche Eingabe.
Darf vendor/bundle zwischen mehreren Cloud Macs geteilt werden?
Nur mit einem strikten Cache-Schlüssel aus Ruby-Version, CPU-Architektur, macOS-Haupt- und Nebenversion sowie der Prüfsumme von Gemfile.lock.
Was ist zu prüfen, wenn die CI läuft, die Login-Shell aber scheitert?
Vergleichen Sie command -v ruby, ruby -v, bundle config list und die Umgebungsvariablen. Häufig laden die Sitzungen unterschiedliche PATH- oder Ruby-Initialisierungen.
Deine Mac-mini-Workflows dauerhaft in der Cloud ausführen
Wähle RunAMac M4, die Mietdauer und den Bereitstellungsstandort, und verlagere Entwicklungs-, Build- oder Testaufgaben auf einen dedizierten physischen Rechner.