skip to content

Codemagic

Codemagic is a hosted CI/CD service built around Flutter: a codemagic.yaml workflow builds, signs and publishes both platforms. Interviewers ask because store signing is where mobile delivery breaks.

on this pageshow

explore

questions

6

In Codemagic, what is a workflow in codemagic.yaml, and which sections does a typical Flutter release workflow define?

level: juniorimportance: must knowfreq 48%

answer

  1. one file, repository root
  2. workflows map keyed by workflow ID
  3. environment, triggering, scripts
  4. artifacts are glob patterns
  5. publishing runs regardless of status

basics

~20 s

A Codemagic workflow is one named pipeline under the workflows key of codemagic.yaml, committed at the repository root. It declares its machine, environment, triggers, scripts, artifacts and publishing, so one file can hold separate test and release workflows.

solid answer

~40 s

`codemagic.yaml` must sit in the repository root under exactly that name. Its `workflows` map is keyed by a workflow ID, and each workflow is a complete pipeline: `name`, `instance_type`, `max_build_duration`, an `environment` block (variable groups, signing references, the Flutter and Xcode versions), `cache`, `triggering`, the `scripts` that run after the clone, the `artifacts` globs to keep, and `publishing` targets such as email, Google Play or App Store Connect. A project usually keeps several workflows in the one file, for example PR checks, an Android release and an iOS release, and shares repeated blocks with YAML anchors. Two details catch people: when the file is present, builds triggered by its events ignore the Workflow Editor settings, and `publishing` scripts run whether or not the build succeeded unless you add a check.

code

yaml · 24 lines
yaml
workflows:
  pr-checks:
    name: Scooter app PR checks
    instance_type: mac_mini_m2
    max_build_duration: 30
    environment:
      flutter: stable
    cache:
      cache_paths:
        - ~/.pub-cache
    triggering:
      events:
        - pull_request
    scripts:
      - name: Get packages
        script: flutter pub get
      - name: Analyze
        script: flutter analyze
      - name: Unit tests
        script: flutter test
    publishing:
      email:
        recipients:
          - [email protected]

go deeper

for a junior

Know where the file lives, that workflows is a map of named pipelines, and the order a build follows: environment, scripts, artifacts, publishing.

for a middle

Explain each section's job, how anchors share blocks between workflows, and why publishing scripts need their own success check.

for a senior

Design the file for a team: separate PR and release workflows, sensible timeouts, shared anchors, and no secrets committed in vars.

for a principal

Judge when one shared codemagic.yaml stays readable and when per-app workflows or build inputs are the better shape for a growing product line.

## What codemagic.yaml is **Codemagic** is a hosted CI/CD service that builds, signs and publishes mobile apps, with first-class support for Flutter. Its build configuration can live in the Workflow Editor (a UI for Flutter projects) or in a file called **`codemagic.yaml`**. The file has two hard rules: - it must be **committed** to the repository, and - it must be named exactly `codemagic.yaml` and sit in the **repository root**. When Codemagic detects the file, builds triggered by the events it defines use it, provided a repository webhook exists, and any Flutter Workflow Editor configuration is ignored for those builds. You can also start a build by hand with **Start new build** and pick a branch and workflow. ## The workflows map The top-level `workflows` key is a map. Each key is a **workflow ID** (for example `ios-release`) and each value is a full pipeline, from what starts it to where its output goes. The sections you meet in almost every Flutter workflow: | Section | What it controls | |---|---| | `name` | The label shown in the Codemagic UI | | `instance_type` | The build machine, e.g. `mac_mini_m2` | | `max_build_duration` | Timeout in minutes, between 1 and 120 | | `environment` | Variable `groups`, `vars`, `flutter`/`xcode` versions, `ios_signing`, `android_signing` | | `cache` | `cache_paths` restored between builds of this workflow | | `triggering` | Repository events and branch or tag patterns that start a build | | `scripts` | Shell steps run after the repository is cloned | | `artifacts` | Glob patterns for files to keep (`.aab`, `.ipa`, logs) | | `publishing` | Email, Google Play, App Store Connect, custom scripts | An `integrations` key also appears on iOS workflows, naming the App Store Connect API key the workflow may use. ## Scripts and artifacts `scripts` is a list. An entry can be a bare command or a mapping with a `name` (shown as a section in the build log) and a `script`. Useful switches: 1. `ignore_failure: true` lets the workflow continue when that one script fails. 2. `working_directory` changes where a script runs; paths are relative to the clone directory. 3. `pre_clone_scripts` runs steps before the repository is cloned, for the rare case that needs it. `artifacts` takes glob patterns relative to the clone directory, such as `build/**/outputs/**/*.aab` and `build/ios/ipa/*.ipa`. Common binary types appear as separate downloads on the build page; the rest are zipped together. ## Publishing and its default `publishing` lists where results go: `email` recipients, `google_play`, `app_store_connect`, or `scripts` of your own. By default **publishing scripts run regardless of the build status**, so a custom upload script should check that the artifact exists or that an earlier step left a success marker. ## Several workflows in one file A team shipping a scooter-sharing app might keep three workflows: `pr-checks` (analyze and test on pull requests), `android-release` and `ios-release` (triggered by a version tag). Each workflow has its own triggers and its own cache. To avoid copying the same environment block three times, YAML **anchors** help: define a block under `definitions` with `&name`, then merge it with `<< : *name`, or anchor a single script entry and reuse it with `*name`. ## The environment block in more detail The `environment` section does more than hold variables. It pins the toolchain the build machine uses: - `flutter`: a channel (`stable`, `beta`, `master`), an exact version such as `3.47.5`, or `fvm`, which reads the version from the project's `.fvmrc` file and fails the build if that file is missing; - `xcode`: `latest`, `edge` or a version number, which also selects the macOS image; - `cocoapods`, `java`, `ndk`, `node` and `ruby`: `default` or a specific version; - `groups` and `vars`: imported variable groups and public workflow variables; - `ios_signing` and `android_signing`: references to signing files stored in Codemagic. If `flutter` is left out, the version preinstalled on the machine is used, which makes builds drift silently when Codemagic updates its images. Pinning the version, or using `fvm`, keeps CI on the same Flutter as the developers. ## Checking the file before pushing Codemagic publishes a JSON schema for `codemagic.yaml`, so an IDE with YAML schema support can flag unknown keys and wrong types while you edit. That catches the most common beginner mistake, a key indented under the wrong parent, before a build is wasted on it. ## What the file does not do - It does not replace the Flutter build commands; `flutter build appbundle` and `flutter build ipa` still run inside `scripts`. - It does not store secrets; those live in environment variable groups and code signing identities in the Codemagic UI and are referenced by name. - It does not start builds on its own; automatic triggering needs a webhook in the repository. Knowing this anatomy is the entry point to every other Codemagic question: signing, triggers and publishing are all keys inside one workflow.

  • How do you stop repeating the same environment block across several Codemagic workflows?
    Use YAML anchors. Define the block once under `definitions` with `&env_versions`, then merge it into each workflow's `environment` with `<< : *env_versions`. A single script entry can be anchored with `&` and reused with `*`. Changing the anchored block changes every workflow that references it.
  • What does max_build_duration do in a Codemagic workflow?
    It sets that workflow's timeout in minutes; `codemagic.yaml` accepts values from 1 to 120. Without it, Codemagic builds time out after 60 minutes. Release workflows that compile both platforms often raise it, while PR checks keep it low so a hung test fails fast.
  • Can a Codemagic workflow run a step before the repository is cloned?
    Yes. `pre_clone_scripts` holds steps that run before the clone; ordinary `scripts` run after the sources are fetched. It is rarely needed, for example to prepare credentials a private submodule clone depends on.

saying these in an interview costs you the question

  • codemagic.yaml can sit in any subfolder and Codemagic will find it
  • One codemagic.yaml file can only describe a single workflow
  • Publishing scripts run only after a successful build
  • Workflow Editor settings are merged into codemagic.yaml builds
  • Secrets such as keystore passwords belong under environment.vars in the file
open as a page

In codemagic.yaml, how does ios_signing, backed by an App Store Connect API key, let Codemagic sign a Flutter iOS build automatically?

level: middleimportance: must knowfreq 52%

basics

~20 s

An App Store Connect API key (Issuer ID, Key ID, .p8 file) lets Codemagic create certificates and fetch provisioning profiles into Code signing identities. ios_signing with distribution_type and bundle_identifier installs the matching files at build time, and xcode-project use-profiles applies them.

open as a page

In Codemagic, what are environment variable groups, and how should a codemagic.yaml workflow receive secrets such as a Google Play service-account key?

level: middleimportance: should knowfreq 40%

basics

~20 s

Codemagic environment variable groups are named sets of variables defined in team or application settings, marked Secret to encrypt them, and imported by name under environment.groups. Binary files are base64-encoded before storing and decoded during the build.

open as a page

In codemagic.yaml, how do you make a Codemagic workflow build automatically on pull requests into main and on release tags, and skip stale builds?

level: middleimportance: should knowfreq 36%

basics

~20 s

Codemagic starts a workflow from its triggering section: events such as push, pull_request or tag, filtered by branch_patterns and tag_patterns and delivered by a repository webhook. cancel_previous_builds and a when block drop stale or irrelevant builds.

open as a page

For a scooter-sharing Flutter app, how would you set up Codemagic so a version tag signs both platforms and ships builds to Google Play internal testing and TestFlight?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Use two tag-triggered workflows sharing anchors: Android with android_signing, a store-derived build number and google_play publishing to the internal track; iOS with ios_signing app_store, use-profiles and app_store_connect publishing via the API-key integration. The first Play upload is manual; App Store Connect needs an app record.

open as a page

In codemagic.yaml, how do instance_type and cache_paths affect a Codemagic Flutter build's speed, and what limits apply to each?

level: middleimportance: nice to knowfreq 22%

basics

~10 s

instance_type selects the build machine; iOS builds need a macOS one such as mac_mini_m2, while mac_mini_m4, linux_x2, linux_x4 and windows_x2 require billing. cache_paths restores listed folders per workflow for up to 14 days.

open as a page