CI/CD Avançado para projetos Kotlin no GitHub Actions
A automação de build, teste e deploy é uma etapa crítica no desenvolvimento de aplicações Kotlin modernas. Se a configuração básica de CI/CD já foi dominada, é hora de avançar para técnicas mais sofisticadas. Neste artigo, vamos explorar como extrair o máximo do GitHub Actions para projetos Kotlin: builds matriciais, cache inteligente, testes paralelos e deploy flexível.
1. Builds matriciais: testando em múltiplas versões e sistemas operacionais
Um dos recursos mais poderosos do GitHub Actions é a estratégia matricial (strategy.matrix). Ela permite executar o mesmo workflow com diferentes parâmetros. Para Kotlin, isso é indispensável se você suporta várias versões da JVM ou plataformas alvo (por exemplo, JVM + Native).
Exemplo de build matricial para um projeto Kotlin Multiplatform:
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 # não interrompe os outros builds se um falhar
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 }}Recomendações:
- Use
fail-fast: falsepara não perder os resultados de outras combinações se uma delas falhar. - Limite a matriz apenas às versões relevantes para não gastar minutos extras do Actions.
- Para Windows, configure corretamente os caminhos do Gradle e verifique as quebras de linha (CRLF).
2. Cache inteligente do Gradle e dependências
Projetos Kotlin no Gradle podem baixar dezenas de megabytes de dependências a cada execução do CI. Sem cache, o build leva de 5 a 10 minutos; com ele, de 30 a 40 segundos. Use as actions integradas para cache.
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-daemonTruques avançados:
- Adicione à chave do cache o hash de
gradle.lockfile(se usar--write-locks) — isso garante a invalidação do cache ao alterar versões de dependências. - Use
gradle-build-actiondo Gradle (action:gradle/gradle-build-action@v3) — ele gerencia o cache automaticamente e inclui suporte a--build-cache. - Não armazene em cache
~/.gradle/daemon— isso pode causar conflitos entre diferentes versões do daemon.
3. Testes paralelos e distribuição dinâmica (sharding)
Para projetos grandes com centenas de testes, o tempo de execução pode ser um gargalo. O GitHub Actions permite executar testes em paralelo, dividindo-os em fragmentos (shards). Isso é especialmente útil para Kotlin + JUnit 5.
Exemplo de divisão de testes em shards:
jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] # 4 shards paralelos steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin'