SonarSource / sonar-scanner-msbuild

SonarScanner for .NET
http://redirect.sonarsource.com/doc/msbuild-sq-runner.html
GNU Lesser General Public License v3.0
365 stars 143 forks source link

Use auto generation for DotnetToolSettings.xml #1764

Open costin-zaharia-sonarsource opened 1 year ago

costin-zaharia-sonarsource commented 1 year ago

This file is generated by the SDK when you set PackAsTool to true, and normally, you do not need to create it yourself. Source: https://natemcmaster.com/blog/2018/05/12/dotnet-global-tools/

Since we decided to drop support for netcore2.1, we should simplify the script by removing the file.

See: https://github.com/SonarSource/sonar-scanner-msbuild/blob/master/nuspec/netcoreglobaltool/dotnet-sonarscanner.nuspec#L32-L34

See the comment below for more info on previous attempts.

antonioaversa commented 12 months ago

My attempts at implementing this task failed, so I am taking out this task of the 6.0.0 sprint, since it's not necessary for the 6.0.0 release and as such, it's a branch that can be cut. Hereafter is a record of the tests made and their results.

First tests

Simply adding <PackAsTool> did not work: the DotnetToolSettings.xml file is not added to the tools\<target>\any directory.

I have first considered a couple of workarounds:

This is because both workarounds above only work with dotnet pack, that is different from the nuget pack. The difference is explained here. At the same time nuget pack still has the issue, as confirmed in this comment.

I have then tried four different approaches:

  1. try to update the pipeline to dotnet pack (a.k.a. DotnetTool a.k.a. global tools), invoked via DotNetCoreCLI@2

    • dotnet pack only supports netcoreapp2.1 and above. Trying on a multi-target project with net462 like the scanner results in an error message: see here. That is why we need to specifically target netcoreapp3.1 in the command line.
    • that requires support for buildProperties by the DotNetCoreCLI@2 task in Azure DevOps, that was fixed recently
    • or the use of a custom command, that allows to pass -p:TargetFramework=netcoreapp3.1
  2. upgrade nuget pack to the latest available version, and see if it makes any difference, although this and this issue seem to suggest that latest versions of nuget only pack non-sdk-style projects.

  3. like 1, but via PowerShell@2, building the command line "by hand" (that is, bypassing the Azure DevOps task layer, and its parameter mapping).

  4. like 2, but with inverted condition on the PackAsTool: <PropertyGroup Condition="'$(TargetFramework)'!='net462'"> instead of <PropertyGroup Condition="'$(TargetFramework)'!='net462'">. Inverted condition is used in the example in this comment.

Approach 1

I tried to change the packing command from the nuget one to the dotnet one (a.k.a. DotnetTool) - via the DotNetCoreCLI@2 task in Azure DevOpz.

However, the packagesToPack parameter, which should in principle work according to the documentation, doesn't seem to work well with DotNetCoreCLI@2 when package specified is a nuspec.

The following task:

- task: DotNetCoreCLI@2
  displayName: 'Package dotnet global tool'
  inputs:
    command: 'pack'
    buildProperties: TargetFrameworks=netcoreapp3.1
    packagesToPack: 'nuspec\netcoreglobaltool\dotnet-sonarscanner.nuspec'
    packDirectory: 'build'
    versioningScheme: 'off'

Generates the following issue:

MSBUILD : error MSB1003: Specify a project or solution file. The current working directory does not contain a project or solution file.
##[warning].NET 5 has some compatibility issues with older Nuget versions(<=5.7), so if you are using an older Nuget version(and not dotnet cli) to restore, then the dotnet cli commands (e.g. dotnet build) which rely on such restored packages might fail. To mitigate such error, you can either: (1) - Use dotnet cli to restore, (2) - Use Nuget version 5.8 to restore, (3) - Use global.json using an older sdk version(<=3) to build
##[error]Error: The process 'C:\Program Files\dotnet\dotnet.exe' failed with exit code 1
##[error]An error occurred while trying to pack the files.

Using projects instead of packagesToPack doesn't work either - it tries to build an unrelated project. It generates the following command line:

"C:\Program Files\dotnet\dotnet.exe" pack D:\a\1\s\TestResults\VssAdministrator_fv-az883-927_2023-11-27_17_35_53\In\8ca7cde5-96fc-4aa5-ae23-32af7a71ba45\fv-az883-927\WpfApplication.csproj --output D:\a\1\s\build /p:Configuration=Release;TargetFrameworks=net8.0 --verbosity Detailed

These issues come from the differences between nuget pack and dotnet pack: the second only supports csproj or sln packing.

Support of nuspec-only packing by dotnet pack is an open issue. It seems that it was possible via dotnet nuget pack up to a point, and then removed afterwards.

Approach 2

Upgrading to the latest version of nuget (i.e. changing versionSpec in NuGetToolInstaller@1 from 5.7.0 to 6.7.0) made no difference. However, I got a green pipeline when adding buildProperties: 'TargetFrameworks=dotnetcore3.1'

- task: NuGetCommand@2
  displayName: 'Package dotnet global tool'
  inputs:
    command: 'pack'
    buildProperties: 'TargetFrameworks=dotnetcore3.1'
    packagesToPack: 'nuspec\netcoreglobaltool\dotnet-sonarscanner.nuspec'
    packDestination: 'build'
    versioningScheme: 'off'

However, the resulting nupkg doesn't contain the DotnetToolSettings.xml file. So it seems that PackAsTool is just ignored. This is consistent with this comment, and with the test of the workaround 2 above.

Approach 3

I have tried to switch to PowerShell@2, running a command line like the following:

dotnet pack src/SonarScanner.MSBuild/SonarScanner.MSBuild.csproj -p:NuspecFile=..\..\nuspec\netcoreglobaltool\dotnet-sonarscanner.nuspec -p:Configuration=Release -p:TargetFrameworks=netcoreapp3.1 --no-restore --no-build --output "build"

For reference, the command executed by NuGetCommand@2:

C:\hostedtoolcache\windows\NuGet\5.7.0\x64\nuget.exe pack D:\a\1\s\nuspec\netcoreglobaltool\dotnet-sonarscanner.nuspec -NonInteractive -OutputDirectory D:\a\1\s\build -Properties Configuration=Release -Verbosity Detailed

Unfortunately, I could not make it work, even locally: the command line above works, but the resulting package is empty (no netcoreapp3.1 present in it), whether we specify -p:TargetFrameworks=netcoreapp3.1 on command line or not. Removing Condition="'$(TargetFrameworks)'=='netcoreapp3.1'" from SonarScanner.MSBuild.csproj produces the following error:

C:\Program Files\dotnet\sdk\8.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.PackTool.targets(117,5): error NETSDK1054: only supports .NET Core. [C:\dev\sonar-scanne
r-msbuild\src\SonarScanner.MSBuild\SonarScanner.MSBuild.csproj::TargetFramework=net462]

Approach 4

Same result as approach 2: inverting the condition doesn't make any difference.