11

Running the .NET Core Pack task, how do I get the outputted NuGet package version to auto-increment itself?

So, for example, if my current version is 1.0.0, then the next time I call the Pack task, I would like to see 1.0.1.

I'm using environment build variables with Build.BuildNumber and getting outputs at the moment of e.g. 20180913-.2.0, etc. I would like to establish to a more traditional versioning system.

Jeremy Caney
  • 4,585
  • 13
  • 32
  • 54
The_Chud
  • 877
  • 1
  • 10
  • 17
  • There are some good answers using out-of-the-box capabilities below, including the answer provided and accepted by the OP. That said, if you are using Git and using a branching workflow such as Git Flow or Github Flow, I'd recommend considering [GitVersion](https://github.com/GitTools/GitVersion), which integrates into a project as a NuGet package and has a corresponding Azure DevOps task. It provides a _lot_ of flexibility, and can deterministically determine major, minor, and patch updates based on branch names, tags, and even commit messages. – Jeremy Caney Apr 24 '20 at 20:00

4 Answers4

26

I may have figured it out. For anyone tearing their hair out, try this:

Pack Task:

  • Automatic Package Versioning: Use an environment variable
  • Environment variable: Build.BuildNumber

Then, up in the top menu where you have Tasks, Variables, Triggers, Options, click Options and set:

  • Build number format: 1.0$(Rev:.r)

Save and queue. This will produce e.g. 1.0.1.

(Please Correct me if I am wrong, or if this does not work long-term.)

Jeremy Caney
  • 4,585
  • 13
  • 32
  • 54
The_Chud
  • 877
  • 1
  • 10
  • 17
  • That's the way to go! – Alex Mullans Sep 13 '18 at 17:13
  • 1
    You could [Accept it as an Answer](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work), This can be beneficial to other community members reading this thread. – Andy Li-MSFT Sep 17 '18 at 06:08
  • 2
    My experience on the matter is that if your solution / build definition contains multiple packages your basically forcing all of them to change version even if you changed one. So this will not be good in the long run. – John Dec 30 '18 at 18:28
  • @John, how have you gone about (automatically) versioning only those package sources that have changed when you have **n** number of projects in any given solution built by the pipeline at the solution level? I've been very interested about how to do this without splicing my build to a per csproj basis. – Josh Gust Feb 26 '19 at 01:20
25

From the docs, the variable Rev:.r is the daily build revision count. The accepted "solution" would lead to one day finishing having a version of 1.0.12, then the next day it will be 1.0.1.

If you want a simple incremental and unique semver, use 1.0.$(BuildID).

$(BuildID) is an internal immutable counter for your builds, and thus far cleaner than $(BuildNumber).


BuildID will always be incrementing - no reset. Thus after a minor bump, you'd end up having say 1.2.123 becoming 1.3.124.

If you want to perform this task well, this can be done using npm version or similar, such as pubspec_version for Dart or Flutter builds.

- script: npm version $RELEASE_TYPE

where $RELEASE_TYPE is a variable you can set based on build (ie: CI, PR etc), having a value of major, minor, patch, prerelease etc.

- script: npm version $RELEASE_TYPE
  condition: startsWith(variables['build.sourceBranch'], 'refs/head/release/')
  env:  
    releaseType: minor

Update: Bump Repo Version and Use In Build (using npm)

To have the repo version update, I ended up including npm version as a DevDependency, with it's precommit hook to bump the project version on any commit.

This technique can be applied to other project types, placing them in a subfolder - although can lead to complications with server OS requirements.

To use this version in your build, add this bash script task, which gets and exports the version as a task variable:

v=`node -p "const p = require('./package.json'); p.version;"`
echo "##vso[task.setvariable variable=packageVersion]$v"

.Net Core Task only version

Unfortunately, no repo-bump.

Workaround 1:
jobs:
  - job: versionJob #reads version number from the source file
    steps:
      - powershell: |
          $fv = Get-Content versionFile
          Write-Host ("##vso[task.setvariable variable=versionFromFile;isOutput=true]$fv")
        displayName: 'version from file' 
        name: setVersionStep  


  - job: buildJob # consumes version number, calculates incremental number and set version using assemblyinfo.cs
    dependsOn: versionJob
    variables:
      versionFromFile: $[ dependencies.versionJob.outputs['setVersionStep.versionFromFile'] ] # please note that spaces required between $[ and dependencies
      buildIncrementalNumber: $[ counter(dependencies.versionJob.outputs['setVersionStep.versionFromFile'],1) ] #can't use $versionFromFile here


    steps:
      - powershell: |
          Write-Host ($env:versionFromFile)
          Write-Host ($env:versionFromFile + '.' + $env:buildIncrementalNumber)
        displayName: 'version from file output' 
Workaround 2:

This post describes a couple of others, using version-prefix and automatically applying the BuildNumber as a version-suffix.

greg.arnott
  • 1,492
  • 14
  • 16
  • 1
    what about updating repository with changes? When I try this solution, yes package receives the new version and publishes. But the version tag in package.json still stays at 1.0.0. I tried to create a custom command to tag and push back to repo but no luck so far. – serdar.sanri Dec 31 '18 at 15:21
  • Same question as above, how does people get this back into their repository? – Poul K. Sørensen Jul 25 '19 at 09:08
  • The bit at the start about the "daily" revision count is wrong (although to be fair it's because the docs aren't particularly clear). The only reason it's a daily count in the docs example is because the date is also included in the build number format, and hence the prefix changes. If you have 1.0$(Rev:.r) then it will just keep incrementing the x in 1.0.x every time. – Kntajus Jul 31 '19 at 13:08
  • For the npm, solution, will it commit the updated version? – aniket7824 Sep 05 '19 at 18:08
  • The problem with repo-bumps in Azure is you've typically got triggers mapped on repo changes - else it gets convoluted in ways that produce more problems than they resolve. What worked best was to have a hook that auto-updated version as part of the commit process, then have Azure read + use this value to use through the different steps it is needed. – greg.arnott Sep 21 '20 at 05:11
4

If you're just looking to bump the major, minor or revision version number, using counter operator in a variable is a simple and elegant approach. It will automatically add one to the current value.

Here's what I use:

variables:
  major: '1'
  minor: '0'
  revision: $[counter(variables['minor'], 1)] #this will get reset when minor gets bumped. The number after Counter is the seed number (in my case, I started at 1).
  app_version: '$(major).$(minor).$(revision)'

If you would like to see a real-world 4-job pipeline that uses this, I have one here https://github.com/LanceMcCarthy/DevReachCompanion/blob/master/azure-pipelines.yml

Lance McCarthy
  • 1,777
  • 17
  • 32
  • how does this keep the latest revision number? if you run it now, you will get 1.0.1 and next time you run it, minor is hardcoded 0, it should get again 1.0.1 – Emil May 20 '20 at 22:38
  • The counter operator keeps track of it as a variable in the pipeline. You don't need to manually update it. – Lance McCarthy May 21 '20 at 00:21
  • How to push version `1.1.0`? Minor version needs to be incremented and revision counter have to be reset somehow. – Serhii Shushliapin Jun 05 '20 at 18:47
  • Revision will automatically get reset when you increase minor, c heck out this blog post's example https://stevenknox.net/auto-versioning-nuget-packages-in-azure-devops-pipelines/ – Lance McCarthy Jun 08 '20 at 21:49
2

For me it's enough to set Build number format on Options tab to

$(date:yyyy).$(date:MMdd)$(rev:.r) 

and add next build argument:

/p:Version=1.$(Build.BuildNumber) /p:AssemblyVersion=1.$(Build.BuildNumber)

In this case we manage major version manually, but minor version and build number will be set automatically. Easy to understand what version you have deployed.

Keen
  • 136
  • 3