Windows Continuous Deployment of Xamarin Apps

This Article will explain how to set up the Windows Continuous Deployment of a Xamarin application. It will describe the automated build process and deployment of a Xamarin Application and create and deploy a mobile and desktop package for deployment to the Universal Windows Platform.

The general concept is described in the previous article Continuous Deployment of Xamarin Projects.

Step 1 – Set up Continuous Integration builds

As before, set up builds to run on every check-in.
Choose the ‘Universal Windows Platform’ build template:
Continuous Deployment of Xamarin Apps to UWP Continuous Deployment of Xamarin Apps to UWP

Make sure to choose the Continuous Integration check box, and set up the repository & branch to target.

Remove the Index Sources & Publish Symbols step:
Continuous Deployment of Xamarin Apps to UWP

Add the following for the Visual Studio Build task’s MSBuild Arguments:

/p:AppxBundlePlatforms=”$(BuildPlatform)”

Note the targets for the Nuget Restore and VS Build steps in this configuration closely. They will restore & build every Solution (*.sln) file in the repository if you leave them as-is. This means if you have configured different solutions anywhere, they’ll be built. If you don’t want to do this, then target those tasks to building only the solution files you want. Also notice again in this definition we have the Publishing of Artifacts to a Drop folder on the Server. Why do we do this? Right. Because they need to be placed on the server for the Release Definition we create later for Deployment to HockeyApp or any other Deployment Service.

Configuring the platforms. Depending whether to build for Mobile and/or Windows Desktop, we do the following to our definition:
Continuous Deployment of Xamarin Apps to UWP

On the ‘Options’ tab, check ‘MultiConfiguration’, put in ‘BuildPlatform’ and select ‘Parallel’. Then:
Continuous Deployment of Xamarin Apps to UWP

Head to the ‘Variables’ tab and put a new ‘BuildPlatform’ variable in with value ‘x86,ARM’. After this you need to tell the VS Build task to use the build platform by putting

$(BuildPlatform)

in to the ‘Platform’ field of the Visual Studio Build task.

This will enable parallel builds of the x86 and ARM configurations for your solution on every CI. You’ll see later how we use these outputs. You could also add x64 in here if needed.

Versioning

When doing a new build of the app for the Store, check the packages.appxmanifest file back into source control. This keeps the build version as a marker in the source and then allows to rev the revision version when Continous Deployment happens.

  1. Build package on Release machine, setting/ incrementing the app version as desired.
  2. Check appxmanifest file into source control (contains the version number used to build the package). This number *always* ends in .0 as required for store submissions.
  3. On CI, set the revision number of the current version number in the appxmanifest file to match the Build ID of the current build (we don’t check this back in).
  4. When CI builds, it’ll stamp the resulting appx file with this version number.

This will show what “base version” of the app this rev was built from. You know it was built after the one in the store with the corresponding Major.Minor.Build matching the one of your CD installation.

To do this we use PowerShell.

The process for Windows 10 builds:

1) Send in the buildNumber so we can put this as the Revision number in the package’s version.
9) Pick out the manifest file for the Windows 10 package. Tune this path to your needs – remember it’s relative to the repository root at the time of the script’s activation.

The remainder of the script is simply parsing the manifest XML, getting the version within the manifest, creating a new version object and putting the buildNumber in for the Revision spot of the Version, then writing that back to the manifest file.

Take this file, save it as a ps1 file and push it up to your repository. For example: prebuild.ps1.

Next, add the build step that will execute it and give it the build number to use.
Continuous Deployment of Xamarin Apps to UWP

Click the ‘Add’ button and click “Close”.
Continuous Deployment of Xamarin Apps to UWP

Move the PowerShell task to be the first in execution, then click the ‘…’ (aka Browse) button in the filename field. You’ll get a live view of your repository and can simply pick the file.

Configure the arguments by setting them to:

-buildNumber $(Build.BuildId)

Which passes the Build’s BuildId (a whole number that increments with each build) to the script as the buildNumber parameter. We don’t use BuildVersion here because that is an arbitrary format that might have dots in it thereby resulting in an invalid version if we were to append that to the end of our Version object in the script.

So now each CI build of the Windows app will have a unique build number which makes it ideal for Continuous Deployment.

Packaging for HockeyApp (Optional)

The default behavior of a Release build for a UWP is it will automatically result in an appx/appxbundle file which is exactly what we need for the purpose of Continuous Deployment. HockeyApp doesn’t support appx deployment for Windows Desktop. It needs a ZIP file containing the artifacts (appx, cert, ps1 installation file, etc) and submitted as your Windows Store Desktop build. This is achievable with another Powershell script.

There’s one assumption built in this script – the check for a BuildPlatform of x86. Since Windows Store Desktop Apps can target x86 or x64, Here We only ever build ARM and x86 of the Windows UWP App as part of the CI build process. The Script can be easily modified to include or not the specific platforms on line 5.

On Line 7 there is a check to see if there is a sent in build number; if there is none It pulls a User Environment Variable denoting what the last build number was. This variable is set on line 20 of the pre-build script. This means that there is no need to pass the build number to this script necessarily.

On Line 11 you can specify where it will put the appx file. This is, in fact, stored in your Solution/project as Metadata, so make sure to have it specified to something (relative!) that will work on a build server. The format of the resulting folder is shown here, which is what we want to ZIP up and make our Deployment for the Windows Store. And the rest is just compressing that folder and creating a ZIP file at the build root named .zip. Make note of this.

Save this file, push it to the repository, create a PowerShell task (last one in our build definition this time), and target this file for it. You don’t need to send the Build ID as an argument this time if you don’t want to because, like I pointed out, we cache it in an environment variable anyway.

Copying output to Drops

This is the step that makes your binaries available to the Release definition that will send them to HockeyApp or Any other Deployment Service.

When we created the UWP build definition, it added a task “Publish Build Artifacts” and put them in ‘drops’. The Continuous Deployment of Xamarin Apps to UWPproblem is we just created a new artifact that is not a build artifact, and we need IT also put in drops. So, remove that task and put in a different one:

Continuous Deployment of Xamarin Apps to UWP

Don’t forget to click ‘Close’ after ‘Add’.

The difference here is not just arbitrarily grabbing build output. This is where we want to grab the Windows Store ZIP file the PowerShell script creates.

Configure this task as shown:
Continuous Deployment of Xamarin Apps to UWP

For ARM builds, any resulting appx files (to submit to the MOBILE deployment) and also any ZIP files at the root of the repository (there will be only one) will be copied to a ‘drop’ folder server-side.

The Continuous Integration is now ready to to build a uniquely-versioned package and set it up for hand-off to a Release Management definition.

Step 2 – Set up Release to HockeyApp (Optional)

Windows Mobile -> HockeyApp

Create a new Release definition with a HockeyApp task, configuring it with your AppID and HockeyApp connection. For the binaries field, point it at the APPX files that were copied to the ‘drop’ folder from the CI build.
To choose the APPX files, just enter

$(System.DefaultWorkingDirectory)\New Universal Windows Platform definition 1\drop\**\*_ARM.appx

into the Binary File Path area of the task.

Windows Store -> HockeyApp

For Android and Windows Mobile HockeyApp took the version number stamped on/in the package that was submitted, created a new version entry for the app corresponding to the AppID parameter, then put the binaries in that version entry for that app beforehand.

For UWP Desktop Apps, there’s no such “automatic” flow. So we have to do these determinations and calls manually. We know the version – it’s the file name of the .zip file. We know the AppID – we have it set up in HockeyApp. So now it’s just a matter of making some REST calls per HockeyApp’s API and getting stuff up there using PowerShell.

The parameters to this script, are the appID in HockeyApp and a HockeyApp access token.

6) Get the first (only!) .zip file in the working directory (‘drop’ folder).
12) Use the base name of the discovered .zip file as the version we’re going to tell HockeyApp to create.
28) Put together the curl command that sends the file up to HockeyApp.

Save it and push it to your repository.
Create a PowerShell task in our Release definition to run it:
Continuous Deployment of Xamarin Apps to UWP

The working folder is important (it’s where curl runs from) make sure to set that correctly as well.

Push curl.exe to the repository, but we also need to get it to the drop folder to be used in the Release script execution for UWP Desktop Apps!

Go to your CI Build definition and add “curl.exe” to the bottom of your “Copy and Publish” task and also add the SCRIPT to be run during release:

**\bin\ARM\$(BuildConfiguration)\*ARM*.appx
*.zip
curl.exe
win10tohockeyapp.ps1

Continuous Deployment of Xamarin Apps to UWPIf the push to the HockeyApp Mobile endpoint fails? Do we want to stop the release of Windows Store Desktop Apps? It is possible to have the Mobile deploy not cease the Application deployment in case of a failure by checking the ‘Continue on error’ box:

CONCLUSION

Once completed with all of our steps we now have a complete functioning Source Code and Version Control with Continuous Integration and Deployment working.

Check in some code to the branch you targeted in each of the 3 Build Definitions and you should see your build definitions something like this:

Continuous Deployment of Xamarin Apps for iOSContinuous Deployment of Xamarin Apps for iOS

With HockeyApp looking like:

Continuous Deployment of Xamarin Apps for UWP
(Big Windows meaning the Desktop version of the UWP App)

Continuous Deployment of Xamarin Apps for UWP

As mentioned in the optional steps we can customize the deployment process greatly and add or remove steps when deploying our app packages. The choices can include our own internal web server for example or HockeyApp’s deployment service etc.

Since we can add PowerShell scripts to run in our process the customization options are quite numerous.

Thank you for reading, I hope this article was useful and will come in handy for any future Xamarin Developers or Deployment specialists.

Please take a look at my Continuous Deployment guides for the other Platforms as well.

Never miss an update by following us and subscribing to our monthly newsletter!

Summary
Continuous Deployment of Xamarin Apps for UWP
Article Name
Continuous Deployment of Xamarin Apps for UWP
Description
This Article will explain how to set up the automated build process and deployment of a Xamarin Application and create and deploy a mobile and desktop package for deployment for the Universal Windows Platform.
Author
Publisher Name
Atos Consulting HU
Publisher Logo

2 thoughts on “Windows Continuous Deployment of Xamarin Apps

  1. Pingback: iOS Continuous Deployment of Xamarin Apps

  2. Pingback: Android Continuous Deployment of Xamarin Applications

Leave a Reply

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