Continuous Deployment: CI/CD for iOS on Azure DevOps (Part 2)

In the last part we created a build using the pipeline feature of Azure DevOps. In this tutorial we are going to use the Azure’s Release pipeline to push the build to the App Store. This is the continuous deployment part of CI/CD.

Open your project on DevOps and select “Releases” under the “Pipelines” section in the left panel. Select the “New Pipeline” which will open up a dialog for selecting a template.

Template Selection & Setup

Screenshot 2021-03-13 at 4.41.25 PM.png

We are going to select an empty job, since there is no pre-defined template for uploading a build to the App Store.Screenshot 2021-03-13 at 4.42.14 PM.png

Enter the stage name as “Deployment”. It can be whatever you want but for clarification purposes I set it as Deployment.Screenshot 2021-03-13 at 4.42.30 PM.png

We will now select an Artifact which we want to upload. An artifact is something that is created whan an Azure Build Pipeline runs. So in our case the artifact is the one that is generated from our previous tutorial.Screenshot 2021-03-13 at 5.52.54 PM.png

Click the Add button besides the Artifacts label or click on Add an artifact. This will open a new dialog on the right.Screenshot 2021-03-13 at 5.54.56 PM.png

In the drop down you will see our CI setup from the last tutorial. Select that and click the Add button.Screenshot 2021-03-13 at 5.59.06 PM.png

After adding the artifact our release pipeline will look something like below.Screenshot 2021-03-13 at 5.59.16 PM.png

Now select the lightning icon for the artifact we just added. This will open a dialog on the right which will have a setting to enable/disable the Continuous Deployment trigger. When the build trigger is enabled our release pipeline will automatically start when a new build is completed by our build (CI) pipeline. We are not going to enable the Pull Request trigger.Screenshot 2021-03-13 at 6.00.48 PM.png

So far we have setup the pipeline to start automatically when a new build is available in our build pipeline. We have also setup a Deployment stage to which we will add tasks for the actual deployment in the next section.

Deployment task

Select 1 job 0 task hyperlink which will switch to the Tasks tab. Select the + plus besides the Agent Job to open a list of new tasks. Search for Apple App Store. If you don’t see any tasks you will have to install the application from the Marketplace. Once installed when you search for Apple App Store again you will see a couple of new tasks as below.Screenshot 2021-03-13 at 6.20.37 PM.png

Add the Apple App Store Release task. It will add the task which requires a Service Connection. A service connection is basically a connection to the Apple’s itunesconnect website.Screenshot 2021-03-13 at 6.23.50 PM.png

We will now add a new service connection. Click on the New button besides Service Connection which will open a new dialog. In the new dialog enter the email & password. Even though the app-specific password and Fastlane Session are marked as optional they are mandatory to automate the process of uploading the build to App Store.

App-Specific Password

To create app-specific password visit in a new tab and scroll down to the security section. Click on the Generate password… link below the label APP-SPECIFIC PASSWORDS which will open a dialog. Enter any name for the label and click Create. Copy the generated text and switch back to our Azure DevOps tab and paste it under App-specific password field.

Fastlane Session token

As a prerequisite you should already have the fastlane installed on your machine. Fastlane is required to generate the session token so that our cloud machine can login automatically without our intervention. Time to open the terminal and fire some commands.

fastlane spaceauth -u [email protected]

You will will be asked for your password and then a 6 digit code as a part of two factor authentication. It will generate the session token for you and will ask if you want to copy it. Press ‘y’ and then switch to your Azure DevOps tab and paste the session token in the Fastlane Session field.

Enter the service connection name as per your preference and the description if you need it.

Screenshot 2021-03-13 at 6.44.23 PM.png

Publish details

You will see the service connection now set. Next enter your app’s bundle id. Select Skip Build Processing Wait and Skip Submission so that our pipeline doesn’t wait for the build to be made available, otherwise it will consume precious build minutes. Lastly enter the App Specific Apple Id which you can get by logging into and clicking your App to view it’s details and then finally visiting App Information under General section.

Screenshot 2021-03-13 at 6.50.41 PM.png

That is it guys. Your hard work will finally pay off when you run your pipeline and see the green ticks going one by one as the tasks are getting completed. This would be one of the best feeling in the world.

Do you have any suggestions, optimisation and/or just want to connect let me know in the comments below.

By arjavdave

Love to be a part of social circle. Always want to eat lots of pasta with red wine. A workaholic and always exploring ways to optimise work and trying out new things.


  1. Hi Sir, I have followed your each step for CI/CD but my Ci part is failed and shown below error.
    The following build commands failed:
    CompileSwift normal arm64
    CompileSwiftSources normal arm64

    I am using Apple M1 chip.
    Please help me to sort out this issue. Thanks in advance.

  2. Hi sir,

    Can we self-hosted agent.if we can part-2 is suitable for that too if not can i know process to self-hosted apple build…?

    Thanks in Advance

  3. followed same step but getting error : Directory ‘/Users/runner/work/1/a’ is empty. Nothing will be added to build artifact ‘drop’. please help me out.

      1. yes sir having Provisioning profile “” doesn’t include signing certificate “Apple Distribution:XXXXXX(XXXX)”. (in target ‘XXX’ from project ‘XXXX’)

  4. Hello. This works, but the fastlane session expires in a couple of hours. I have to regenerate it (spaceauth) and replace the one in the service connection before every release, or else, it will fail. Is there any workaround for this?

  5. Hi arjavdave,

    Great job on the blog!
    Thank you for the detailed explanation. I have everything setup and when I am trying to run the Release task, I keep getting this error – “Error: The Apple app Store Release task can only run on a Mac Computer”. I am running all these tasks on my MacBook Pro. Am I missing anything here?


  6. Hey arjavdave thks so much for both guides part 1 and part 2, I have a angular app using capacitor, i manage to use majority of your steps i have a lot issue in some of them in the part 1 (capacitor specific).

    I want to ask you a question do you know how can we control the version number with the CI? At the moment manual what i do is, i open the app in xcode and change the version number before I manually archive and then i sent to Apple Connect.

    Let me know if you can give a hand on that.

Leave a comment

Your email address will not be published. Required fields are marked *