How to set up a CI/CD pipeline for your iOS app using Bitrise
Building and uploading an iOS app from Xcode is a task almost every iOS developer performs at least once in their career. For many indie developers and small teams, this manual approach can indefinitely remain a perfectly acceptable way to prepare a binary for App Store distribution. But, as team size grows or the quality bar raises, this way of building and shipping becomes increasingly unsustainable. Making sure other developers on the team have the right environment, tools, and code signing certificates on their own machines can be tedious, and even small differences between the environments on two developerâs machines can have disastrous consequences, especially in situations where time is of the essence. For these reasons, most growing mobile teams recognize that CI/CD is critical for scaling their dev and release process. Having a robust CI/CD workflow in place increases confidence in the process, and helps ensure reliability and consistency across releases.
These days, there are lots of CI/CD providers to choose from, and figuring out where to start can be daunting. At Runway, our team has lots of experience with many of the popular CI/CD solutions out there, so weâve set out to make things easier for developers and teams looking to get started with â or migrate their â CI/CD. By providing concrete, step-by-step tutorials, we hope to get you from zero to having a fully functional build & upload pipeline without any pain. Our first tutorial covered GitHub Actions, and now weâre turning our attention to Bitrise.
A quick intro on Bitrise
Bitrise is one of a few CI/CD providers that caters specifically to mobile app builds. Itâs also unique in that it provides a user-friendly interface for configuring your workflows â a refreshing alternative to the ubiquitous (but often unwieldy and esoteric!) <code>.yml<code> file. Because of this, Bitrise can be an appealing choice for mobile developers looking to set up a standard CI/CD pipeline quickly and easily â in fact, you can create a complete build & deploy workflow on Bitrise without needing to write any code at all!
âHey â what about fastlane?Â
Many teams will turn to a tool like fastlane which, among other benefits, makes it possible to track changes to your build workflows and their unique configurations over time, through version control. fastlane also allows you to more easily migrate your workflows to another CI/CD provider if needed. But setting up and maintaining a fastlane Fastfile is a time investment, especially as your team and needs grow. Although Bitrise does have solid support for fastlane (via a fastlane Bitrise step), having it in place is not strictly necessary for setting up a complete (if basic) build & upload pipeline on Bitrise. So, if youâre short on time and motivation, Bitrise can be an attractive option.
In this tutorial, weâll show you how to spin up a complete Bitrise iOS build & deploy workflow in just 30 minutes. By the end of the tutorial, youâll have a fully functional workflow that builds your app and uploads iOS binaries to TestFlight on any push to a branch of your choosing.
Letâs get started!
Steps
- Create a Bitrise account & add a new app
- Configure your workflow
- Configure workflow triggers
- Kick off a build
Create a Bitrise account & add a new app
â

Bitrise will give you the option to set up your new app through their web app UI, or using their CLI. Weâll choose the web UI.

Youâll be taken through an app configuration flow that will hook up your new Bitrise app with your appâs version control repository. At the end of the configuration flow, youâll have the option to register a webhook for your repo so that Bitrise can start a new build any time you push to the main branch you configure.
Bitrise will automatically create a starter workflow (called primary) and kick off your first build once youâve finished the new app configuration flow.

Hereâs what the workflow does out of the box:
- It clones your repo and checks out your configured main branch
- It builds your app and runs any tests
- It uploads any files resulting from the tests run to the workflow runâs Artifacts, where you can view and download them to your machine

â
For a basic CI workflow, thatâs pretty good! But in order to build our app for App Store distribution and upload builds to TestFlight, weâll need a workflow that does a bit more.
Configure your release workflow
Having a workflow that verifies that your app builds and your tests pass is a good thing to have set up on a development branch, but when youâre ready to distribute your app to the App Store, youâll want a workflow that does a bit more than that. Weâll create a new workflow that will expand on our primary workflow to accomplish the tasks commonly needed to prepare for an App Store release: building, testing, then signing and uploading to TestFlight.
From your main appâs dashboard on Bitrise, navigate to the âWorkflowsâ tab:

Click âAdd new workflowâ.

Weâll name our new workflow release, and weâll base it off of our primary workflow. This will allow us to copy over some of the basic workflow functionality that weâll be reusing.

Once the workflow is created, youâll be placed in the workflow editor. In the workflow editor you can view and configure all of the steps that make up the workflow, and re-order them if needed.Â
Configure code signing and add an App Store Connect API key
Before we start adding steps to our release workflow, weâll need to configure code signing and add an App Store Connect API Key to the workflow. Code signing will allow us to sign App Store builds within our Bitrise workflow, and adding an App Store Connect API key will enable Bitrise to use the official App Store Connect API to upload builds to TestFlight.Â
Switch to the âCode Signingâ tab, and add your distribution signing certificate and private key pair (<code>.p12<code>) under the âCode signing certificatesâ section. Enter in a password for the certificate if one was set when you originally exported the certificate.Â

Note: You can skip adding a provisioning profile, since weâll use one of Bitriseâs ready-made steps to download the correct provisioning profile directly from App Store Connect.
Next, weâll add an App Store Connect API Key. If you need to create a new ASC API key, follow the steps outlined here. Once you have the API key (<code>.p8<code>), add it under the âGeneric File Storageâ section in the âCode Signingâ workflow tab, and set the File Store ID field to <code>BITRISEIO_ASC_API_KEY_URL<code>. Weâll need this for one of our workflow steps later.

After adding your API key to the âCode Signingâ tab, switch over to the âSecretsâ tab. This is where weâll add another important piece of information that goes together with the App Store Connect API key â the keyâs âIssuer IDâ. Add it as a secret environment variable with the name <code>ASC_API_ISSUER_ID<code>. You can choose whether or not to mark this secret env var âprotectedâ â meaning the environment variable cannot be viewed, copied, or downloaded once saved. If you choose to make any secret environment variables protected, make sure you have a backup copy of the variableâs value, since you wonât be able to retrieve it in the future from Bitrise.

And thatâs it for adding code signing and App Store Connect authentication to our workflow!
Next, weâll want to set up some more environment variables that will come in handy when configuring our build and upload steps.
Configure environment variables
Bitrise will rely on a few configuration details to correctly execute the build and upload steps in our workflow, captured in the form of environment variables. You can scope environment variables to specific workflows, or add environment variables that will be available to all workflows for your Bitrise app. Navigate to the âEnv varsâ tab in the release workflow, and add the following env variables to the release workflow environment variables list:

<code>BITRISE_PROJECT_PATH<code>: the path, relative to the root directory of your repo, to your <code>.xcodeproj<code> or <code>.xcworkspace<code>.
<code>BITRISE_SCHEME<code>: the shared scheme that you use to build your app for distribution.
<code>BITRISE_EXPORT_METHOD<code>: here enter <code>app-store<code>, since this workflow will be used to build and upload binaries to App Store Connect.
<code>BITRISE_INFO_PLIST_PATH<code>: the path, relative to the root directory of your repo, to your main targetâs âInfo.plistâ file. This will be used to increment the project build number as part of the workflow.
With these workflow environment variables set up, we can start adding and configuring the steps required for our workflow to build and upload binaries to App Store Connect.
Add steps to the workflow
Switch back to the workflow editor and click the â+â after our âXcode Test for iOSâ step to add a step.

â
This will pull up the step search UI where you can browse available steps for your workflows.Â

Search for the step called âSet Xcode Project Build Numberâ and select it. Next weâll set the required Input variables for the step. Under Info.plist file path, click âInsert variableâ and select the <code>BITRISE_INFO_PLIST_PATH<code> environment variable we configured earlier. Under Build number youâll notice the default is the <code>BITRISE_BUILD_NUMBER<code> environment variable. This is the build number of the Bitrise workflow run, and it will increment each time you run the Bitrise workflow, which makes it a good default option. If you need to offset the build number by some value, an option exists to do that as well.

Next, add the âXcode Archive & Export for iOSâ step immediately after the âSet Xcode Project Build Numberâ step. This step will build our app for release, properly sign it using the correct signing certificate and provisioning profile, and create an <code>.ipa<code> file for upload to App Store Connect.
Under the Input variables section, the step will already have the <code>BITRISE_PROJECT_PATH<code> and <code>BITRISE_SCHEME<code> environment variables that were added to the environment variables for the workflow pre-populated. Update the âDistribution methodâ by clicking âInsert variableâ and choosing the <code>BITRISE_EXPORT_METHOD<code> environment variable.

Next, open up the Automatic code signing section in the step.
Choose the âapi-keyâ option for the Automatic code signing method field. This will tell Bitrise to use the App Store Connect API key we added to the âCode signingâ section to download the correct provisioning profiles for our workflow during this step.
And that should be it for configuring the âXcode Archive & Export for iOSâ step!Â
Next, weâll add a step to upload the resulting <code>.ipa<code> file to TestFlight.
Click the â+â button after the âXcode Archive & Export for iOSâ, and add the âDeploy to App Store Connectâ step.

Under the input variables for the step, change the âBitrise Apple Developer Connectionâ to âapi-keyâ. As before, this will allow Bitrise to use the App Store Connect API key we added to the âCode signingâ tab to authenticate with the App Store Connect API when uploading binaries to TestFlight.
The API Key: URL field should already be correctly populated with the <code>BITRISEIO_ASC_API_KEY_URL<code> environment variable. On the next field, API Key: Issuer ID, insert the <code>ASC_API_ISSUER_ID<code> secret environment variable.

The rest of the fields on the step can be left as they are.
After all that, what you should have is a workflow called release, that has the following steps in this order:
- Activate SSH key
- Git clone repository
- Bitrise.io Cache:Pull
- Set Xcode Project Build Number
- Xcode Archive & Export for iOS
- Deploy to App Store Connect
- Bitrise.io Cache:Push
- Deploy to Bitrise.io: Apps, Logs, Artifacts
Next, weâll configure the triggers that will start our new release workflow, and then weâll give it a spin.
Configure workflow triggers
Navigate to the âTriggersâ tab in the release workflow to view a list of triggers configured for your Bitrise app. Triggers are special events that cause a workflow to run against a specific branch. Some common triggers include pushing to a branch, opening a pull request against a branch, and creating a tag. Triggers are a great way to automate the kickoff event for builds.Â
Letâs add a push trigger on branches with the pattern <code>release-*<code> â meaning pushes to any branches that start with `release-` will trigger our workflow.

With this trigger set up, pushes to release branches will automatically trigger our new release workflow, building the app and uploading an IPA to App Store Connect!
Kick off a build
Triggers are great for automatically starting workflows in response to events happening on your version control system, but you can also manually start workflows right from the Bitrise UI. Letâs do this now to run our new release workflow for the first time.
From the main app dashboard, click âStart/Schedule buildâ. Choose a branch for your workflow to be run on, and then select release as the workflow.

The release workflow will run through each step we defined above, and at the end of all of that an IPA will be uploaded to App Store Connect. We can also find any artifacts created as part of the workflow (including the final <code>.ipa<code> file and the dSYMs for the binary) on the âApps & Artifactsâ tab in the workflow runâs build page. The logs for the workflow run will also appear there.

And thatâs it! Weâve successfully set up a build & deploy workflow for an iOS app entirely using Bitriseâs UI. Now, with this pipeline in place, anyone on your team is empowered to create and upload builds, removing a common bottleneck while also increasing reliability and consistency in the process. And you donât have to stop there â in addition to all of the (open source!) Bitrise-maintained workflow steps available in the UI, there are plenty more steps created and maintained by the awesome community of mobile developers leveraging Bitrise to improve their own CI/CD pipelines.Â
Questions or issues? Get in touch!