Codemagic Integration
This guide will help you integrate Shorebird into your Codemagic Workflow using the Codemagic YAML.
The reference code is available on GitHub at https://github.com/shorebirdtech/codemagic_demo.
This guide assumes that:
- Shorebird CLI is installed on your machine (guide).
- Codemagic is connected to your repository (guide).
Most Shorebird functionality, like creating releases and patches, requires being authenticated. In order to authenticate with Shorebird in CI, you will need to generate a CI token.
shorebird login:ci
You will be prompted to go through a similar OAuth Flow as when using shorebird login
, however, shorebird login:ci
will not store any credentials on your
device. Instead, it will output a base-64 encoded auth token that you will use
in your CI environment.
The output of this command should look something like:
$ shorebird login:ciThe Shorebird CLI needs your authorization to manage apps, releases, and patches on your behalf.
In a browser, visit this URL to log in:
https://accounts.google.com/o/oauth2/v2/auth...
Waiting for your authorization...
🎉 Success! Use the following token to login on a CI server:
qwerasdf1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqwer1234asdfqw==
Example:
export SHOREBIRD_TOKEN="$SHOREBIRD_TOKEN" && shorebird patch android
Next, copy the generated SHOREBIRD_TOKEN
and navigate to your Codemagic
secrets:
- Select the “teams” tab on the left sidebar.
- Select the team you want to add the secret to.
- Select the “Global Variables and Secrets” tab.
- Enter
SHOREBIRD_TOKEN
as variable name. - Paste the token into the variable value field.
- Add it to a group named
shorebird
. - Ensure “Secure” is checked.
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.
As a preview, our finished codemagic.yaml
file will look like this:
definitions: environment: shared_env: &shared_env flutter: 3.24.1 groups: - shorebird - play_store vars: FLUTTER_VERSION: 3.24.1 scripts: - &shorebird_install name: Install Shorebird script: | # Install Shorebird curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | 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_m1 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_m1 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 }}
You can follow the Codemagic guide
here
to set this up. We put the GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
variable in a
group named play_store
.
You can follow the Codemagic guide
here to create a
keystore and upload it to Codemagic. We used 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'] } }}
At the top of our 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.24.1 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.24.1 scripts: # A step to install Shorebird and add it to the host machine's PATH - &shorebird_install name: Install Shorebird script: | # Install Shorebird curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | bash
# Add Shorebird to PATH echo PATH="$HOME/.shorebird/bin:$PATH" >> $CM_ENV - &fetch_dependencies name: Fetch Dependencies script: | flutter pub get
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_m1 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 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_m1 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 }}
With this, you should be able to patch a release in Shorebird via Codemagic.
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.
Codemagic has a guide on how to set up code signing for iOS here. 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 runcat /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 to obtainios_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.
We put all of these variables into a group named app_store
.
At the top of our 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: shared_env: &shared_env flutter: 3.24.1 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.24.1 scripts: # Download the Shorebird CLI and add it to the PATH. - &shorebird_install name: Install Shorebird script: | # Install Shorebird curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/install/main/install.sh -sSf | 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 our app. We explicitly set # manageAppVersionAndBuildNumber so that we can 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
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_m1 integrations: # "Codemagic" is the name of our App Store Connect API key name. app_store_connect: Codemagic environment: <<: *shared_env # Tell Codemagic that we're signing our app 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 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_m1 environment: <<: *shared_env # Tell Codemagic that we're signing our app for App Store distribution # and to use the bundle ID we 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 }} \ --export-options-plist=/Users/builder/export_options.plist
With this, you should be able to patch a release in Shorebird via Codemagic.