Nuget MsBuild Integration - Snapshot and Release versioning - c#

Currently we are evaluating NuGet tool for our dot net project built on framework 4.6.2 using VS2017. Our goal is to refer our common libraries in our solution as reference (like Maven dependencies) pulling it from internal nexus repository.
We are familiar with maven concepts like snapshot and release. We would like to achieve the same using NuGet tool. Brief search on internet says this is not supported in Nuget. Any pointers to do it in elegant way for dotnet projects with NuGet?
Any assistance in this regards is appreciated. Thanks

Using the new SDK-based project system, NuGet and MSBuild are integrated. There currently isn't a project template for this in VS2017 but you can create a .NET Standard library and change the <TargetFramework> value in the .csproj file to:
<TargetFramework>net462</TargetFramework>
Then you need to define a version number for your library. This can be done through setting a Versionproperty OR setting a combination of VersionPrefix and VersionSuffix property that are combined during build. For CI-szenarios, you usually want to set only the VersionPrefix value in your .csproj file, inside of a <PropertyGroup> element:
<VersionPrefix>1.2.3</VersionPrefix>
This can also be set inside a Directory.Build.props file in the solution directory to have a single place to set the property for all projects in one place:
<Project>
<PropertyGroup>
<VersionPrefix>1.2.3</VersionPrefix>
</PropertyGroup>
</Project>
When building through CI or locally, you can set the VersionSuffix property through command line, the pack command of the dotnet cli offers a convenience option for this:
dotnet pack -c Release --version-suffix SNAPSHOT
Alternatively, the same result can be accomplished when using the VS version of MSBuild via the Developer Command Prompt:
msbuild /t:Pack /p:Configuration=Release /p:VersionSuffix=SNAPSHOT
Currently (VS 2017 15.2, .NET CLI 1.0.*), there is a bug when having multiple projects that reference each other - the dependency versions aren't generated with a the specified version suffix. There is a workaround: Perform an additional restore before packing using the same property:
dotnet msbuild "/t:Pack;Restore" /p:Configuration=Release /p:VersionSuffix=SNAPSHOT
On your CI system you would typically overwrite the Suffix with a build number to generate a version like 1.2.3-ci-20170102 or just generate SNAPSHOT / PREVIEW etc. packages.
Since msbuild allows for scripting, you can also extend the csproj file to set the version suffix automatically if some conditions are met - e.g. always generate a suffix for debug builds so you don't accidentally publish a debug build.
<VersionSuffix Condition=" '$(Configuration)' != 'Release' ">SNAPSHOT</VersionSuffix>

Related

Exclude Project in sln from dotnet build

I have a roslyn analyzer project based on Microsoft's default template. I can easily build the analyzer in Visual Studio or with msbuild.
The problem is that the solution includes a vsix project that relies on the microsoft.vssdk.buildtools which are not supported by dotnet build.
This results in an error message when trying to build the solution in the command line with dotnet build: microsoft.vssdk.buildtools\17.4.2119\tools\VSSDK\Microsoft.VsSDK.targets(826,5): error : VSIX deployment is not supported with 'dotnet build'
The vsix is nice to have when developing with Visual Studio, but I do publish my analyzer via NuGet package instead of as vsix so I don't need the vsix on the CLI.
Is there a way to specify in the csproj that I don't want it to be built when it is invoked from dotnet build? I'd like to avoid having a separate sln file or a specific dotnet configuration that excludes the project if possible.
Two possible approaches include using a solution filter and changing the project to not build under certain conditions.
Use a Solution Filter
dotnet build will accept a solution filter file (.slnf).
To create the solution filter:
Open the solution in Visual Studio
Go to the solution explorer window
Right-click on the VSIX project, choose 'Unload Project'
Right-click on the solution, choose 'Save As Solution Filter'
When building with dotnet the .slnf will need to be used. Using the .sln file or the VSIX project file with dotnet will be an error.
Detecting when Invoked from dotnet build
There isn't a defined property or function in MSBuild that identifies the executable that is running the MSBuild engine.
However there is a MSBuildRuntimeType property.
Prior to MSBuild 15, MSBuildRuntimeType will be undefined. In MSBuild 15 and later MSBuildRuntimeType will have a value of Full, Core, or Mono. From the documentation MSBuildRuntimeType will have a value of Core when dotnet build is used. (Further the error message "VSIX deployment is not supported with 'dotnet build'" is only displayed when '$(MSBuildRuntimeType)' == 'Core'.)
There isn't an 'exit build' task so the project can't detect and then end. We need to detect before the project really starts. But wrapping a project within a project is clunky especially if you want to be able to work with the project and change properties from the Visual Studio IDE.
Targets can be redefined and an Import can have a condition. A file can be imported when MSBuildRuntimeType is Core and the file can redefine the 'Build' target.
Add to the VSIX project file:
<Import Project="noop.targets" Condition="'$(MSBuildRuntimeType)' == 'Core'" />
The noop.targets may contain the following:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Text="$(MSBuildProjectName) has been skipped." />
</Target>
</Project>
Hope this helps or at least provides some ideas.

.NET Core 6.0 standalone binary compilation

I'm trying to create a .NET Core 6.0 binary as a standalone, with all dependencies packaged in one .exe file.
The trouble I am having is that whilst the binary compiles ok it is reliant on the DLLs placed in the Release/Debug folder.
I have tried compiling from the command line with
dotnet publish --standalone
but in that instance I just get a similar issue with a load more DLLs and the binary itself is the same size and needs to be in that folder to run.
Is what I'm looking for even possible and if so how can this be achieved? I have tried with Visual Studio, dotnet cli and Rider so far.
There are a number of old solutions that mention solutions such as ilmerge but this appears to have been long since deprecated and is no longer maintained.
-- EDIT for future me:
Final solution looked like this, thanks to Andrew's answer below.
My final project.csproj file looked like this based on MS Docs
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishSingleFile>true</PublishSingleFile>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
Publish either via Visual Studio GUI or:
dotnet publish -c release -r win-x64
I'd suggest looking at https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file which should hopefully be up to date. I believe the key bit is <PublishSingleFile>true</PublishSingleFile> in the .csproj.

How to push to or query local my local .NET nuget repository

I have a C# project that makes a lib. I build it just fine with dotnet build. I'd love to publish the dll to ~/.nuget/packages (I am on a Mac, using Rider). Is there a nuget command to query the local repository?
In terms of publishing, I have <GeneratePackageOnBuild>true</GeneratePackageOnBuild> added to the csproj file of the lib. Also <IsPackable>true</IsPackable>, yet nothing is put into ~/.nuget/packages if I do dotnet pack.
dotnet build
dotnet pack
nuget add path/to/<yourProjeName>.nupkg -source ~/.nuget/packages
For Mac, brew install nuget is how you add a version of Nuget to your system. At least one that is different to the nuget built into the dotnet command that has a different syntax.
Then use ls, find, ag an wotnot for ~/.nuget file location
To publish NuGet package to your local repository you can either add the following property.
<PackageOutputPath>PATH_TO_YOUR_LOCAL_REPO</PackageOutputPath>
NOTE: Don't add the property to a csproj file, better adding it to Directory.Build.props and have it in .gitignore so you don't accidentally apply these changes to your CI build if there's any.
another way of doing it is by using dotnet cli pack via o option
dotnet pack -o PATH_TO_YOUR_LOCAL_REPO

Solution targeting .NET Core 2.1 builds with old System.ServiceModel.Primitives and System.Private.ServiceModel

I have a solution made up of projects targeting .NET Standard 2.0 and .NET Core 2.1.304. When built this solution utilizes old vulnerable versions of System.ServiceModel.Primitives and System.Private.ServiceModel (CVE-2018-0786).
I am probably missing something obvious about the configuration of the overall solution or one of the projects that is causing the utilization of the old versions, but everything I know to check looks correct:
Global.json
{
"sdk": {
"version": "2.1.302"
}
}
Example .NET Core Project File
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Configurations>Debug;Dev;Qual;Release</Configurations>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
Example .NET Standard Project File
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Configurations>Debug;Dev;Qual;Release</Configurations>
</PropertyGroup>
I have ensured all NuGet packages are up to date. That said is it possible that one of my NuGet package references is causing a fallback to the old versions? What other configurations should I be checking?
Interestingly when I build a different, but similarly configured solution (from what I can tell) that solution produces a build using the newer non vulnerable versions.
You can use a tool such as dotnet-outdated to determine both your the versions of your dependencies and transitive dependencies in your project.
Install via dotnet tool install --global dotnet-outdated on the powershell command line
and run dotnet outdated -t -td 100 in your solution folder to see 100 levels of transitive dependencies.
Your output will look something like the following
» MyProject
[.NETCoreApp,Version=v2.1]
System.Private.ServiceModel [T] 4.4.0 -> 4.5.3
System.ServiceModel.Primitives [T] 4.4.0 -> 4.5.3
You can then use the above stated out of date dependencies to track down which project(s) in your solution needs to be further investigated.
From there eliminate dependencies that are known to be safe, as they appear in other projects that don't have a dependency on the bad library (regardless of version). At this point it may be a matter of using nuget.org and investigating each suspect dependency to see what version of sub-dependencies it uses.

Force compile with MSBuild on local environment and use dotnet on continous integration

I have one project configured with AppVeyor for Nuget deployments. Recently I decide add support for .Net Core Framework. On continuous integration environment dotnet is used to compile, run unit tests and pack the project, but when I added a project.json and compile with Visual Studio 2015 dotnet is used instead MSBuild. So I have in the project folder the .csproj and project.json files.
QUESTION:
There is any way to configure Visual Studio to use always MSBuild with .csproj instead dotnet with project.json and leave the use of these for continuous integration only?
There is any way to configure Visual Studio to use always MSBuild with .csproj instead dotnet with project.json and leave the use of these for continuous integration only?
You can use the dotnet migrate command to migrate a project.json project to the csproj format. This command will also migrate any project-to-project references you have in your
project.json file automatically. for more information, please refer to: https://learn.microsoft.com/en-us/dotnet/articles/core/preview3/tools/dotnet-migrate
The following blogs provide an example about migrate project.json to csproj for your reference(please check the phase “Upgrading project.json projects”)
https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-net-core-tools-msbuild-alpha/

Categories