Back to Journal
Development
May 18, 2026
15 min read

CI/CD Tutorial: Fastlane + GitHub Actions for Flutter Android

A
Arumi Dev Team
Flutter Developers
CI/CD Tutorial: Fastlane + GitHub Actions for Flutter Android

Overview

The pipeline does the following on every manual trigger:

  1. Decodes secrets (keystore, service account) from GitHub Secrets
  2. Sets up Java, Flutter, and Ruby environments
  3. Runs Fastlane to auto-increment the build number, build the AAB + APK, and upload to Play Store (internal track)
  4. Uploads artifacts to GitHub Actions
  5. Creates a GitHub Release with the AAB and APK attached

Prerequisites

  • A Flutter Android project
  • A Google Play Console account with your app created (at least one manual upload done)
  • A Google Cloud Platform (GCP) project
  • A signing keystore for your Android app
  • Ruby installed locally (for running fastlane init)

Step 1: Create a Keystore for App Signing

If you don't already have a keystore, generate one:

keytool -genkey -v -keystore release-keystore.jks -alias your-key-alias -keyalg RSA -keysize 2048 -validity 10000

Keep note of:

  • storePassword — the keystore password
  • keyPassword — the key password
  • keyAlias — the alias you chose

Do not commit the .jks file. Add it to .gitignore.

Step 2: Configure key.properties in Android

Create android/key.properties (also add to .gitignore):

storePassword=YOUR_STORE_PASSWORD keyPassword=YOUR_KEY_PASSWORD keyAlias=YOUR_KEY_ALIAS storeFile=release-keystore.jks

In android/app/build.gradle.kts, load and use this file for signing:

val keystorePropertiesFile = rootProject.file("key.properties") val keystoreProperties = Properties() if (keystorePropertiesFile.exists()) { keystoreProperties.load(FileInputStream(keystorePropertiesFile)) }

signingConfigs { create("release") { keyAlias = keystoreProperties.getProperty("keyAlias") keyPassword = keystoreProperties.getProperty("keyPassword") storeFile = keystoreProperties.getProperty("storeFile")?.let { file(it) } storePassword = keystoreProperties.getProperty("storePassword") } }

buildTypes { release { signingConfig = signingConfigs.getByName("release") } }

Step 3: Set Up GCP Service Account

Fastlane uses a Google Play API service account to upload builds.

  1. Go to Google Cloud Console
  2. Create a new project (or use an existing one)
  3. Enable the Google Play Android Developer API
  4. Go to IAM & Admin → Service Accounts → Create Service Account
  5. Give it a name (e.g., fastlane-cicd)
  6. Grant it no roles at the project level
  7. Create and download a JSON key for this service account

Grant Access in Play Console

  1. Open Google Play Console
  2. Go to Setup → API access
  3. Link to the GCP project you created
  4. Find your service account, click Grant Access
  5. Assign the Release Manager role

Step 4: Initialize Fastlane

From the android/ directory:

cd android fastlane init

When prompted, choose Google Play as the deployment target and provide your package name.

This generates:

  • android/Gemfile
  • android/fastlane/Appfile
  • android/fastlane/Fastfile

Step 5: Configure Fastlane Files

android/Gemfile

source "https://rubygems.org" gem "fastlane"

android/fastlane/Appfile

json_key_file("~/fastlane/service_account.json") package_name("com.example.yourapp")

android/fastlane/Fastfile

Fastlane automatically:

  • Fetches the highest version code across all tracks
  • Increments build number automatically
  • Builds APK and AAB files
  • Uploads to internal testing track
  • Writes build_number.txt for GitHub Releases

Key points:

  • No manual version bumping needed
  • Internal track upload by default
  • Faster uploads by skipping metadata/images/screenshots

Step 6: Add GitHub Secrets

Go to GitHub → Settings → Secrets and variables → Actions.

Add:

  • ANDROID_KEYSTORE
  • SERVICE_ACCOUNT
  • KEYSTORE_PASSWORD
  • KEY_PASSWORD
  • KEY_ALIAS

Use Base64 encoding for keystore and service account files.

Step 7: GitHub Actions Workflow

Create .github/workflows/deploy_android.yml.

The workflow:

  • Checks out repository
  • Sets up Java, Flutter, and Ruby
  • Decodes secrets
  • Runs Fastlane deploy
  • Uploads APK/AAB artifacts
  • Creates GitHub Release automatically

Notable Decisions

  • workflow_dispatch allows manual release triggering
  • continue-on-error keeps artifact upload running even if Play Store upload fails
  • permissions: contents: write is required for GitHub Releases
  • working-directory: android ensures Fastlane runs correctly

File Structure Summary

project-root/ ├── .github/ │ └── workflows/ │ └── deploy_android.yml ├── android/ │ ├── Gemfile │ ├── Gemfile.lock │ ├── key.properties │ ├── app/ │ │ ├── build.gradle.kts │ │ └── release-keystore.jks │ └── fastlane/ │ ├── Appfile │ └── Fastfile └── pubspec.yaml

Triggering a Release

  1. Go to GitHub Actions
  2. Select Deploy Flutter Android
  3. Click Run workflow

The pipeline will:

  • Auto-detect next versionCode
  • Build APK and AAB
  • Upload to Play Store internal track
  • Create GitHub Release

Supply (upload_to_play_store) Reference

Available tracks:

  • internal
  • alpha
  • beta
  • production

Key parameters:

  • track
  • aab
  • rollout
  • release_status
  • track_promote_to

Fastlane also supports:

  • Gradual rollouts
  • Track promotion
  • Metadata downloads
  • Screenshot management

Important: First Upload Must Be Manual

The Play Store API cannot push to an app that has never had a build uploaded manually through Play Console.

Common Issues

Google Api Error

Only releases with status draft may be created on draft app.

Solution: Complete at least one manual Play Store upload first.

Version code already exists

Re-run the workflow to get a fresh build number.

base64: invalid input

Encode files without line breaks:

  • Linux: base64 -w 0 file
  • macOS: base64 -i file

Pro-Tip: Optimize App Store Screenshots and Assets with DocShrink

When deploying to the Google Play Store, minimizing your app size is crucial for download conversion. You can compress your app's image assets and screenshots using DocShrink's AI Photo Compressor by up to 90% without any visible quality loss. If you're building products that require transparent background product images or clean App Store screenshots, check out DocShrink's AI Background Remover to remove backgrounds instantly right in your browser.

Conclusion

Using Fastlane with GitHub Actions creates a powerful CI/CD pipeline for Flutter Android apps. It automates versioning, building, Play Store deployment, artifact uploads, and GitHub Releases while reducing manual work and deployment errors.

#Flutter#CI/CD#Fastlane#GitHub Actions#Android#DevOps