2015-12-10

So, you just made a new version of your application. Nice.:-)

“Oh, wait, did I update the assembly version?” you think to yourself. Ok, a quick check-in and the build is running again. Nice.

“Oh, was the build version in the build server updated?” you worry.

Update. Rebuild. Commit and go! (Again.)

Well, at least the deploy server is covered—that one takes the release version from the package.

Make mine DRY

What would be nice is to set the version once and Don’t Repeat Yourself—let’s call it DRY. It’s easier and there’s less risk of making mistakes.

The CI setup used is: GitHub – AppVeyor – Octopus Deploy

To accomplish DRY versioning, I use the version from the Git release branch, using the GitFlow branching structure. In the Appveyor build server, this is used to update the build version and patch the Assembly Version in the AssemblyInfo.cs. I call this a Git version.

To keep the builds unique, the AppVeyor build nr is added.

For example:

Becomes 1.2.{build nr}. With build nr 1 that is: 1.2.1

Scripting it

Some notes: AppVeyor uses environment variables, which I use to get the branch:

and the build nr:

which I use to complete the version:

the build version can be updated with the UpdateBuild command:

I cover calling the script a bit later in this post: The power of yaml.

Patch it

Wait, this is done at the build server. That means that the code is already checked in, together with the Assembly Version in AssemblyInfo.cs.

Indeed. But that can be fixed with AssemblyInfo patching in AppVeyor. If your turn that on, the file will be updated before the build. (You can even adjust it, but for me the default is fine).

Side step: Pushing the build output to Octopus

When the build is done, the output needs to pushed to Octopus Deploy.

With the package OctoPack in your project, you can add MsBuild parameters to push a NuGet package generated by OctoPack to Octopus.

The power of yaml

There was another challenge, calling the git version script and the AssemblyInfo patching in the right order.

To add the OctoPack parameters to MSBuild, we have to use the build script option in AppVeyor. That means that there is no pre-build script option, in which we can update the build version before the AssemblyInfo patching takes place.

Well, there is another way to setup AppVeyor. You can add a appveyor.yml file to your solution, which describes the override actions regarding the gui/website. And in that yaml file, you have the option of an init section, that is run before the git cloning.

It is pretty powerful. You can put all the settings in that yaml file, so in the AppVeyor gui you only have to create the project, the rest will be done in the appveyor.yml. See the example below:

Package it all

To make it all easier to use, I created a NuGet package of it. That has a script to copy the appveyor.yml to the solution file and add it to the solution in a (virtual) solution folder. The package is hosted in our internal NuGet Server. So a nuget.config is also added to the package, with the url of that NuGet server.

Conclusion

The steps needed to get this working:

Put the application in a GitHub repo

Add OctoPack and the AppVeyorYml package to the application project

Adjust the OctoPack parameters to the real Octopus values

Create an AppVeyor project

Set Octopus Deploy to use the version number from the NuGet package

Create a build & release:

Make a new release branch with the version (vX.Y) and push it

AppVeyor is triggered to build this branch

– Retrieves the git version

– Updates the build version

– Patches the assembly version

OctoPack creates a packages with the version in the filename and sends it to Octopus

Octopus bases the release version on the version of the package

Now there is one place to fill in the version. If in AppVeyor another build of the same check-in is needed, the build nr is increased, so the build version stays unique. If a new Octopus release is needed, with the same package, the fourth digit can be increased.

Show more