Skip to content

Ship nuget-plugin-forge as a dotnet tool (dotnet tool install -g) #165

Open

Description

@schmitch

Part of #44. Packages the Rust plugin from #164 so .NET developers install it the way they install any other tool:

dotnet tool install -g <package-id>

dotnet tool install -g puts the command on PATH (~/.dotnet/tools), and NuGet 6.13+ picks up nuget-plugin-* from there. That path is what the NuGet spec for dotnet-tool plugins is about.

A native binary in a tool package

The .NET 10 SDK supports RID-specific tools, and their DotnetToolSettings.xml (format version 2) accepts Runner="executable". The SDK doesn't care what the executable was built with:

  • Pointer package <id> (package type DotnetTool) lists the RID packages under <RuntimeIdentifierPackages>.
  • One package per RID <id>.<rid> (package type DotnetToolRidPackage) holds the Rust binary and a <Command Name="nuget-plugin-forge" EntryPoint="nuget-plugin-forge" Runner="executable" />.
  • On Linux and macOS the CLI symlinks ~/.dotnet/tools/nuget-plugin-forge to the binary. NuGet's discovery only needs the executable bit there, so this works as is.

Installing a version-2 tool needs the .NET 10 SDK. dotnet pack can't package a non-.NET binary, so an xtask should write the .nuspec files and settings and zip the .nupkgs.

Suggested RIDs:

  • linux-x64, linux-arm64
  • linux-musl-x64, linux-musl-arm64 (a static musl build could serve both Linux pairs)
  • osx-x64, osx-arm64
  • win-x64, win-arm64

The Windows catch

  • The shim: for Runner="executable" the SDK writes the shim as nuget-plugin-forge.cmd (see ShellShimRepository.cs in dotnet/sdk).
  • Discovery: NuGet's discovery on Windows only accepts .exe and .bat (PluginDiscoverer.IsValidPluginFile in NuGet.Client). So on Windows a plain executable tool installs fine but NuGet never finds it.

Options, to spike:

  1. Packaged shim. The Windows RID packages use Runner="dotnet" and ship the Rust binary as the packaged shim under tools/<tfm>/any/shims/<rid>/nuget-plugin-forge.exe. The CLI copies that file to ~/.dotnet/tools/nuget-plugin-forge.exe, so the native plugin itself lands on PATH with no .NET in the call path. The package still needs a managed entry-point DLL. Ideally that's a tiny forwarder, so dotnet nuget-plugin-forge.dll also works.
  2. Managed forwarder. The Windows RID packages use Runner="dotnet" with a small forwarder that starts the Rust .exe next to it with inherited stdio. This is simpler and documented behaviour, but each restore pays .NET start-up (well within the 5-second handshake).
  3. No Windows tool. Windows users install nuget-plugin-forge.exe through winget or the release zip (Release pipeline for the client helpers: signed binaries for Linux, macOS and Windows #166), or set NUGET_PLUGIN_PATHS.

Either way, open an upstream issue: NuGet/Home could accept .cmd, or dotnet/sdk could emit an .exe shim for executable tools.

Publishing

  • nuget.org, with a nuget-plugin tag so dotnet package search nuget-plugin finds it.
  • Forge's own public feed: Forge is a NuGet server, so --add-source works without authentication.
  • Package ID to decide (e.g. Forge.NuGet.CredentialProvider).

Local tools (dotnet tool install without -g) are not supported by NuGet's plugin discovery, which the docs should state.

Acceptance criteria

  • On Linux, macOS and Windows, dotnet tool install -g <id> followed by dotnet restore --interactive authenticates against Forge.
  • dotnet tool update -g and dotnet tool uninstall -g keep working, and uninstalling removes the plugin from discovery.
  • Installing with an SDK older than 10 fails with a clear message, not a broken install.
  • Release CI builds and publishes the pointer package and all RID packages for the same version.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions