Supporting a GitHub Release Flow with Azure DevOps Builds

It has been a busy few months, and with the weather changing, I have a little more time in front of the computer for hobby work. Some of my public projects were in need of a few package updates, so I started down that road. Most of the updates were pretty simple: a few package updates and some Azure DevOps step template updates and I was ready to go. However, I had been delaying my upgrade to GitVersion 6, and in taking that leap, I changed my deployment process slightly.

Original State

My current development process supports three environments: test, stage, and production. Commits to feature/* branches are automatically deployed to the test environment, and any builds from main are first deployed to stage and then can be deployed to production.

For me, this works: I am usually only working on one branch at a time, so publishing feature branches to the test environment works. When I am done with a branch, I merge it into main and get it deployed.

New State

As I have been working through some processes at work, it occurred to me that versions are about release, not necessarily commits. While commits can help us number releases, they shouldn’t be the driving force. GitVersion 6 and its new workflow defaults drive this home.

So my new state would be pretty similar: feature/* branches get deployed to the test environment automatically. The difference lies in main: I no longer want to release with every commit to main. I want to be able to control releases through the use of tags (and GitHub releases, which generate tags.

So I flipped over to GitVersion 6 and modified my GitVersion.yml file:

workflow: GitHubFlow/v1
merge-message-formats:
  pull-request: 'Merge pull request \#(?<PullRequestNumber>\d+) from'
branches:
  feature:
    mode: ContinuousDelivery

I modified my build pipeline to always build, but only trigger code release for feature/* branch builds and builds from a tag. I figured this would work fine, but Azure DevOps threw me a curve ball.

Azure DevOps Checkouts

When you build from a tag, Azure DevOps checks that tag out directly, using the /tags/<tagname> branch reference. When I tried to run GitVersion on this, I got a weird branch number: A build on tag 1.3.0 resulted in 1.3.1-tags-1-3-0.1.

I dug into GitVersion’s default configuration, and noticed this corresponded with the unknown branch configuration. To get around Azure Devops, I had to do configure the tags/ branches:

workflow: GitHubFlow/v1
merge-message-formats:
  pull-request: 'Merge pull request \#(?<PullRequestNumber>\d+) from'
branches:
  feature:
    mode: ContinuousDelivery
  tags:
    mode: ManualDeployment
    label: ''
    increment: Inherit
    prevent-increment:
      when-current-commit-tagged: true
    source-branches:
    - main
    track-merge-message: true
    regex: ^tags?[/-](?<BranchName>.+)
    is-main-branch: true

This treats tags as main branches when calculating the version.

Caveat Emptor

This works if you ONLY tag your main branch. If you are in the habit of tagging other branches, this will not work for you. However, I only ever release from main branches, and I am in a fix-forward scenario, so this works for me. If you use release/* branches and need builds from there, you may need additional GitVersion configuration to get the correct version numbers to generate.


Posted

in

by