0

Overview

I have managed to package and push a dotnet Project Template file to the Github nuget package feed. Package is visible here: https://github.com/TristanRhodes/TestedLibraryTemplate/pkgs/nuget/TestTemplate

I am unable to pull / install this package.

Source Configuration

I have configured a source like this:

dotnet nuget add source https://nuget.pkg.github.com/TristanRhodes/index.json?apikey={apikey} --name TR.Packages

Note: I have also managed to authenticate succesfully with user/password. I can get past the 401 errors either way.

Dotnet Nuget Add

If I attempt to install a template project using the following command:

dotnet new install TestTemplate --nuget-source TR.Packages --force -d

I get:

NuGet.Protocol.Core.Types.FatalProtocolException: Failed to fetch results from V2 feed at 'https://nuget.pkg.github.com/TristanRhodes/index.json/FindPackagesById()?id='TestTemplate'&semVerLevel=2.0.0' with following message : Response status code does not indicate success: 405 (Method Not Allowed).

Nuget List

I've also tried updating my local install of nuget and using the following search command with user/pass:

nuget list TestTemplate

And this errors with:

The V2 feed at 'https://nuget.pkg.github.com/TristanRhodes/index.json/Search()?$filter=IsLatestVersion&$orderby=Id&searchTerm='TestTemplate'&targetFramework=''&includePrerelease=false&$skip=0&$top=30&semVerLevel=2.0.0' returned an unexpected status code '405 Method Not Allowed'.

Full logs for dotnet new install TestTemplate --nuget-source TR.Packages --force:

The following template packages will be installed:

TestTemplate

[2023-03-31 19:20:15.505] [Debug] [Microsoft.TemplateEngine.Edge.Installers.NuGet.NuGetInstaller] => [Execute]: TestTemplate is identified as the downloadable NuGet package.

[2023-03-31 19:20:15.508] [Debug] [Microsoft.TemplateEngine.Edge.Installers.NuGet.NuGetInstaller] => [Execute]: TestTemplate is identified as the downloadable NuGet package.

[2023-03-31 19:20:15.560] [Debug] [NuGetLogger] => [Execute]: GET https://api.nuget.org/v3/registration5-gz-semver2/testtemplate/index.json

[2023-03-31 19:20:15.584] [Debug] [NuGetLogger] => [Execute]: Searching for TestTemplate in https://nuget.pkg.github.com/TristanRhodes/index.json?apikey={apikey}.

[2023-03-31 19:20:15.593] [Debug] [NuGetLogger] => [Execute]: Searching for TestTemplate in C:\Program Files (x86)\Microsoft SDKs\NuGetPackages.

[2023-03-31 19:20:15.597] [Debug] [NuGetLogger] => [Execute]: TestTemplate is not found in NuGet feed C:\Program Files (x86)\Microsoft SDKs\NuGetPackages.

[2023-03-31 19:20:15.777] [Debug] [NuGetLogger] => [Execute]: OK https://api.nuget.org/v3/registration5-gz-semver2/testtemplate/index.json 215ms

[2023-03-31 19:20:15.834] [Debug] [NuGetLogger] => [Execute]: TestTemplate is not found in NuGet feed https://api.nuget.org/v3/index.json.

[2023-03-31 19:20:15.902] [Debug] [NuGetLogger] => [Execute]: GET https://nuget.pkg.github.com/TristanRhodes/index.json/FindPackagesById()?id='TestTemplate'&semVerLevel=2.0.0

[2023-03-31 19:20:16.013] [Debug] [NuGetLogger] => [Execute]:
MethodNotAllowed https://nuget.pkg.github.com/TristanRhodes/index.json/FindPackagesById()?id='TestTemplate'&semVerLevel=2.0.0 110ms

[2023-03-31 19:20:16.021] [Debug] [NuGetLogger] => [Execute]: Details: NuGet.Protocol.Core.Types.FatalProtocolException: Failed to fetch results from V2 feed at 'https://nuget.pkg.github.com/TristanRhodes/index.json/FindPackagesById()?id='TestTemplate'&semVerLevel=2.0.0' with following message : Response status code does not indicate success: 405 (Method Not Allowed). ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 405 (Method Not Allowed).

at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()

at NuGet.Protocol.HttpSource.<>c__DisplayClass15_0`1.<b__0>d.MoveNext()

--- End of stack trace from previous location ---

at NuGet.Common.ConcurrencyUtilities.ExecuteWithFileLockedAsync[T](String filePath, Func`2 action, CancellationToken token)

at NuGet.Protocol.V2FeedParser.LoadXmlAsync(String uri, String cacheKey, Boolean ignoreNotFounds, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token)

--- End of inner exception stack trace ---

at NuGet.Protocol.V2FeedParser.LoadXmlAsync(String uri, String cacheKey, Boolean ignoreNotFounds, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token)

at NuGet.Protocol.V2FeedParser.QueryV2FeedAsync(String relativeUri, String id, Int32 max, Boolean ignoreNotFounds, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token)

at NuGet.Protocol.V2FeedParser.FindPackagesByIdAsync(String id, Boolean includeUnlisted, Boolean includePrerelease, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token)

at NuGet.Protocol.PackageMetadataResourceV2Feed.GetMetadataAsync(String packageId, Boolean includePrerelease, Boolean includeUnlisted, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token)

at Microsoft.TemplateEngine.Edge.Installers.NuGet.NuGetApiPackageManager.GetPackageMetadataAsync(PackageSource source, String packageIdentifier, Boolean includePrerelease, CancellationToken cancellationToken).

Question

So.. how do I get to my package that feels so tantalisingly close? :(

Tristan Rhodes
  • 393
  • 6
  • 19

1 Answers1

0

According to GitHub's documentation on using the GitHub Package Registry with NuGet, their suggested way of authenticating to the package source is:

dotnet nuget add source --username USERNAME \
--password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text \
--name github "https://nuget.pkg.github.com/NAMESPACE/index.json"

I'm not sure where you got the idea to append ?apikey={apikey} to the URL from, I haven't seen anyone else do it before so don't know if it works. However, as you can see from the errors you're getting, it doesn't work with how NuGet itself works.

NuGet has two "protocols" over HTTP. V2 is based on OData, and V3 is based on generated URLs, the NuGet's feed (other than search and push) to be hostable on a static file server, reducing hosting costs. It's possible to override NuGet's protocol detection by setting protocolVersion in the nuget.config file, but currently there is no way to specify protocolVersion on the CLI (but there is a community PR out implementing it, so hopefully soon it'll be merged then the next version of .NET will support it). Alternatively you can script editing nuget.config however you prefer, if you wish to go down that path. One example is in the linked issue on GitHub.

However, if protocolVersion isn't specified in the nuget.config file, then NuGet will assume that anything where urlString.EndsWith("/index.json") is V3, and everything else is V2. You might say that ?apiKey= is a query parameter and should be ignored in "url ends with" checks. But, that's not how NuGet is implemented. Discussions about how it should work is out of scope for a Q&A site like Stack Overflow.

Therefore, NuGet needs the URL to feeds implementing the V3 protocol to end in /index.json, or for the nuget.config file to explicitly specify protocolVersion="3". Otherwise NuGet will assume it's a V2 feed and try to talk OData. If NuGet sends requests to the remote web server that it doesn't understand, you'll get different types of errors, depending on how the server is written. HTTP 405 (method not allowed) and HTTP 404 (not found) responses are common, but HTTP 400 (bad request) might happen, or servers with poor error handling might return HTTP 500 (server internal error).

zivkan
  • 12,793
  • 2
  • 34
  • 51