CI mit GitLab
Diese Anleitung richtet CodeGuard für Merge Requests, den Default-Branch und nächtliche Läufe in GitLab CI/CD ein. Sie setzt self-hosted GitLab-Runner auf macOS voraus, die ephemer und isoliert sind, sodass CodeGuard dort bauen und testen darf.
So funktioniert CodeGuard in der CI
- Jeder Aufruf bekommt
--ci. Das Profil ist nicht interaktiv, lokale Trust-Tickets gelten nicht,trust grantist verboten. compileundtestsstarten nur, wenn der Runner eine Attestierung der Organisation trägt (siehe Organisationsrichtlinie). Fehlt sie, laufen nur die statischen Prüfungen und der Lauf endet mit Exit 6.- Der Job-Status folgt dem Exit-Code von CodeGuard. Die Berichte werden als Job-Artefakt abgelegt.
Voraussetzungen
- GitLab-Runner auf macOS 15 oder neuer, dessen Jobs jeweils in einer frischen, ephemeren Umgebung laufen, die dateisystem- und netzwerkisoliert ist. Nur dann darf die Attestierungsdatei dort liegen.
- Admin-Zugriff auf das Runner-Image, um Dateien als
rootabzulegen. - Das Projekt liegt im Wurzelverzeichnis des Repositorys.
check-diffbricht ab, wenn Projektwurzel und Git-Wurzel verschieden sind.
Schritt 1: Runner-Image vorbereiten
Die Vorbereitung ist dieselbe wie bei GitHub Actions:
-
Xcode (
xcodebuild >= 26.0.0, < 28.0.0) und die benötigten Simulator-Runtimes installieren. -
CodeGuard mit
Scripts/install.shinstallieren (Repository-URL: Platzhalter<REPOSITORY-URL>). -
SwiftLint als root-eigene Kopie nach
/usr/local/binlegen. -
Organisationsrichtlinie mit
trusted_rootsundexecution_environmentnach/Library/Application Support/CodeGuard/policy.ymlinstallieren. -
Attestierungsdatei mit exakt diesem Inhalt als
rootmit Modus0644ablegen:version: 1runner_class: ephemeralephemeral: truefilesystem_isolated: truenetwork_isolated: true -
Als Runner-Benutzer prüfen:
codeguard version,codeguard --ci config validate,codeguard --ci doctor.
Alle Befehle und Dateien im Detail: CI mit GitHub Actions, Schritt 1.
Die Attestierung sichert zu, dass der Runner ephemer und isoliert ist. CodeGuard führt daraufhin Projektcode aus Merge Requests ohne menschliche Freigabe aus. Lege sie nie auf einem dauerhaften oder vernetzten Runner ab.
Weise dem Runner einen Tag zu, z. B. macos-codeguard (Platzhalter), damit nur passende Jobs dort laufen.
Schritt 2: Repository vorbereiten
.codeguard.ymlund gegebenenfalls.swift-formatund.swiftlint.ymlins Wurzelverzeichnis committen..gitlab-ci.yml,.codeguard.yml,Package.swift,Package.resolved,*.xcconfig,project.pbxprojund Entitlements sind geschützte Dateien. Ein Merge Request, der eine davon ändert, endet mit Exit 6 (protected_file). Solche Änderungen brauchen bewusst eine menschliche Prüfung.
Schritt 3: Pipeline anlegen
Datei .gitlab-ci.yml:
stages:
- codeguard
variables:
GIT_DEPTH: "0" # voller Klon, damit die Basis-Revision existiert
.codeguard:
stage: codeguard
tags: [macos-codeguard] # Platzhalter: Tag deiner ephemeren macOS-Runner
timeout: 3h
artifacts:
when: always
expire_in: 30 days
paths:
- codeguard-reports/
codeguard:diff:
extends: .codeguard
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- mkdir -p codeguard-reports
- set +e
- codeguard --ci --format json --output codeguard-reports/codeguard.json check-diff --base "$CI_MERGE_REQUEST_DIFF_BASE_SHA"
- rc=$?
- echo "CodeGuard exit code $rc"
- exit $rc
codeguard:project:
extends: .codeguard
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- mkdir -p codeguard-reports
- set +e
- codeguard --ci --format sarif --output codeguard-reports/codeguard.sarif check-project
- rc=$?
- echo "CodeGuard exit code $rc"
- exit $rc
Erläuterungen:
GIT_DEPTH: "0": GitLab klont standardmäßig flach. Ohne die Basis-Revision endetcheck-diffmit Exit 2 (unbekannte Referenz) bzw. Exit 3 (Commit-Objekt fehlt).CI_MERGE_REQUEST_DIFF_BASE_SHA: Basis des Merge-Request-Diffs. Die Variable gibt es nur in Merge-Request-Pipelines, deshalb dierulesmitmerge_request_event.set +eundexit $rc: Das Skript läuft bis zum Ende und übernimmt den Exit-Code von CodeGuard als Job-Ergebnis. Diese Form setzt voraus, dass die Skriptzeilen in einer gemeinsamen Shell laufen, wie beim Shell-Executor üblich. Prüfe das in deiner Runner-Konfiguration.artifacts: when: always: Der Bericht wird auch bei Funden abgelegt.- Nächtlicher Lauf: Lege dafür im Projekt einen Pipeline-Zeitplan (Pipeline schedules) an.
codeguard:projectläuft dann mit$CI_PIPELINE_SOURCE == "schedule". timeout: Builds für mehrere Plattformen und Simulator-Tests dauern. CodeGuard hat kein Gesamtzeitlimit über den ganzen Lauf.
gitlab-sarifCodeGuard kennt zusätzlich --format gitlab-sarif. Diese Variante enthält nur sicherheitsbezogene Funde mit Datei und Position, höchstens 5000 Ergebnisse und kürzt Meldungen auf 1024 Zeichen. Eine Anbindung an die GitLab-Sicherheitsberichte ist nicht Teil dieser Anleitung; die Berichte werden hier nur als Artefakt abgelegt.
Ergebnis prüfen
Mit gültiger Attestierung steht im JSON-Bericht "build_authorization": "operator_attested" unter run, und compile und tests erscheinen unter Completed. Fehlt die Attestierung, meldet der Bericht:
1. ERROR
Rule: codeguard-build-execution-denied
Build and test execution was not authorized: ci-untrusted execution requires an attested isolated runner: no declaration is installed at the organisation's execution-environment path.
Grant project trust, or run inside an attested isolated environment.
Den vollständigen Bericht dazu und die Bedeutung aller Exit-Codes im Pipeline-Kontext findest du unter CI mit GitHub Actions; sie gelten für GitLab genauso.
Simulatoren auf dem Runner
CodeGuard legt für Tests Wegwerf-Simulatoren im Standard-Device-Set des Runner-Benutzers an und löscht sie danach. Auf einem ephemeren Runner verschwinden die bleibenden Logs mit der Umgebung. Bricht ein Job hart ab, räumt erst der nächste Lauf auf demselben Runner ein zurückgebliebenes Gerät ab. Siehe Trust und Sicherheit.