CI/CD для Kotlin проектов с GitHub Actions: пошаговое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему CI/CD незаменим для Kotlin-разработки

Современная разработка на Kotlin — это не только написание лаконичного и безопасного кода, но и обеспечение его непрерывной поставки. Будь вы создаете серверное приложение на Ktor, Android-приложение или мультиплатформенный проект, ручные сборки и тестирование быстро становятся узким местом. CI/CD (Continuous Integration / Continuous Deployment) автоматизирует эти процессы, снижая риск человеческой ошибки и ускоряя выход новых фич.

GitHub Actions — один из самых популярных инструментов для реализации CI/CD, особенно если ваш код уже хранится на GitHub. Он тесно интегрируется с экосистемой Kotlin, поддерживает Gradle и Maven, а также позволяет гибко настраивать пайплайны под любые нужды. В этой статье мы разберем, как настроить полный цикл сборки, тестирования и деплоя для Kotlin-проекта с помощью GitHub Actions.

Основы GitHub Actions: Структура workflow

Прежде чем писать код, разберемся с базовыми понятиями. Workflow (рабочий процесс) в GitHub Actions — это автоматизированный процесс, который запускается по определенному событию (например, push в ветку main). Workflow описывается в YAML-файле, который хранится в директории .github/workflows/ вашего репозитория.

Типичная структура workflow включает:

  • name — название workflow (отображается в интерфейсе GitHub).
  • on — триггеры запуска (например, push, pull_request).
  • jobs — набор задач, которые выполняются последовательно или параллельно.
  • steps — шаги внутри job (установка JDK, кэширование зависимостей, запуск тестов).

Для Kotlin-проектов ключевым шагом является настройка правильной версии JDK (обычно 11, 17 или 21) и использование Gradle Wrapper (./gradlew), который гарантирует воспроизводимость сборки на любой машине.

Шаг 1: Базовая сборка и тестирование Kotlin-проекта

Начнем с самого простого: workflow, который будет запускать тесты при каждом push в main или при создании Pull Request. Это основа любого CI/CD — гарантировать, что код не сломал существующую функциональность.

Создайте файл .github/workflows/ci.yml со следующим содержимым:

name: CI for Kotlin

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Cache Gradle packages
        uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      - name: Build with Gradle
        run: ./gradlew build

      - name: Run tests
        run: ./gradlew test

Разберем ключевые моменты:

  • actions/checkout@v4 — клонирует репозиторий в runner.
  • actions/setup-java@v4 — устанавливает JDK 17 (Temurin). Вы можете выбрать другую версию, если ваш проект требует, например, JDK 11 или 21.
  • actions/cache@v4 — кэширует зависимости Gradle. Это критически важно для скорости: без кэша каждая сборка будет скачивать все библиотеки заново (может занимать 2-5 минут). Кэш ускоряет этот процесс до нескольких секунд.
  • ./gradlew build — полная сборка проекта (компиляция + тесты). Если вы хотите только тесты, используйте ./gradlew test.

После пуша этого файла в репозиторий, GitHub автоматически запустит workflow. Вы увидите зеленую галочку рядом с коммитом, если все тесты прошли успешно.

Шаг 2: Продвинутая настройка: многомодульные проекты и линтеры

Реальные Kotlin-проекты часто состоят из нескольких модулей (например, :core, :server, :shared). В таких случаях важно контролировать, какие модули были изменены, чтобы не запускать полную сборку без необходимости. GitHub Actions поддерживает стратегию matrix и условные шаги.

Пример для многомодульного проекта с линтером detekt:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Run detekt
        run: ./gradlew detekt

  test:
    runs-on: ubuntu-latest
    needs: lint  # Запускается только после успешного линтинга
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Cache Gradle
        uses: actions/cache@v4
        with:
          path: ~/.gradle/caches
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
      - name: Run tests for all modules
        run: ./gradlew test

Здесь мы разделили задачи на lint и test. Задача test использует needs: lint, что означает: она запустится только если линтер прошел успешно. Это экономит время, так как не нужно ждать тестов, если код стилистически некорректен.

Для условного запуска только измененных модулей можно использовать paths-filter action, но для простоты часто ограничиваются полной сборкой — она все равно занимает не более 5-7 минут для среднего проекта.

Шаг 3: Автоматический деплой (CD) для Kotlin-приложений

После того как тесты прошли, следующий логичный шаг — деплой. Рассмотрим два популярных сценария

Блоги

Рекомендаций по книгам