Auto-increment NuGet package version - nuget

Is there a way to auto-increment the NuGet package version when using "Generate NuGetPackage on Build" in C#/.NET Standard 2.1?

If you build and publish the project by a build server, and manage the version by Git, you can try the MSBuild GitVersion task. For a similar issue, see here.
But if you just want a clean build and publish in local Visual Studio without using Git, then I'm afraid for now there isn't any Visual Studio option or MSBuild task to support this behavior. You can go to the Developer Community to suggest the feature because it's a meaningful idea, but currently it's not available.
Also, as from hints from Martin and Alexandre, you can add this script into xx.csproj:
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetPackageVersion</GenerateNuspecDependsOn>
</PropertyGroup>
<Target Name="SetPackageVersion" DependsOnTargets="Build">
<PropertyGroup>
<!-- <PackageVersion>$([System.DateTime]::Now.ToString("yyyy.MM.dd.HHmmss"))</PackageVersion> -->
<!-- You can customize the format and the rule about how version increases here. -->
<PackageVersion>$([System.DateTime]::Now.ToString("1.MM.dd"))</PackageVersion>
</PropertyGroup>
</Target>
Then when you publish the package today, its version is 1.10.4. Tomorrow for 1.10.5, it works if you don't really need to publish different versions of one package in a day. Also you can customize the script to define your version-increasing rule.
If targeting multiple frameworks, see Build project with multiple targetframeworks in TFS as a NuGet package
This works when setting the assembly version to wildcard.
<Deterministic>false</Deterministic>
<AssemblyVersion>3.0.*</AssemblyVersion>

As of toDate with Visual Studio 2019 and .NET 5.0, what LoLance suggested about scripting the increment inside the .csproj file still works, and we now can use shell commands directly inside the package definition's PropertyGroup for multiple fields, as shown in the picture below:

Related

.Net Core 2 - Let Nuget package create default ruleset and implement it

I'm interested in using the Stylecop.Analyzers nuget package, because it integrates Stylecop with Roslyn and because of that builds will fail if they do not meet the defined requirements. The idea that I have is as follows:
I create a custom nuget package containing a stylecop.json file and a Stylecop.Analyzers.ruleset file, with the package having a dependency on Stylecop.Analyzers.
I am able to get this to work in a .Net Core 2 project if I add the mentioned files manually and make the following changes to the .csproj:
<PropertyGroup>
<CodeAnalysisRuleSet>Stylecop.Analyzers.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
and the following for the stylecop.json file:
<ItemGroup>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
Now I would like to automate this with the Nuget package, so I can easily install and use this in a variety of solutions/projects. Unfortunately I am not able to do this.
The first problem I run into is that I'm unable to update the .csproj from a nuget package. I tried to do so by creating the folder structure mentioned in the following thread: Providing a code analysis ruleset to a .net core project through NuGet
This did not seem to do anything...
Next I tried to solve this by using a Powershell install script that transforms the .csproj. I cloned the following project on Github: https://github.com/FantasticFiasco/csproj-ignition that uses Powershell to update the csproj. I tested this and I did get it to work for .Net Framework projects, but unfortunately not for my .Net Core 2 project.
So in short: does anyone know how to transform the .csproj of a .Net Core 2 project through the installation of a nuget package or is this mission impossible?

How do I set the build-specific version number for a projectReference so that the NuGet package dependency lists the correct version

Using the new CSProj format in Visual Studio 2017, I have written a targets file to handle a new Configuration called CreateLocalPackages, which has the build create a NuGet package in a specific local folder and has it automatically increment its version number to be one higher than the highest number on any of the solution's packages in that folder.
My solution has several projects, each builds a NuGet package, with some having a dependency on other projects in the solution.
For example, with these files in the local package directory:
BaseLibrary.2.1.0.1-betalocal.nupkg
BaseLibrary.2.1.0.1-betalocal.symbols.nupkg
BaseLibrary.Specialized.2.1.0.1-betalocal.nupkg
BaseLibrary.Specialized.2.1.0.1-betalocal.symbols.nupkg
It would choose to create these packages the next time that the CreateLocalPackages Configuration was built clean:
BaseLibrary.2.1.0.2-betalocal.nupkg
BaseLibrary.2.1.0.2-betalocal.symbols.nupkg
BaseLibrary.Specialized.2.1.0.2-betalocal.nupkg
BaseLibrary.Specialized.2.1.0.2-betalocal.symbols.nupkg
I have gotten this working great, except for the fact that Visual Studio seems to create the BaseLibrary\BaseLibrary.Specialized\obj\project.assets.json file before I can hook into a MSBuild target and change $(Version) to 2.1.0.2, causing BaseLibrary.Specialized.2.1.0.2-betalocal.nupkg to instead just reference this dependency: BaseLibrary.2.1.0-betalocal. Visual Studio appears to generate project.assets.json during the NuGet restore step that it does before calling MSBuild to build the projects.
I have tried running my version number logic BeforeTargets="CollectPackageReferences;_ComputeTargetFrameworkItems" in order to get called early in the Restore target chain, but it doesn't seem like Visual Studio calls MSBuild /t:Restore in order to restore NuGet package references (and generate project.assets.json). I don't know if it has its own logic, or if it calls another tool.
I would like to be able to just tell VS to Rebuild and have it figure out the new version, build and pack everything, with the correct dependency versions listed, as well.
How do I set the build-specific version number for a projectReference so that the NuGet package dependency lists the correct version
If I understand you correct, you want call the version number logic target CreateLocalPackages before VS/MSBuild Restore target.
You can add an MSBuild Target that runs before the target Restore or _GenerateRestoreProjectSpec by following code snippet in your MSBuild .*csproj file:
<Target Name="VersionNumberLogicBeforeRestore"
BeforeTargets="Restore">
<Message Text="Version Number Logic Before Restore!" Importance="high" />
</Target>
Or
<Target Name="VersionNumberLogicBeforeRestore"
BeforeTargets="_GenerateRestoreProjectSpec">
<Message Text="Version Number Logic Before Restore!" Importance="high" />
</Target>
However, this only does work for dotnet cli not in Visual Studio.
dotnet restore "xx.csproj"
Besides, The NuGet restore changes will be part of 15.4 if it still makes it in. Otherwise 15.5.
See Add support for pre restore MSBuild target that Visual Studio triggers for detail info.
So, at this moment, we have to use dotnet cli to call the the version number logic target before Restore target and you can also use dotnet cli build the project.

How to package a .NET library that targets the Universal Windows Platform and depends on Visual Studio extension SDKs?

How do I package a Universal Windows Platform library that depends on Visual Studio extension SDKs such as the Microsoft Player Framework?
Specifically, I want users of my library to be able to use it immediately after pressing the Install button in NuGet, without having to manually add the extension SDKs to their projects. Assuming, of course, that the appropriate extension SDKs are actually installed.
This is a series of questions and answers that document my findings on the topic of modern NuGet package authoring, focusing especially on the changes introduced with NuGet 3. You may also be interested in some related questions:
How to package a .NET Framework library?
How to package a .NET library targeting the Universal Windows Platform?
How to package a portable .NET library targeting .NET Core?
How to package a .NET library targeting .NET Framework and Universal Windows Platform and include platform-specific functionality?
How to package a multi-architecture .NET library that targets the Universal Windows Platform?
This answer builds upon the principles of .NET Framework library packaging and the principles of Universal Windows Platform library packaging. Read the linked answers first to better understand the following.
When you directly reference a Visual Studio extension SDK in a project, the following snippet is included in the .csproj file:
<SDKReference Include="Microsoft.PlayerFramework.Xaml.UWP, Version=3.0.0.2">
<Name>Microsoft Player Framework</Name>
</SDKReference>
NuGet offers functionality that enables an equivalent action to be performed when installing a NuGet package. The first thing you must do is to create in your project a .targets file (e.g. MyLibraryUsingExtensionSdk.targets) that contains the relevant XML to be added to the project into which your library is installed. You will want to copy the relevant <SDKReference> element from your library's .csproj file and also include any parent elements, creating a full XML document that can be merged.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SDKReference Include="Microsoft.PlayerFramework.Xaml.UWP, Version=3.0.0.2">
<Name>Microsoft Player Framework</Name>
</SDKReference>
</ItemGroup>
</Project>
Set the build action of this file to None, to avoid it being needlessly touched by the build process.
By including this .targets file in the appropriate location in the NuGet package structure, it will be automatically merged at runtime into projects that make use of your library. You want to achieve the following package structure:
+---build
| \---uap10.0
| MyLibraryUsingExtensionSdk.targets
|
\---lib
\---uap10.0
| MyLibraryUsingExtensionSdk.dll
| MyLibraryUsingExtensionSdk.pdb
| MyLibraryUsingExtensionSdk.pri
| MyLibraryUsingExtensionSdk.XML
|
\---MyLibraryUsingExtensionSdk
ExampleControl.xaml
MyLibraryUsingExtensionSdk.xr.xml
You can create such a package using the following .nuspec template:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.2">
<id>Example.MyLibraryUsingExtensionSdk</id>
<version>1.0.0</version>
<authors>Firstname Lastname</authors>
<description>Example of a simple UWP library that depends on an extension SDK.</description>
</metadata>
<files>
<!-- Causes referencing this NuGet package to also automatically reference the relevant extension SDKs. -->
<file src="MyLibraryUsingExtensionSdk.targets" target="build\uap10.0\MyLibraryUsingExtensionSdk.targets" />
<file src="..\bin\Release\MyLibraryUsingExtensionSdk**" target="lib\uap10.0" />
</files>
</package>
Note that Visual Studio will require a solution reload to fully recognize the extension SDK after installing such a NuGet package. Builds will work immediately without problems but IntelliSense will not pick up the new extension SDK until a reload.
Unfortunately, this approach does require you to hardcode the version number of the extension SDK, which can be problematic. At the moment of writing, I know of no way to specify a range of versions or a version-independent reference.
Remember to build your solution using the Release configuration before creating the NuGet package.
A sample library and the relevant packaging files are available on GitHub. The solution corresponding to this answer is UwpLibraryDependingOnExtensionSdks.

NuGet Restore Fails when dependency adds a .targets import to the .csproj

I ran into an issue recently with NuGet restore. I added a project dependency (in this case PostSharp) and then enabled restore. I checked in the source, but not the /packages directory (as I shouldn't needed to....right!). When TeamCity or another developer grabs the source and runs MsBuild, they receive the following error:
C:\TeamCity\buildAgent\work\e374975c0264c72e\ProjectName\ProjectName.csproj(70, 3): error MSB4019: The imported project "C:\TeamCity\buildAgent\work\e374975c0264c72e\packages\PostSharp.2.1.5.1\tools\PostSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
The problem is, NuGet hasn't run yet to restore/download PostSharp or it's .targets file. This feels like a NuGet bug to me, but wanted to see if others have this same issue.
Anybody have this issue or know the resolution. Yes, I could check-in the /packages directory, but then why use NuGet at all?
Another approach is to modify the <Import> element in question, to make it conditional, e.g.:
<Import Project="$(CodeAssassinTargets)" Condition="Exists($(CodeAssassinTargets))" />
This depends on a new property defined in an earlier <PropertyGroup>. I usually add one at the top of csproj file with other "global" flags, e.g.:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CodeAssassinTargets>$(SolutionDir)packages\CodeAssassin.ConfigTransform.1.1\tools\CodeAssassin.ConfigTransform.targets</CodeAssassinTargets>
<AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>
<UseMsdeployExe>true</UseMsdeployExe>
</PropertyGroup>
Then in an appropriate target, like BeforeBuild, give a helpful error message:
<Target Name="BeforeBuild">
<Error Text="CodeAssassin.ConfigTransforms target is missing. It needs to exist at $(CodeAssassinTargets) in order to build this project!" Condition="!Exists($(CodeAssassinTargets))" />
</Target>
With these modifications, the project will load even if the nuget package restore has never been done. If auto package restore is enabled, the first build attempt should clear up the missing target issue, but if it does not, one manual package restore will.
#porterhouse91, have you checked your csproj file to make sure it has been set up with the appropriate build target?
I haven't yet tried the new built-in Package Restore feature, but I'm assuming it works at least somewhat like the previous workflows out there on the interwebs. If that's the case, enabling Package Restore in your solution only affects the projects in your solution at the time you enable it. If you've added a new project (having NuGet dependencies) to the solution since enabling Package Restore, you're gonna need to enable it again.
Another possibility: the previous workflows involved having a .nuget folder that you needed to check in to VCS, so you might need to check that in if it hasn't been checked in yet (if the built-in Package Restore feature does indeed use this approach).
BTW, if this answer is at all helpful, thank Stephen Ritchie -- he asked me to give it a shot for you.
I had a problem like this as well, but I was able to modify the .targets file in the source package to work around it. Basically, RestorePackages is a build target that runs when the project is built. Unfortunately, the package won't even load properly before the imports are satisfied. The only way I know to fix this is to include the .targets file as content and then change the BuildDependsOn property so it restores the packages before it runs your custom tasks.
<PropertyGroup>
<BuildDependsOn Condition="$(BuildDependsOn.Contains('RestorePackages'))">
RestorePackages;
CustomTarget;
$(BuildDependsOn);
</BuildDependsOn>
<BuildDependsOn Condition="!$(BuildDependsOn.Contains('RestorePackages'))">
CustomTarget;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
To be clear, this doesn't help with pre-built packages, but if you can build the package again yourself, you can fix it.
I ran into this same issue with Visual Studio 2012 and NuGet packages not checked into source control.
The error:
The imported project "\packages\Microsoft.Bcl.Build.1.0.7\tools\Microsoft.Bcl.Build.targets" was not found.
Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
I found a msdn writeup on the situation that gave the following workarounds for grabbing a project from source control without the NuGet packages.
Stop using package restore and check-in all package files
Explicitly run package restore before building the project
Check-in the .targets files
I decided to go with option #2, however, NuGet currently (v2.6) does not include a way to install all packges from the packages.config file from within visual studio. Some searching revealed that you need to use the NuGet Command Line to execute the following command before opening Visual Studio (reference).
c:\path\to\nuget.exe install -o packages project-folder\packages.config

Checking in packages from NuGet into version control?

Prior to NuGet, it was common accepted 'best practice' to check-in all external DLLs used on a project. Typically in a Libs or 3rdParty directory.
When working with NuGet, am I supposed to check-in the packages directory, or is there a way for MSBuild to auto download the needed packages from the nuget feed?
No
Since this question was asked there is now an easy workflow to use NuGet without commiting packages to source control
From your package manager console you need to install the 'NuGetPowerTools':
Install-Package NuGetPowerTools
Then to enable your projects to support pack restore you need to run another command:
Enable-PackageRestore
Now you are ready to commit your code base without the packages folder. The previous command changed your project files so that if packages are missing they get automatically downloaded and added.
Source
Using NuGet without committing packages to source control
Yes. Consider the "packages" directory to be equivalent to your "libs" directory that you mentioned in your question. This is the approach I personally take with my OSS projects.
We are investigating features that would allow MSBuild to auto download the needed packages, but that hasn't been implemented (as of NuGet 1.1).
I think some people may have already implemented such features on their own, but our plan is to look at having that feature built in to NuGet 1.2 or 1.3 hopefully.
Despite all the answers here, it is still a plain ole' horrible solution to not have all your dependencies under "some kind" of version control.
For GIT, this would mean GIT-LFS.
The recent episode with NPM shows why: If the internet repository of which you depend breaks, are unavailable etc., well then you're screwed aint you?
You are no longer able to build your stuff - and therefore not able to deliver.
Since asking the question, I've put in the following approach so that I do not have to check in the toplovel Packages directory.
In a toplevel build.msbuild file:
<Target Name="NuGet">
<ItemGroup>
<NuGetPackage Include="*\packages.config" />
</ItemGroup>
<Exec Command='libs\NuGet.exe install "%(NuGetPackage.FullPath)" -o Packages' />
<!-- optional for project that has JavaScript content -->
<CreateItem Include="Packages\*\Content\Scripts\*">
<Output TaskParameter="Include" ItemName="NuGetJSFiles"/>
</CreateItem>
<Copy SourceFiles="#(NuGetJSFiles)" DestinationFolder="MainProj\Scripts\" OverwriteReadOnlyFiles="true" SkipUnchngedFiles="true" />
<Delete Files="MainProj\Scripts\.gitignore" />
<WriteLinesToFile File="MainProj\Scripts\.gitignore" Lines="%(NuGetJSFiles.Filename)%(NuGetJSFiles.Extension)" /
<Delete Files="#(PostNuGetFiles)" />
</Target>
In each project.csproj file
<Target Name="BeforeBuild">
<Error Condition="!Exists('..\Packages\')" Text="You must run > msbuild build.msbuild to download required NuGet
Packages" />
<!-- optional for project that has JavaScript content -->
<ReadLinesFromFile File="Scripts\.gitignore">
<Output TaskParameter="Lines" ItemName="ReqJSFiles" />
</ReadLinesFromFile>
<Message Text="#(ReqJSFiles)" />
<Error Condition="!Exists('Scripts\%(ReqJSFiles.Identity)')" Text="You must run > msbuild build.msbuild to download required NuGet JS Package - Scripts\%(ReqJSFiles.Identity)" />
</Target>
I realize the reality was different when this question has been originally posted and answered, but fortunately the answer changed a bit. It is now possible to use NuGet to download dependencies via MSBuild using a Pre-Build event. You don't need to put the packages folder in your code repository, all dependencies will be downloaded and/or updated on build. It may a workaround, but it looks decent enough. See the following blog post for details: http://blog.davidebbo.com/2011/03/using-nuget-without-committing-packages.html
AS of 09/20/13, there is something called "Nuget Restore". You actually don't have to check in package folder if you wish to do so. (Especially if you are using DVCS)
Check out this: Using NuGet Without commiting packages to source control
http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
This post has become very outdated. The answer is still NO, but the solution has changed.
As of NuGet 2.7+ you can enable automatic package restore without including the NuGet.exe file in your source (this is undesirable to say the least) and if you use any modern DVCS you can ignore the packages folder. If you need any special customizations you can create a nuget.config file in the solution root.
http://docs.nuget.org/docs/reference/package-restore
Also, with the new csproj format you can avoid the extra nuget.config files as well since that is integrated now. Please check out this post which explains that better:
Should .nuget folder be added to version control?