Photo by SpaceX on Unsplash

Fastlane + KMM: The Ultimate CI/CD Combo for Cross-Platform Success

Jakub Pruszyński

--

Sample repo: https://github.com/qbit-me/kmm_fastlane

As an Android developer, I’ve always been intrigued by the possibilities of expanding my skills beyond a single platform. Kotlin Multiplatform Mobile (KMM) has emerged as an exciting direction for us to explore and experiment with other platforms while leveraging our existing Kotlin expertise.

In any software project, continuous integration and continuous delivery (CI/CD) play a crucial role, especially in commercial production environments. This becomes even more critical when a technology like KMM is marked as stable, opening doors for wider adoption. The importance of efficient CI/CD cannot be overstated, particularly in the fast-paced world of startups where time-to-market can make or break a product.

Throughout my career, I’ve often found myself setting up CI/CD pipelines manually, relying on custom scripts and direct Gradle commands. While this approach works, it’s time-consuming and prone to errors. However, a game-changer entered the scene when I encountered Fastlane in one of my projects. This tool simplified the entire CI/CD process, making it more manageable and less error-prone.

fastlane is a powerful automation tool designed for simplifying the deployment and release processes of iOS and Android applications. It automates tedious tasks such as generating screenshots, managing code signing, and releasing apps to various platforms. Docs: https://docs.fastlane.tools/

Naturally, when I started exploring KMM and its potential applications in various aspects of production, my mind immediately turned to Fastlane. The combination of KMM’s cross-platform capabilities and Fastlane’s streamlined CI/CD processes seemed like a perfect match, especially for teams looking to maximize efficiency and minimize time-to-market.

In this post, we’ll dive into how to set up Fastlane in a KMM project, using a simple GitHub repository as our guide. Whether you’re an Android developer looking to expand your horizons, or a team lead considering KMM for your next project, this step-by-step walkthrough will show you how to establish a robust, yet surprisingly simple, CI/CD pipeline for your cross-platform mobile applications.

Project structure

project_root
/ composeApp <-- code source for Android and kotlin code
/ iosApp <-- code source for iOS
/ ... other files

Getting Started with Fastlane in KMM

Before we jump into the specifics of our GitHub repository, let’s go through the initial steps to set up Fastlane in a KMM project. This process is surprisingly straightforward and can be done in just a few steps.

Prerequisites

Before we begin, ensure you have the following:

  1. A KMM project set up (we’ll be using a basic one in our example)
  2. Ruby installed on your system (Fastlane is a Ruby gem)
  3. Xcode command line tools (for iOS)
  4. Android SDK (for Android)

🚫 If you use macOS, system Ruby is not recommended

Installing Fastlane

First, we need to install Fastlane. Open your terminal and run:

sudo gem install fastlane

More details you can find at this page https://docs.fastlane.tools/.

Initializing Fastlane in Your Project

Now, navigate to your KMM project’s root directory in the terminal. We’ll need to initialize Fastlane for both Android and iOS:

For Android:

cd project_root/composeApp
fastlane init

For iOS:

cd project_root/iosApp
fastlane init

During the initialization, Fastlane will ask you a series of questions. For our simple setup, we can choose the basic options, but feel free to customize based on your project’s needs.

Directory Structure

After initialization, you should see a new fastlane directory in both your Android and iOS project folders. Each will contain two important files:

  1. Fastfile: This is where we define our lanes (automation tasks).
  2. Appfile: This stores app-specific information like bundle ID and Apple ID.

In our next section, we’ll examine the specific Fastlane configuration in our example GitHub repository, which will give you a clear picture of how to set up your lanes for both platforms.

Remember, the beauty of this setup is its simplicity. With just these few steps, we’ve laid the groundwork for a powerful CI/CD pipeline that can handle both the Android and iOS sides of our KMM project

Setup lanes

👉🏻 List of all out-of-box actions https://docs.fastlane.tools/actions/

First, let’s open the fastlane/Fastfile in your Android project directory. We'll define several lanes to handle common Android CI/CD tasks:

default_platform(:android)

platform :android do
desc "Runs all the tests except iOS"
lane :test do
gradle(
task: "test",
gradle_path: "../gradlew"
)
end
end

🔑 It’s super important to set gradle_path as the fastlane files is nested inside composeApp directory

Now, go to the fastlane/Fastfile in your iOS project directory and add the following sample lane:

default_platform(:ios)

platform :ios do
desc "It runs unit tests on iPhone 15 Plus simulator"
lane :test do
run_tests(
project: "iosApp.xcodeproj",
scheme: "kmm_fastlaneTests",
sdk: "iphonesimulator",
devices: ["iPhone 15 Plus"],
derived_data_path: "build",
)
end
end

Testing lanes locally

To test these lanes locally, you can run commands from composeApp or iosApp directory in your command line:

fastlane lane_name

Sample Github Actions configuration

Excellent, let’s create a GitHub Actions workflow that integrates our Fastlane setup for both Android and iOS. We’ll create a .github/workflows/ci.yml file in your repository root. Here's a setup that covers both platforms:

name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
android:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
working-directory: 'composeApp'
- name: Run Android tests
uses: maierj/fastlane-action@v3.1.0
with:
lane: 'test'
subdirectory: 'composeApp'
ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
working-directory: 'iosApp'
- name: Run iOS tests
uses: maierj/fastlane-action@v3.1.0
with:
lane: 'test'
subdirectory: 'iosApp'

Let’s break down this workflow:

  1. We trigger the workflow on pushes to the main branch and for all pull requests targeting main.
  2. We define two separate jobs: one for Android and one for iOS. In both cases we use macos-latest for simiplicity.
  3. For each job:.
    - We check out the code using actions/checkout@v3.
    - We set up Ruby using ruby/setup-ruby@v1, which also handles bundler caching.
    - We run the test lane using the maierjfastlane-action.
  4. We use the subdirectory parameter in the Fastlane action to specify where the Fastlane files are located for each platform.

This setup will run your Android and iOS tests in parallel whenever you push to main or open a pull request.

You can extend this workflow by adding more lanes.

👉🏻 More about maierjfastlane-action under https://github.com/marketplace/actions/fastlane-action

Benefits and Use cases

  • Streamlined Cross-Platform CI/CD - Fastlane + KMM creates a unified pipeline for both Android and iOS, significantly reducing the complexity of managing separate build processes. This streamlined approach is particularly valuable for small teams or startups where resources are limited. With a single configuration, you can automate testing, building, and deployment for both platforms, ensuring consistency and saving valuable development time.
  • Accelerated Time-to-Market- By automating repetitive tasks like building, testing, and deploying, this setup dramatically speeds up the release cycle. For KMM projects, where you’re already saving time by sharing code between platforms, adding Fastlane further accelerates development. This is crucial for businesses that need to rapidly iterate on their mobile applications or respond quickly to market demands, giving them a competitive edge in fast-paced industries.
  • Improved Code Quality and Reliability - Integrating Fastlane in your KMM project enforces consistent testing and build processes across both platforms. This setup makes it easier to implement practices like continuous integration, where every code change triggers automated tests. As a result, bugs are caught earlier, and the overall quality of your cross-platform app improves. This is especially beneficial for projects with complex requirements or those in regulated industries where reliability is paramount.

Conclusion

Integrating Fastlane with Kotlin Multiplatform Mobile (KMM) represents a powerful step forward in cross-platform mobile development. Through this article, we’ve explored how to set up a streamlined CI/CD pipeline that handles both Android and iOS builds within a single KMM project. By leveraging Fastlane’s automation capabilities alongside KMM’s code-sharing benefits, we’ve created a workflow that not only saves time but also improves code quality and accelerates time-to-market. This combination is particularly potent for teams looking to maximize efficiency in their mobile development process.

The step-by-step guide we’ve provided, from initial setup to GitHub Actions integration, offers a clear path for implementing this solution in your own projects. Whether you’re a seasoned mobile developer or just starting with cross-platform development, this approach provides a solid foundation for building and deploying high-quality mobile applications. As the mobile development landscape continues to evolve, tools like Fastlane and frameworks like KMM will play an increasingly crucial role in helping developers meet the demands of rapid development cycles and multi-platform deployment. By adopting this setup, you’re not just optimizing your current workflow — you’re future-proofing your development process.

I encourage you to try this Fastlane + KMM setup in your next project. Experience firsthand how it can transform your mobile development workflow, and don’t hesitate to expand upon this foundation to suit your specific needs. The world of cross-platform mobile development is full of possibilities, and with tools like these at your disposal, you’re well-equipped to explore them.

--

--

Jakub Pruszyński
Jakub Pruszyński

Written by Jakub Pruszyński

senior android developer, reading & learning enthusiast

Responses (1)