Skip to content

About

This repository is a minimal Kotlin Multiplatform sample for a portable mobile CI setup built with Amper, Fastlane, and GitHub Actions.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Portable KMP CI Sample

This repository is a minimal Kotlin Multiplatform sample for a portable mobile CI setup built with Kotlin Toolchain, Fastlane, GitHub Actions, and GitLab CI.

It is intentionally small:

  • android-app/
  • ios-app/
  • shared/
  • .github/workflows/mobile-ci.yml
  • .gitlab-ci.yml
  • fastlane/
  • scripts/ci/
  • scripts/regenerate_from_kotlin_toolchain.sh

The app itself started from:

kotlin init compose-multiplatform

and was then trimmed down to a mobile-only shape by removing the generated JVM module.

You can refresh the generated app layer in place with:

./scripts/regenerate_from_kotlin_toolchain.sh

That script deletes and recreates the Kotlin Toolchain-generated app layer:

  • kotlin
  • kotlin.bat
  • project.yaml
  • android-app/
  • ios-app/
  • shared/

while preserving the CI files and release helpers that belong to this sample.

Purpose

This sample is not trying to show app architecture. It exists to prove that the CI pattern is reproducible with a minimal Kotlin Multiplatform project.

For the longer explanation of the design, see docs/portable-kmp-ci.md.

The published documentation site is available at: https://mekate-studio.github.io/Portable-KMP-CI/

It exercises:

  • Android debug and release builds
  • Android tests
  • iOS debug and release builds
  • shared CI job dispatch
  • runtime secret materialization for release flows

It also shows the same repo-owned job contract through multiple CI adapters:

Local smoke test

Set a writable Kotlin Toolchain cache:

export KOTLIN_CLI_BOOTSTRAP_CACHE_DIR="$PWD/.kotlin-cli-cache"

Use JDK 21 for local runs. The GitHub Actions workflows in this repo also pin Temurin 21 because the current Kotlin Toolchain Android integration requires it.

Run the shared jobs:

./scripts/ci/run_job.sh android-build-debug
./scripts/ci/run_job.sh android-test
./scripts/ci/run_job.sh android-build-release
./scripts/ci/run_job.sh ios-build-debug

Those jobs run bundle install through the shared CI helper layer, so you do not need a separate manual Bundler step just to smoke-test the sample.

Run those smoke-test commands sequentially when using a single local checkout. In CI they run in separate jobs, but locally multiple first-run Kotlin Toolchain processes can contend with each other.

The iOS build jobs target a generic iOS Simulator destination and then force a single simulator architecture that matches the host machine. That avoids both a precreated device dependency and Kotlin Toolchain's current limitation around building multiple simulator architectures in one pass. The remaining host requirement is that Xcode has an iOS Simulator runtime installed.

On GitHub-hosted macOS images, Simulator runtime availability can still vary with runner image updates. If an iOS build fails because no iOS Simulator runtime is installed, the remaining fix is at the runner-image level: select an image/Xcode combination that includes a runtime, or install one explicitly.

Self-hosted GitHub Actions verification

If you want to verify the workflow using real GitHub Actions orchestration on your own Mac, this repo also includes:

That workflow is intended for a self-hosted macOS runner with the label:

  • kmp-sample

Recommended setup:

  1. Add your Mac as a self-hosted runner for this repository in GitHub.
  2. Give it the labels self-hosted, macOS, ARM64, and kmp-sample.
  3. Install JDK 21 on that Mac runner. The workflow pins Temurin 21, and the current Kotlin Toolchain Android integration expects a Java 21 runtime.
  4. Install a working host Ruby on that Mac runner, preferably via brew install ruby. The shared CI helper will install the Bundler version required by Gemfile.lock automatically. This sample's self-hosted workflow intentionally uses the machine's Ruby instead of ruby/setup-ruby, because ruby/setup-ruby expects the GitHub-hosted macOS toolcache layout under /Users/runner.
  5. Run the Mobile CI (Self-hosted) workflow manually from GitHub using workflow_dispatch.

For a public repository, keep this self-hosted workflow on manual dispatch only. That avoids exposing your machine to arbitrary fork pull requests.

GitLab CI parity

This repository also includes .gitlab-ci.yml as a thin GitLab adapter for the same shared job contract.

That file intentionally stays small: it defines stages, tags, and artifacts, then calls the same ./scripts/ci/run_job.sh ... entrypoint used by the GitHub workflows.

If you are copying this setup into GitLab, the main repo-owned logic does not change. The GitLab adapter only needs to express:

  • which runner tags should pick up a job
  • which stage a job belongs to
  • which artifacts should be preserved
  • which jobs are manual or default-branch-only

Shared CI job names

These are the portable job names used by the dispatcher:

  • android-build-debug
  • android-build-release
  • android-test
  • ios-build-debug
  • ios-build-release
  • ios-archive-release
  • ios-testflight
  • publish-internal
  • promote-alpha
  • promote-beta
  • promote-production

Required GitHub secrets for release flows

Android

  • GOOGLE_PLAY_JSON_KEY
  • ANDROID_KEYSTORE_FILE or ANDROID_KEYSTORE_BASE64
  • ANDROID_KEYSTORE_PASSWORD
  • ANDROID_KEY_ALIAS
  • ANDROID_KEY_PASSWORD
  • ANDROID_PACKAGE_NAME if you change the sample package name

To use real Play publishing, also enable the commented Android signing block in android-app/module.yaml.

iOS

  • IOS_BUNDLE_IDENTIFIER
  • IOS_DEVELOPMENT_TEAM
  • IOS_PROVISIONING_PROFILE_SPECIFIER
  • APP_STORE_CONNECT_KEY_ID
  • APP_STORE_CONNECT_ISSUER_ID
  • APP_STORE_CONNECT_API_KEY_FILE or APP_STORE_CONNECT_API_KEY_BASE64

Important: the Apple signing certificate and provisioning profile still need to exist on the macOS runner host.

License

MIT

About

This repository is a minimal Kotlin Multiplatform sample for a portable mobile CI setup built with Amper, Fastlane, and GitHub Actions.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages