cake-build / cake

:cake: Cake (C# Make) is a cross platform build automation system.
https://cakebuild.net
MIT License
3.92k stars 730 forks source link

DotNetTool Module: Not using the same version of dotnet as Cake DotNetCoreTool #3210

Open augustoproiete opened 3 years ago

augustoproiete commented 3 years ago

Creating a new issue for tracking https://github.com/cake-contrib/Cake.DotNetTool.Module/issues/21 created by @brianfeucht given that GitHub doesn't allow transferring issues from one organization to another.


@brianfeucht wrote:

I'm running into an issue where the Cake DotNetCoreTool is not able to find the tool installed with this module. It looks like the underlying issue is due to Cake and this module using different versions of the dotnet cli tool.

Expected Behavior

The module and Cake use same dotnet cli version so I'm able to use the tool installed with this module.

Current Behavior

Log from my CAKE script:

Installing tools...
Configured Tools Folder: Z:/Teamcity/Work/3aedfc86eaf25d80/scripts/tools
Executing: "dotnet" tool list --global
Package Id               Version      Commands     
---------------------------------------------------
amazon.lambda.tools      4.0.0        dotnet-lambda
Adding tool amazon.lambda.tools
There are 1 dotnet tools installed
Checking for tool: amazon.lambda.tools
Tool Amazon.Lambda.Tools is already installed, with required version.
Tool Folder: C:/Windows/system32/config/systemprofile/.dotnet/tools/.store/amazon.lambda.tools
Found 10 files in tool folder
Executing: "C:/Program Files/dotnet/dotnet.exe" lambda package
Could not execute because the specified command or file was not found.
Possible reasons for this include:
  * You misspelled a built-in dotnet command.
  * You intended to execute a .NET Core program, but dotnet-lambda does not exist.
  * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.
Executing custom task teardown action (PackageLambda)...
An error occurred when executing task 'PackageLambda'.
Error: System.AggregateException: One or more errors occurred. ---> Cake.Core.CakeException: .NET Core CLI: Process returned an error (exit code 1).
   at Cake.Core.Tooling.Tool`1.ProcessExitCode(Int32 exitCode)
   at Cake.Core.Tooling.Tool`1.Run(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings processSettings, Action`1 postAction)
   at Cake.Common.Tools.DotNetCore.Tool.DotNetCoreToolRunner.Execute(FilePath projectPath, String command, ProcessArgumentBuilder arguments, DotNetCoreToolSettings settings)
   at Cake.Common.Tools.DotNetCore.DotNetCoreAliases.DotNetCoreTool(ICakeContext context, FilePath projectPath, String command, ProcessArgumentBuilder arguments)
   at Submission#0.DotNetCoreTool(FilePath projectPath, String command, ProcessArgumentBuilder arguments) in :line 1058
   at Submission#0.<<Initialize>>b__0_0() in Z:\Teamcity\Work\3aedfc86eaf25d80\scripts\Package.cake:line 92
   at Cake.Core.CakeTaskBuilderExtensions.<>c__DisplayClass32_0.<Does>b__0(ICakeContext x)
   at Cake.Core.CakeTask.<Execute>d__43.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.DefaultExecutionStrategy.<ExecuteAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.CakeEngine.<RunTask>d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<RunTargetAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Scripting.BuildScriptHost.<RunTargetAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.Scripting.ScriptHost.RunTarget(String target)
   at Submission#0.<<Initialize>>d__0.MoveNext() in Z:\Teamcity\Work\3aedfc86eaf25d80\scripts\build.cake:line 109
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.<RunSubmissionsAsync>d__9`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.Scripting.Script`1.<RunSubmissionsAsync>d__21.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at Cake.Scripting.Roslyn.RoslynScriptSession.Execute(Script script)
   at Cake.Core.Scripting.ScriptRunner.Run(IScriptHost host, FilePath scriptPath, IDictionary`2 arguments)
   at Cake.Commands.BuildCommand.Execute(CakeOptions options)
   at Cake.CakeApplication.Run(CakeOptions options)
   at Cake.Program.Main()
---> (Inner Exception #0) Cake.Core.CakeException: .NET Core CLI: Process returned an error (exit code 1).
   at Cake.Core.Tooling.Tool`1.ProcessExitCode(Int32 exitCode)
   at Cake.Core.Tooling.Tool`1.Run(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings processSettings, Action`1 postAction)
   at Cake.Common.Tools.DotNetCore.Tool.DotNetCoreToolRunner.Execute(FilePath projectPath, String command, ProcessArgumentBuilder arguments, DotNetCoreToolSettings settings)
   at Cake.Common.Tools.DotNetCore.DotNetCoreAliases.DotNetCoreTool(ICakeContext context, FilePath projectPath, String command, ProcessArgumentBuilder arguments)
   at Submission#0.DotNetCoreTool(FilePath projectPath, String command, ProcessArgumentBuilder arguments) in :line 1058
   at Submission#0.<<Initialize>>b__0_0() in Z:\Teamcity\Work\3aedfc86eaf25d80\scripts\Package.cake:line 92
   at Cake.Core.CakeTaskBuilderExtensions.<>c__DisplayClass32_0.<Does>b__0(ICakeContext x)
   at Cake.Core.CakeTask.<Execute>d__43.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.DefaultExecutionStrategy.<ExecuteAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<ExecuteTaskAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.CakeEngine.<RunTask>d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Cake.Core.CakeEngine.<RunTargetAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Scripting.BuildScriptHost.<RunTargetAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Cake.Core.Scripting.ScriptHost.RunTarget(String target)
   at Submission#0.<<Initialize>>d__0.MoveNext() in Z:\Teamcity\Work\3aedfc86eaf25d80\scripts\build.cake:line 109
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.<RunSubmissionsAsync>d__9`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.Scripting.Script`1.<RunSubmissionsAsync>d__21.MoveNext()<---

Steps to Reproduce (for bugs)

#module "nuget:?package=Cake.DotNetTool.Module&version=0.4.0"
#tool dotnet:?package=Amazon.Lambda.Tools&version=4.0.0&global

DotNetCoreTool(projectPath: projectPath, command: "lambda", arguments: "package");

Context

I'm unable to use this module to manage my global tools on our build server

Your Environment

    <package id="Cake" version="0.37.0" />
gjhommersom commented 3 years ago

I think I'm running into the same issue. I'm using the dotnet-sonarscanner tool and when I try to resolve the tool it returns the netcore 2.0 version while I'm running on net5. Because we use images for our builds old versions of the sdk are not available.

To my understanding the root issue is that the tool is registered 3 times and the paths look something like this:

The ToolResolutionStrategy will return the last one registered:

private static FilePath LookInRegistrations(IToolRepository repository, string tool)
{
    return repository.Resolve(tool).LastOrDefault();
}

If this method could be extended to try and match the path with the version of Dotnet that is being run the issue could be resolved.

augustoproiete commented 3 years ago

Hey @gjhommersom, could you provide more details on how you're resolving the SonarScanner tool and some sample code?

Cake runs dotnet tool install behind the scenes in order to install the tool, so the directive below:

#tool "dotnet:?package=dotnet-sonarscanner&version=5.2.1"

Would cause Cake to execute a command similar to the following:

dotnet tool install "dotnet-sonarscanner" --tool-path "{build.cake path}/tools" --version 5.2.1

This would install the tool in the ./tools/.store/dotnet-sonarscanner/5.2.1 folder, and create a shim to execute the tool inside ./tools, e.g. if you're using Windows it would create a dotnet-sonarscanner.exe which is what it the tool that would be resolved by Cake.

The same if you're installing as a global tool:

C:/Users/augustoproiete/.dotnet/tools/dotnet-sonarscanner.exe

Thus, in theory, it's .NET who's deciding which version of the SDK to use, and not Cake.


A couple of things you might want to try:

1. Force the .NET version to use when installing the tool:

#tool "dotnet:?package=dotnet-sonarscanner&version=5.2.1&framework=net5.0"

Which should execute a command similar to the following:

dotnet tool install "dotnet-sonarscanner" --tool-path "{build.cake path}/tools" --version 5.2.1 --framework net5.0

and/or

2. Add a global.json file at the root of your repo, to force the .NET version for dotnet tool to use:

{
  "sdk": {
    "allowPrerelease": false,
    "version": "5.0.100",
    "rollForward": "latestFeature"
  }
}
gjhommersom commented 3 years ago

I use Cake.Sonar extension. Internally it calls context.Tool.Resolve('SonarScanner.MSBuild.dll") to get the tool. To what should that be changed because I tried using dotnet-sonarscanner.exe. It works on my dev machine but the buildserver runs on Linux and couldn't execute the exe.

I will try the options you provided to see if I can resolve it that way.