GitLab now supports nuget public and private feed repository.I've got a public project (e.g: https://gitlab.com/sunnyatticsoftware/sasw-test-support)I create an access token for my user with api
and write_repository
(e.g: AAABBBCCCDDD)
I create a group variable in my CI/CD: SASW_API_ACCESS_TOKEN
: AAABBBCCCDDD
. All normal.
Then I create the multi stage CI/CD script to build, pack and publish.When attempting to publish the nuGet package with the following:dotnet nuget push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api-key AAABBBCCCDDD --skip-duplicate
I get the error:
info : Pushing Sasw.TestSupport.2.0.2.nupkg to 'https://gitlab.com/api/v4/projects/17141695/packages/nuget'...info : PUT https://gitlab.com/api/v4/projects/17141695/packages/nuget/info : Unauthorized https://gitlab.com/api/v4/projects/17141695/packages/nuget/ 397mserror: Response status code does not indicate success: 401 (Unauthorized).ERROR: Job failed: exit code 1
The documentation doesn't mention anything special, but I notice that when using the (legacy?) nuget CLI it passes a username. Dotnet CLI, however, doesn't support username, just API KEY.
Any idea why this is not working?
This is my CI/CD script:
variables: GITLAB_RUNNER_DOTNET_CORE: mcr.microsoft.com/dotnet/core/sdk:3.1 NUGET_REPOSITORY: https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/nuget/index.json NUGET_API_KEY: $SASW_API_ACCESS_TOKEN NUGET_FOLDER_NAME: nupkgs NUGET_VERSION_SUFFIX: $SASW_PRERELEASE_SUFFIXstages: - build - pack - release#Docker imageimage: $GITLAB_RUNNER_DOTNET_CORE#Jobsci: stage: build script: - dotnet restore --no-cache --force - dotnet build --configuration Release --no-restore #- dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll #- dotnet vstest test/*IntegrationTests/bin/Release/**/*IntegrationTests.dllpack-prerelease: stage: pack script: - dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME --version-suffix $NUGET_VERSION_SUFFIX --include-symbols -p:SymbolPackageFormat=snupkg artifacts: paths: - $NUGET_FOLDER_NAME expire_in: 1 week except: - masterpack-release: stage: pack script: - dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME artifacts: paths: - $NUGET_FOLDER_NAME expire_in: 1 week only: - masterpublish-nuget: stage: release script: - dotnet nuget push **/*.nupkg --source $NUGET_REPOSITORY --api-key $NUGET_API_KEY --skip-duplicate
PS: The project is public, so in case it's needed have a look at: https://gitlab.com/sunnyatticsoftware/sasw-test-support/-/jobs/451080235
UPDATE 1: Further verbosity from my local linux console
$ dotnet nuget -v Debug push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api-key cBwt5_hidden_ --skip-duplicatetrace: NuGet Command Line Version: 5.4.0.2info : Pushing Sasw.TestSupport.2.0.2.nupkg to 'https://gitlab.com/api/v4/projects/17141695/packages/nuget'...info : PUT https://gitlab.com/api/v4/projects/17141695/packages/nuget/info : Unauthorized https://gitlab.com/api/v4/projects/17141695/packages/nuget/ 1159mserror: Response status code does not indicate success: 401 (Unauthorized).trace: System.AggregateException: One or more errors occurred. (Response status code does not indicate success: 401 (Unauthorized).)trace: ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).trace: at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.EnsureSuccessStatusCode(HttpResponseMessage response, Nullable`1 codeNotToThrow, ILogger logger)trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.<>c__DisplayClass23_0.<PushPackageToServer>b__0(HttpResponseMessage response)trace: at NuGet.Protocol.HttpSource.ProcessResponseAsync[T](HttpSourceRequest request, Func`2 processAsync, SourceCacheContext cacheContext, ILogger log, CancellationToken token)trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackageToServer(String source, String apiKey, String pathToPackage, Int64 packageSize, Boolean noServiceEndpoint, Boolean skipDuplicate, TimeSpan requestTimeout, ILogger logger, CancellationToken token)trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackageCore(String source, String apiKey, String packageToPush, Boolean noServiceEndpoint, Boolean skipDuplicate, TimeSpan requestTimeout, ILogger log, CancellationToken token)trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackage(String packagePath, String source, String apiKey, Boolean noServiceEndpoint, Boolean skipDuplicate, TimeSpan requestTimeout, ILogger log, CancellationToken token, Boolean isSnupkgPush)trace: at NuGet.Protocol.Core.Types.PackageUpdateResource.Push(String packagePath, String symbolSource, Int32 timeoutInSecond, Boolean disableBuffering, Func`2 getApiKey, Func`2 getSymbolApiKey, Boolean noServiceEndpoint, Boolean skipDuplicate, SymbolPackageUpdateResourceV3 symbolPackageUpdateResource, ILogger log)trace: at NuGet.Commands.PushRunner.Run(ISettings settings, IPackageSourceProvider sourceProvider, String packagePath, String source, String apiKey, String symbolSource, String symbolApiKey, Int32 timeoutSeconds, Boolean disableBuffering, Boolean noSymbols, Boolean noServiceEndpoint, Boolean skipDuplicate, ILogger logger)trace: at NuGet.CommandLine.XPlat.PushCommand.<>c__DisplayClass0_1.<<Register>b__1>d.MoveNext()trace: --- End of inner exception stack trace ---trace: at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)trace: at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)trace: at System.Threading.Tasks.Task`1.get_Result()trace: at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass56_0.<OnExecute>b__0()trace: at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)trace: at NuGet.CommandLine.XPlat.Program.MainInternal(String[] args, CommandOutputLogger log)