Release Xamarin iOS app with Azure DevOps

Releasing an iOS App means that you have already created the executable file and is correctly signed. So it is ready to be deployed to the App Store.

If you are not sure how to preform that you can follow these two links: 

Create release

Initial creation 

  • From the Pipelines in the menu choose Releases, on the plus button click New and New release pipeline 
  • Select start with an empty job and add name to the stage e.g. Deploy app to Test Flight and close the dialog the updated name will be auto saved
  • On the + Add an artifact from the build source choose the definition that builds your app and contains the ipa file in the artifacts 
  • All other fields will be preselected, if you want to make more additional changes change the available options.
  • Click add 

Create Task that builds your app

  • On stages select the stage that deploys your app and in the tasks click on the plus button 
  • From the Tasks search for “Apple app Store release” and choose the task named like that 

Note: In the Agent Job > Agent specification you should choose Mac OS or choose your Mac as self hosted agent 

Lets get back to the task

– Authentication method

There are two options to authenticate with App Store. The Service connection and Username and Password. The main difference between these two is that Service connection can be used between other pipelines (if access granted).

User Name and Password

  • In the email field enter your email and in the password enter the password from your Apple Store account, if you are using two steps verification check the field and type those credentials as well.

Service connection 

  • Click on manage and you will be navigated to Service connections in Settings 
  • Click on new service connection and choose Apple App Store than Next
    • In App Store email add your email address form App Store 
    • In Password your personal password from App Store
    • In the Service connection name add meaningful name for your connection

Since other fields are optional you can just click save and the connection will be created for you 

  • Navigate back to the release task and click on the refresh button next to the Service connection field and the connection will appear.

– Bundle ID

In the Bundle ID enter your unique identifier. That can be find in the info.plist from your Xamarin.iOS project the string form CFBundleIdentifier key.

– Binary Path

In the Binary Path choose the .ipa file from the drop, that file is the one from the artifacts that was created from the previous successful build definition.

Save and Create a release.

Build Xamarin iOS app with Azure DevOps

In this post will be shown how to create Xamarin.iOS Build definition that will build your Xamarin iOS app and also create an archive file. The .ipa file later on can be deployed to the Test Flight and App Store. On how to deploy the app to the store can be seen in the following link: Release Xamarin iOS app with Azure DevOps

Before any app can be successfully distributed to the App Store there are some steps that needs to be done so the app will be recognized and verified from the Apple. That means that that every app has to have a Certificate and a Provisioning Profile valid files. For how to create those, check the following link: Create distribution certificates and provisioning profiles for your iOS app.

Create build definition

  • Navigate to your Azure DevOps account.
  • Form the Pipelines choose Pipelines and New pipeline 
  • Click on Use the classic editor to create a pipeline without YAML.
  • Select your source. Than find the project you want to build
  • Select the default branch and click continue 
  • From templates search for Xamarin.iOS and select the “Xamarin.iOS” task than apply
  • The definition will be created for you

Lets do some modifications

  • In the Pipeline > Agent Pool select the machine that will build your app “Hosted” if you want to use agent assigned to you or “Private” if you want to use your device as agent.
  • Enable “Install an Apple certificate” and “Install an Apple provisioning profile” tasks
  • Also remove “Select Xamarin SDK version“, “Copy Files to: $(build.artifactstagingdirectory)”, “Test with Visual Studio App Center”, “Deploy **/*.ipa to Visual Studio App Center” because we won’t need them for now.

Add the Provisioning profile and the .p12 files in Library

  • Choose from Pipeline > Library Library is used for keeping secure files 
  • Choose Secure files and click on the +Secure files
  • Click on browse and add these two files separately 

Build Pipeline

Install Apple certificate

  • Choose the .p12 file from the secure files in Certificate (P12) field 
  • Navigate in the Variables from the menu and in P12password field as value add your p12 password also lock it so it wont be visible.

Install Apple provisioning profile

  • Choose the Provisioning profile from secure files in the Provisioning profile field 

Xamarin.iOS 

  • Unselect the “Build for iOS Simulator” checkbox
  • In the Signing & Provisioning in Signing identity enter $(APPLE_CERTIFICATE_SIGNING_IDENTITY). This variable is automatically set by the Install Apple Certificate task for the certificate you selected
  • In the Signing & Provisioning in Provisioning profile UUID enter $(APPLE_PROV_PROFILE_UUID). This variable is automatically set by the Install Apple Provisioning Profile task for the provisioning profile you selected.
  • Open the Advanced drop down list and in Arguments enter /p:IpaPackageDir=”$(Build.ArtifactStagingDirectory)”. With this set up the created .ipa file will be stored in the artifacts directory. 

All other fields and tasks can be left as default 

Save & Queue.

Add Google JSON Auth file in Azure DevOps Release Pipeline

What is Json Auth File?

To understand what Json Auth File is for we need to know what Google Service Accounts stands for. As it stands in the documentation “A service account is a special kind of account used by an application or a virtual machine (VM) instance, not a person. Applications use service accounts to make authorized API calls.” “Each service account is associated with two sets of public/private RSA key pairs that are used to authenticate to Google: Google – managed keys and user-managed keys.” And that is what Json Auth File stands for.

More on this can be read on:
Google Cloud – Service accounts
Google Cloud – Verifying credentials

If we try to explore the Json auth file we can see that it’s format looks like this:

{
  "type": "",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_id": "",
  "auth_uri": "",
  "token_uri": "",
  "auth_provider_x509_cert_url": "",
  "client_x509_cert_url": ""
}

We will use this file to Authenticate our Azure DevOps account with the Google console. That way we will be able to manage our deploys right from there.

How to use the Json Auth File.

Lets navigate to our project on Azure DevOps.

First, we need to securely store our Json Auth file. To make that possible, save the file under Pipelines->Library by adding new secure file on +Secure file button

The next thing to do is to edit the existing release pipeline for our app. Go into the tasks of the stage that deploys the app. Before “Google Play – Release Bundle” task add one more:

Download Secure File

  1. Download Secure File
    1. Add in the tasks “Download Secure File” task by Matt Labrum. Optionally you can use the other task by Microsoft Corporation.
    2. In Display name add a representative name for your task e.g. “Download Secure Json File”.
    3. In Secure file choose the json file that we previously added in the Library.
    4. In the Target path folder we set the folder to download where the file needs to be downloaded. Because this is a secure file we need to be sure that when the job completes whether it succeeds, fails, or is canceled, the secure file is deleted from its download location. That’s why we have to set the target folder as $(mySecureFile.secureFilePath) or $(Agent.TempDirectory)
    5. In Target file name choose a name that will represent the json file e.g. “ourappjsonfile.json”

Once we have that all set up our task will look something like this:

Download secure file task
steps:
- task: mattlabrum.build-task.custom-build-task.downloadsSecureFile@0
  displayName: 'Download Secure Json File'
  inputs:
    fileInput: ourappjsonfile.json
    targetPath: '$(Agent.TempDirectory)'
    targetName: ourappjsonfile.json

After the set up the job should look something like this:

Add changes to the Google play task

Navigate to the Google Play – Release Bundle task.

  1. In the Authentication method choose Json Auth File
  2. Once that is chosen new field will appear JSON key path. Put the Target path folder/Target file name from the Download secure task. It should look something like this: $(Agent.TempDirectory)/ourappjsonfile.json

Save & Queue.

Authenticate Google Play with Azure DevOps

Why we need the Google Play service connection?

We use the service connections to connect an external service for the purpose to execute tasks in a job. To release a Xamarin.Android app (or any other Android app in general) more particularly an executable file .apk/.aab through Azure DevOps we have two authentication methods to connect to Google Play store. By Service connection or by using the Json Auth File. For both methods the first few steps are the same and in the end decide which method we prefer more. To achieve that we need first to set up the Service account. (If you want to learn more on service accounts read the link: Google Cloud – Service accounts

Create Service account on Google Play Console

Navigate to Google Play Console. Note that to make these changes we need to have owner role. Once logged in with the correct role follow these steps:

  • Select Settings from the menu.
  • From Developer account menu choose API access Sub Menu
  • At the bottom section Service Accounts choose Create Service Account. We will be provided with a few steps that need to be done in order to create a service account. Let’s see them in details:
    • Press on +Create service account
    • Add service account name, we can see that the Service account ID is created for us, we can make some changes by editing the field independently
    • Service account description is optional so we can leave it empty for now
  • By clicking create we will proceed on the second steps
    • To have full access to all resources choose for role: Project -> Owner
  • By clicking Continue we will proceed to the last step
    • Here you can grant access for more users or groups. But since it is optional let’s leave it empty for now.
  • By clicking Done new service account will be created.
  • Navigate to Service account details by clicking on created service account.
    • At the bottom under Key section choose Add Key
    • Choose JSON
    • The Json File will be automatically created and downloaded locally on our PC
  • Get back to Google Play Console, we can now see that under Service accounts new account was created for us. Just accept the premissions, and add some edits if needed.

Authorize Azure DevOps with Google Play

  • Under Authentication method choose the preferred method for your pipeline

Authorize Azure DevOps with Google Play using the JSON Auth File

  • If you you choose JSON Auth File the new required field JSON key path will appear.

Authorize Azure DevOps with Google Play using Service connection

  • If you you choose Service connection the new required field Service connection will appear.

Here we have two options, to create a connection for this particular project by clicking the +New button or to add global Service by clicking on Manage. If you have multiple projects on the same Google play console account I would prefer setting that is in the Service connection under Project Settings – by clicking Manage.

  • By choosing the second option, we will be directed to Project settings -> Service connections
  • Search for Google Play and choose it. Click Next. Open the downloaded .json file
    • In Service Account E-mail copy the client_email value from the .json file
    • In Private Key copy the private_key value from the .json file
    • In Service connection name add Connection Name you find representative for this connection
    • Description is optional so let’s leave it empty by now

Click save.

  • Navigate back to Release task and refresh the Service connection field. The connection will appear. Choose it and save.

Done.

Release Android App Bundle for Xamarin.Android apps using Azure DevOps

In this article, we are going to explain how to release the artifact to Google Play store created from a previous successful build. For more on how to create a build pipeline visit this link: Android App bundle for Xamarin.Android Apps Using Azure DevOps build pipeline

Let’s start

Navigate to Releases sub-menu from the Pipelines menu and create a new release pipeline or edit the existing one. If you are going with a new release pipeline choose an empty job as a template. Once that is done New release pipeline will be added, ready for edits.

By clicking on Add an artifact choose as source type the build definition you used for building the solution and creating the artifact file. It should look something like this:

By pressing on the Add button the artifact will be linked and ready to proceed to the stage. Next, select the stage that is intended to deploy the app to Play store and navigate to Tasks.

If we search for Google Play tasks we can see there are several different tasks for deploying the app to the store. If we were about to choose the oldfashioned way for deploying the app to Play Store by providing a .apk file we would have chosen the Google Play – Release task. But because now we have the .aab file we need the Google Play – Release Bundle task.

By adding the task we can see there are several fields that are required for successful deployment:

  1. Service connection – Google Play service connection that is configured with your account credentials.
  2. Application id (com.google.MyApp) – The application id of the bundle you want to release, e.g. com.company.MyApp
  3. Bundle path – path to the bundle (.aab) file you want to publish to the specified track. Wildcards can be used. For example, */.aab to match the first APK file, in any directory.

One by one

Lets take a look at them, one by one:

  1. Service connection:
    Here is needed to authenticate with Play Store service so we can upload our .aab file. There are two methods for authentication: by using a Service connection or the Json Auth File. More on how to perform that see on this link: Authenticate Google Play with Azure DevOps. Once that is set correctly we are able to connect to the store and have a secure delivery for the app from this to that service.
  1. Application id (com.google.MyApp)
    This refers to the package name. You can check that in your AndroidManifest.xml file
  1. Bundle path
    Choose the .aab file you want to deploy from linked artifats.

And finally select the track you want to publish the bundle to. The Internal is selected by default.

There are other additional options in the pipeline that can be defined but with this is enough to deploy the app successfully to Play store.

Save & Create a release.

Android App Bundle for Xamarin.Android apps using Azure DevOps and App Center

Few days passed since the amazing event – Xamarin Experts Day and most of the questions I got were how to support the new presented upload format Android App Bundle – .aab using Azure DevOps and AppCenter since my topic was DevOps: Continuous delivery for Xamarin application, Azure DevOps and App Center, and in the demo I was using a Xamarin.Android build definition.

Note: The source code used for the build definition can be found on Github

And YES, more than expected, because many of us has seen this warning when creating a release on Play Store.

Further more, this awesome new publishing format will allow us to deliver smaller app, optimized for lots of devices and factors. If still not using it do not worry, Xamarin team already took care for all. You can read more in the Official site for Android developers or in the initial support for Xamarin.Android in Xamarin.Android 9.4 release notes and the Xamarin.Android 10.0 release notes

Android App Bundle with Azure DevOps

Prepare your app

Before looking into the processes, let’s take a look at the steps that need to be done, so your app will be prepared for deployment in this format.

Set AndroidPackageFormat property. It can be done by adding these lines of code in the .csproj file for the Android project.

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

    <AndroidPackageFormat>aab</AndroidPackageFormat>

</PropertyGroup>

Edit your build definition

With all this set up navigate to Azure DevOps and edit the Android build definition. The definition that builds the app should look something like this:

For now just disable the current Xamarin.Android task that builds the Android app with Xamarin. It is important not to delete it because soon this feature will be available directly in this task. But let’s take a look at the alternative for now. 

Search for MsBuild task, that builds with MSBuild. After adding it, in the Project field set your Android .csproj file and set the MsBuild options like they are on your Xamarin.Android task. 

Next thing to do is to add additional arguments for the build. Set these arguments in the MSBuild Arguments field:

-t:SignAndroidPackage 

-p:Configuration=Release 

-p:AndroidKeyStore=True

-p:AndroidSigningKeyStore=$(KeyStoreName)

-p:AndroidSigningStorePass=$(KeyStorePass) 

-p:AndroidSigningKeyAlias=$(KeyStoreAlias)

-p:AndroidSigningKeyPass=$(KeyPass)

When AndroidPackageFormat is set as shown above, the SignAndroidPackage will create the .aab file in the bin directory, respectively in the chosen build configuration folder – the Release folder.

In the AndroidSigningKeyStore set the path where you store your .keystore file, if downloading from Secure Files – Library, check the target path folder inserted in the Download Secure File task.

After setting all these your YAML should look something like this:

steps:

- task: MSBuild@1

  displayName: 'Build XamExpertsDay App'

  inputs:

    solution: XamExpertsDay.Android/XamExpertsDay.Android.csproj

    msbuildArchitecture: x64

    msbuildArguments: '-t:SignAndroidPackage -p:Configuration=Release -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(KeyStoreName) -p:AndroidSigningStorePass=$(KeyStorePass) -p:AndroidSigningKeyAlias=$(KeyStoreAlias) -p:AndroidSigningKeyPass=$(KeyPass)'

Running this task will sign the app, so the Android Signing task will no longer be needed. Disable that task, or just simply remove it.

Few more additional steps

The MSBuild will create the .aab file in the bin folder within the Android Project folder. If the folder or file path you want to publish is Artifact staging directory or Binary directory and you want to continue using them in the artifact for publishing, add the Copy files task in between and move the .aab file there. For source folder set the path to .aab file and for target folder the publishing path.

After filling in this the YAML for Copy files task should look something like this:

steps:

- task: CopyFiles@2

  displayName: 'Copy .aab to Binaries directory'

  inputs:

    SourceFolder: '$(System.DefaultWorkingDirectory)/XamExpertsDay.Android/bin/$(BuildConfiguration)/com.xamexpertsday.devopsdemo-Signed.aab'

    TargetFolder: '$(build.binariesdirectory)/$(BuildConfiguration)'

With setting all these the build definition should look like this:

Next redeploy the app, and everything will be ready for publishing.

Once we have the .aab file the build artifacts we will probably need to deploy it on the Play Store. To see how to do that visit this link: Release Android App Bundle for Xamarin.Android apps using Azure DevOps

Android App Bundle with App Center

For App Center just use the simple switch, that can be found by editing the already existing Android Build Definition.

Save & Build. Done 🙂