Azure DevOps - James Montemagno https://staging.montemagno.com/tag/azure-devops/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png Azure DevOps - James Montemagno https://staging.montemagno.com/tag/azure-devops/ Hugo -- gohugo.io Tue, 13 Oct 2026 20:48:55 GMT 60 Using Java SDK 11 on Xamarin Android Builds on Azure DevOps & GitHub Actions https://staging.montemagno.com/java-sdk-11-azure-devops-github-actions/ 6578dab01270dd000126e748 Tue, 12 Dec 2023 22:45:42 GMT Everything is building great in your CI/CD pipeline and then BOOM your build fails for no reason. You didn't change anything in your code!?!?! That was me this morning as I was updating my InAppBilling Plugin for .NET. I got hit with this beauty:

error XA0031: Java SDK 11.0 or above is required when using $(TargetFrameworkVersion) v13.0

What is going on?!?!? Starting with Visual Studio 2022 17.8, which was just released, the Xamarin.Andriod tooling requires Java SDK 11.... but the default images on Azure DevOps still have the default set to an earlier version. No worries! as you can manually set this with the Java tool installer task as the first step in the process.

Here is the YAML:

steps:
- task: JavaToolInstaller@0
  displayName: 'Use Java 11'
  inputs:
    versionSpec: 11
    jdkArchitectureOption: x64
    jdkSourceOption: PreInstalled

If you are using GitHub Actions, you can use the actions/setup-java action first: https://github.com/actions/setup-java

After that you are good to go!

]]>
Azure DevOps Settings for Xamarin iOS 13 and Android 10 Apps https://staging.montemagno.com/azure-devops-settings-for-xamarin-ios-13-and-android-10-apps/ 5dd43e2784e2c7003870dfe2 Wed, 20 Nov 2019 20:12:00 GMT

Settings up continuous integration can be tricky when there are new versions coming out. Recently Visual Studio 2019 updated to support Xcode 11, iOS 13, Android 10, .NET Core 3, and C# 8. What a whirlwind of new updates that CI servers got all around the same time! This means that as you were updating your apps your hosted machines also got updated and probably broke your builds :(. My good friend Jonathan Peppers wrote an amazing tool called Boots that allows you to manually install dependencies and previews of Xamarin and Mono.

Boots task in Azure DevOps installing Mono 6.4.0

This is great, but it also means that your build takes a little bit longer to manually install items. Did you know that Azure DevOps has all of the latest bits installed on their hosted agents and even have simple scripts enabling you to decide what version of Xamarin and Mono to run? Here is what you need to know to build your apps in Azure DevOps with C# 8, iOS 13, and Android 10.

Use macOS 10.14

Be sure that you select the latest version of macOS to build your iOS and Android apps on. You can simply specify macOS-latest or macOS-10.14 in your Pipeline settings.

macOS-version selection in Azure DevOps

You can find what software is installed here.

Install .NET Core

This may sound funny to install .NET Core for a Xamarin build, but the latest reference assemblies and build system require it. You can find what version of .NET Core is compatible with Visual Studio for Mac on the docs site.

You can add the Use .NET Core task to install .NET Core 2.2.x or 3.0.x. Either work just fine.

.NET-Core version task in Azure DevOps

Set Xamarin & Mono Version

This next task is very important as it will tell the build agent what version of Xamarin and Mono to use when compiling the app. I like to define a variable with the version number in the format Major_Minor_Revision. For the latest we will use 6_4_0:

Variable in Azure DevOps specifying Mono 6.4.0

Then we will add a task to run a bash script to set the version of Xamarin. This is done with the following inline script:

sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MonoVersion)

Bash script setting the version of Xamarin to use

That is it! Now you are good to go to build your apps with C# 8, iOS 13, and Android 10!

More DevOps!

Looking for more DevOps? Checkout my Channel 9 series on DevOps for Mobile Developers where I walk you through everything you need to know about DevOps with my friend Abel.

]]>
Super Simple Git Tagging & Releases in Azure DevOps https://staging.montemagno.com/super-simple-git-tagging-releases-in-azure-devops/ 5c13e3d958056200bf4c25ae Mon, 21 Jan 2019 16:30:00 GMT I am going to be honest with all of you, I never really understood Git tags and releases inside of GitHub. In my old TFVC days I would just create a branch with the name of the release and call that my "tag" so I could always go back to it. What sparked my interest was seeing a bunch of popular projects that I was using combine tags with the GitHub releases. I started reading the documentation and still wasn't sold on it because I have a full CI/CD pipeline setup for all of my projects and I wasn't sure how this would fit in. Then the lightbulb went off when I saw Jon Dick implement an amazing tagging scheme that would fire off a build, compile a NuGet, and then release the artifacts to NuGet automatatically...

mindblown

Even though this was the coolest thing ever I didn't want to go changing all of my pipelines, but it did encourage me stop doing random branches for releases and streamline my tagging and releases when publishing NuGets. This is surprisingly easy to do with the new GitHub Release task. It is a very nice extension that allows you to create a tag, or re-use a tag, add a changelog file, specify release name, add artifacts, and a bunch more.

In my continuous delivery pipeline I have the following workflow:

Pipeline

My strategy here is to ensure that when I go to NuGet (beta) I create a pre-release tag and release and then when I go to full production I simply update that existing release/tag with updated information.

Uploading a Changelog

Traditionally I never uploaded anything to the drop folder except for the NuGet packages, but a nice thing with the the release task is that you can attach a changelog file (or manually enter it). Since I have a changelog file checked in to each of my repositories that I regularly update, I can just add it to the drop folder in my CI pipeline. In the Copy Files task I simply added:

**\bin\$(BuildConfiguration)\**
**\CHANGELOG.md

Adding a Pre-Release Tag & Release

After I release my pre-release package to NuGet, I want to create my very first Tag and Release. First step is to simply add the GitHub Release task:

Task

Now, it is time to fill in the information for the tag and release:

  • Select GitHub connection
  • Select GitHub repository
  • Action: Create
  • Target: $(Build.SourceVersion)
  • Tag Source: User Specified Tag (if you want to you can have it use an existing tag)
  • Tag: v$(Build.BuildNumber)
  • Release Title: v$(Build.BuildNumber)
  • Release note source: Release notes file
  • Release notes file path: $(System.DefaultWorkingDirectory)/**/CHANGELOG.md
  • Assets:
$(System.DefaultWorkingDirectory)/**/drop/beta-public/*.nupkg
  • Options: Pre-release & Add changelog

Editing a Release

Now, when I go into my final phase to publish my packages to stable on NuGet I want to modify the release I just created. You could optionally create a new release and different tag, but this makes no sense to me currently (leave comments below to let me know what you think).

You can simply add the same exact Task and instead of specifying Create for the Action specify Edit. You will fill in all of the same information except at the end:

  • Assets: Instead of beta-public folder, I change it to public
  • Replace existing assets
  • Uncheck pre-release

And just like that you will have beautiful releases automatically when you publich to NuGet in pre-release or stable:

Capture

]]>
Enhanced Mobile App Versioning in Azure DevOps (VSTS) with Mobile Tasks https://staging.montemagno.com/enhanced-mobile-app-versioning-in-azure-devops-vsts-with-mobile-tasks/ 5c39652e58056200bf4c25d0 Tue, 15 Jan 2019 22:30:00 GMT A little over a year ago, I introduced my Mobile App Tasks Extensions for iOS and Android into the Azure DevOps (VSTS) marketplace. For iOS and Android developers it made the tasks of versioning and adjusting package names a breeze. They were written completely in TypeScript with VS Code and of course are open source on GitHub. Since the initial release I have received overall positive feedback and a few feature requests to add new features. Over the last year I teamed up with my good friend Andrew Hoefling to add small features and optimizations, but finally this week we released version 1.0 with tons of great new features!

New

PList Transform

The first feature you will see is a brand new PList Transform Task. Andrew sent down this pull request and it is super slick. Basically just set any property name and value you want to set in your iOS plist file and you are good to go!

Unix Timestamp

When versioning apps I always had the assumption that developers wanted to manually configure version numbers. However, sometimes you want an auto incrementing number such as a timestamp. When versioning iOS and Android apps you now have the ability to select a custom version number or auto numbering with the Unix time in seconds. This matches App Center functionality, which is super cool :)

format

Misc Updates of Joy

Beyond that we fixed a few other items such as adding the iOS Bundle Identifier to the package name task, fixed issues when comments were in the Android Manifest, handled escaped paths, and updated to the latest packages.

Grab the Extension

You can grab the latest update of the Mobile App Tasks from the Visual Studio Marketplace right now!

Watch Me & Donovan

Last year my good friend Donovan Brown asked me to come on Visual Studio Toolbox to show off the awesome extension and talk Mobile DevOps. Check it out as I walk through the extensions:

How It Was Developed

If you want to see more on how it was developed be sure to check me out on Twitch where I live code. I recently did a full live stream where I added the unix timestamp feature to iOS and Android build tasks. You can watch the full video on YouTube right now!

]]>
Continuous Integration & Delivery for Xamarin & .NET Libraries with Azure DevOps (VSTS) https://staging.montemagno.com/continuous-integration-delivery-for-net-libraries-with-vsts/ 5af5cc81dc592200bfc9400b Mon, 21 May 2018 19:20:00 GMT I build a lot of .NET libraries that include simple .NET Standard libraries to fully cross-platform plugins for Xamarin and Windows that target up to 10 different platforms. When I got started building libraries and shipping them to NuGet I went down a simple path of just building everything locally on my machine and manually uploading them to NuGet. This worked great for a single library, but as soon as I took on a second... third... forth... and so on, things got out of hand and I knew I had to put some sort of CI/CD in place. I went down many paths over the years and have now settled on using Visual Studio Team Services to fully automate the build of every library I create and a full distribution pipe line that goes to MyGet then to NuGet preview, and finally NuGet public release with a click of a button. Now I can develop and let VSTS handle everything for me so I can be productive:

If you look at this screenshot from VSTS it is everything that I wanted for so long in my development cycle. I push code, things are built, and automatically packages are pushed. In this post I am going to show you how I set this up for my projects and how you can too in just a few minutes.

.NET Standard and Multi-Target Projects

Before we start to setup our CI/CD for libraries I highly recommend you move your projects to SDK style projects. You can read my full guide on how to convert a PCL to .NET Standard or how to convert a Xamarin.iOS or Xamarin.Android project to SDK Style.

Everything that I develop now is based on a single .NET Standard 2.0 library or a Multi-Targeted project for plugins. I have previously written on how to convert your PCLs to .NET Standard and also have templates for Visual Studio 2017 to create Multi-Target projects for plugins.

SDKStyle

The reason to use these types of projects is that they include full NuGet packaging including all metadata and dependencies. This also means you can fully delete the .nuspec file that always gets out of sync. It is worth your time to update any and all projects to these types of projects to simplify your life.

If you need to learn more about multi-targeting be sure to check out Oren's amazing MSBuildSdkExtras package which is the core of my templates and all of my projects.

If you are building only an iOS or Android library do not fear as you can still just convert your existing library over to an SDK Style. Take a look at my MonoDroid.Toolkit csproj on GitHub.

Build Definition in VSTS

My builds inside of VSTS are actually really simplistic and only contain 6 steps to fully build my libraries. You can use the Hosted Visual Studio 2017 machines, however I have a small Intel NUC that runs a local VSTS agent so all my NuGets are cached which reduces my build times to seconds instead of minutes.

Empty Definition

Select New and pick your source code that you would like to build. I then like to select Empty process because we can easily fill it in.

Empty

NuGet Steps

Under Phase 1 we are going to add two NUGet steps.

First is the NuGet Tool Installer task and change the Version to 4.5.1

NuGetInstaller

Second will be the regular NuGet task which we will use the restore command on our solution that we are going to build. I like to pick the specific .sln or folder where it lives (no need to build other stuff).

NuGetRestore

Build Steps

I build my libraries twice! That is right twice! Once for a "beta" NuGet and once again for "public" NuGet. They are super quick and all it is really doing is changing the version flags. The reason I do this is for my release definition that will allow me to have a single release that goes from beta to public easily. We will be building the .csproj specifically using the MSBuild task:

MSBuild

We will add it twice so we can build the beta and public releases. Name the first Build Beta and the second Build Public. For each of them set the following:

  • Project: Select the .csproj specifically
  • Configuration: $(BuildConfiguration)

For MSBuild Arguments user the following for Beta:

/t:restore;build;pack /p:PackageVersion=$(Build.BuildNumber)-beta /p:PackageOutputPath=$(build.artifactstagingdirectory)/beta /p:AssemblyFileVersion=$(Build.BuildNumber)

For Public use:

/t:restore;build;pack /p:PackageVersion=$(Build.BuildNumber) /p:PackageOutputPath=$(build.artifactstagingdirectory)/public  /p:AssemblyFileVersion=$(Build.BuildNumber)

This will ensure that the build numbers are configured correctly and copy the artifacts to different folders.

Optionally, you may have some additional unit tests or device runners that may need to be run here.

Copy and Publish

The next thing to add is the Copy Files task to stage the NuGet packages for release.

Set these properties:

  • Source Folder: $(build.sourcesdirectory)
  • Contents: **\bin\$(BuildConfiguration)\**\*.nupkg
  • Target Folder: $(build.artifactstagingdirectory)

Finally, add the Publish Build Artifacts task and set the following:

  • Path to publish: $(build.artifactstagingdirectory)
  • Artifact name: drop
  • Artifact public location: Visual Studio Team Services/TFS

This will pull only .nupkg files that we will distribute into a folder that release can pick up.

All in all the definition should look like:

AllDone

Configure Version Number

Under the Options tab in the build definition I like to format the Build number format such as: 4.5.0$(rev:.r)

This means that the next version would be: 4.5.0.1 and then 4.5.0.2.

Now if you change this to: 5.0.0$(rev:.r) it will reset the revision so it will be 5.0.0.1.

Other things!

You will probably want to setup *Triggers so CI and PR validation are configured. This means that every time master is pushed to a package is generated.

Release Definition in VSTS

Now we have our full build complete it is time to setup our release. Our goal for me was to automatically have every build of master go to MyGet and then manually approve the next release to go to NuGet (beta) and finally another approval to go to NuGet with the public non-beta package.

Battery-CD-1

Head over to the Releases section and create a new release definition with an Empty process. Think of Environments as the stages of release. We can create three of them to define each release of the artifacts. Inside of each environment are a sequence of tasks, just like our build definition, that will be run. For my libraries it is really simple as each has just one task. However, before the NuGet beta and production environments I turn on pre-deployment approval steps.

Push to MyGet

In our first environment we will want to push to MyGet. Add the NuGet task with the following settings:

  • Command: push
  • Path to NuGet package: $(System.DefaultWorkingDirectory)/**/drop/beta/*.nupkg
  • Target Feed: External NuGet server

For this step you will want to configure the feed information from MyGet:

MyGet

Push NuGet Beta

For this step you can select Clone or if you already create the new environment simply add the NuGet task again. The settings will be the same as above:

  • Command: push
  • Path to NuGet package: $(System.DefaultWorkingDirectory)/**/drop/beta/*.nupkg
  • Target Feed: External NuGet server

However, we will now want to select or configure NuGet as our destination:

NuGet

Head back to Pipeline and for this environment we don't want it to automatically trigger, we want to approve this release. You will see a lightning bolt and a person shape on the left side of the environment to configure pre-deployment conditions. I turn on pre-deployment approvals and select myself and turn off the policies since I am a solo developer:

predeploy

There is all sorts of rad stuff you can do here on pre and post-deployment so you should totally look into that for larger projects.

Push NuGet Production

Add or clone another environment for after the Beta environment. This is going to be almost the same as the previous step but we are going to change our Path to NuGet package:

  • Command: push
  • Path to NuGet package: $(System.DefaultWorkingDirectory)/**/drop/public/*.nupkg
  • Target Feed: External NuGet server

Notice I am using public here :)

Add Artifact

Finally, click the big Add artifact button on the left side and select the build definition that you created earlier. Also tap on that little lightning bolt and turn on the Continuous deployment trigger so this flow automatically happens!

CI/CD Pro!

You did it! You are totally a Continuous integration and delivery pro!! Enjoy a seamless deployment of every push to master to MyGet and then approval steps to push to NuGet for any and all of your .NET Libraries. <3 Feel free to ask questions below.

]]>
Building Xamarin.Android Apps in Azure DevOps (VSTS) with Hosted Agents! https://staging.montemagno.com/building-xamarin-android-apps-in-team-services-vsts-with-hosted-vs-2017-agents/ 5a76277cda32ce0022cbd5ef Sat, 03 Feb 2018 21:42:30 GMT I recently wrote about how to build any Xamarin.iOS application inside of Visual Studio Team Services using Hosted macOS Agents for free! I have updated the guide a little bit if you are leveraging .NET Standard libraries to ensure that you build with MSBuild, which is pretty important seeing that all of the new templates will soon use these. That had me thinking "I wonder if there are any small tweaks that are needed for Xamarin.Android when building on the Hosted Agents?"... Which led me to finding a few tweaks that I figured I would blog about.

If you want to understand my passion for VSTS then make sure to listen to Merge Conflict Episode 71.

Xamarin.Android Template

When you head into VSTS and create a new build definition you will find the Xamarin.iOS and Xamarin.Android templates. Go ahead and select that Xamarin.Android template!

NewTemplatesAndroid

For now go ahead and:

  1. Delete the Xamarin Test Cloud Step
  2. Disable the MSBuild step for Test. If you have tests go ahead and leave it on.

Select Build Host

Under Process we can fill in some additional information for the build such as what Solution to do a NuGet restore on and what build host to use. For now I will select the Hosted VS2017 agent.

HostedVS2017

Use Nuget 4.5.1

Since the templates in VS 2017 for Xamarin.Forms apps include a UWP (Fall Creators Update app) we will need to update NuGet to use the latest version, which happens to be 4.5.1. This seems necessary due to changes with .NET Standard.

NuGet

Tweak Android Build Task

We recently changed how the default Android templates are generated on disk and create a csproj that is titled: .Android.csproj Previously it was .Droid.csproj. Regardless the default csproj the Android task tries to build is a regex that looks like:

**/*Droid*.csproj

I am not a fan of using a regex regardless and always pick the specific project, but you should make sure it matches your actual projects. So for me it would be:

**/*Android*.csproj

Like I said, be sure to check your project names or pick the specific one to build, which is what I recommend.

Finally, there are multiple versions of the JDK and Java that are installed. As of today Xamarin.Android apps should be built against JDK 8 x64, which you can select under Advanced.

Final-Build

Queue a Build!

That is it! You can queue up a build and will have a full Android app built up. The final thing that you probably want to do is upload your keystore and ensure you Sign and do a Zip Align in that task step.

How about Hosted macOS?

I knew you would ask! The only difference is that you DO NOT need to modify the Java JDK version to use. It looks like macOS has a specific version installed and you can just leave it to default for now.

Want More VSTS?

We use VSTS for all sorts of different applciations and I recently sat down with Damian Brady on his show The DevOps Lab to talk about how we use VSTS to build the Xamarin Live Player.

]]>
Building Azure DevOps (VSTS) Tasks with TypeScript and VS Code https://staging.montemagno.com/building-vsts-tasks-with-typescript-and-vs-code/ 5a36c138538da90021c4b260 Tue, 30 Jan 2018 17:55:40 GMT Over the last few years I have fallen in love with Azure DevOps (VSTS) for handling all of my application and backend continuous integration, deployment, and release management. Each of these services offer a task based build and release definition that enable you to easily start automating anything. There are a ton of built in tasks, and a whole marketplace where you can install them into your Azure DevOps (VSTS) project. At some point though, you may need to do something custom that isn't a task that has been built. Don't worry, because there is a task called Command Line, which enables you to run any script that you could possibly want. While this is super powerful it also means that these scripts aren't re-usable between applications without copy and pasting them around and don't offer up a friendly user interface since it it just script.This is why Azure DevOps (VSTS) allows anyone to create re-usable tasks that can be shared privately or publicly with the world in the marketplace.

IQsRzovW

Shared Tasks with TypeScript

Wait, why is James talking about TypeScript? We all know that everything JavaScript annoys him and he loves C# with all of his heart and soul. While you can run any custom command in Azure DevOps (VSTS) if you want to write a shareable task that runs on any platform (such as macOS or Linux), then it must be written in JavaScript or TypeScript that is compiled down to JavaScript.

download

Don't run away, it really isn't that bad I promise!!! I tried everything to write tasks in any other language including bash and PowerShell Core, but nope you really need TS/JS for now. Luckily, once you get everything setup inside of VS Code, it is a nice experience. So, let's do it!!!

Development Setup

To get started you will need a Azure DevOps (VSTS) account, VS Code, the latest version of node, the Azure DevOps (VSTS) CLI, and a scaffolded out structure for your code. The Microsoft Documentation on Adding a Task has this entire structure laid out perfectly, so go do that right now! Then come back and we will pick up from this point.

Multi-Task Structure

The documentation above sets you up to build a single task, which is okay, but a unique ability is to create a bunch of tasks into a shareable task extension. So, before we start crushing some code and npm packages, let's structure our code a bit.

Update vss-extension.json

The vss-extension.json lists out all of the tasks that you want bundled into the extension that is compiled. There are two sections, files and contributions, which need to be updated with the multiple tasks and paths that we are creating. You can see what my vss-extension.json looks like with multiple tasks on my GitHub.

Development == Start

Now it is finally time to start development yay! Before we do, we need to insure that we have the TypeScript compiler installed. It is as easy as running:

npm install -g typescript

There is great documentation over on the VS Code site.

Inside of each tak folder we need to create a tsconfig.json file that tells TypeScript what the compiler options should be.

Here is what mine looks like:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": false,
        "outDir": "built",
        "rootDir": ".",
        "sourceMap": true,
        "moduleResolution": "node"
    },
    "exclude": [
        "node_modules"
    ]
}

Again, there is great documentation over on the VS Code website that goes over all of this.

We will create one more file called package.json which will have information about our task and what to point to when finished and what dependencies exist:

{
  "name": "hello world",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "util": "^0.11.1",
    "azure-pipelines-task-lib": "^2.7.7"
  },
  "devDependencies": {
    "@types/node": "^8.5.1",
    "@types/q": "^1.0.6"
  }
}

Now we can create our actual TypeScript file that will be run by Azure DevOps (VSTS). Here is what the base looks like:

//Grab the Azure DevOps (VSTS) task library helpers
import tl = require('azure-pipelines-task-lib/task');
import trm = require('azure-pipelines-task-lib/toolrunner');
import { isNullOrUndefined } from 'util';

//This is the function that get run
async function run() {
    try {
        let tool: trm.ToolRunner;

        // Grab any variables the user set
        let message: string = tl.getInput("key_from_task");

        if(isNullOrUndefined(message))
        {
            message = "No message defined";
        }

        console.log(message);
    }
    catch (err) {
        tl.setResult(tl.TaskResult.Failed, err.message);
    }
}

run();

Before we try to build and run this task, we must restore our packages. Down in the terminal window of VS Code we can navigate to our Task folder and run npm commands to install the packages we need.

npm install @types/node --save-dev
npm install @types/q --save-dev
npm install azure-pipelines-task-lib --save
npm install util
echo node_modules > .gitignore

NPM-install

Build and Debug!

Now, it is time to compile our TypeScript down into JavaScript and actually debug it.

VS Code has some nifty commands built in for TypeScript. The command palette can be brought up with Ctrl + Shift + P or under View:

Run-Build

Then we can find Tasks: Run Build which will list all of the TypeScript files that can be compiled:

Run-Build-2

This can be brought up also with a keyboard shortcut of Ctrl + Shift + B.

We can select the tsconfig that we want to build and hopefully we get no errors.

This compilation will output some nice JavaScript that will be executed under the hood:

JavaScript

VS Code should have generated a launch.json file at the root of the solution. Here is what mine looks like:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceFolder}/tasks\\HelloWorld\\task.ts",
            "outFiles": [
                "${workspaceFolder}/**/*.js"
            ]
        }
    ]
}

We can now set a breakpoint and start to debug our task.

Debugging

The final thing to do is to package up our task and ship it to the marketplace for testing. This can be done with a simple command line at the root of the project to first install tfx-cli and then bundle the package:

npm i -g tfx-cli
tfx extension create --manifest-globs vss-extension.json

Learn More

There you have it from scratch to a fully built Azure DevOps (VSTS) tasks ready to be re-used in any project. Be sure to checkout my Azure DevOps (VSTS) tasks that are fully open source on GitHub and browse through the VSTS documentation for building tasks.

]]>
Version Bumping iOS & Android apps in Azure DevOps (VSTS) https://staging.montemagno.com/version-bumping-ios-and-android-apps-in-visual-studio-te/ 598df8f2c121b60019bf2fd4 Wed, 22 Feb 2017 17:46:37 GMT I love Continuous Integration and Deployment for mobile applications and have given several talks on it in the past. It streamlines your entire development process and makes it drop dead simple to simply commit code and have everything you don’t want to do manually be taken care of for you. This means build, test, bump versions, and ship off to testers with integrations like HockeyApp. Notice I mention “bump versions”, which is actually really important. Every build should be assigned a unique number so developers and testers know exactly what is out there. There is nothing worse then seeing 1.0 on every single build and it makes it impossible to ship out to the app store. Today, I will walk you through bumping version numbers on your iOS and Android apps. 

If you are looking to get your Xamarin apps setup in VSTS then checkout my blogs for Android and iOS that offer a full walk through. This blog will work with any iOS or Android app regardless of how you build it :)

ALM Build & Release Tools

There unfortunately is no out of the box support from what I have seen to actually bump versions, but we can leverage a marketplace extension from Colin called ALM Build & Release, specifically the “Version Assemblies” step.

Android Version Bumping

In my Android manifest my name and code look like this:

android:versionCode="1" android:versionName="1.0.0"

These are important, as we will use a regex to update them.

We will want to add the “Version Assemblies” task TWICE, once for the version name and once for the version code.

Once added, we will bump the name.

First insert the following (with examples):

  • Source Path: src/MobileApps/MyDriving/MyDriving.Android/Properties
  • File Pattern: AndroidManifest.xml
  • Build Regex Pattern: (?:\d+.\d+.\d+.)(\d+)

Under Advanced:

  • Build Regex Group Index: 0

  • Regex Replace Pattern: versionName=“\d+.\d+.\d+

  • Prefix for Replacements: versionName=”

What this will do is update the version name to the Build number format found under “General”, which mine is set to 1.0.0$(rev:.r)

Now for the next one, which is the version code:

  • Source Path: src/MobileApps/MyDriving/MyDriving.Android/Properties
  • File Pattern: AndroidManifest.xml
  • Build Regex Pattern: (?:\d+.\d+.\d+.)(\d+)

Under Advanced:

  • Build Regex Group Index: 1

  • Regex Replace Pattern: versionCode=“\d+

  • Prefix for Replacements: versionCode\

And just like that you are good to go. This will simply update it with the current version revision :)

iOS Version Bumping

This one is a bit trickier and requires some specific things set in the Info.plist. We will need to ensure that the following are set to these very very specific version numbers in the actual Info.plist:

  • CFBundleShortVersionString: 1.0.1

  • CFBundleVersion: 1.1.1 

Don’t ask me why, just trust me!

Under General I have set my build number format to 1.2.$(rev:.r):

I think we just happened to be on 1.2 which is why it is like this, your mileage may vary here. Now we will add the Version Assemblies task TWICE, just like we did for Android.

Let’s first bump the CFBundleShortVersionString:

  • Source Path: src/MobileApps/MyDriving/MyDriving.iOS
  • File Pattern: /Info.plist
  • Build Regex Pattern: (?:\d+.\d+.)(\d+)

Under Advanced:

  • Build Regex Group Index: 1

  • Regex Replace Pattern: 1.0.\d+

  • Prefix for Replacements: 1.2.

That will bump it to 1.2.BuildNumber. 

Let’s then bump the CFBundleVersion:

  • Source Path: src/MobileApps/MyDriving/MyDriving.iOS
  • File Pattern: /Info.plist
  • Build Regex Pattern: (?:\d+.\d+.)(\d+)

Under Advanced:

  • Build Regex Group Index: 1

  • Regex Replace Pattern: 1.1.\d+

  • Prefix for Replacements: 1.2.

As you can see I have to execute these in a specific order to not bump versions differently. It is tricky, but so are regex. And there you have it, bumping versions for both iOS and Android inside of Visual Studio Team Services.

]]>