Add build number to package version with `dotnet pack` in VSTS Build process - versioning

With a .NET Framework library you could specify a version with a wildcard and NUGET pack command would append the build date and version automatically when running a NUGET Build Task in VSTS.
[assembly: AssemblyVersion("1.0.*")]
NUGET PACK would generate a NUPKG file with a version like 1.0.6604.1234 appending the date number and a build ID.
NET Standard issues
In .NET Core and .NET standard the new .csproj format does not support this wildcard format.
We can't package with Nuget.exe (reason: this issue) but we can use dotnet pack except I need to auto-increment the build numbers. The dotnet Build Task in VSTS allows me to wholly replace the version number, but I want to retain the version in the csproj file, and just append a build number (as I used to).
I found that using <VersionPrefix>x.y</VersionPrefix> in the csproj file would work with nuget pack and I could then add the additional parameter VersionSuffix=$(Build.BuildNumber) to the pack task.
All looked good until the first dev updated the project version in the project properties dialog. Visual Studio ignored the VersionPrefix and set the <Version> tag - and the build number fix is ignored because a Version tag exists.
Is there a way to read the Version from the csproj? If so I could set the build property to Version=$(ProjectVersion).$(Build.BuildNumber) ?
Or are there alternative ways to handle auto-incrementing the build version when packaging?

First you can select Use an environment variable for Automatic package versioning, use your defined variable such as temp ($(build.buildNumber)) as Environment variable.
More details take a look at this link: Dotnet pack automatic package versioning build number clarification
Another way is using the "arguments" field in the dotnet CLI task, you can pass additional arguments to the dotnet cli.
Using --version-suffix $(Build.BuildNumber) will pass the build
number as version suffix. Make sure you don't have a <version>
element set in your csproj, but rather a <versionprefix> element.
The built version will look like versionprefix-versionsuffix, so for
example, if you have <versionprefix>1.2.3</versionprefix> and build
number 201805002, the built version will be 1.2.3-201805002. In this case do not select the automatic package versioning.

Thanks to #patricklu-msft for his suggestions.
There is it appears no built-in way to emulate the wildcard behaviour we previously had NUGET pack with dotnet pack, nor was there way to get the <Version> tag out of the project file.
So I've created a new VSTS Build task that does this: VersionTaskReader in the MarketPlace.
This extension can be pointed to a .csproj or .vbproj and will set an environment variable VERSION, and VERSION_BUILD which has the BUILDID appended. You can optionally add a prefix to make each instance different if needed.
For example, if your project contains <Version>1.1</Version> then the VERSION_BUILD would be something like 1.1.8680
Then the dotnet pack task can use the environment variable VERSION_BUILD in the versioning options screen, so that the build number automatically increments.

Related

MSB4062 error publishing .NET7 app with publish profile

This is pretty easy to replicate but also code here:
https://github.com/dominicshaw/dotnet-publish-error
create an empty wpf project using .NET7
create a publish profile for ClickOnce
publish via command line (not visual studio)
Publish profile is almost totally standard (view here)
Command line from project directory:
dotnet publish PublishError.csproj -p:PublishProfile=ClickOnceProfile
Subsequent error:
MSBuild version 17.4.0+18d5aef85 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
C:\Program Files\dotnet\sdk\7.0.100\Microsoft.Common.CurrentVersion.targets(4149,5): error MSB4062: The "Microsoft.Build.Tasks.RequiresFr
amework35SP1Assembly" task could not be loaded from the assembly Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKey
Token=b03f5f7f11d50a3a. Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, a
nd that the task contains a public class that implements Microsoft.Build.Framework.ITask. [C:\Users\shawd\source\repos\PublishError\Publi
shError\PublishError.csproj]
I have the latest SDKs installed and VS2022 up to date. This only happens via command line - I am able to publish from Visual Studio (I am setting up devops, so require command line).
This happens regardless of adding nuget package for Microsoft.Build.Tasks.Core. Note however nuget package v15.1.0.0 is not available - I have tried 15.1.548 and the latest instead.
Totally at a loss! Any ideas very welcome.
Thanks vm
During the tests with your project and files, I finally managed to publish it successfully with the command dotnet publish PublishError.csproj -p:PublishProfile=FolderProfile.
Here is the document for dotnet publish, as is referred,
The preceding example uses the FolderProfile.pubxml file that is found
in the <project_folder>/Properties/PublishProfiles folder. If you
specify a path and file extension when setting the PublishProfile
property, they are ignored. MSBuild by default looks in the
Properties/PublishProfiles folder and assumes the pubxml file
extension.
And I also succeeded with dotnet publish with your project.
==============================
update on 11/19
So I suppose that the issue is resulted from your definition for -p:PublishProfile=ClickOnceProfile,it will change the path where this command would search for the publish file
A partial answer as my workaround for anyone struggling with a similar problem:
I have found it impossible to do this with the dotnet cli but I can do it with MSBuild if I specifically target 17.4 (VS2022). By default, my Azure DevOps Server 2020 capability is the 2019 MSBuild (15.X), so I have to be explicit:
"C:\Program Files\Microsoft Visual Studio\2022\Professional\Msbuild\Current\Bin\MSBuild.exe" /restore /Verbosity:m /t:Publish /p:RuntimeIdentifier=win-x64 /p:configuration=Release /p:PublishProfile=ClickOnceProfile
This works - so in my pipeline I have created a batch file which runs this, then I copy the files to my ClickOnce location.
Not ideal, but a working pipeline.
Interesting side note - this dotnet cli command which should be idenitical (and indeed uses the correct 17.4 MSBuild) - does not work (with the same error):
dotnet msbuild -target:Publish -property:RuntimeIdentifiers=win-x64;Configuration=Release;PublishProfile=ClickOnceProfile

How can I automate supplying a version in appxmanifest?

I am using the desktop bridge for a WPF desktop application and am looking to automate the creation of my msix packages during build. I do not want to store any version information in source control.
The WPF project in the solution uses the gitversion msbuild task to automatically infer the version for my executable every time a build is done.
Unfortunately, I'm not sure if any such similar mechanism exists for .appxmanifest.
My thinking is that it would be nice to have this nicely integrated with the build process, similar to gitversion, but I haven't been able to find any documentation about what my options are during build or the Create App Packages process.
Perhaps there's some transform step during build that I'm not aware of that can be done to the .appxmanifest? Or maybe there's a way to have the version always reflect the version of the executable being bundled?
(MSDN forums question)
Your should modify the .appxmanifest file in your build pipeline before you create the package. After all, it's just a text-based XML file.
If you are using Azure Pipelines, you could accomsplish this using a Powershell task and a counter variable that gets incremented for each build:
pool:
vmImage: vs2017-win2016
variables:
buildPlatform: 'x86'
buildConfiguration: 'release'
major: 1
minor: 0
build: 0
revision: $[counter('rev', 0)]
steps:
- powershell: |
[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
$path = "Msix/Package.appxmanifest"
$doc = [System.Xml.Linq.XDocument]::Load($path)
$xName =
[System.Xml.Linq.XName]
"{http://schemas.microsoft.com/appx/manifest/foundation/windows10}Identity"
$doc.Root.Element($xName).Attribute("Version").Value =
"$(major).$(minor).$(build).$(revision)";
$doc.Save($path)
displayName: 'Version Package Manifest'
+Build, Package and Sign.
Please refer to this MSDN Magazine article for more information and a complete example of how to set up continuous integration (CI), continuous deployment (CD) and automatic updates of sideloaded MSIX packaged WPF applications using Azure Pipelines.
You must update the manifest before packaging. Check out this sample including a powershell script to poke the xml with the gitversion provided. https://github.com/microsoft/devops-for-windows-apps/blob/master/azure-pipelines.yml#L72

display my own tab using command line tool

Before creating a new tab report, i have tried to display the example (with attachement tab) provided on allure-report-plugins repository .
I have downloaded and upgraded the last command-line tool
I have copied the generated attachments-plugin-1.0-SNAPSHOT.jar in the same directory than the allure-cli.jar
I have executed the following command :
java -cp .;attachments-plugin-1.0-SNAPSHOT.jar allure-cli.jar generate path/to/xml
I get the a report but i don't find the new tab with attachements.
How to take into account the plugin.jar with command line tool ? Same question, if i want to use the jenkins plugin to generate report in a CI environnement.
thanks
As I understand CLI Tool is being migrated to Allure core (it already supports plugins). So, you can:
use your own patched version (please have a look at ReportGenerate.java in Allure Core repository)
wait for new version (will create pull request ~next week)
Allure plugins support in Jenkins is in progress.
(Already supported in Allure maven plugin.)

How to sync version numbers for nuget packages when targeting multiple project files

I have a project which has three project files targeting various .net versions (mylib.net20.csproj, mylib.net40.csproj, and mylib.net40-client.csproj). I have a single nuspec file named mylib.nuspec for packaging them all together.
It might help to see the files section of the nuspec file, so here it is:
<files>
<file src="bin\net20\*.dll" target="lib\net20\" />
<file src="bin\net40-client\*.dll" target="lib\net40-client\" />
<file src="bin\net40\*.dll" target="lib\net40\" />
</files>
Right now I use a static version number in the nuspec file and I can successfully package everything by running nuget pack mylib.nuspec. However, I would like to start using $version$ so I don't have to remember to update the version number in two places.
If I simply change the version number to $version$, and build in the same way I get the predictable error:
Attempting to build package from 'mylib.nuspec'.
The replacement token 'version' has no value.
If I use $version$ and package with nuget pack mylib.net40.csproj, it is successful, but I get a package that completely ignores the nuspec file.
Q: What can I do to get the $version$ variable to work?
Technically, I could rename my nuspec file to mylib.net20.nuspec and then package with nuget pack mylib.net20.nuspec. I really don't want to rename my nuspec file in this way though.
creating a package can be done two ways
Using nuspec directly
Using your csproj file , which in fact uses your nuspec file at run time.
First case is pretty straight forward where all metadata defined in nuspec file will be considered for package creation.
nuget pack nuspecfilename.nuspec
On executing above command all hard coded values in your nuspec file will be used for package creation
Above Procedure uses nuspec file directly.
Now let come to your requirement , Using token $version$ in your nuspec files.
In order to work with tokens rather than hard coded values , we need to use csproj file while running nuget pack command.
nuget pack nameofyourprojectfile.csproj -p "configuration=Release;platform=x64"
I'll explain the command i have used ,the concept of using csproj file while generating a package is it will replace all tokens in nuspec file at the run time.
Your corresponding assembly info file to your csproj file will contain required metadata of version which will be replaced at run time.
-p is parameters to be used at run time , here i have assumed that my proj file builds in release and x64 platform so i have passed that at run time so nuget which for artifacts to bundle accordingly.
please refer Here for more details on how to create nuget packages from csproj.
But Ideally when you package from csproj file your nuspec file will be used at run time so ,technically nuspec file should have same name as that of your csproj file.
so requirement of dealing with multiple project files with different frame work may not be achieved with single nuspec file. you need to have individual nuspec accordingly to achieve this.
But if you still want to stick with same nuspec file with out renaming it or making changes to it.
i would suggest passing version at run time
nuget pack nameofnuspec.nuspec -v 1.3.4.5
-v - is version , or you can use -version as well followed by the version of your choice.
after running above command nuget package will be created with the version specified.
to check nuget package created , rename it .zip file and check ...)

How to compare two files in Notepad++

I want to compare values from two different files.
In Notepad++ version 5.0.3 we had shortcut button Alt+d but in version 6.6.8 I cannot find any option to compare.
Also let me know which version is most stable.
There is the "Compare" plugin. You can install it via Plugins > Plugin Manager.
Alternatively you can install a specialized file compare software like WinMerge.
Update:
for Notepad++ 7.5 and above use Compare v2.0.0
for Notepad++ 7.7 and above use Compare v2.0.0 for Notepad++ 7.7, if you need to install manually follow the description below, otherwise use "Plugin Admin".
I use Compare plugin 2 for notepad++ 7.5 and newer versions. Notepad++ 7.5 and newer versions does not have plugin manager. You have to download and install plugins manually. And YES it matters if you use 64bit or 32bit (86x).
So Keep in mind, if you use 64 bit version of Notepad++, you should also use 64 bit version of plugin, and the same valid for 32bit.
I wrote a guideline how to install it:
Start your Notepad++ as administrator mode.
Press F1 to find out if your Notepad++ is 64bit or 32bit (86x), hence you need to download the correct plugin version. Download Compare-plugin 2.
Unzip Compare-plugin in temporary folder.
Import plugin from the temporary folder.
The plugin should appear under Plugins menu.
Note:
It is also possible to drag and drop the plugin .dll file
directly in plugin folder.
64bit: %programfiles%\Notepad++\plugins
32bit: %programfiles(x86)%\Notepad++\plugins
Update
Thanks to #TylerH with this update: Notepad++ Now has "Plugin Admin" as a replacement for the old Plugin Manager. But this method (answer) is still valid for adding plugins manually for almost any Notepad++ plugins.
Disclaimer: the link of this guideline refer to my personal web site.
I give the answer because I need to compare 2 files in notepad++ and there is no option available.
So first enable the plugin manager as asked by question here, Then follow this step to compare 2 files which is free in this software.
1.open notepad++, go to
Plugin -> Plugin Manager -> Show Plugin Manager
2.Show the available plugin list, choose Compare and Install
3.Restart Notepad++.
http://www.technicaloverload.com/compare-two-files-using-notepad/
Alternatively, you can install "SourceForge Notepad++ Compare Plugin 1.5.6".
It provides compare functionality between two files and show the differences between two files.
Link to refer : https://sourceforge.net/projects/npp-compare/files/1.5.6/
Update (2022-09-22): use the ComparePlus plug-in, and not the outdated Compare plug-in.
Demo:
Open 2 files side-by-side
Plug-ins -> ComparePlus -> Compare:
Features:
The Compare plug-in is no longer maintained:
Compare plugin will not be supported anymore (at least by me) because I consider it obsolete and because (as Peter Jones said) I am working on another plugin - ComparePlus that is Compare plugin’s successor.
For example, the Compare plug-in doesn't show the compared text clearly with dark mode:
2018 10 25. Update.
Notepad++ 7.5.8 does not have plugin manager by default. You have to download plugins manually.
Keep in mind, if you use 64 bit version of Notepad++, you should also use 64 bit version of plugin. I had a similar issue here.
If you installed Notepad++ with the Plugin Manager then its easy: open notepad++, go to
Plugin -> Plugin Manager -> Show Plugin Manager and then search/install the Plugin „compare“. Restart Notepad++
Tutorial:
https://youtu.be/8ESbIZbXI7I
If you do not have installed the Plugin Manager:
download the plugin manually :
https://github.com/pnedev/compare-plugin/releases/tag/v2.0.0_npp7.7
-Copy the contents of the zip file into Notepad++'s plugins installation folder (%Notepad++_program_folder%\Plugins). use the correct archive version based on your Notepad++ architecture - x86 or x64.
restart Notepad++
If you are looking for the latest release of Compare, here it is:
https://github.com/pnedev/compare-plugin/releases/latest

Resources