Home
Dart
OOP
Flutter
Contact

CI/CD & Deployment — Automated Flutter Pipelines

Automate testing, building, and releasing your Flutter apps with industry-standard CI/CD tools.

Why CI/CD?

Continuous Integration (CI) and Continuous Deployment (CD) eliminate manual, error-prone release processes. A solid CI/CD pipeline ensures:

  • Every commit is tested — no broken code reaches production
  • Automated builds — consistent, reproducible APK/IPA builds
  • Faster releases — deploy to stores with a single push
  • Team confidence — know that the main branch is always deployable

GitHub Actions

GitHub Actions is the most popular free CI/CD solution for open-source Flutter projects.

Basic Flutter CI Pipeline

.github/workflows/ci.yml
name: Flutter CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.22.0'
          channel: 'stable'

      - name: Install dependencies
        run: flutter pub get

      - name: Analyze code
        run: flutter analyze --fatal-infos

      - name: Run tests
        run: flutter test --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: coverage/lcov.info

Build APK on Push to Main

.github/workflows/build.yml
name: Build Android

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build-android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: '17'

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.22.0'

      - name: Build APK
        run: flutter build apk --release --split-per-abi

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: release-apk
          path: build/app/outputs/flutter-apk/*.apk
💡 Pro Tip Use --split-per-abi to generate separate APKs for arm64-v8a, armeabi-v7a, and x86_64. This reduces APK size by ~30% compared to a universal APK.

Codemagic

Codemagic is a Flutter-first CI/CD platform that simplifies building, testing, and deploying to both app stores.

codemagic.yaml
workflows:
  production:
    name: Production Build
    max_build_duration: 60
    environment:
      flutter: stable
      groups:
        - google_play_credentials
        - app_store_credentials
    scripts:
      - name: Install dependencies
        script: flutter pub get
      - name: Run tests
        script: flutter test
      - name: Build Android
        script: flutter build appbundle --release
      - name: Build iOS
        script: flutter build ipa --release
    artifacts:
      - build/**/outputs/**/*.aab
      - build/**/outputs/**/*.ipa
    publishing:
      google_play:
        credentials: $GOOGLE_PLAY_CREDENTIALS
        track: internal

Fastlane for Store Deployment

Fastlane automates screenshots, beta distribution, and store submission.

android/fastlane/Fastfile
default_platform(:android)

platform :android do
  desc "Build and upload to internal track"
  lane :beta do
    gradle(
      task: "bundle",
      build_type: "Release",
    )

    upload_to_play_store(
      track: "internal",
      aab: "app/build/outputs/bundle/release/app-release.aab",
    )
  end
end

Code Signing

Both Android and iOS require code signing for release builds.

Android Keystore

keytool -genkey -v -keystore release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias my-key-alias
⚠️ Apple Developer Account Required You need an Apple Developer account ($99/year) to generate provisioning profiles and certificates. Use fastlane match for team-based certificate management.

Store Deployment

Android (Google Play)

# Build AAB (required by Google Play)
flutter build appbundle --release

iOS (App Store)

# Build IPA
flutter build ipa --release --export-options-plist=ios/ExportOptions.plist

# Upload via Fastlane
cd ios && fastlane beta
📱 Bundle Naming Convention Use semantic versioning: 1.0.0+1 in pubspec.yaml. The number after + is the build number (Android versionCode, iOS build number).

Environment Management

Use --dart-define to pass environment variables at build time without hardcoding secrets.

main.dart
const String apiUrl = String.fromEnvironment(
  'API_URL',
  defaultValue: 'https://api.dev.example.com',
);
# Development build
flutter run --dart-define=API_URL=https://api.dev.example.com

# Production build
flutter build apk --dart-define=API_URL=https://api.prod.example.com

Summary

  • GitHub Actions — Free, great for open-source Flutter CI
  • Codemagic — Flutter-first, easiest setup for mobile CI/CD
  • Fastlane — Automates store submission and screenshots
  • Code signing — Required for release builds on both platforms
  • Environment variables — Use --dart-define for secrets and config
🚀 Next Step Continue to Firebase Integration to add backend services to your app.
K
Kesavaraja Murugesan
Flutter Developer & Educator

Flutter developer with 3 years of experience building production-grade mobile applications. Passionate about teaching clean architecture patterns and helping developers write maintainable, scalable code.

← Testing Next: Firebase Integration →