Final Chapter: Continuous Mobile Deployment with VSTS

By | February 4, 2016

In the final installment of my Continuous Integration & Continuous Deployment series we’ll tackle the real wrench in the system: iOS.

This is the final installment in a 3-part series on how you can embrace Continuous Deployment/Delivery as part of your Agile practices your mobile development environment. If you haven’t already, check out parts 1 and two for the primer! (Also I kinda assume you already did this anyway.)

Step 1 – Get a Mac

Yup. Hey, they gotta sell the things somehow right? What better way than to require you to have one to build for their (unfortunately wildly successful) mobile platform? If you can’t get one set up from your own equipment (or, hell, a friend’s) the next best thing is going with a Pay-as-you-Go (or Dedicated Build Agent) plan from Unfortunately, you can’t use the VSTS Build Agent plan they offer because we need the build to generate the IPA file which requires all the certificate/provisioning profile madness and therefore actual UI access.

Add the Mac as a Build Agent

The Mac needs to field the build requests from VSTS. So you have to install the build agent on it much like in my post on creating your own build agent in the cloud.

To create a build agent on a Mac, follow the instructions from Microsoft. I do recommend you follow the “How to run as a service” steps at the end so it survives any reboots that might get done unbeknownst to you. Go ahead, I’ll be here when you get back.

You’re back? Good. Hopefully that wasn’t too painful.

If you go to your VSTS account now, you should see the Mac Build Agent in the agent pool you specified during setup, like this:

In my case, I put my Xamarin build agents in to a Xamarin queue. If you don’t see the agent in that list with a  green bar next to it you need to redo the installation of the agent on the target Mac; something didn’t go right.

Do the Cert dance

Once you’ve got the build agent configured, you need to get all the certs & junk on the Mac. The best guide I found for this frall-de-rall is the one from Xamarin.

To save bandwidth, I’m not going to be walking through all that.

We’ll be building an Ad-Hoc distribution for the HockeyApp deploy so remember that as you walk through everything related to all the app signing stuff.

Install Xamarin Studio

We’ll be building our iOS app using Xamarin.iOS so you need to have this installed on all build agents that might service the CI request.

Step 2 – Configure the Continuous Integration build

Now that that’s over and done, it’s time to configure the build much like we did for our other two platforms:


The important part is the one I’ve (literally) pointed out; the agent queue. You need to select the queue in to which you placed the Mac Build Agent for this one, not the Hosted queue.

Since you will be building a solution specific to Xamarin.iOS, my recommendation is you create a separate SLN for building the iOS project. This will also work well for any devs on your team actually using a Mac (with Xamarin Studio) for development. Target this solution in the “Xamarin.iOS” task that shows in the build definition after completing the wizard. Remove the Xamarin Test Cloud task (unless you know what this is and want to actually do it). When you’re done, it should look like this:

Here’s where things get hairy, thanks to Xamarin’s lack of compatibility with NuGet. Xamarin ships with nuGet v2.8.5 – which has a bug in it regarding dependency evaluation which will rear its head if you choose the right (wrong?) packages. That being said it’s not too hard to fix. With shell scripts!

Add a new build task to the start (kinda like we did with the PowerShell ones, remember?) pointing at a script file looking something like this:

curl -s -O
mono nuget.exe restore App-MacOSX.sln


Save this file and push it to your repo then target it in your new build task:

The point of that script is to:
1) pull down the v2.8.6 version of nuget and
2) restore the nuget packages for the solution

The only other step we need to add is…. remember? Yes, Copy and Publish Build Artifacts!

Setting this up is easy enough as well:

the ‘Copy Root’ part here serves as the directory housing all things iOS-specific (if you recall our repo structure from part 1). The process then pulls all resulting IPA files and puts ‘em in a ‘drop’ folder on the Server, just like we want.

Step 3 – Create the Release Definition

Now it’s time to kick it off to HockeyApp! As you might expect, Hockey’s got great integration with iOS of course. Just set it up exactly as we did the Android one, but use *.ipa for ‘Binary File Path’ instead of *.apk:

And we’re done!

Check in some code to the branch you targeted in each of the 3 Build Definitions and you should see some glorious output a little something like:

With HockeyApp looking like