CI/CD for Kotlin Multiplatform in 2025: GitHub Actions + Fastlane + Code Signing the sane way
Step-by-step guide to automate Android and iOS releases in a Kotlin Multiplatform app using GitHub Actions, Fastlane, and secure code signing.
Posted by
Related reading
Compose Multiplatform design system guide 2026
Learn how to create a robust Compose Multiplatform design system for seamless cross-platform UI components in 2026.
Migrate Android app to Kotlin Multiplatform: A guide for 2026
Learn how to migrate your Android app to Kotlin Multiplatform, focusing on incremental adoption and shared modules for iOS integration.
Building a Revenue-Generating Mobile App: Complete KMP Monetization Guide 2025
Master mobile app monetization with Kotlin Multiplatform. Learn proven revenue strategies, implementation techniques, and why 95% of apps fail to reach $1,000 monthly revenue. Includes real code examples and cost-benefit analysis.

Why CI/CD matters in Kotlin Multiplatform projects
- Two different signing systems (keystore vs certificate and provisioning profile)
- Different build tools (Gradle vs Xcode)
- Different store APIs (Google Play vs App Store Connect)
- ✅ Build your app for Android and iOS
- ✅ Sign it securely using GitHub secrets
- ✅ Upload new versions to Google Play and App Store Connect
- ✅ Let you trigger releases directly from GitHub
Android CI/CD setup
Step 1: Generate and encode your keystore
bashBuild > Generate Signed Bundle / APK > Create new
androidApp/config/keystore/my_app.keystore
bashbase64 -i androidApp/config/keystore/my_app.keystore | pbcopy
ANDROID_KEYSTORE_RELEASE_B64
ANDROID_KEY_ALIAS_RELEASE
ANDROID_KEY_PASSWORD_RELEASE
ANDROID_STORE_PASSWORD_RELEASE
Step 2: Connect to Google Play
- Create a Service Account in Google Cloud and link it to your Play Console.
- Download the JSON key and encode it:
bash
base64 -i androidApp/google-play-uploader.json | pbcopy - Add it to GitHub Secrets:
GOOGLE_PLAY_UPLOADER_JSON_KEY_B64
JAVA_JDK_VERSION = 21
bash./gradlew :androidApp:publishReleaseBundle
iOS CI/CD setup
Step 1: Create an App Store Connect API Key
- Generate an API key with the App Manager role.
- Download the
.p8file. - Encode it and store as secrets:
APP_STORE_API_KEY_BASE64 APP_STORE_ISSUER_ID APP_STORE_KEY_ID
Step 2: Create a Distribution Certificate
.p12 file. Encode it:bashbase64 -i YourCertificate.p12 | pbcopy
IOS_APP_CERTIFICATE_P12_B64
IOS_APP_CERTIFICATE_P12_PASSWORD
Step 3: Add your provisioning profile
bashbase64 -i MyApp_AppStore_Profile.mobileprovision | pbcopy
IOS_PROVISIONING_PROFILE_B64
IOS_PROVISIONING_PROFILE_NAME
XCODE_VERSION = 16.2
bashcd iosApp fastlane release
GitHub Actions: the unified pipeline
Each time you tag a new version or trigger a workflow manually, GitHub spins up runners that:
- Install JDK and Xcode
- Build both targets
- Use secrets to sign artifacts
- Upload the final builds to their respective stores
Local publishing (optional)
bash# Android ./gradlew :androidApp:publishReleaseBundle # iOS cd iosApp fastlane release
Secure by design
- Base64-encoded to prevent file corruption
- Stored as GitHub Secrets, never committed to Git
- Loaded only at runtime in the workflow environment
Quick checklist
- ✅ Android keystore encoded and stored in GitHub Secrets
- ✅ Google Play service account JSON added
- ✅ iOS App Store API key configured
- ✅ Distribution certificate and provisioning profile encoded
- ✅ Java and Xcode versions defined as repository variables
- ✅ GitHub Actions workflow triggered on push or tag
Why this matters for developers
KMPShip ships with everything preconfigured, so you can focus on building features, not pipeline maintenance.
- Unit tests and linting
- Firebase App Distribution or TestFlight
- Crashlytics symbol upload
- Automated changelog generation
FAQ
Yes. KMPShip’s structure is portable. You can adapt the same Fastlane lanes and Gradle tasks for other CI providers.
Double-check that your
.mobileprovision file matches your app’s bundle ID and certificate. If needed, regenerate both from Apple Developer Portal.Yes. The default workflow triggers on tags, ensuring that only versioned builds get deployed.
internal, beta, or production) directly in the workflow file.Ready to ship faster?
Build your KMP app faster
Skip the setup and start shipping with a production-ready Kotlin Multiplatform starter kit.