---
title: "Codemagic Integration"
description: "Release and patch with Shorebird in Codemagic, from the Workflow Editor or from Android and iOS workflows in codemagic.yaml."
---

This guide will help you integrate Shorebird into your Codemagic workflows.

## Choose how to configure Codemagic

Codemagic runs Shorebird from either of its two ways of configuring a build:

* **Workflow Editor.** Codemagic’s Flutter Workflow Editor has a Shorebird section for Android and iOS. Under **Publish updates to user devices using Shorebird**, choose **Release** or **Patch**, and paste a key (see [Authentication](#authentication)) into its **Shorebird token** field. Codemagic’s [Shorebird guide](https://docs.codemagic.io/flutter-distributing/shorebird/) walks through each field.
* **codemagic.yaml.** Write the `shorebird release` and `shorebird patch` steps yourself, which works for every platform Shorebird supports and lets you run other Shorebird commands. The rest of this page covers this route. If you’re new to the file, see the [Codemagic YAML documentation](https://docs.codemagic.io/yaml-basic-configuration/yaml-getting-started/).

## Prerequisites

This guide assumes that:

1. Your app has been initialized with `shorebird init`, and `shorebird.yaml` is committed to your repository.
2. Codemagic is connected to your repository ([guide](https://docs.codemagic.io/yaml-quick-start/building-a-flutter-app/#adding-the-app-to-codemagic)).

## Authentication

Creating releases and patches needs a signed-in Shorebird CLI. In CI, the CLI reads an API key from the `SHOREBIRD_TOKEN` environment variable, so nobody has to run `shorebird login` on the builder.

Use a key that belongs to a [service account](/account/service-accounts/). A service account belongs to your organization rather than to a person, so its key keeps working when whoever set up CI leaves or changes roles, and the audit log shows the job’s actions under the service account’s name. Service accounts are available on every plan. To create one, you need the Admin or Owner role in the organization:

1. In the [Shorebird Console](https://console.shorebird.dev), open your organization’s **Settings** and select **Service accounts**.
2. Click **Create service account**, name it after the CI system that will use it (such as `GitHub Actions`), and click **Create**.
3. Keep the **Developer** role, which can create releases and patches. Choose **App Manager** instead if the job also creates apps, for example by running `shorebird init`.
4. Under **API keys**, click **Create key**, enter a name, and choose an expiration.
5. Copy the key. It is shown only once.

Store the key as `SHOREBIRD_TOKEN` in your CI platform’s secrets manager, as the steps below show.

Caution

`SHOREBIRD_TOKEN` is a secret. Do not check it into source control or share it publicly.

If you can’t create a service account, a personal API key from **Account → API Keys** goes in `SHOREBIRD_TOKEN` the same way. It acts as you, can do at most what your own role allows, and stops working if your account is deleted. See [API Keys](/account/api-keys/).

Migrating from `shorebird login:ci`

Tokens from `shorebird login:ci` stopped working on October 1, 2026. Replace the value of your `SHOREBIRD_TOKEN` secret with a new key; the variable name and your workflow files stay the same.

Next, with the key copied, navigate to your Codemagic secrets:

1. Select the “teams” tab on the left sidebar.
2. Select the team you want to add the secret to.
3. Select the “Global Variables and Secrets” tab.
4. Enter `SHOREBIRD_TOKEN` as variable name.
5. Paste the token into the variable value field.
6. Add it to a group named `shorebird`.
7. Ensure “Secure” is checked.

![Screenshot of the "Environment Variables" tab in
Codemagic](/_astro/codemagic_environment_variables.CA6Bp5xP_131JXp.webp)

## Set up an Android workflow

This section shows you how to set up a Codemagic workflow to create Android releases, distribute them to the Play Store, and patch them once they’ve been distributed, using `codemagic.yaml`. To use the Workflow Editor instead, see [Choose how to configure Codemagic](#choose-how-to-configure-codemagic).

As a preview, the finished `codemagic.yaml` file will look like this:

```
definitions:
  environment:
    shared_env: &shared_env
      flutter: 3.47.9
      groups:
        - shorebird
        - play_store
      vars:
        FLUTTER_VERSION: 3.47.9
  scripts:
    - &shorebird_install
      name: Install Shorebird
      script: |
        # Install Shorebird
        curl -fsSL https://shorebird.dev/install.sh | bash

        # Add Shorebird to PATH
        echo PATH="$HOME/.shorebird/bin:$PATH" >> $CM_ENV
    - &fetch_dependencies
      name: Fetch Dependencies
      script: |
        flutter pub get

workflows:
  release-android-workflow:
    name: Release Android
    instance_type: mac_mini_m2
    environment:
      <<: *shared_env
      android_signing:
        - android_keystore
    scripts:
      - *shorebird_install
      - *fetch_dependencies
      - name: Shorebird Release
        script: |
          shorebird release android \
            --flutter-version="$FLUTTER_VERSION"
    artifacts:
      - build/**/outputs/**/*.aab
      - build/**/outputs/**/mapping.txt
      - flutter_drive.log
    publishing:
      google_play:
        credentials: $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
        track: internal
  patch-android-workflow:
    name: Patch Android
    instance_type: mac_mini_m2
    environment:
      <<: *shared_env
      android_signing:
        - android_keystore
    inputs:
      release_version:
        description: The release version to patch
    scripts:
      - *shorebird_install
      - *fetch_dependencies
      - name: Shorebird Patch
        script: |
          shorebird patch android \
            --release-version=${{ inputs.release_version }} \
            --track=stable
```

### Prerequisites

#### Give Codemagic permission to publish to the Play Store

You can follow the Codemagic guide [here](https://docs.codemagic.io/yaml-code-signing/signing-android/#google-play-store-credentials) to set this up. This example places the `GCLOUD_SERVICE_ACCOUNT_CREDENTIALS` variable in a group named `play_store`.

#### Set up your Android keystore in Codemagic

You can follow the Codemagic guide [here](https://docs.codemagic.io/yaml-code-signing/signing-android/) to create a keystore and upload it to Codemagic. This example uses `android_keystore` as the name of the uploaded keystore.

You will also also need to update your `android/app/build.gradle` file to use this keystore in the Codemagic CI environment:

```
signingConfigs {
  release {
    if (System.getenv()['CI']) { // CI=true is exported by Codemagic
      storeFile file(System.getenv()['CM_KEYSTORE_PATH'])
      storePassword System.getenv()['CM_KEYSTORE_PASSWORD']
      keyAlias System.getenv()['CM_KEY_ALIAS']
      keyPassword System.getenv()['CM_KEY_PASSWORD']
    } else {
      keyAlias keystoreProperties['keyAlias']
      keyPassword keystoreProperties['keyPassword']
      storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
      storePassword keystoreProperties['storePassword']
    }
  }
}
```

### Create shared configuration

At the top of the `codemagic.yaml` file, define shared environment variables and scripts that will be used by multiple workflows. This has been annotated to explain what each part does.

```
definitions:
  environment:
    # Use &shared_env to allow us to reference this environment in other
    #   parts of the file
    shared_env: &shared_env
      flutter: 3.47.9
      groups:
        # Add the shorebird group to make $SHOREBIRD_TOKEN available to
        #   the Shorebird CLI.
        - shorebird
        # Add the play_store group to make $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
        #   available to the Google Play Publishing step.
        - play_store
      vars:
        FLUTTER_VERSION: 3.47.9
  scripts:
    # A step to install Shorebird and add it to the host machine's PATH
    - &shorebird_install
      name: Install Shorebird
      script: |
        # Install Shorebird
        curl -fsSL https://shorebird.dev/install.sh | bash

        # Add Shorebird to PATH
        echo PATH="$HOME/.shorebird/bin:$PATH" >> $CM_ENV
    - &fetch_dependencies
      name: Fetch Dependencies
      script: |
        flutter pub get
```

### Add the Android release workflow

Add the following workflow to your `codemagic.yaml` file. This has been annotated to explain what each part does.

```
workflows:
  release-android-workflow:
    name: Release Android
    # This can run on any instance type.
    instance_type: mac_mini_m2
    environment:
      # Add the shared_env we defined in the definitions section.
      <<: *shared_env
      # Make the keystore available so we can use release signing.
      android_signing:
        # "android_keystore" is the name of the keystore we uploaded
        #   to Codemagic.
        - android_keystore
    scripts:
      - *shorebird_install
      - *fetch_dependencies
      # Run `shorebird release android` to create a release.
      # This will upload the release to Shorebird and generate
      #   the artifacts listed below.
      - name: Shorebird Release
        script: |
          shorebird release android \
            --flutter-version="$FLUTTER_VERSION"
    # Tell Codemagic where to find the artifacts to publish.
    artifacts:
      - build/**/outputs/**/*.aab
      - build/**/outputs/**/mapping.txt
      - flutter_drive.log
    publishing:
      # Publish to the Google Play Store on the internal track.
      google_play:
        credentials: $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
        track: internal
```

With this, you should be able to create a release in Shorebird and publish it to the Google Play Store via Codemagic.

### Add the Android patch workflow

Add the following workflow to your `codemagic.yaml` file. This has been annotated to explain what each part does.

```
workflows:
  patch-android-workflow:
    name: Patch Android
    # As with the release workflow, this can run on any instance type.
    instance_type: mac_mini_m2
    environment:
      # Add the shared_env we defined in the definitions section.
      <<: *shared_env
      # Make the keystore available so we can use release signing.
      android_signing:
        # "android_keystore" is the name of the keystore we uploaded
        #   to Codemagic.
        - android_keystore
    # Add an input to allow us to specify the release version to patch.
    # This will make this workflow reusable across releases.
    inputs:
      release_version:
        description: The release version to patch
    scripts:
      - *shorebird_install
      - *fetch_dependencies
      - name: Shorebird Patch
        # Run `shorebird patch android` to patch the specified release.
        script: |
          shorebird patch android \
            --release-version=${{ inputs.release_version }} \
            --track=stable
```

With this, you should be able to patch a release in Shorebird via Codemagic.

## Set up an iOS workflow

This section shows you how to set up a Codemagic workflow to create iOS releases, distribute them to TestFlight, and patch them once they’ve been distributed, using `codemagic.yaml`. To use the Workflow Editor instead, see [Choose how to configure Codemagic](#choose-how-to-configure-codemagic).

### Prerequisites

#### Prepare your iOS code signing

Codemagic has a guide on how to set up code signing for iOS [here](https://docs.codemagic.io/yaml-quick-start/building-a-flutter-app/). This guide will help you generate the necessary keys, certificates, and provisioning profiles and load them into Codemagic.

Once you’ve done that, you will need to make these available to your `codemagic.yaml` scripts. You will end up with four environment variables to support this:

* `KEY_ID`: This will be copied directly from App Store Connect.
* `ISSUER_ID`: This will be copied directly from App Store Connect.
* `APP_STORE_CONNECT_PRIVATE_KEY`: This will be the contents of the private key file you downloaded from App Store Connect. An easy way to get this into Codemagic is to run `cat /path/to/AuthKey_12345678.p8 | pbcopy` which will copy the contents of the file to your clipboard. You can then paste this into Codemagic.
* `CERTIFICATE_PRIVATE_KEY`: Follow [this guide](https://docs.codemagic.io/partials/code-signing-ios-obtain-certificate/) to obtain `ios_distribution_private_key` file. You can then paste the contents of this file into Codemagic. `cat ios_distribution_private_key | pbcopy` works well for this.

This example places all of these variables into a group named `app_store`.

### Create a shared configuration

At the top of the `codemagic.yaml` file, define shared environment variables and scripts that will be used by multiple workflows. This has been annotated to explain what each part does.

Note

Many of these scripts use the [Codemagic CLI tools](https://docs.codemagic.io/knowledge-codemagic/codemagic-cli-tools/). You don’t need to install these, but they can be helpful if you want to debug locally.

```
definitions:
  environment:
    shared_env: &shared_env
      flutter: 3.47.9
      # Pin Xcode and CocoaPods so the release and its patches build with the
      # same versions.
      xcode: 26.6
      cocoapods: 1.16.2
      groups:
        # Export the shorebird group to make $SHOREBIRD_TOKEN available to
        #   the Shorebird CLI.
        - shorebird
        # Export the app_store group to make the iOS code signing variables
        #   available the scripts below.
        - app_store
      vars:
        # The bundle ID of this example app.
        # Replace this with your app's bundle id.
        BUNDLE_ID: dev.shorebird.codemagic-demo
        FLUTTER_VERSION: 3.47.9
  scripts:
    # Download the Shorebird CLI and add it to the PATH.
    - &shorebird_install
      name: Install Shorebird
      script: |
        # Install Shorebird
        curl -fsSL https://shorebird.dev/install.sh | bash

        # Add Shorebird to PATH
        echo PATH="$HOME/.shorebird/bin:$PATH" >> $CM_ENV
    - &ios_initialize_keychain
      # Set up the keychain to be used for code signing. Create the keychain
      #   at specified path with specified password with given timeout.
      # Make it default and unlock it for upcoming use.
      name:
        Set up keychain to be used for codesigning using Codemagic CLI
        'keychain' command
      script: |
        keychain initialize
    - &fetch_signing_files
      # Fetch provisioning profiles and code signing certificates for
      #   the Bundle ID with given identifier.
      name: Fetch signing files
      script: |
        app-store-connect fetch-signing-files "$BUNDLE_ID" \
          --type IOS_APP_STORE --create \
          --issuer-id "$ISSUER_ID" \
          --key-id "$KEY_ID" \
          --private-key="$APP_STORE_CONNECT_PRIVATE_KEY"
    - &add_certs_to_keychain
      name: Add certs to keychain
      script: |
        keychain add-certificates
    - &use_profiles
      # This generates an export_options.plist file that tells Xcode
      #   how to package the app. This explicitly sets
      #   manageAppVersionAndBuildNumber to control which
      #   version and build number are used for releasing and patching.
      name: Set up code signing settings on Xcode project
      script: |
        xcode-project use-profiles --custom-export-options={\"manageAppVersionAndBuildNumber\":false}
    - &fetch_dependencies
      name: Fetch Dependencies
      script: |
        flutter pub get
```

### Pin the Xcode version

Without an `xcode:` value, Codemagic builds with its default Xcode, which moves to a newer version when Codemagic updates its machines. Build each iOS patch with the same Xcode as the release it patches: a different Xcode can make the patch report asset or `Podfile.lock` changes you didn’t make, which stops it in CI (see [Build patches with the same toolchain as the release](/code-push/ci/generic/#build-patches-with-the-same-toolchain-as-the-release)).

So the shared configuration above sets `xcode:` to a version from [Codemagic’s macOS machine list](https://docs.codemagic.io/specs/versions-macos/), rather than `latest` or `edge`. It also sets `cocoapods:` to a version, since the default is whatever the machine image has when the build runs, and the CocoaPods version is recorded in `Podfile.lock`. Use the version on the `COCOAPODS:` line of your `Podfile.lock`. Keep both while you patch a release, and change them when you create a new one.

### Add the iOS release workflow

Add the following workflow to your `codemagic.yaml` file. This has been annotated to explain what each part does.

```
workflows:
  release-ios-workflow:
    name: Release iOS
    # This needs to run on a Mac instance.
    instance_type: mac_mini_m2
    integrations:
      # "Codemagic" is the name of the App Store Connect API key.
      app_store_connect: Codemagic
    environment:
      <<: *shared_env
      # Tell Codemagic that this app is being signed for App Store distribution
      #   and to use the bundle ID we defined above.
      ios_signing:
        distribution_type: app_store
        bundle_identifier: '$BUNDLE_ID'
    scripts:
      # Use the scripts we defined in the definitions section.
      - *shorebird_install
      - *fetch_dependencies
      - *fetch_signing_files
      - *ios_initialize_keychain
      - *add_certs_to_keychain
      - *use_profiles
      - name: Shorebird Release
        # Run `shorebird release ios` to create a release.
        script: |
          shorebird release ios \
            --flutter-version="$FLUTTER_VERSION" \
            --export-options-plist=/Users/builder/export_options.plist
    # Tell Codemagic where to find the artifacts generated by
    #   the `shorebird release ios` command.
    artifacts:
      - build/ios/ipa/*.ipa
    publishing:
      app_store_connect:
        # Use referenced App Store Connect API key to authenticate binary upload.
        auth: integration
        # Submit the release to TestFlight, where it can be downloaded by beta
        #   users and later patched by Shorebird.
        submit_to_testflight: true
```

With this, you should be able to create a release in Shorebird and publish it to TestFlight via Codemagic.

### Add the iOS patch workflow

Add the following workflow to your `codemagic.yaml` file:

```
workflows:
  patch-ios-workflow:
    name: Patch iOS
    # This needs to run on a Mac instance.
    instance_type: mac_mini_m2
    environment:
      <<: *shared_env
      # Tell Codemagic that this app is being signed for App Store distribution
      #   and to use the bundle ID defined above.
      ios_signing:
        distribution_type: app_store
        bundle_identifier: '$BUNDLE_ID'
    # Add an input to allow us to specify the release version to patch.
    # This will make this workflow reusable across releases.
    inputs:
      release_version:
        description: The release version to patch
    scripts:
      - *shorebird_install
      - *fetch_dependencies
      - *fetch_signing_files
      - *ios_initialize_keychain
      - *add_certs_to_keychain
      - *use_profiles
      - name: Shorebird Patch
        # Run `shorebird patch ios` to patch the specified release.
        script: |
          shorebird patch ios \
            --release-version=${{ inputs.release_version }} \
            --track=stable \
            --export-options-plist=/Users/builder/export_options.plist
```

With this, you should be able to patch a release in Shorebird via Codemagic.
