GitHub Actions se tornou a ferramenta de CI/CD mais popular para projetos open source e comerciais. Para projetos Kotlin, a integracao e poderosa e permite automatizar desde testes simples ate pipelines completos de deploy. Neste guia, vamos construir workflows reais para projetos Kotlin.

Por Que GitHub Actions para Kotlin

GitHub Actions oferece vantagens especificas para projetos Kotlin:

  • Integracao nativa com repositorios GitHub
  • Runners gratuitos para projetos open source
  • Cache de dependencias Gradle nativo
  • Marketplace com milhares de actions prontas
  • Suporte a matrix builds para testar em multiplas versoes de JDK

Workflow Basico para Kotlin Backend

Vamos comecar com um workflow para um projeto Spring Boot com Kotlin:

// O workflow YAML fica em .github/workflows/ci.yml
// Aqui vamos focar na configuracao do projeto Kotlin

// build.gradle.kts otimizado para CI
plugins {
    kotlin("jvm") version "2.1.0"
    kotlin("plugin.spring") version "2.1.0"
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.4"
    id("org.jetbrains.kotlinx.kover") version "0.7.5"
    id("io.gitlab.arturbosch.detekt") version "1.23.4"
}

tasks.withType<Test> {
    useJUnitPlatform()
    testLogging {
        events("passed", "skipped", "failed")
        showStandardStreams = true
    }
    // Gerar relatorios para CI
    reports {
        junitXml.required.set(true)
        html.required.set(true)
    }
}

// Configuracao kover para relatorio de cobertura
koverReport {
    defaults {
        xml { onCheck = true }
        html { onCheck = true }
    }
}

O workflow GitHub Actions correspondente inclui etapas de checkout, setup JDK, cache Gradle, execucao de testes e upload de relatorios. A configuracao permite rodar em pushes para main e em pull requests.

Cache Eficiente de Gradle

O cache de dependencias Gradle e critico para performance do CI:

// gradle.properties - Otimizacoes para CI
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx2g -XX:+UseParallelGC
kotlin.incremental=true

GitHub Actions tem uma action oficial para cache de Gradle que armazena:

  • Dependencias baixadas (~/.gradle/caches)
  • Wrapper do Gradle (~/.gradle/wrapper)
  • Build cache (.gradle/build-cache)

Isso pode reduzir o tempo de build de 5-10 minutos para 1-2 minutos em builds subsequentes.

Workflow para Projeto Android

Projetos Android com Kotlin tem necessidades especificas:

// build.gradle.kts (modulo app) - Configuracao para CI
android {
    compileSdk = 34

    defaultConfig {
        minSdk = 24
        targetSdk = 34
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    lint {
        abortOnError = true
        xmlReport = true
        htmlReport = true
    }

    testOptions {
        unitTests {
            isIncludeAndroidResources = true
            all {
                it.useJUnitPlatform()
            }
        }
    }
}

O workflow Android inclui:

  • Setup do JDK e Android SDK
  • Execucao de lint
  • Testes unitarios
  • Build do APK/AAB
  • Opcionalmente, testes instrumentados com emulador

Testes Instrumentados no CI

Para rodar testes instrumentados, voce pode usar emuladores no GitHub Actions:

// Teste instrumentado com Compose
@HiltAndroidTest
class LoginScreenTest {

    @get:Rule(order = 0)
    val hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 1)
    val composeRule = createAndroidComposeRule<MainActivity>()

    @Test
    fun loginComCredenciaisValidas_deveNavegar() {
        composeRule.apply {
            onNodeWithTag("email_field")
                .performTextInput("user@test.com")

            onNodeWithTag("password_field")
                .performTextInput("senha123")

            onNodeWithTag("login_button")
                .performClick()

            waitForIdle()

            onNodeWithTag("home_screen")
                .assertIsDisplayed()
        }
    }
}

Automacoes Avancadas

Publicacao Automatica de Releases

Quando voce cria uma tag, o workflow pode automaticamente:

// build.gradle.kts - Versao baseada em tags
val gitTag = System.getenv("GITHUB_REF_NAME") ?: "dev"

version = if (gitTag.startsWith("v")) {
    gitTag.removePrefix("v")
} else {
    "0.0.0-SNAPSHOT"
}

// Publicacao no Maven Central
publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["java"])
            groupId = "com.example"
            artifactId = "minha-biblioteca"
        }
    }
}

Deploy Automatico para Cloud

Workflows podem fazer deploy para diferentes provedores de cloud:

// Exemplo de configuracao para deploy em produtao
// Aplicacao Kotlin com Spring Boot

@Configuration
@Profile("production")
class ProductionConfig {
    @Bean
    fun corsConfig(): WebMvcConfigurer {
        return object : WebMvcConfigurer {
            override fun addCorsMappings(registry: CorsRegistry) {
                registry.addMapping("/api/**")
                    .allowedOrigins("https://meusite.com.br")
                    .allowedMethods("GET", "POST", "PUT", "DELETE")
                    .allowCredentials(true)
            }
        }
    }
}

// Health check para validacao pos-deploy
@RestController
class HealthController(
    private val dataSource: DataSource
) {
    @GetMapping("/health")
    fun health(): Map<String, Any> {
        val dbHealthy = try {
            dataSource.connection.use { it.isValid(5) }
        } catch (e: Exception) {
            false
        }

        return mapOf(
            "status" to if (dbHealthy) "UP" else "DOWN",
            "version" to (System.getenv("APP_VERSION") ?: "unknown"),
            "timestamp" to Instant.now().toString(),
            "checks" to mapOf(
                "database" to if (dbHealthy) "UP" else "DOWN"
            )
        )
    }
}

Dependabot para Atualizacoes

Configure Dependabot para manter dependencias atualizadas. A configuracao monitora atualizacoes de dependencias Gradle e GitHub Actions semanalmente, agrupando-as por tipo.

Workflow para Kotlin Multiplatform

Projetos KMP precisam de configuracao especifica:

// build.gradle.kts para KMP
kotlin {
    androidTarget()
    iosX64()
    iosArm64()
    iosSimulatorArm64()
    jvm()

    sourceSets {
        commonMain.dependencies {
            implementation("io.ktor:ktor-client-core:3.0.0")
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
            implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
        }
        commonTest.dependencies {
            implementation(kotlin("test"))
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
        }
    }
}

O workflow KMP roda testes em multiplas plataformas: JVM tests no Linux, iOS tests no macOS e Android tests no Linux.

Matrix Builds

Teste seu projeto Kotlin em multiplas versoes de JDK:

// Codigo que pode se comportar diferente entre JDKs
// Importante testar com matrix build

class DateTimeService {
    fun formatarData(instant: Instant): String {
        val formatter = DateTimeFormatter
            .ofPattern("dd/MM/yyyy HH:mm")
            .withZone(ZoneId.of("America/Sao_Paulo"))
        return formatter.format(instant)
    }

    fun parsearData(texto: String): Instant {
        val formatter = DateTimeFormatter
            .ofPattern("dd/MM/yyyy HH:mm")
            .withZone(ZoneId.of("America/Sao_Paulo"))
        return Instant.from(formatter.parse(texto))
    }
}

Uma strategy matrix com JDK 17, 21 e 23 garante compatibilidade.

Notificacoes e Badges

Configure notificacoes para falhas de pipeline:

  • Slack: Actions para enviar notificacoes em canais de time
  • Email: Notificacoes nativas do GitHub
  • Badge no README: Mostra o status do build no repositorio

Seguranca no CI

Protecao de Segredos

// NUNCA coloque segredos no codigo
// Use GitHub Secrets e acesse via variaveis de ambiente

@Configuration
class ExternalServiceConfig(
    @Value("\${API_KEY:default}") private val apiKey: String,
    @Value("\${API_SECRET:default}") private val apiSecret: String
) {
    @Bean
    fun externalClient(): ExternalClient {
        return ExternalClient.builder()
            .apiKey(apiKey)
            .apiSecret(apiSecret)
            .build()
    }
}

Scanning de Vulnerabilidades

GitHub oferece Dependabot alerts e code scanning que identificam vulnerabilidades em dependencias e no codigo. Habilite essas features para manter seu projeto seguro.

Otimizacao de Performance do CI

Dicas para pipelines mais rapidos:

  1. Use cache agressivamente: Gradle, dependencias Maven, imagens Docker
  2. Paralelismo: Execute jobs independentes em paralelo
  3. Skip desnecessario: Nao rode testes Android se so mudou codigo backend
  4. Runners self-hosted: Para projetos com muitos builds, considere runners proprios

Conclusao

GitHub Actions e uma ferramenta poderosa e flexivel para automatizar projetos Kotlin. De testes simples a pipelines complexos de deploy, a plataforma oferece tudo que voce precisa para manter a qualidade e a velocidade de entrega.

Comece com um workflow basico de build e testes, e evolua gradualmente adicionando analise estatica, cobertura de codigo, deploys automaticos e notificacoes. A automacao e um investimento que se paga exponencialmente ao longo do tempo, e GitHub Actions torna esse investimento acessivel para projetos de qualquer tamanho.