I am configuring semantic versioning with GitLab for my dotnet core apps and netstandard 2.0 packages.
After reading quite a bit of opinions, some of them contradictory, this is what is clear to me.
A semantic version should be something like
M.m.P.B-abc123
where
M
is major versionm
is minor versionP
is patch versionB
is build version (optional)-abc123
is suffix (optional) in case I use pre-releases. It must start with letter
So the following package versions would be valid:
1.0.0
1.0.1.20190301123
1.0.1.20190301123-beta
1.0.1-rc1
I have the following gitlab script for my versioning
#Stages
stages:
- ci
- pack
#Global variables
variables:
GITLAB_RUNNER_DOTNET_CORE: mcr.microsoft.com/dotnet/core/sdk:2.2
NUGET_REPOSITORY: $NEXUS_NUGET_REPOSITORY
NUGET_API_KEY: $NEXUS_API_KEY
NUGET_FOLDER_NAME: nupkgs
#Docker image
image: $GITLAB_RUNNER_DOTNET_CORE
#Jobs
ci:
stage: ci
script:
- dotnet restore --no-cache --force
- dotnet build --configuration Release
- dotnet vstest *Tests/bin/Release/**/*Tests.dll
pack-beta-nuget:
stage: pack
script:
- export VERSION_SUFFIX=beta$CI_PIPELINE_ID
- dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME --version-suffix $VERSION_SUFFIX --include-symbols
- dotnet nuget push **/*.nupkg --api-key $NUGET_API_KEY --source $NUGET_REPOSITORY
except:
- master
pack-nuget:
stage: pack
script:
- dotnet restore
- dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME
- dotnet nuget push **/*.nupkg --api-key $NUGET_API_KEY --source $NUGET_REPOSITORY
only:
- master
This generates packages such as:
1.0.0
for master branch (stable or production ready) and 1.0.0-beta1234567
for any other branch.
The problem with my approach is that I have VS solutions with multiple projects, each project will be a nuget package and each one has its own version. Sometimes I modify one project but not the other, therefore in theory I shouldn't need to produce a new artifact of the project that I didn't touch nor a new version, of course.
Right now my nuget repository prevents overwriting packages, so If there is a XXX.YYY 1.0.0
and I generate another XXX.YYY 1.0.0
and push it to the repository, it will throw an error and the pipeline will fail.
I have thought that maybe it's not such a bad idea to generate a new package each time I run the CI/CD pipeline, so I considered introducing the build number and have something like XXX.YYY 1.0.0.12345
and, even if I don't touch anything there, the next time a new package XXX.YYY 1.0.0.123499
would be produced.
Is this a correct approach in a continuous deployment scenario? or should I look for a way to make my script smarter and not to produce a new artifact if there is already one with the same version in my nuget repository?
Assuming it's ok to use build numbers always, how do I make sure that only the build number is retrieved from the pipeline but the M.m.P
version numbers remain in my csproj as per the following?
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Description>Whatever</Description>
<VersionPrefix>1.0.1</VersionPrefix>
</PropertyGroup>
</Project>
I would need something like:
dotnet pack *.sln --configuration Release -p:PackageVersion=$FIXED_VERSION.$CI_PIPELINE_ID --output nupkg
but I don't know how to retrieve the <VersionPrefix>
content from the csproj through the CLI.
Any advice, good read or solution for my approach assuming it's valid?
Thanks