Введение: Почему CI/CD критически важен для Kotlin проектов
В современной разработке на Kotlin, будь то бэкенд на Ktor, Android-приложение или мультиплатформенный проект, ручное выполнение однотипных операций (сборка, прогон тестов, проверка стиля кода) — это не только потеря времени, но и источник ошибок. CI/CD (Continuous Integration / Continuous Deployment) решает эту проблему, автоматизируя весь конвейер от коммита до продакшена.
GitHub Actions — это встроенный инструмент автоматизации, который идеально подходит для Kotlin проектов. Он позволяет создавать пайплайны прямо в репозитории, не требуя сторонних сервисов. В этой статье мы разберем, как настроить полноценный CI/CD для Kotlin с использованием GitHub Actions, от базовой сборки до деплоя.
1. Основы GitHub Actions и Kotlin
GitHub Actions работает на основе воркфлоу (workflow) — YAML-файлов, которые определяют последовательность шагов. Каждый воркфлоу запускается по триггеру (push, pull request, schedule) и выполняется в виртуальной среде runner.
Для Kotlin проектов стандартный стек включает:
- Gradle или Maven — система сборки;
- JUnit / Kotest — фреймворки тестирования;
- Detekt / ktlint — линтеры для Kotlin.
Первый шаг — создание файла .github/workflows/ci.yml в корне репозитория. Рассмотрим минимальную конфигурацию для сборки и тестирования.
1.1 Базовая сборка и тестирование
Начнем с простого пайплайна, который срабатывает на каждый push и pull request в main ветку:
name: CI for Kotlin
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test
Этот код делает следующее: клонирует репозиторий, устанавливает JDK 17 (рекомендуемая версия для Kotlin 1.9+), делает gradlew исполняемым, выполняет сборку и запускает тесты. Если тесты падают — пайплайн останавливается с ошибкой.
2. Расширенная конфигурация: линтинг, кэширование и матрица сборок
Базовая настройка — это хорошо, но для реального проекта нужно больше. Добавим проверку стиля кода с помощью Detekt и кэширование зависимостей Gradle для ускорения работы.
2.1 Кэширование Gradle
Без кэширования каждый запуск скачивает зависимости заново, что может занимать 2-5 минут. Используем встроенное кэширование:
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
2.2 Линтинг с Detekt
Добавим задачу для проверки кода. Detekt можно запускать через Gradle plugin:
- name: Run Detekt
run: ./gradlew detekt
Если Detekt находит нарушения — пайплайн завершится с ошибкой. Это гарантирует, что в репозиторий не попадет "грязный" код.
2.3 Матрица сборок (Matrix Build)
Если ваш проект поддерживает несколько версий Kotlin или JDK, используйте матрицу. Это позволяет проверить совместимость без дублирования кода:
jobs:
build:
strategy:
matrix:
java: [11, 17, 21]
kotlin: [1.9.0, 2.0.0]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: 'temurin'
- name: Build with Gradle
run: ./gradlew build -PkotlinVersion=${{ matrix.kotlin }}
Такой подход выявляет ошибки совместимости до того, как они попадут в продакшен.
3. Деплой Kotlin приложения (Continuous Deployment)
После успешной сборки и тестирования логично автоматизировать деплой. Рассмотрим два популярных сценария: публикация библиотеки в Maven Central и деплой веб-сервиса на сервер.
3.1 Публикация в Maven Central
Для открытых Kotlin библиотек часто требуется автоматическая публикация при создании релиза. Используем Gradle плагин maven-publish и GitHub Actions:
name: Publish to Maven Central
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Publish package
run: ./gradlew publish
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }}
Важно: все чувствительные данные (ключи подписи, пароли) храним в GitHub Secrets (Settings → Secrets and variables → Actions).
3.2 Деплой веб-приложения на Ktor
Для веб-сервиса на Ktor можно использовать деплой на VPS через SSH или на облачные платформы (Heroku, Railway). Пример деплоя через SSH с использованием scp и запуском systemd:
name: Deploy Ktor App
on:
push:
branches: [