Published on

Effortless Flutter CI/CD with Codemagic & AWS

Authors
  • avatar
    Name
    Phat Tran
    Twitter

Codemagic Setup for Acme App

Build, sign, and ship your Mono-repo Flutter super-app with one tag push - then relax and enjoy a coffee. 🚀 All you need is one Git tag that matches build/<env>-vX.Y.Z+N

Project Overview

Our Flutter project Acme App is hosted on AWS CodeCommit and has three parallel environments:

  • UAT
  • STAGING
  • PRODUCTION

A build is triggered when a tag is pushed with the format:

build/<env>-v{versionNumber}+{buildNumber}
# Example
build/uat-v2.5.0+120
  • Android → published to Firebase App Distribution
  • iOS → uploaded to TestFlight

1. Connecting AWS CodeCommit to Codemagic

StepAction
1Log in to CodemagicAdd application
2Choose Other → Connect via SSH, paste your repo's SSH URL, select Flutter
3Follow the official guide Connecting repository via SSH to create an SSH key pair. Add the public key to AWS IAM, store the private key in Codemagic
4In CodeCommit → Settings → Triggers, add a Webhook that points to the Codemagic endpoint. See Setting up webhooks for AWS CodeCommit

  1. Open Teams → General settings → Team integrations
  2. Click Developer Portal → Connect
  3. Upload an App Store Connect API Key (recommended) or sign in with Apple ID

3. Upload iOS Code-Signing Assets

  • Teams → Code signing identities
    • iOS certificates → upload Distribution Certificate (.p12)
    • iOS provisioning profiles → upload Distribution Profile (.mobileprovision)

Codemagic decrypts and installs these during every iOS build.


4. Global Variables & Secret Groups (optional but tidy)

Teams → Global variables and secrets

GroupKeysPurpose
firebase_credentialsFIREBASE_SERVICE_ACCOUNTPublish Android builds to Firebase
TelegramTELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, TELEGRAM_TOPIC_IDChat notifications

All values are AES-encrypted and redacted from logs.


5. codemagic.yaml

Create the file in your repo root. Add the workflow below (Android-UAT).
Copy-paste and tweak the few flavour-specific lines for Staging and Production.

workflows:
  android-uat-workflow:
    name: android-acme-app-uat
    instance_type: mac_mini_m2
    max_build_duration: 120

    environment:
      groups:
        - firebase_credentials
        - Telegram
      vars:
        PACKAGE_NAME: 'com.acme.app.uat'
        APP_SCHEME: 'uat'
        JAVA_TOOL_OPTIONS: '-Xmx5g'
      flutter: 3.13.3

    triggering:
      events:
        - tag
      tag_patterns:
        - pattern: 'build/uat-*'
          include: true

    scripts:
      - name: Initialize development environment
        script: |
          flutter pub global activate melos
          flutter pub global run melos clean
          flutter pub global run melos bootstrap
          sh gen.sh
      - name: Configure script permissions
        script: |
          chmod +x ./scripts/*.sh
      - name: Process version tag
        script: |
          ./scripts/cicd_extract_tag.sh
      - name: Build UAT APK
        script: |
          cd apps/mobile_app
          if flutter build apk --release \
            --flavor uat \
            --build-name=$APP_BUILD_VERSION \
            --build-number=$APP_BUILD_NUMBER; then
            echo "BUILD_STATUS=success" >> $CM_ENV
          else
            echo "BUILD_STATUS=failed" >> $CM_ENV
            exit 1
          fi

    artifacts:
      - apps/mobile_app/build/**/outputs/**/*.apk
      - apps/mobile_app/build/**/outputs/**/mapping.txt
      - flutter_drive.log

    publishing:
      firebase:
        firebase_service_account: $FIREBASE_SERVICE_ACCOUNT
        android:
          app_id: 1:702077598571:android:857d8fea89643f3c6baa2e
          groups:
            - all
          artifact_type: 'apk'
      scripts:
        - name: Send SMS to Telegram
          script: |
            ./scripts/cicd_send_sms_telegram.sh

  ios-uat-workflow:
    name: ios-acme-app-uat
    instance_type: mac_mini_m2
    max_build_duration: 120

    integrations:
      app_store_connect: Acme Codemagic App Manager API Key

    environment:
      ios_signing:
        distribution_type: app_store
        bundle_identifier: com.acme.app.uat
      vars:
        APP_ID: 6476961138
        APP_SCHEME: 'uat'
      groups:
        - Telegram
      flutter: 3.13.3
      xcode: 16.2
      cocoapods: default

    triggering:
      events:
        - tag
      tag_patterns:
        - pattern: 'build/uat-*'
          include: true

    scripts:
      - name: Configure Xcode code signing
        script: |
          xcode-project use-profiles
      - name: Initialize development environment
        script: |
          flutter pub global activate melos
          flutter pub global run melos clean
          flutter pub global run melos bootstrap
          sh gen.sh
      - name: Configure script permissions
        script: |
          chmod +x ./scripts/*.sh
      - name: Process version tag
        script: |
          ./scripts/cicd_extract_tag.sh
      - name: Install Flutter dependencies
        script: |
          cd apps/mobile_app
          flutter pub get
      - name: Setup iOS dependencies
        script: |
          cd apps/mobile_app/ios
          pod deintegrate
          pod install --repo-update
      - name: Build UAT IPA
        script: |
          cd apps/mobile_app
          if flutter build ipa --release \
            --build-name=$APP_BUILD_VERSION \
            --build-number=$APP_BUILD_NUMBER \
            --export-options-plist=/Users/builder/export_options.plist \
            --flavor uat; then
            echo "BUILD_STATUS=success" >> $CM_ENV
          else
            echo "BUILD_STATUS=failed" >> $CM_ENV
            exit 1
          fi

    artifacts:
      - apps/mobile_app/build/ios/ipa/*.ipa
      - $CM_BUILD_DIR/build/ios/ipa/*.ipa
      - /tmp/xcodebuild_logs/*.log
      - flutter_drive.log

    publishing:
      app_store_connect:
        auth: integration
        submit_to_testflight: true
      scripts:
        - name: Send SMS to Telegram
          script: |
            ./scripts/cicd_send_sms_telegram.sh

What do these keys do?

  • instance_type - Apple Silicon for faster builds.
  • triggering.tag_patterns - only tags that match build/uat-* run this workflow.
  • artifacts - everything kept after the VM self-destructs.
  • publishing.firebase - one-click deploy to testers.
  • publishing.scripts - post-deploy actions (Telegram, JIRA, GitHub Release...).

Push a tag like build/uat-v2.5.0+120, watch Codemagic do its magic.