You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This proposal introduces a new workflow for both plugin authors and consumers:
30
-
- Plugin authors will now have the ability to publish their NuGet plugins as .NET Tools.
29
+
This proposal introduces a new workflow for plugin authors, consumers, and NuGet Client tooling:
30
+
- Plugin authors will now be able to publish their NuGet plugins as .NET Tools.
31
+
The only requirement is that the .NET Tool command name should begin with `nuget-plugin-`.
31
32
- Consumers can install these NuGet plugins as [global .NET tools](https://learn.microsoft.com/dotnet/core/tools/global-tools-how-to-use#use-the-tool-as-a-global-tool).
32
-
Upon installation, these global .NET tools are added to the PATH. This allows NuGet to easily determine which file in the package should be run at runtime.
33
+
- Upon installation, these global .NET tools are added to the PATH by the .NET SDK.
34
+
This allows NuGet to easily determine which file in the package should be run at runtime.
35
+
It does this by scanning the `PATH` environment variable for plugins whose file name begins with `nuget-plugin-`.
36
+
On Windows, NuGet will look for plugins with a `.exe` extension, whereas on Linux/Mac, it will look for plugins with the executable bit set.
37
+
These plugins are launched in a separate process, which aligns with the current design.
33
38
34
39
## Motivation
35
40
@@ -128,9 +133,9 @@ It also simplifies the installation process by removing the necessity for plugin
128
133
129
134
To distribute a NuGet cross platform plugin as a .NET Tool, plugin authors need to follow these steps:
- Ensure that the .NET Tool command name begins with `nuget-plugin-*`.
138
+
- Execute `dotnet pack` to generate the package.
134
139
135
140
```xml
136
141
<PackAsTool>true</PackAsTool>
@@ -176,17 +181,28 @@ The plugins specified in the `NUGET_DOTNET_TOOLS_PLUGIN_PATHS` environment varia
176
181
The primary reason for this is that plugins installed as .NET tools can be executed in both .NET Framework and .NET Core tooling.
177
182
If customers prefer to install NuGet plugins as a [tool-path global tool](https://learn.microsoft.com/dotnet/core/tools/global-tools-how-to-use#use-the-tool-as-a-global-tool-installed-in-a-custom-location), they can set the `NUGET_DOTNET_TOOLS_PLUGIN_PATHS` environment variable.This variable should point to the location of the .NET Tool executable that the NuGet Client tooling can invoke when needed.
178
183
179
-
Considering the varying ways different platforms handle file casing, the implementation could convert all file names to lowercase before checking for a file.
180
-
Specifically, it should look for files whose names begin with `nuget-plugin-*` by scanning all the directories in the PATH environment variable.
181
-
On Windows, NuGet should search for files with the `.exe` extension. On other platforms, it should look for files with the executable bit set.
182
-
`NuGet.exe` currently [scans all directories in the PATH environment variable](https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.CommandLine/MsBuildUtility.cs#L708-L736) to find `MSBuild.exe`.
184
+
NuGet should search for files whose names begin with `nuget-plugin-*` by scanning all the directories in the `PATH` environment variable.
185
+
To ensure compatibility across different platforms, the implementation could convert all file names to lowercase before checking for a file.
186
+
187
+
- On Windows, NuGet should search for plugins using the `.exe` extension.
188
+
The `PATHEXT` environment variable in Windows specifies the file extensions that the operating system considers to be executable.
189
+
When you enter a command without specifying an extension, Windows will look for files with the extensions listed in `PATHEXT` in the directories specified by the `PATH` environment variable.
190
+
For example, if `PATHEXT` is set to `.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC`, and you enter the command `myprogram`, Windows will search for `myprogram.com`, `myprogram.exe`, `myprogram.bat`, and so on, in that order, in the directories listed in your `PATH` environment variable.
191
+
It will execute the first match it finds.
192
+
Given that .NET Tools are console applications, they should have the `.exe` extension on Windows to be considered valid plugins if the naming convention is followed.
193
+
194
+
- Similarly, on other platforms, NuGet should search for plugins with the executable bit set to identify them as valid plugins.
195
+
This is because on Mac and Linux, executable files typically don't have extensions.
196
+
Given that .NET Tools, when installed on Linux and Mac, have a native shim with an executable bit set, they should be considered valid plugins if the naming convention is followed.
197
+
198
+
Currently, `NuGet.exe`[scans all directories in the `PATH` environment variable](https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.CommandLine/MsBuildUtility.cs#L708-L736) to find `MSBuild.exe`.
183
199
184
200
#### Plugin execution
185
201
186
202
In the [current implementation](https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs#L155-L181), NuGet launches the `.exe` file in a separate process when running on the .NET Framework.
187
203
On the other hand, when running on .NET, NuGet executes the `dotnet plugin-in.dll` command in a separate process.
188
204
189
-
The plan is to slightly adjust this implementation. NuGet will launch the `.exe` file in a separate process when running on Windows, irrespective of whether the runtime is .NET Framework or .NET.
205
+
The plan is to slightly adjust this implementation. NuGet will launch the `.exe` file in a separate process when running on Windows, irrespective of whether the runtime is .NET Framework or .NET.
190
206
For non-Windows platforms, if the file does not have an extension, it will launch the executable directly in a separate process.
191
207
If the file has a `.dll` extension, it will continue to execute the `dotnet nuget-plugin-name.dll` command in a separate process.
192
208
@@ -207,6 +223,10 @@ See the `Future Possibilities` section for more details.
207
223
- The discoverability of NuGet plugins published as .NET Tools is challenging for users because the `dotnet tool search` command only filters based on the `PackageType` being `DotnetTool`.
208
224
Please refer to the `Future Possibilities` section for more related information.
209
225
226
+
- On Windows, NuGet searches for plugins using the `.exe` extension.
227
+
This is the case even though Windows recognizes all extensions configured in `PATHEXT` as executables.
228
+
For more information, please refer to the `Future Possibilities` section.
229
+
210
230
## Rationale and alternatives
211
231
212
232
### Installing NuGet plugins as tool-path .NET Tools
@@ -266,7 +286,7 @@ However, NuGet plugins and .NET tools share the similarity of being console appl
266
286
This approach is similar to the alternative design that [Andy Zivkovic](https://github.com/zivkan) kindly proposed in [[Feature]: Make NuGet credential providers installable via the dotnet cli](https://github.com/NuGet/Home/issues/11325).
267
287
The recommendation was developing a command like `dotnet nuget credential-provider install Microsoft.Azure.Artifacts.CredentialProvider`.
268
288
269
-
### Technical explanation
289
+
####Technical explanation
270
290
271
291
If none of the above environment variables are set, NuGet will default to the conventional method of discovering plugins from predefined directories.
272
292
In the [current implementation](https://github.com/NuGet/NuGet.Client/blob/8b658e2eee6391936887b9fd1b39f7918d16a9cb/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoveryUtility.cs#L65-L77), the NuGet code looks for plugin files in the `netfx` directory when running on .NET Framework, and in the `netcore` directory when running on .NET Core. This implementation should be updated to include the new `any` directory.
- The ideal workflow for repositories accessing private NuGet feeds, such as Azure DevOps, is to easily search for NuGet plugins and install them as global tool.
330
-
However, this approach suggests installing the plugin as a tool-path .NET tool.
350
+
However, this approach suggests installing the plugin as a tool-path .NET tool.
331
351
Customers can opt to install NuGet plugins as a global tool instead of a tool-path tool.
332
352
To do this, they need to set the `NUGET_DOTNET_TOOLS_PLUGIN_PATHS` environment variable.
333
353
This variable should point to the location of the .NET Tool executable, which the NuGet Client tooling can invoke when needed.
@@ -448,3 +468,27 @@ This might be because the new package type, `CredentialProvider`, which I added
448
468
If the `dotnet pack` command could generate a .nupkg for .NET Tool with multiple package types, we could introduce a new `dotnet nuget plugin search` command.
449
469
This command would act as a wrapper for the `dotnet tool search` command, further refining the results based on the additional package type, such as `CredentialProvider`.
450
470
These package types can be found in the `.nuspec` metadata file of the generated nupkg.
471
+
472
+
### Support for other extensions on Windows.
473
+
474
+
- In the future, we could consider supporting extensions other than `.exe` configured in `PATHEXT` as executables.
475
+
To achieve this, NuGet would need to identify the correct executable or interpretter to run a particular file.
476
+
For example, to execute a PowerShell script, NuGet would need to launch the process as shown below.
477
+
However, the challenge lies in identifying the appropriate executable for each type of file, which is not an immediate requirement.
0 commit comments