CI/CD & App Store Deployment

CI/CD with Codemagic: Workflows and Triggers

16 min Lesson 7 of 12

CI/CD with Codemagic: Workflows and Triggers

Codemagic is a cloud-based CI/CD platform purpose-built for Flutter and mobile applications. Rather than wrestling with generic CI tools, Codemagic understands Flutter's build system out of the box — it handles Flutter version management, platform-specific signing, and direct publication to Google Play and the App Store without additional scripting. In this lesson you will learn how to define repeatable, automated build pipelines using both the declarative codemagic.yaml file and the GUI Workflow Editor.

The codemagic.yaml File

The preferred way to configure Codemagic is to place a codemagic.yaml file in the root of your repository. This approach is version-controlled, reviewable in pull requests, and can define multiple independent workflows in a single file. Each top-level key under workflows is one named pipeline.

Minimal codemagic.yaml skeleton

# codemagic.yaml — place in repo root
workflows:
  android-release:
    name: Android Release
    max_build_duration: 60          # minutes; build cancelled if exceeded
    environment:
      flutter: stable               # or a specific version like 3.22.0
      android_signing:
        - my_keystore                # references a code signing identity stored in Codemagic
    triggering:
      events:
        - tag                        # run only when a git tag is pushed
      tag_patterns:
        - pattern: 'v*'
          include: true
    scripts:
      - name: Get dependencies
        script: flutter pub get
      - name: Run tests
        script: flutter test
      - name: Build release APK
        script: |
          flutter build apk --release \
            --build-name=$PROJECT_BUILD_NUMBER \
            --build-number=$BUILD_NUMBER
    artifacts:
      - build/**/outputs/**/*.apk
    publishing:
      google_play:
        credentials: $GPLAY_SERVICE_ACCOUNT_JSON
        track: internal
Note: The codemagic.yaml file is loaded at build time from the commit being built. This means changes to the pipeline take effect as soon as they land on the target branch — no manual re-configuration in the Codemagic dashboard is needed.

Triggering Builds: Events and Patterns

The triggering block decides when a workflow runs. Codemagic supports five core trigger events:

  • push — every commit pushed to matched branches
  • pull_request — when a PR is opened or its head branch receives new commits
  • tag — when a git tag is pushed (ideal for release builds)
  • scheduled — cron-based nightly or weekly runs
  • manual — triggered only from the Codemagic dashboard or API

Branch and tag patterns use glob syntax. You can combine include: true and include: false entries to whitelist or blacklist specific refs:

Branch and tag pattern examples

triggering:
  events:
    - push
    - pull_request
  branch_patterns:
    - pattern: 'main'
      include: true
      source: true         # the source branch of a PR
    - pattern: 'release/*'
      include: true
    - pattern: 'wip/*'
      include: false       # never build work-in-progress branches
  tag_patterns:
    - pattern: 'v[0-9]*.[0-9]*.[0-9]*'   # semver tags like v1.4.2
      include: true
  cancel_previous_builds: true            # avoid queuing duplicate builds

Managing Signing Identities in Codemagic's Secure Storage

Code signing credentials — Android keystores, iOS certificates, and provisioning profiles — must never be committed to your repository. Codemagic provides Secure Storage (encrypted at rest, injected as environment variables or files at build time) via two mechanisms:

  • Environment variable groups — store base64-encoded secrets or plain API tokens; referenced in codemagic.yaml with the groups key under environment.vars.
  • Code Signing Identities (Android) — upload a .jks or .keystore file through the Codemagic dashboard; reference its alias under android_signing. Codemagic sets the CM_KEYSTORE, CM_KEY_ALIAS, CM_KEY_PASSWORD, and CM_KEYSTORE_PASSWORD environment variables automatically.
  • iOS Automatic Signing — connect your Apple Developer account once in Codemagic; it handles certificate and provisioning profile renewal. Reference the bundle ID under ios_signing.

Android signing wired up in codemagic.yaml

workflows:
  android-production:
    name: Android Production
    environment:
      flutter: stable
      android_signing:
        - my_production_keystore     # alias set in Codemagic dashboard
      groups:
        - google_play_credentials    # env var group containing GPLAY_SERVICE_ACCOUNT_JSON
    scripts:
      - name: Build release bundle
        script: |
          flutter build appbundle --release \
            --build-name=1.0.$BUILD_NUMBER \
            --build-number=$BUILD_NUMBER
    artifacts:
      - build/**/outputs/**/*.aab
    publishing:
      google_play:
        credentials: $GPLAY_SERVICE_ACCOUNT_JSON
        track: production
        submit_as_draft: false
Warning: Never hard-code keystore passwords, API keys, or service-account JSON inline in codemagic.yaml. The file lives in your public repository. Always reference secrets through Codemagic's Secure Storage environment variables.

Publishing Artifacts to Testers Automatically

After a successful build, Codemagic can push artifacts directly to distribution channels without any manual steps:

  • Firebase App Distribution — upload APKs/IPAs and notify tester groups instantly.
  • Google Play — publish AABs to internal, alpha, beta, or production tracks.
  • App Store Connect (TestFlight) — submit IPAs for TestFlight review automatically.
  • Email / Slack notifications — alert stakeholders on build success or failure.

Publishing to Firebase App Distribution

publishing:
  firebase:
    firebase_token: $FIREBASE_TOKEN      # from Codemagic Secure Storage
    android:
      app_id: $FIREBASE_ANDROID_APP_ID
      groups:
        - qa-team
        - beta-testers
      artifact_type: apk
  email:
    recipients:
      - dev@example.com
    notify:
      success: true
      failure: true

GUI Workflow Editor vs codemagic.yaml

For teams new to CI/CD, Codemagic's GUI Workflow Editor (available in the dashboard) offers a point-and-click alternative. It writes the same underlying configuration but exposes it through form fields. The trade-off is that GUI workflows are not stored in the repository — they can drift from the codebase. The recommendation is to start with the GUI to learn the options, then export to codemagic.yaml for long-term maintainability.

Tip: Use the codemagic.yaml approach from day one in production projects. It gives you a full audit trail via git history, enables peer review of pipeline changes, and lets multiple developers manage the CI configuration the same way they manage application code.

Summary

Codemagic brings production-grade CI/CD to Flutter with minimal boilerplate. A codemagic.yaml file in your repository root defines one or more named workflows, each with its own trigger rules (push, tag, PR, schedule), environment (Flutter version, signing identities from Secure Storage), build scripts, and publishing destinations. Keeping secrets out of the repository and using Codemagic's encrypted variable groups is mandatory for secure pipelines. Once configured, every green commit on main or every v* tag can automatically build, sign, and ship your Flutter app to testers or the stores.