Build a Flutter iOS app and deploy it to Testflight using Bitrise CI/CD platform

Igor Kurochka
Apr 15 · 7 min read

Bitrise is a Continuous Integration and Delivery (CI/CD) Platform as a Service (PaaS) with a main focus on mobile apps, and it has Flutter supported out of the box.

Their documentation is great, but some things may be outdated as it seems they are delivering new features and updates pretty often. I had a bit of a struggle configuring the workflows, so I’ve decided to write down the solutions in this article.

Create Bitrise application

The process of creating and setting up flutter-based application with pre-defined basic workflows is very straightforward and intuitive, just login to Dashboard, click “Add New App on Web UI” and follow their wizard steps. After you connect a git repository it will detect Flutter project and pre-populate workflow with steps to test and build Flutter app.

few notes:

  • “Scheme name” — name of the “flavor” you want to use for distribution, e.g. “prod”, “release” etc
  • “Select ipa export method” — select “app-store”
  • “Webhook setup” — allow Bitrise to set up webhooks by clicking “Register a Webhook for me!”

Update Workflows steps

By default the wizard creates two workflows:

  • Primary — only runs the flutter analyze and flutter test commands, this flow is configured to be triggered whenever a push to any branch is made
  • Deploy — in addition to analyze and tests also creates a build and publishes the builds via Bitrise Apps&Artifacts section of the platform. This flow is not configured to be triggered automatically.

First we need to fix a few issues in the default configuration:

  • “Git clone” step has an outdated version of their plugin. To fix this click on the step and in the “Version” section select “5.x.x” to keep the plugin on the latest released version
  • “Flutter install” by default doesn’t update flutter sdk to the latest, and we need to change that. Click on the step and change the parameter “Update to the latest version” to “true”
  • Switch to the “Deploy” workflow and repeat these steps for it as well.
  • “Flutter test” step can be to be tweaked with some additional parameters, for example --no-sound-null-safety. Select the step and paste the param in the field “Additional parameters”
  • “Flutter build” step also can be tweaked with similar way. Check sections “iOS Platform Configs” and “Android Platform Configs".
    Adding additional parameter --build-number $BITRISE_BUILD_NUMBER may be very useful to automatically increase the build version before uploading it to AppstoreConnect (former itunesconnect)

Set Up iOS Appstore deployments

To sign the iOS build and upload it to AppstoreConnect (aka Testflight) you will need:

  • Apple account with an access to Apple Developer program
  • AppstoreConnect API Key
  • iOS Application identifier, aka BundleID
  • iOS Distribution Certificate
  • Provisioning Profile for App Store Distribution, which includes these AppID and Distribution Certificate

In this document I will not cover enrolling into Apple Developer Program and assume that you already have an Apple account included into a Developer account.

What we need from this account is to create an App Specific password, to be able to use the account without exposing our main password and to avoid 2-factor auth mechanism.

To create an API Key, go to AppstoreConnect, Users and Access, click on the tab “Keys”

To enable ability to use the Connect API you may need to ask an owner of the Developer account to enable the permission.

After it’s enabled you will be able to generate the Key. After it’s generated download the .p8 private key.

Go to Bitrise Dashboard and navigate to Account Settings

On the left sidebar find the “Connected Accounts” section and click “Apple Service Connection”

Click “Add Connection” and upload there created Api Key, copy&paste Issuer and Key IDs, name the connection.

To create Bundle ID (or App ID) you need to signin into Apple Developer Account, navigate to Certificates, IDs & Profiles → Identifiers section and click the “+” button to create the record.

Select App ID, choose “App” as a type on the next step and then fill in the form with “Description” and “Bundle Id”, leave “Capabilities” at their defaults, you can edit those later.

Same section, switch to the subsection Certificates and click the “+” button.

Select “Apple Distribution”

At the next step you will need to upload a Certificate Signing Request (CSR) file. To generate it you need to open an application called “Keychain Access” on your mac. Using main menu select Certificate Assistant → Request a Certificate From a Cert Authority”

in the form that opens fill in your email and name, select “Request is Saved to disk” and then save the file to a folder on your choice.

Go back to your browser, upload this file to the step you left off and click “Continue”.

This will create the certificate file (i.e. distribution.cer), download it and open via “Keychain Access” on your mac (simply double click it). Find the certificate under “My certificates” end export the private key (.p12)

Save the private key, we will need it later.

Same section, switch to the subsection Profiles and click the “+” button.

Select Distribution → App Store, then the App ID and Certificate you’ve just created, name the Profile with some name that tells it’s purpose (e.g. myapp-bitrise-distribution-profile)

Download the file and place somewhere near the others, you will need that one in a moment.

Launch Xcode and click “Open a project or file” and open xcworkspace file: /path/to/flutter-project/ios/Runner.xcworkspace

Open “Signing & Capabilities” of Runner target

Make sure to switch off “Auto manage signing”

Paste you App ID into Bundle identifier

Import your Provision Profile

Save the project and at this point Xcode can be closed

Configure the App in Bitrise to Sign&Deploy to Appstore

Navigate to Bitrise Dashboard and open the Application you created earlier.

First, let’s select the Apple Service connection that the App will use to talk to AppstoreConnect. To do this, go to the Team tab, scroll down to the “Apple Service connection” section and select the API key authentication that you added few minutes ago.

Upload Provision Profile and Distribution Certificate to Code Signing

Switch to Code Signing Tab and upload the files you saved on the previous steps: ***.mobileprovision and ***.p12 to the corresponding areas.

Configure Steps in Deploy Workflow

Finally, navigate to Workflows and switch to Deploy Workflow.

Make sure that you have the step Certificate and profile installer no need to change anything, it just has to be before the Flutter build step.

Add new step after XCode Archive & Export, click the “+” after that step and in the search bar that appears on the right side, type and find Deploy to iTunes Connect plugin, click on it.

The only thing we need to change in the params is to fill the value for “App Bundle ID”, paste there the App Identifier we created a few steps back.

And that should be it! Try to make a build with “Deploy” workflow, after all steps passed a new build should appear in the Testflight section of your AppstoreConnect account.

Pitfalls

In this section I’ll list errors and problems I met and had to figure out how to solve while was setting up the workflow. Just to help someone who might be looking for a solution in the future.

flutter “analyze” failed
Because “app” requires SDK version >=2.12.0 < 3.0.0, version solving failed. Solved by changing “Update to the latest version” to “true" for “Install Flutter” step

Error: Cannot run with sound null safety, because the following dependencies don’t support null safety: package:validation_extensions
solved by adding --no-sound-null-safety parameter

error: {module} does not support provisioning profiles
solved by importing correct provision profile into xcproject and into Bitrise

error: Provisioning profile “xxx-provision-profile” doesn’t include signing certificate “iPhone Developer: Igor Kurochka (5D94675R35)”.
also, bitrise error: No signing certificate “iOS Development” found: No “iOS Development”
also, No profiles for “name” were found

Solved by uploading correct Profision Profile as well as distribution certificate (not a Developer certificate) and including correct certificate into Provision Profile

ERROR ITMS-90189: “Redundant Binary Upload. You’ve already uploaded a build with build number ‘1’ for version number ‘1.0.0’
Solved by setting incremented version number from $BITRISE_BUILD_NUMBER env variable

I hope this tutorial will save someone some time and sanity.

Nerd For Tech

From Confusion to Clarification

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/. Don’t forget to check out Ask-NFT, a mentorship ecosystem we’ve started

Igor Kurochka

Written by

Building a fintech @ InfluencerIndex

Nerd For Tech

NFT is an Educational Media House. Our mission is to bring the invaluable knowledge and experiences of experts from all over the world to the novice. To know more about us, visit https://www.nerdfortech.org/. Don’t forget to check out Ask-NFT, a mentorship ecosystem we’ve started

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store