GuidesOctober 15, 2025
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
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.

TL;DR: Automate Your Kotlin Multiplatform Releases
Building and publishing a mobile app should not be a manual chore. Yet, many Kotlin Multiplatform developers still spend hours exporting
.ipa
files or signing Android bundles locally before every release.This guide shows you how to make CI/CD for Kotlin Multiplatform apps simple, secure, and repeatable using:
- GitHub Actions for automated workflows
- Fastlane for iOS deployment automation
- Secure code signing for both Android and iOS
- One-click releases to Google Play and App Store Connect
The verdict: With proper CI/CD setup, shipping updates becomes a single command or button click, freeing you to focus on building features instead of pipeline maintenance.
Why CI/CD matters in Kotlin Multiplatform projects
In 2025, Kotlin Multiplatform has matured enough to let you ship truly production-ready Android and iOS apps from a single codebase. But with great power comes complexity:
- 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)
CI/CD is the glue that keeps both worlds aligned.
KMPShip automates this entire process. It ships with preconfigured pipelines that:
✅ 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
✅ 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
Let’s see how it works.
Android CI/CD setup
KMPShip’s Android workflow is powered by Gradle and GitHub Actions. The first step is to create a secure keystore for signing your app.
Step 1: Generate and encode your keystore
Inside Android Studio:
bashBuild > Generate Signed Bundle / APK > Create new
Save it under:
androidApp/config/keystore/my_app.keystore
Then encode it for GitHub Actions:
bashbase64 -i androidApp/config/keystore/my_app.keystore | pbcopy
Store it as a secret:
ANDROID_KEYSTORE_RELEASE_B64
Add the other signing credentials:
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
Finally, set your Java version for CI:
JAVA_JDK_VERSION = 21
Your app is now ready for one-click publishing from CI:
bash./gradlew :androidApp:publishReleaseBundle
iOS CI/CD setup
On iOS, KMPShip uses Fastlane to automate builds, signing, and uploads to App Store Connect.
Step 1: Create an App Store Connect API Key
In App Store Connect → Users and Access → Keys tab:
- Generate an API key with the App Manager role.
- Download the
.p8
file. - 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
Use Keychain Access to generate a CSR and export a
.p12
file. Encode it:bashbase64 -i YourCertificate.p12 | pbcopy
Add to GitHub Secrets:
IOS_APP_CERTIFICATE_P12_B64
IOS_APP_CERTIFICATE_P12_PASSWORD
Step 3: Add your provisioning profile
Generate an App Store provisioning profile in the Apple Developer Portal and encode it:
bashbase64 -i MyApp_AppStore_Profile.mobileprovision | pbcopy
Store as:
IOS_PROVISIONING_PROFILE_B64
IOS_PROVISIONING_PROFILE_NAME
Add your Xcode version to CI:
XCODE_VERSION = 16.2
You can now publish directly via Fastlane:
bashcd iosApp fastlane release
GitHub Actions: the unified pipeline
Both Android and iOS pipelines run through GitHub Actions.
Each time you tag a new version or trigger a workflow manually, GitHub spins up runners that:
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
Your releases are consistent, automated, and reproducible, whether you are a solo developer or part of a small team.
Local publishing (optional)
If you prefer manual control or want to test a release locally before pushing to CI, KMPShip supports that too:
bash# Android ./gradlew :androidApp:publishReleaseBundle # iOS cd iosApp fastlane release
Secure by design
Every secret in KMPShip’s CI setup is:
- Base64-encoded to prevent file corruption
- Stored as GitHub Secrets, never committed to Git
- Loaded only at runtime in the workflow environment
This keeps your certificates and keys safe while allowing fully automated delivery.
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
✅ 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
Once everything is configured, shipping updates becomes a single command or button click.
Why this matters for developers
Setting up CI/CD for a multiplatform project used to take days, juggling different build systems, credentials, and YAML pipelines.
KMPShip ships with everything preconfigured, so you can focus on building features, not pipeline maintenance.
KMPShip ships with everything preconfigured, so you can focus on building features, not pipeline maintenance.
And because it is built with GitHub Actions and Fastlane, it is fully transparent and extensible. You can add steps for:
- Unit tests and linting
- Firebase App Distribution or TestFlight
- Crashlytics symbol upload
- Automated changelog generation
It is production-ready from day one.
FAQ
Q: Can I use Bitrise or CircleCI instead of GitHub Actions?
Yes. KMPShip’s structure is portable. You can adapt the same Fastlane lanes and Gradle tasks for other CI providers.
Yes. KMPShip’s structure is portable. You can adapt the same Fastlane lanes and Gradle tasks for other CI providers.
Q: What if my iOS build fails due to provisioning?
Double-check that your
Double-check that your
.mobileprovision
file matches your app’s bundle ID and certificate. If needed, regenerate both from Apple Developer Portal.Q: Can I trigger builds only on tagged commits?
Yes. The default workflow triggers on tags, ensuring that only versioned builds get deployed.
Yes. The default workflow triggers on tags, ensuring that only versioned builds get deployed.
Q: Does this work for internal testing tracks?
Yes. You can modify the Play Console track (for example,
Yes. You can modify the Play Console track (for example,
internal
, beta
, or production
) directly in the workflow file.Ready to ship faster?
CI/CD should not feel like DevOps homework.
With KMPShip, you get ready-to-use pipelines, secure signing, and reproducible releases for both platforms from the start.
If you have ever dreaded uploading a new version to the stores, it is time to automate it.
Set it up once, then ship your next release with confidence.
KMPShip provides a production-ready foundation with CI/CD already configured, plus authentication, payments, notifications, and deployment pipelines. Skip the setup complexity and start shipping your app today.