CI/CD avanzado para proyectos Kotlin en GitHub Actions
La automatización de la compilación, las pruebas y el despliegue es una etapa crítica en el desarrollo de aplicaciones Kotlin modernas. Si ya domina la configuración básica de CI/CD, es hora de pasar a técnicas avanzadas. En este artículo, analizaremos cómo aprovechar al máximo GitHub Actions para proyectos Kotlin: compilaciones matriciales, almacenamiento en caché inteligente, pruebas paralelas y despliegue flexible.
1. Compilaciones matriciales: probar en múltiples versiones y SO
Una de las funciones más potentes de GitHub Actions es la estrategia matricial (strategy.matrix). Permite ejecutar el mismo flujo de trabajo con diferentes parámetros. Para Kotlin, esto es indispensable si admite varias versiones de JVM o plataformas de destino (por ejemplo, JVM + Native).
Ejemplo de compilación matricial para un proyecto 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 # no detener otras compilaciones si una falla
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 }}Recomendaciones:
- Use
fail-fast: falsepara no perder los resultados de otras combinaciones si una falla. - Limite la matriz solo a versiones relevantes para no gastar minutos adicionales de Actions.
- Para Windows, asegúrese de configurar las rutas correctas a Gradle y verifique los saltos de línea (CRLF).
2. Almacenamiento en caché inteligente de Gradle y dependencias
Los proyectos Kotlin con Gradle pueden descargar decenas de megabytes de dependencias en cada ejecución de CI. Sin almacenamiento en caché, la compilación puede tardar de 5 a 10 minutos; con él, de 30 a 40 segundos. Utilice las acciones integradas para el almacenamiento en caché.
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-daemonTrucos avanzados:
- Agregue a la clave de caché el hash de
gradle.lockfile(si usa--write-locks) — esto garantiza la invalidación de la caché al cambiar las versiones de las dependencias. - Use
gradle-build-actionde Gradle (acción:gradle/gradle-build-action@v3) — gestiona automáticamente el almacenamiento en caché e incluye soporte para--build-cache. - No almacene en caché
~/.gradle/daemon— esto puede provocar conflictos entre diferentes versiones del daemon.
3. Pruebas paralelas y distribución dinámica (sharding)
Para proyectos grandes con cientos de pruebas, el tiempo de ejecución puede ser un cuello de botella. GitHub Actions permite ejecutar pruebas en paralelo, dividiéndolas en fragmentos. Esto es especialmente útil para Kotlin + JUnit 5.
Ejemplo de división de pruebas en fragmentos:
jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] # 4 fragmentos paralelos steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin'