CI, публикация и сборка под обе платформы
KMP-проект собирается под несколько ОС, и CI это диктует: что можно на Linux, а что только на macOS.
CI для KMP — конвейер, который собирает и тестирует общий модуль под все цели; сборка и тесты iOS требуют раннера на macOS.
Главное ограничение CI
Kotlin/Native под iOS компилируется только на macOS — нужны Xcode и Apple-тулчейн. Поэтому CI обычно делят: Android-сборку и общие JVM-тесты гоняют на дешёвых Linux-раннерах, а iOS-сборку и iOS-тесты — на macOS-раннерах. Это влияет на стоимость и время пайплайна.
jobs:
android:
runs-on: ubuntu-latest
steps:
- run: ./gradlew :shared:testDebugUnitTest assembleDebug
ios:
runs-on: macos-latest
steps:
- run: ./gradlew :shared:iosSimulatorArm64TestКэширование Gradle и Konan
Сборки KMP небыстрые: Kotlin/Native тянет зависимости тулчейна (Konan). На CI обязательно кэшируйте ~/.gradle и ~/.konan, иначе каждый запуск будет качать тулчейн заново. Это одна из самых частых причин медленных пайплайнов.
Публикация общего модуля
Если iOS-команда работает в отдельном репозитории, общий модуль публикуют как артефакт: для Android — в Maven-репозиторий (обычный AAR/JAR с метаданными KMP), для iOS — как XCFramework через Swift Package Manager или CocoaPods. Тогда iOS-разработчику не нужен Kotlin-тулчейн локально — он тянет готовый бинарник.
Как работает под капотом
При публикации Gradle с плагином Kotlin Multiplatform выкладывает несколько артефактов под общими координатами: корневой модуль с метаданными плюс по варианту на каждую цель. Когда потребитель добавляет зависимость, Gradle по метаданным выбирает нужный вариант под его платформу. Для iOS-стороны XCFramework публикуется отдельно, так как Swift Package Manager/CocoaPods не понимают Gradle-метаданные — им нужен готовый фреймворк. Поэтому iOS-публикация — это отдельный шаг пайплайна, собирающий и выкладывающий XCFramework.
Частые ошибки
Пытаться собрать iOS на Linux-раннере — не выйдет, нужен macOS. Вторая ошибка — не кэшировать Konan и тулчейн, получая многоминутные сборки. Третья — публиковать только Android-артефакт и забыть XCFramework, после чего iOS-команда не может подключить обновление. Четвёртая — не закрепить версии Xcode/Kotlin на CI, ловя «работает локально, падает на CI».
Итоги
- iOS-сборка и тесты требуют macOS-раннеров; Android можно на Linux.
- Кэшируйте Gradle и Konan, иначе пайплайн будет долгим.
- Общий модуль публикуют как Maven-артефакт (Android) и XCFramework (iOS).
- Gradle-метаданные выбирают вариант под платформу; iOS-фреймворк публикуется отдельно.