AL Extensions: Managing Version Numbering With VSTS Builds

I wanted to do this post to talk a bit more about something that Soren Klemmensen had in Part 2 of the blog series on automated builds with VSTS. We wanted to keep those original posts as simple as possible but there are a few more topics that we would like to expand upon.

In that particular post, he covered the PowerShell code needed to generate the AL extension using the ALC compiler tool, and in there is some interesting code around setting the version number of the extension package that gets created. That’s what I want to talk a bit more about here.

As we know, the version number that is assigned to the AL extension needs to be stored in the app.json that sits in the the AL project, and that value needs to be there before the compile process can be executed, like this:

ALExtensionVersion

Typically, this means that the developer is updating that value as needed before they compile and package the extension.

Wouldn’t it be nice to not have to have the developer do that every build? They’ve already got so much to worry about! 🙂

Well…it just so happens that one of the many great features in VSTS build definitions is the ability to automatically generate build numbers. Using a combination of static values and tokens, you’re able to generate any build number that you would like and in pretty much any format you would like.

You can read up on what tokens are available here, and how you can use them to build whatever format of build number you want.

In VSTS, these build numbers can be used to tag checkins so that you can track which checkin represents a build, but we’re going to leverage this and build ourselves a properly formatted version number that we will inject into the AL extension during the build process. This way, the developer can sit back and relax wait for the VSTS magic to happen!

Here’s how we’re going to do it…

1. Update build definition

We need to update our build definition to create our version number for us. We do that by populating the Build number format box on the Options tab of the build definition. Here’s where you can use the VSTS tokens and/or static text.

For this walkthrough, my version number needs to meet the following criteria:

  1. It will follow the standard #.#.#.# formatting that is required for an AL extension.
  2. It will be based on the date that the build is executed.
  3. I need to ensure I always get a unique version number even if I generate multiple builds in a day.
  4. This is the first version of my extension, so I want to make sure the version number begins with 1.0.

Given all of this criteria, I’ll populate the field like this:

BuildVersionFormat

As you can see, I am just hard-coding the “1.0.” so that every version I get begins the same. I’m using the date token (note the format can be changed if you like) so that the version contains the date on which the build is executed. Last but not least, I’m using the revision token to ensure that every time the build is executed I will get a unique version number. If you’re implementing Continuous Integration (and you really should!) you will certainly at some point have multiple builds done within the same day.

NOTE: The revision token is 1-based, so in my example the first build on a given day will end with .1 and not .0 (not what I would have preferred but what can you do).

2. Update build script

Remember I mentioned Soren’s post? In that post the following code is added to your build script. We only really need to update 1 line in this script, but I do want to talk about a few of the other lines so you know what’s going on here. The specific code we’re interested in is shown in red:

$ExtensionAppJsonFile = “.\app.json”
$ExtensionAppJsonObject = Get-Content -Raw -Path $ExtensionAppJsonFile | ConvertFrom-Json
$Publisher = $ExtensionAppJsonObject.Publisher
$Name = $ExtensionAppJsonObject.Name
$ExtensionAppJsonObject.Version = ‘1.0.’+$env:Build_BuildID + ‘.0’
$ExtensionName = $Publisher + ‘_’ + $Name + ‘_’ + $ExtensionAppJsonObject.Version + ‘.app’
$ExtensionAppJsonObject | ConvertTo-Json | set-content $ExtensionAppJsonFile
$ALProjectFolder = $env:System_DefaultWorkingDirectory
$ALPackageCachePath = ‘C:\ALBuild\Symbols’
Write-Host “Using Symbols Folder: ” $ALPackageCachePath
$ALCompilerPath = ‘C:\ALBuild\bin’
Write-Host “Using Compiler: ” $ALCompilerPath
$AlPackageOutPath = Join-Path -Path $env:Build_StagingDirectory -ChildPath $ExtensionName
Write-Host “Using Output Folder: ” $AlPackageOutPath
Set-Location -Path $ALCompilerPath
.\alc.exe /project:$ALProjectFolder /packagecachepath:$ALPackageCachePath /out:$AlPackageOutPath

 

The first 2 lines of highlighted code read the app.json file from the AL project into a PowerShell object using ConvertFrom-Json. This will allow us to read/write any of the properties within the json file:

$ExtensionAppJsonFile = ".\app.json"
$ExtensionAppJsonObject = Get-Content -Raw -Path $ExtensionAppJsonFile | ConvertFrom-Json

Now what we want to do is update the Version property with the build number that our VSTS build definition generated. We can get that value by using one of the environment variables that VSTS makes available while the build process is running. There are a bunch of environment variables available to us (see here for more info) but the one that we’re interested in is Build.BuildNumber. The value in this variable is the value that VSTS generated based on the Build number format that you populated in your build definition. If you leave that field blank, then this environment variable would be empty.

This is where we need to replace some of the code from Soren’s post. The original code (shown below) sets the version number to Build.BuildID, which is the identifier that VSTS assigns to each build:

$ExtensionAppJsonObject.Version = ‘1.0.’+$env:Build_BuildID + ‘.0’

Since we want to control the version number format using our build definition, this is where we need to make a small change. We’ll replace the above line of code with the following that will update the Version property to Build.BuildNumber:

$ExtensionAppJsonObject.Version = $env:Build_BuildNumber

Notes

  • To access VSTS environment variables in your PowerShell script, begin the variable name with ‘$env:’ and replace ‘.’ with ‘_’.
  • Because this environment variables are only generated during the build process you will not be able to manually run your PowerShell script to test the values of these variables.

Finally, we need to write our changes to the app.json file as so far we’ve only made the changes in the PowerShell object We use ConvertTo-Json for that:

$ExtensionAppJsonObject | ConvertTo-Json | set-content $ExtensionAppJsonFile

That’s It!

After you’ve done the above updates to your build definition and script, when you generate your build either manually or via trigger, your packaged AL extension will have version numbers similar to the following:

1.0.20180407.1   (first build of the day)
1.0.20180407.2   (second build of the day)
1.0.20180407.3   (third build of the day)
1.0.20180407.n   (nth build of the day)

Source code management

One of the obvious questions if you implement your build process like this is that if the version number is only updated at the time the build is done, what happens with source code management? Well to be honest, I do not track the version number of my extension in source code management at all.

Personally, I don’t see the value since when my build runs, it tags the checkin that represents that build, so at any point in time I can go back and find the source code for any build that I’ve done, and if I need to I can rebuild it.

So what do I keep in source code management? I keep all of my extension versions permanently set to ‘0.0.0.0’. This means that no developer ever needs to touch the version property during the development stage. It also helps identify if a database has a released version of my extension installed versus a pre-release development version, which does happen from time to time.

Hopefully you’ve found this useful and you’ve now updated your build definition to provide you the exact version number format that you want.

For a listing of the all the automated build articles, see my post here.

That’s it for now, happy coding!

Advertisements

Source control…is it really worth it?

Alright, thought I’d kick things off here with something that has become a large part of my life over the past 5 years or so; source control. More importantly…Microsoft’s Team Foundation Server.

Yes, I’m sure by now that you’ve seen a number of blogs that are out there touting the power of TFS and what it can do for you, and those blogs would all be correct. What I want to do here though is not talk “how-to” here, but rather dig into what it’s like to move to TFS, and what are some of the benefits that come along with it.

First off, I won’t lie, moving to a TFS system is not necessarily a piece of cake for everyone. For some it’s a complete shift in the way development is done, and to introduce source control to the world of NAV which has had next to no controls in place since day 1…well that can be tricky to say the least.

I was a NAV developer for about 6 years when I was introduced to TFS. Right away, I was in the “I’m not using that” camp. Why would I? I’d been making out “fine” without a source control tool, so of course adding a tool to the process would only make developing harder and the whole process longer. An administrative headache I think I once said. Well, fast-forward over 5 years later and I don’t know how we could live without TFS.

Ok, probably some time for a bit of background. I started at IndustryBuilt Software in 2003. I’d only been a NAV developer for just over a year or so at that point. I, as was common back then for most NAV developers, worked on custom projects where each project was different from the last. Skip ahead a few years and I moved to a still rather new department, the one that was doing things that few others were doing at the time; they were building vertical product! That’s when things got truly exciting!! We could finally concentrate on building out a product platform that we could roll out to a number of customers.

It was a few years into building product that TFS came along as this “cool thing we need to try”. So….reluctantly I tried it. It was weird, cumbersome, and yeah at the start it did add overhead to the way I did things, but the things it opened up for us was amazing! We were able to track our builds from week to week. We could see what was changed in the core NAV product to see what impact it had on our product. We could take our entire development process and empower each developer with their own development database and TFS workspace. No more did we have to check with other developers to ensure we didn’t change the same object as they were working on.

Fast forward to the present. The product development team (now referred to as R&D) has grown by more than 300% and has had anywhere from 4-7 developers amongst the group. Without TFS I don’t know what we’d do. We have .NET developers and NAV developers all working within one development ecosystem, all playing with the same tools. Further to that, all of our product initiatives and features are managed using TFS. We’re also a year into implementing the agile scrum process, all within TFS.

We’re able to implement the Cumulative Updates from Microsoft every month within just a few hours. We’re able to publish our own hot fix rollups each month to our implementation team. Finally, we’re able to upgrade our products without having to stop the normal course of development. All with TFS.

Oh, did I mention as well that our implementation and support teams also use TFS to manage every single customer project? That’s right, every customer that comes on board gets their own branch in TFS, where all changes (custom or not) are tracked in the same manner that we track the R&D work.

So, at the end of what has become a rather wordy post, let’s reflect on the real message here: TFS is by far an invaluable tool for any development team. From the 1-man show to the multi-developer team, everyone should get on the TFS train. Sure, it may be a bit of a culture shock, but the return is definitely worth the effort. The first time you need to roll back a change because something broke in the 11th hour of putting together a product release is when you will “thank the TFS gods” so to speak and wonder how you ever made out without TFS for all those years.