CI/CD for Flutter is a piece of cake with Fastlane and Codemagic
By: Maks Majer
Tags: Test Automation, Flutter, Continuous Delivery, Ci Cd Pipeline, Continuous Integration

iOS Setup

Bundle identifier

The first thing you need to do in order to publish your app to App Store is to change the bundle identifier to something unique.

To make it quick we will use a find and replace all function.

Replace all occurrences of com.itcraftship.truth-or-dare with the bundle identifier of your choice.

For Android Studio You can use ⌘⇧R on Mac and Ctrl+Shift+R on Windows

on Mac and on Windows For Visual Studio Code You can use ⌘⇧F on Mac and Ctrl+Shift+F on Windows, then you need to click the arrow in the top left corner to enable replacing

The files that should be affected are:

fastlane/Appfile

fastlane/Fastfile

fastlane/Matchfile

ios/Runner.xcodeproj/project.pbxproj

It will also replace the value in the tutorial Markdown, but you don’t need to worry about it 😉

Team ID

Next, You need to update the Team ID inside Appfile. To access it, go to https://developer.apple.com/account , log in to your account and click the Membership tab. Team ID should be the 3rd row from the top.

Now, go to Appfile and replace the team_id value with your own.

Apple ID

You will also need to add your Apple ID to environment variables, to avoid typing it every time Fastlane or Match needs it. Apple ID is the email address you use to log in.

export TOD_APPLE_ID=<your apple id>

Application-specific password

For the CI to be able to upload builds to App Store Connect, you will need to generate an application-specific password. Here is a tutorial on how to do that.

As before, you should add it to environment variables:

export TOD_APP_SPECIFIC_PASSWORD=<your app specific password for CI/CD>

Create an application with Fastlane

Now we would like to create the app inside App Store Connect. In order to do that, run the following command:

bundle exec fastlane produce --app_name <application name of your choice> --language <primary language e.g. en-US>

As an example you could call this:

bundle exec fastlane produce --app_name "Tod Tutorial" --language en-US

after that new iOS application should be visible in App Store Connect with the Bundle ID taken from the Appfile.

When you have the app created, you should go to App Store Connect and get the Apple ID for your app from the App Information:

You should copy this Apple ID and set it in the Fastfile for the pilot action. See the code below for reference:

pilot(

username: APPLE_ID,

team_id: '120815547',

skip_submission: true,

skip_waiting_for_build_processing: true,

apple_id: "1546377180" # this is where you set it

)

Match

We want to use a tool called match which will be responsible for managing application code signing certificates and provisioning profiles. This is an amazing way to keep code signing in sync with your entire team/company. You can read more about this approach in the Code Signing Guide.

Firstly, create a private repository (e.x on GitHub) where certificates will be stored.

Secondly, add the SSH URL of the repository to environment variables:

export TOD_MATCH_REPO=<repository url>

NOTE: To use Match on Codemagic later on, you will need SSH access from the build machine, so the best practice is to use SSH locally as well — both for the app repository as well as for the certificates repository.

We set this environment variable because later Match will use it during code signing — see the Matchfile.

If you want to include an additional layer of security and add a password to your certificates repository (RECOMMENDED), you will be asked for it the first time you run Match. After it is done You should of course add it also to your environment variables:

export TOD_MATCH_PASSPHRASE=[the password to encrypt/decrypt your match repository]

Later, when you run any match commands, you will need to switch this password to a different environment variable: MATCH_PASSWORD that Fastlane uses by default. Here is an example command:

MATCH_PASSWORD=$TOD_MATCH_PASSPHRASE bundle exec fastlane match development

By doing this Match will not ask you for the password each time. The trick of prefixing your environment variables will come in very handy when you set up your local environment to build and sign several different applications. This is why we add the TOD_ prefix for the case of this Truth or Dare repository. Other projects may have different prefixes like TETRIS_ , PRO_ or whatever you decide to use as an abbreviation for your project.

After you have set these environment variables, you should set up your new Keychain. This is another trick that will come in handy when codesigning different projects. It’s also very convenient to create your own keychain on different build servers. That way you specify your own keychain password and make unlocking and picking the right keychain easier. The password isn’t really sensitive (unless you leave your computer unlocked), but you might want to move it to environment variables for added security. Having a separate keychain for your project will also help you keep it clean and don’t pollute your Login keychain with codesigning certificates and profiles. To create your keychain use this command:

bundle exec fastlane ios setup_keychain

By default the keychain will be created in:

/Users/<username>/Library/Keychains/itcKeychain-db

In the future, you may want to replace the itc prefix to something related to your project or company, but you might just leave it like this to keep us warm in your memory 😉

Now, to create the certificates run the following command:

bundle exec fastlane refresh_all_profiles

NOTE: When you have no provisioning profiles for your app, this command will create new ones for you. You will also want to use this command whenever you add a new device to your development or ad-hoc provisioning profiles. We added a helpful command in the Fastfile for this specific purpose: bundle exec fastlane add_device .

Match SSH Key

The most secure way to connect to git repository is by using SSH keys. When you start the deploy build on Codemagic, it will try to download signing certificates and provisioning profiles using Match. When you try it for the first time, however, it will give you an unauthorized error. This is because your certificate repository is private. In order to connect successfully, Codemagic will need to have an SSH key which it can use to connect to the repository. It is considered unsafe to share your private key with external CI tools, so we will create a new one, just for Codemagic to use.

To generate an SSH key, run:

ssh-keygen -t ed25519

You can name the file however you want.

Be sure to Skip the password prompt (press enter when you are asked for it). If you set a password for your SSH key, then Codemagic will not be able to load this key when setting up the build agent. Don’t worry, you will encrypt this SSH key later using the awesome environment variable encryption feature in Codemagic.

Now add the key to the account that you created a private certificates repository with: Here is a GitHub guide. If you’re using a different git provider than GitHub, then consult appropriate documentation to add your SSH key.

We will use that key later, during Codemagic setup.

Setup the testers

In order to set up testers, go to https://appstoreconnect.apple.com , login, and go to My Apps section. Select the app you created and go to TestFlight tab. In there, select App Store Connect Users on the left.

Press the plus sign next to Testers and check whoever you want to test your application.

Release the app from your local machine

Before you build your app for the first time, make sure to install all pods using:

find . -name "Podfile" -execdir pod install \;

Now you should be all set to release the app from your local machine. Just run the following command:

sh ci/build_ios_qa.sh

If all went according to plan, then you’ll have a shiny new build uploaded to TestFlight 🚀