Injecting pre-release versions into CSPROJ NuPkg generation - msbuild

I'm using the new CSPROJ schema introduced in Visual Studio 2017.
Additionally, I use this to create a NuPkg for my assembly.
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>MyComponent</PackageId>
<Version>2.1.0</Version>
.
.
.
</PropertyGroup>
I'm using VSTS to build my solution and I'd like to use the build to control the package quality, by adding a pre-release designation to the tag. Something like this:
<Version>2.1.0$(VERSIONSUFFIX)</Version>
To yield package names such as:
MyComponent.2.1.0-alpha-12345.nupkg
MyComponent.2.1.0-beta-67890.nupkg
MyComponent.2.1.0.nupkg
This works ok, but I found a nasty side effect - if I edit the version number interactively in Visual Studio it strips the $(VERSIONSUFFIX) placeholder. The only way I can update the version number is to edit the CSPROJ directly.
Is there a better way of allowing the build to control the NuPkg generation?
Thanks
-John

The editor will always change Version and remove all customisations.
The suggested way of the new SDK is to set VersionPrefix in the build and VersionSuffix - if set - will be appended to it.
So you'd have
<VersionPrefix>1.2.3</VersionPrefix>
and could build using -p:VersionSuffix=beta-123 to produce a 1.2.3-beta-123.nupkg file.
But editing in VS properties becomes impossible in any way.

You can use build variables to specify the package version and prefix version in NuGet pack task as you need.
If you want to use assembly version for the package version and change the prefix version as you want, you can use below steps:
1. Get assembly version
You can add the task Assembly Info Reader, then you can get the assembly version by the variable $(ASSEMBLYINFO.ASSEMBLYVERSION).
2. Define package version and prefix version as you need
You can define a variable in your build definition to specify the prefix version only. Such as the variable ver with the prefix part beta-1.1.
Add a PowerShell task to combine $(ASSEMBLYINFO.ASSEMBLYVERSION) and the prefix version together for packing nuget package. The PowerShell script can be:
Write-Host "##vso[task.setvariable variable=ver]$(ASSEMBLYINFO.ASSEMBLYVERSION)-$(ver)"
So the variable $(ver) contains the version with prefix version.
3. Specify the defined version with prefix for the package to be pack
In NuGet pack task, select Use an environment variable for Automatic package versioning option and specify ver as the Environment variable.
Then the packed package will as the format MyComponent.2.1.0-beta-1.1.nupkg etc.

Related

Create a nuget package with GeneratePackageOnBuild and version patching

What I've been strugling with for some time:
I have a "traditional" (i.e. non-SDK) csproj file. I want to create a nuget package. That's easy but devil hides in the details and I end up in the following catch-22
I can manually call nuget pack .\Foo.csproj, with or without a nuspec file, but then I get the dreaded NU5128 error. The chosen answer suggests to simply ignore the error. I would happily do that, but after publishing the package locally, I noticed that the dependencies are not included. Though there is one dependency to JSON.net that I added for the sake of testing. The same error appears in AppVeyor if I configure my yml to create the package.
I can specify all the packaging related properties in the .csproj file by setting GeneratePackageOnBuild to true. It works and takes the dependencies right but then I can't patch the version like I could do with the replacement tokens of nuspec. The version defaults to 1.0.0.0 even if I change it in the AssemblyInfo.cs to 1.2.3.4.
Notes
This answer suggests that nuspec and csproj configuration can coexist and they are merged. The question is from 2013 so I guess it's not referring to SDK projects. Unfortunately that's not the case for me.
I tried adding a <NuspecFile> in the csproj but then it seems that replacement tokens don't work and I get the error described here. Probably because this instructed nuget to run pack on the nuspec instead of running it on csproj and merge the nuspec. I can't know for sure though as setting the build verbosity to Detailed didn't help to understand what nuget pack tried to do.
Getting the AssemblyInformationalVersion in msbuild and use it straight to the <Version> property isn't as straightforward as one might think and it also defeats the purpose as $version$ is doing exactly that according to the documentation:
AssemblyInformationalVersion if present, otherwise AssemblyVersion
Is there a way to really "merge" .csproj and .nuspec with $version$ patching and get the dependencies in the nuspec right?
So far the best course of action was to convert the project to SDK format. It has several advantages. Less configuration, no need for .nuspec file, no need for AssemblyInfo.cs or VersionInfo.cs files, .nupkg dependencies are correct and AppVeyor can patch directly the .csproj file if it's an SDK project file.
Not a solution per se if one wants to keep the legacy format, but it gets you going with the CI/CD instead of having you fighting with tools.

Overriding nuget package name when using "nuget pack" with a visual studio project

I am currently generating nuget packages by passing in a csproj file instead of a nuspec file. The problem is that I need to change the name of the nuget package to avoid conflicts with another project.
This is the command I'm running:
"C:\Program Files\dotnet\dotnet.exe" pack C:\VSTS\Agent\_work\1\s\src\MyProject\MyProject.csproj --include-symbols --include-source --output C:\VSTS\Agent\_work\1\a --no-build /p:Configuration=debug --include-symbols --include-source /p:PackageVersion=2018.10.11.3
I tried appending the following to the command, but it seems to be ignored:
/p:Id=ThisIsWhatThePackageNameShouldBe
And also tried changing the assembly name in the project (but not the project name), and then doing this:
/p:Id=$(AssemblyName)
But this was also ignored.
Something automatically added a <PackageId> element into the csproj file, and that was taking precedence. I updated this value to what I want the package named and now it's working as expected.
I'm guessing the reason /p:Id argument was being ignored, was because it might have needed to be /p:PackageId, instead.

How can I get GitVersion /UpdateAssemblyInfo to work with ASP.NET Core 2.0 project

We have been using a Bamboo build server for a while now and we have GitVersion installed so it can be selected as a task in the Build plan. We typically use the /UpdateAssembleInfo argument when we run the task. For .NET Framework projects, this would update the assemblyinfo file in the source with the bamboo versioning settings so the .NET assemblies had the same version info as our Bamboo builds and subsequent Bamboo deployment, allowing us to know the version of the deployed project in the field by examining the assembly file properties. This was all working quite well.
However, we are now building and deploying .NET Core 2.0 solutions and are finding that GitVersion /UpdateAssemblyInfo is not working.
I searched for a fix for .NET Core but was only able to find solutions that involved using the project.json file, which is no longer used with .NET Core 2.0 ( it changed to the *.csproj file).
I looked at http://gitversion.readthedocs.io/en/latest/usage/command-line/ and I tried running
gitversion.exe /UpdateAssemblyInfo MyProjectName.AssemblyInfo.cs /EnsureAssemblyInfo
where MyProjectName represents the actual project name suffix for the assemblyinfo.cs file in the .NET Core 2.0 ..\\obj\release\netcoreapp2.0 folder. But it did not update that file.
I have to assume that there has to be a solution for using GitVersion with Bamboo and.NET Core 2.0 but I am having a hard time finding one.
Any ideas?
The latest version of GitVersion provides /updateprojectfiles switch to update version info in the Sdk-style .csproj/.vbproj/.fsproj recursively.
From GitVersion/Usage/CommandLine/Arguments:
/updateprojectfiles
Will recursively search for all project files
(.csproj/.vbproj/.fsproj) files in the git repo and update them
Note: This is only compatible with the newer Sdk projects
It produces the needed attributes even if they are not present in the project files, resulting in following properties:
<Project>
<PropertyGroup>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<InformationalVersion>1.0.0-versionNumber.N+Branch.branchName.Sha.commitId</InformationalVersion>
<Version>1.0.0-versionNumberNNNN</Version>
</PropertyGroup>
As a workaround, you may consider specifying the assembly info as project properties in .csproj
<PropertyGroup>
<Version>1.2.3.4</Version>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
...
</PropertyGroup>
and then setting values during dotnet build. In addition to its options, the dotnet build command accepts MSBuild options like /property
/property:name=value
/p:name=value
Set or override the specified project-level properties, where name is the property name and value is the property value. Specify each property separately, or use a semicolon or comma to separate multiple properties.
So your build command will be something like
dotnet build /p:Version=1.2.3.4;AssemblyVersion=1.2.3.4

CPack: How to specify different package versions for components?

I have a CMake project to build multiple shared libraries and tools, most of these under subdirectories:
add_directory(libFirst)
add_directory(libSecond)
add_directory(myTool)
# etc...
The install(TARGET "someTarget" COMPONENT "someTarget" ...) rules are in the respective subdirectory/CMakeLists.txt files.
I would like to generate Debian packages for all of these using a make package command from the build directory. I have CPACK_DEB_COMPONENT_INSTALL set to ON.
The problem I'm facing, is that not all of the targets have the same VERSION and/or SOVERSION. For example, libFirst is at version 1.0.0.0 and libSecond is version 4.3.0.0. This means that the generated packages should also have different version, but the only way I've found to specify the version is to specify the CPACK_PACKAGE_VERSION_MAJOR, CPACK_PACKAGE_VERSION_MINOR and CPACK_PACKAGE_VERSION_PATCH variables (and perhaps the internal CPACK_PACKAGE_VERSION variable), which set the version for all generated packages.
Is there a way to set package versions per-component, for example by setting some variables similarly to the other CPACK_COMPONENT_<COMPONENT>_* or CPACK_DEBIAN_<COMPONENT>_* variables?
I don't think this is possible at the moment but I have created a merge-request (https://gitlab.kitware.com/cmake/cmake/merge_requests/2305) which provides this functionality.
I hope it will get approved but in the meantime you can locally change your CPackDeb.cmake as shown in this diff: https://gitlab.kitware.com/cmake/cmake/merge_requests/2305/diffs. The default location of that file is in /usr/share/cmake/Modules/CPackDeb.cmake.

How to set version and build number from build server and also update an assembly with this version?

I would like to create a setup project based on WiX which does the following (as well as creating the installation package):
callable from msbuild running on a CI build server (Hudson)
take a version number from some asset in either the setup project or the main assembly
take the current build number from the CI system
create a full product version number [version].[build] such as 1.3.432
store this value in an asset (e.g. the main assembly) is such a way that it can be read out at run time and displayed on the splash window
I have tried a number of approaches and googled a lot but have not found a workable solution. Can anyone help?
The WiX toolset does this by creating a version.cs, a version.h and a version.wxi during the MSBuild then including those files in all the projects. That way our executable can print out their version when you run something like candle.exe -? and all of the bundles and .msi packages have their versions set correctly.
You can see how we do this in tools\WixBuild.Version.targets (here). It would straight forward to override the properties in WixBuild.Version.targets with properties passed via the command-line to MSBuild via Hudson if you wanted.