First thing – – usage must be simple . So this is something that can be reproduces easy on each ASPIRE project :
builder.AddDotnetGlobalTools(“dotnet-ef”, “dotnet-depends”);
I cannot imagine simpler than this – and , of course, you can add many more other dotnet tools – see https://www.nuget.org/packages?q=&includeComputedFrameworks=true&packagetype=dotnettool&prerel=true&sortby=relevance
What happens:
Now a Aspire resource will be created with a command to install the specified global tools. Also, a All command will be created to install all specified global tools – or you can click to install one by one
Now , how this is executed : I have created a new class, derived from ExecutableResource , that executes
dotnet tool list -g
in order to see the global tools.
public class DotnetGlobalToolResource: ExecutableResource { public DotnetGlobalToolResource(): base("DotnetGlobalTool","dotnet","") { } } public static IResourceBuilder<DotnetGlobalToolResource> AddDotnetGlobalTools( this IDistributedApplicationBuilder builder, params string[] arr ) { ArgumentNullException.ThrowIfNull(builder); var resource = new DotnetGlobalToolResource(); var res = builder.AddResource(resource).WithArgs(new string[] { "tool", "list", "-g" }) .ExcludeFromManifest() ; if ((arr?.Length ?? 0) == 0) return res; //more code, see below arr
Also, for each tool enumerated in
builder.AddDotnetGlobalTools(“dotnet-ef”, “dotnet-depends”);
I have created a command to execute.
foreach (var toolName in arr) { res.WithCommand(toolName, toolName,async (ExecuteCommandContext ecc)=> { var loggerService = ecc.ServiceProvider.GetService(typeof(ResourceLoggerService)) as ResourceLoggerService; var logger = loggerService?.GetLogger(resource); if (logger == null) { Console.WriteLine($"Logger not found for {resource.Name}"); return new ExecuteCommandResult() { Success = false, ErrorMessage = "Logger not found" }; } return await FromTool(toolName, logger); }); }
Finally, I have created an ALL command to install all at once
res.WithCommand("All", "!All!", async ecc => { var loggerService = ecc.ServiceProvider.GetService(typeof(ResourceLoggerService)) as ResourceLoggerService; var logger = loggerService?.GetLogger(resource); if (logger == null) { Console.WriteLine($"Logger not found for {resource.Name}"); return new ExecuteCommandResult() { Success = false, ErrorMessage = "Logger not found" }; } var commandService = ecc.ServiceProvider.GetService(typeof(ResourceCommandService)) as ResourceCommandService; if (commandService == null) { Console.WriteLine($"command service not found for {resource.Name}"); return new ExecuteCommandResult() { Success = false, ErrorMessage = "Logger not found" }; } logger.LogInformation("Starting full install..."); var nrSuccess = 0; foreach (var toolName in arr) { var resTool = await commandService.ExecuteCommandAsync(resource, toolName); if (resTool.Success) { nrSuccess++; logger.LogInformation($"Installing {toolName} succeeded."); } else { logger.LogError($"Installing {toolName} failed: {resTool.ErrorMessage}"); } } if (nrSuccess == arr.Length) { logger.LogInformation("All tools installed successfully."); return new ExecuteCommandResult() { Success = true }; } else { //logger.LogWarning($"Only {nrSuccess} out of {arr.Length} tools were installed successfully."); return new ExecuteCommandResult() { Success = false, ErrorMessage = $"Only {nrSuccess} out of {arr.Length} tools were installed successfully." }; } });
You find the nuget package at https://www.nuget.org/packages/DotnetGlobalToolsExtensionAspire – and the source code at https://github.com/ignatandrei/aspireExtensions
Enjoy !