Fortgeschrittenes CI/CD für Kotlin-Projekte auf GitHub Actions
Die Automatisierung von Build, Tests und Deployment ist ein kritisch wichtiger Schritt in der Entwicklung moderner Kotlin-Anwendungen. Wenn die grundlegende CI/CD-Einrichtung bereits gemeistert ist, ist es an der Zeit, zu fortgeschrittenen Techniken überzugehen. In diesem Artikel werden wir behandeln, wie Sie das Maximum aus GitHub Actions für Kotlin-Projekte herausholen: Matrix-Builds, intelligentes Caching, parallele Tests und flexibles Deployment.
1. Matrix-Builds: Testen mit mehreren Versionen und Betriebssystemen
Eine der leistungsstärksten Funktionen von GitHub Actions ist die Matrix-Strategie (strategy.matrix). Sie ermöglicht es, denselben Workflow mit verschiedenen Parametern auszuführen. Für Kotlin ist dies unverzichtbar, wenn Sie mehrere JVM-Versionen oder Zielplattformen (z. B. JVM + Native) unterstützen.
Beispiel für einen Matrix-Build für ein Kotlin-Multiplatform-Projekt:
name: Matrix Build Kotlinon: [push, pull_request]
jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] java: [11, 17, 21] kotlin-version: [1.9.22, 2.0.0] fail-fast: false # Stoppt andere Builds nicht bei einem Fehler
steps: - uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: 'temurin'
- name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v2
- name: Build with Gradle run: ./gradlew build -Dkotlin.version=${{ matrix.kotlin-version }}Empfehlungen:
- Verwenden Sie
fail-fast: false, um die Ergebnisse anderer Kombinationen nicht zu verlieren, falls eine fehlschlägt. - Beschränken Sie die Matrix auf relevante Versionen, um keine unnötigen Actions-Minuten zu verbrauchen.
- Konfigurieren Sie für Windows die korrekten Pfade zu Gradle und überprüfen Sie die Zeilenumbrüche (CRLF).
2. Intelligentes Caching von Gradle und Abhängigkeiten
Kotlin-Projekte mit Gradle können bei jedem CI-Start Dutzende Megabyte an Abhängigkeiten herunterladen. Ohne Caching dauert der Build 5–10 Minuten, damit 30–40 Sekunden. Verwenden Sie die integrierten Actions für das Caching.
steps: - uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper build/ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle-
- name: Build with Gradle run: ./gradlew build --build-cache --no-daemonFortgeschrittene Tricks:
- Fügen Sie dem Cache-Schlüssel den Hash von
gradle.lockfilehinzu (falls Sie--write-locksverwenden) – dies garantiert eine Cache-Invalidierung bei Änderungen der Abhängigkeitsversionen. - Verwenden Sie
gradle-build-actionvon Gradle (Aktion:gradle/gradle-build-action@v3) – es verwaltet das Caching automatisch und unterstützt--build-cache. - Cachen Sie nicht
~/.gradle/daemon– dies kann zu Konflikten zwischen verschiedenen Daemon-Versionen führen.
3. Parallele Tests und dynamische Verteilung (Sharding)
Bei großen Projekten mit Hunderten von Tests kann die Ausführungszeit ein Engpass sein. GitHub Actions ermöglicht das parallele Ausführen von Tests, indem sie in Shards aufgeteilt werden. Dies ist besonders nützlich für Kotlin + JUnit 5.
Beispiel für die Aufteilung von Tests in Shards:
jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] # 4 parallele Shards steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin'