I would like to integrate an automated versioning system in my ASP.NET project. For each release, it should have a version number based on the previous release. I am planning to integrate Gitversion https://gitversion.net/. Does anyone use it in your projects? For the CI/CD pipeline we have teamcity and octopus deploy.
What is the best practice for automated software release versions?
Thanks in advance
As one of the maintainers of GitVersion, I'm obviously biased, but since you're asking how to use GitVersion to implement a "best practice for automated software release", I'm going to unashamedly give you a textual description of a talk I've done on how I prefer to version and release software with GitVersion, TeamCity and Octopus Deploy.
Developer Workflow
The first thing you should figure out is what kind of developer workflow you want for your software. GitVersion supports Git Flow and many simplified variants of it, and GitHub Flow (as well as many other trunk based development flows). Which workflow you should choose depends on what type of software you are developing, your team and most importantly; your personal preference.
Once you have chosen your workflow, you can configure which mode GitVersion should operate under.
Version Source
GitVersion works by calculating a version number from your Git repository. This means that you should not commit a version number to Git in any shape or form. Not within a package.json, pom.xml, .csproj, or any other build- or project-related file that often mandates the existence of a version number.
Versioning
Instead, you should allow GitVersion to produce a version number based on the Git history, using the currently checked out commit as its starting point, and searching through the parents and their tags to calculate an appropriate version number for the current commit. This version number can then be used in any way you want in your build pipeline. You can, for instance, write GitVersion's FullSemVer variable to package.json by executing the following command:
npm version $GitVersion_FullSemVer
If you are developing on the .NET platform, it's also possible to use GitVersion to patch your AssemblyInfo.cs files so the calculated version number is compiled into your assemblies. With InformationalVersion containing the SHA of the Git commit being built and versioned, you'll be able to identify the exact origin of a compiled assembly.
Build
Once you have your workflow in order and GitVersion has a good source of information to use for its versioning, you can go ahead and create a build pipeline for your software. A typical build pipeline will look something like this:
git clone. (Ensure that the clone is complete and not shallow or a detached HEAD. See requirements for more information.)
GitVersion. Execute GitVersion by whichever means make most sense to your environment.
Patch. Patch the version number created by GitVersion in step 2 into every file in your repository that makes sense, such as AssemblyInfo.cs, package.json, etc.
Build. Perform the build of your software.
Test. Run tests that ensure the quality of the software.
Package. Create a package of your software, using the version number created by GitVersion in step 2.
Release. Release the package using the package management software of your choice, such as Octopus Deploy, npm, nuget, composer, or similar.
Test. Perform automatic tests of the released software, if possible. If successful, it's possible to automatically promote the released software to other environments, if applicable.
Through GitVersion's built-in support for build servers, the calculated version number will also be promoted to the build server to version the build itself. This will be done automatically on TeamCity, for instance. In TeamCity, I recommend that you run GitVersion as its own build configuration exposing the required variables which can then be used in dependent build configurations later on.
Release
Once you have a built artifact containing the version number generated by GitVersion, you can use the same version number to create a package, create a release and deploy the release in Octopus Deploy.
You told you want to integrate an automated versioning system? I would like to throw my hat in the ring.
I am author of Vernuntii, a simple semantic versioning library with git integration.
The answer of #Asbjørn told you already about the best practices for example choosing a workflow that is suited for your project.
The main part a versioning tool like GitVesion or Vernuntii is to generate a suitable NEXT VERSION based on (non-)existing git tags.
So at the end of the day it is a matter of taste what kind of complexity you want HOW the NEXT VERSION is calculated.
So when you want cross-branch versioning, then you are good to go with GitVersion, but if you don't need that kind of complexity then you can try a single-branch versioning like it is implemented in Vernuntii.
For more informations take a look at the README.md of Vernuntii.
Here, for giving you my impression of versioning tools and their complexity, let me give you a list (sorted from least complex to most complex):
MinVer
Verlite
Vernuntii
Nerdbank.GitVersioning
GitVersion
A fun fact beside: all libraries from top to Vernuntii also allows to calculate the next version from detached HEAD.
Related
I have yet to find clear guidance on semantically versioning software releases using Azure DevOps (Server) CI/CD.
My basic understanding is that I would set up a CI pipeline for our team so that we get the benefits of build failure notifications, test execution, code coverage, static code analysis and even more goodies.
The CD pipeline picks up on the CI pipeline, rolling out the artifacts on the different environments upon their completion.
Using this approach seems to not make sense to me. What about builds that fail because a dev didn't pay attention or that the team wants to discard? Such builds won't find their way into production but might use up version numbers, leading to gaps in our versioning scheme.
What is your experience or approach for semantically versioning software releases using CI/CD pipelines? Do you cherry-pick builds? Do you have a separate build pipeline for building releases?
Builds that fail don't get deployed. For builds that succeed but fail QA or integration testing when deployed to lower environments, you can put approval gates so that someone has to approve the release before it proceeds to higher environments.
If you build version 1.0.1 of your application and deploy it to dev and it's no good, that doesn't mean that version 1.0.1 doesn't exist. It exists. It was comprised of specific code assets. It was bad, and your users will never see it, but that's fine. If the users see version 1.0.1 jump to 1.0.94, why does it matter?
I am looking for a tool to manage the collection of binary files (input components) that make up a software release. This is a software product and we have released multiple versions each year for the last 20 years. The details and types of files may vary, but this is something many software teams need to manage.
What's a Software Release made of?
A mixture of files go into our software releases, including:
Windows executables/binaries (40 DLLs and 30+ EXE files).
Scripts used by the installer to create a database
API assemblies for various platforms (.NET, ActiveX, and Java)
Documentation files (HTML, PDF, CHM)
Source code for example applications
The full collected files for a single version of the release are about 90MB. Most are built from source code, but some are 3rd party.
Manual Process
Long ago we managed this manually.
When starting each new release the files used to build the last release would be copied to a new folder on a shared drive.
The developers would manually add or update files in this folder (hoping nothing was lost or deleted accidentally).
The software installer script would be compiled using the files in this folder to produce a SETUP.EXE (output).
Iterate steps 2 and 3 during validation & testing until release.
Automatic Process
Some years ago we adopted CI (building our binaries nightly or on-demand).
We resorted to putting 3rd party binaries under version control since they usually don't change as often.
Then we automated the process of collecting & updating files for a release based on the CI build outputs. Finally we were able to automate the construction of our SETUP.EXE.
Remaining Gaps
Great so far, but this leaves us with two problems:
Rebuilding Assemblies The CI mostly builds projects when something has changed, but when forced it will re-compile a binary that doesn't have any code change. The output is a fresh build of a binary we've previously tested (hint: should we always trust these are equivalent?).
Latest vs Stable Mostly our CI machine builds the latest versions of each project. In some cases this is ok, but often we want to release an older tested or stable version. To do this we have separate CI projects for the latest and stable builds - this works but is clumsy.
Thanks for your patience if you've got this far :-)
I Still Haven't Found What I'm Looking For
After some time searching for solutions it seems it might be easier to build our own solution, but surely someone else has solved these problems before!?
What we want is a way to store and manage binary files (either outputs from CI, or 3rd party files) such that each is tagged with a version (v1.2.3.4) that allows:
The CI to publish new versions of each binary (but reject rebuilt versions that already exist).
The development team to make a recipe for a software release (kinda like NuGet packages.config) that specifies components to include:
package name
version
path/destination in the release folder
The Automatic package script to use the recipe collect the required files, and compile the install package (e.g. SETUP.EXE).
I am aware of past debates about storing binaries in a VCS. For now I am looking for a better solution. That approach does not appear ideal for long-term ongoing use (e.g. how to prune old binaries)... amongst other issues.
I have tried some artifact repositories currently available. From my investigation these provide a solution for component/artifact storage and version control. However they do not provide tools for managing a list of components/artifacts to include in a software release.
Does anybody out there know of tools for this?
Have you found a way to get your CI infrastructure to address these remaining issues?
If you're using an artifact repository to solve this problem, how do you manage and automate the process?
This is a very broad topic, but it sounds like you want a release management tool (e.g. BuildMaster, developed by my company Inedo), possibly in conjunction with a package management server like ProGet (which you tagged, and is how I discovered this question).
To address some specific questions you have, I'll associate it with a feature that would solve the problem:
A mixture of files go into our software releases, including...
This is handled in BuildMaster with artifacts. This video gives a basic overview of how they are manually added to releases and deployed to a file system: https://inedo.com/support/tutorials/buildmaster/deployments/deploying-a-simple-web-app-to-iis
Of course, once that works to satisfaction, you can automate the import of artifacts from your existing CI tool, create them from a BuildMaster deployment plan itself, pull them from your package server, whatever. Down the line you can also have your CI tool call the BuildMaster release management API to create a release and automatically have it include all the artifacts and components you want (this is what most of our customers do now, i.e. have a build step in TeamCity create a release from a template).
Rebuilding Assemblies ... The output is a fresh build of a binary we've previously tested (hint: should we always trust these are equivalent?)
You can mostly assume they are equivalent functionally, but it's only the times that they are not that problems arise. This is especially true with package managers that do not lock dependencies to specific version numbers (i.e. NuGet, npm). You should be releasing exactly the same binary that was tested in previous environments.
[we want] the development team to make a recipe for a software release (kinda like NuGet packages.config) that specifies components to include:
This is handled with releases. A developer can choose its name, dates, etc., and associate it with a pipeline (i.e. a set of testing stages that the artifacts are deployed to), then can "click the deploy button" and have the automation do all the work.
Releases are grouped by "application", similar to a project in TeamCity. As a more advanced use case, you can use deployables. Deployables are essentially individual components of an application you include in a release; in your case the "Documentation" could be a deployable, and maybe contain an artifact of the .pdf and .docx files. Deployables from other applications (maybe a different team is responsible for them, or whatever) can then be referenced and "included" in a release, or you can reference ones from a past release.
Hopefully that provides some overview and fits your needs. Getting into this space is a bit overwhelming because there are so many terms, technologies, and methodologies, but my advice is to start simple and then slowly build upon it, e.g.:
deploy a single, manually uploaded component through BuildMaster to a share drive, then manually deploy it from there
add a deployment plan that imports the component
add a second plan and associate it with the 2nd stage that takes the uploaded artifact and deploys it to the target, bypassing the need for the share drive
add more deployment plans and associate them with pipeline stages and promote through them all to "close out" a release
add an agent and deploy to that instead of the default localhost server
add more components and segregate their deployment with deployables
add event listeners to email team members at points in the process
start adding approvals if you require gated "sign-offs"
and so on.
We have a Mainline build versioned "x.0.0.r" where we publish a web service using octopus. Our branches are versioned "x.y.z.r" for specific releases. We DO NOT want to publish this web service when building from a branch.
We are using TFS: 2013 xaml build def; msbuild args: "... /p:RunOctoPack=true ..."
Short of setting /p:RunOctoPack=false or removing the OctoPack arguments from the branch build definition, is there any other way to NOT run Octopus? Perhaps in the packages.config file, to say if the version is NOT ".0.0." set "\p:RunOctoPack=false"?
We have missed removing this parameter when branching and cloning the build def and have mistakenly published the web service from the branch a few times. Would like to avoid this going forward.
Thanks,
tom
The deployments you describe are a bit confusing. I think you are wanting to deploy all versions tagged with version 18.x.y.z and not deploy any other version numbers.
Using Channels in Octopus would allow you to achieve this, without adding logic into your build process.
In your deployment process in Octopus, you would have a step that is deployment of your application. This is the one that you only want run when you are deploying version 18.x.
In the Channels section, add a channel and create a version rule for the channel. The package step will be the deployment step created earlier, and the version range will be something like [18.0.0,18.999.999.999)
The Version Rule Design screen gives you the ability to add sample version numbers to test your version expression.
This means that all deployments of version 18 will run the package step, and all others will skip it.
You can also get additional help via the Support channels
I understand that there is currently a feature request for something like this, but I'm hoping that there is some sort of workaround using the current version (1.6)
We build for our dev and test environments from a dev branch in TFS, and build for our QA and Production environments from a release branch in TFS. Since these produce distinct nuget packages, I can't use the same package feed. The deploy package step doesn't seem to have a environment scope option. Is there some other way to say "Deploy package X version Y for Dev/Test, and package A version B for QA/Production?"
You can use the same feed, with the following caveats:
The nugets built from the two branches obviously have to have different (non-colliding) versions. I add the 'dev' suffix to the package built from the 'dev' branch (eg 1.2.3.4-dev), and leave my 'stable' branch bare.
You have to be explicit when you 'create release', because by default Octopus will pick up the highest version nuget available, and that might not be the release you want (stable presumably lags dev). Pick the version of the package you want (and set the deployment version appropriately). If you are creating your release via TeamCity, ensure you use the --packageVersion argument as well as set the release number.
Since the above only works if there's only one package in the release, your deployment process does (unfortunately) have to produce one monolithic nuget, or you will get version-mismatches.
The advantage of this kind of arrangement, of course, is that at a pinch you could push your dev build to QA (or Prod) if the need ever arose.
All this assumes both branches build as the same package of course. You could build different packages between the dev and stable branches (but I don't think I'd recommend this because of duplicating all the Octopus config).
Update: apparently you can use Octo.exe to specify different version numbers across different packages - see https://github.com/OctopusDeploy/Octopus-Tools.
TeamCity is a great CI tool and we also use Semantic Versioning to manage our DLL version for a long time, now we are reaching a idea to integrate TeamCity and Semantic Versioning together, meanwhile we do some research on this topic, Let's say the Version infor like
MajorVersion.MinorVersion.PatchVersion.BuildNumber
The buildNumber we always use teamcity buildnumber, and other 3 versions we maintains within assemblyinfo.cs
the question here is - how can we use teamcity to feed its build number into assemblyinfo.cs, i can find Msbuild support this parameter, and is there any best practice to handle the same thing? and we also would like to feed the whole version into nuget packs as the published version information to our developers
Thanks a lot
I tried to describe the approach that works for me in this article.
http://www.developerfusion.com/article/144809/continuous-integration-using-nuget-and-teamcity/
Notice NuGet doesn't support SemVer fully (yet), e.g. PrereleaseTags combined with build numbers won't work the way you expect it to. I've described a bit of guidance on versioning in Top 10 NuGet (Anti-)Patterns on MSDN.
You can use AssemblyInfo Patcher feature. Build features are configured on the Build Steps page of the build configuration settings. It's documented here. If you have are keep your AssemblyInfo in not standard place you can use MSBuild community task AssemblyInfo to rewrite it by msbuild.
There is a very complete SemVer Build Number meta-runner available as part of the TeamCity meta-runners power pack (https://github.com/JetBrains/meta-runner-power-pack).
Here's a description of the features by the author:
http://johanleino.wordpress.com/2013/10/11/teamcity-meta-runner-semantic-version-build-number/
The SemVer Build Number meta-runner is a runner based on PowerShell. It can (at the time of this posting):
Get version numbers from nuspec (nuget) files.
Use manual version numbers (from parameters if you need that). Overrides other methods.
Include TeamCity build counter.
Include VCS revision.
Translate Git commit hash to short hash.
Ignore Build MetaData if needed.
Logging etc.
Here's a blog post I wrote of how to create version numbers from the first two numbers from AssemblyInfo.cs for a C# .Net project and adding a build counter and branch name to form the complete version number. Can easily be modified for other situations, it's just scripts together with the File Content Replacer build feature.
http://www.meadow.se/wordpress/generating-semantic-version-build-numbers-in-teamcity/
Hope this helps.