由于未经授权的错误,无法使用dotnet CLI将nuGet软件包推送到GitLab

由于未经授权的错误,无法使用dotnet CLI将nuGet软件包推送到GitLab,gitlab,gitlab-ci,nuget-package,dotnet-cli,Gitlab,Gitlab Ci,Nuget Package,Dotnet Cli,GitLab现在支持nuget公共和私有提要存储库。 我有一个公共项目(例如:) 我使用api和write\u repository为我的用户创建访问令牌(例如:aaabbbccddd) 我在我的CI/CD中创建了一个组变量:SASW\u API\u ACCESS\u TOKEN:aaabbbccddd。一切正常 然后我创建多阶段CI/CD脚本来构建、打包和发布。 尝试发布包含以下内容的nuGet包时: dotnet nuget push**/*.nupkg--源代码https://gitlab

GitLab现在支持nuget公共和私有提要存储库。 我有一个公共项目(例如:) 我使用
api
write\u repository
为我的用户创建访问令牌(例如:aaabbbccddd)

我在我的CI/CD中创建了一个组变量:
SASW\u API\u ACCESS\u TOKEN
aaabbbccddd
。一切正常

然后我创建多阶段CI/CD脚本来构建、打包和发布。 尝试发布包含以下内容的nuGet包时:
dotnet nuget push**/*.nupkg--源代码https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api键aaabbbccddd--跳过重复项

我得到一个错误:

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/ 397ms
error: Response status code does not indicate success: 401 (Unauthorized).
ERROR: Job failed: exit code 1
没有提到任何特殊的内容,但我注意到,在使用(legacy?)nuget CLI时,它会传递一个用户名。然而,DotnetCLI不支持用户名,只支持API密钥

你知道为什么这样不行吗

这是我的CI/CD脚本:

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_SUFFIX

stages:
  - build
  - pack
  - release
  
#Docker image
image: $GITLAB_RUNNER_DOTNET_CORE

#Jobs
ci:
  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.dll
    
pack-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:
    - master

pack-release:
  stage: pack
  script:
    - dotnet pack *.sln --configuration Release --output $NUGET_FOLDER_NAME
  artifacts:
    paths:
    - $NUGET_FOLDER_NAME
    expire_in: 1 week
  only:
    - master

publish-nuget:
  stage: release
  script:
    - dotnet nuget push **/*.nupkg --source $NUGET_REPOSITORY --api-key $NUGET_API_KEY --skip-duplicate
PS:该项目是公开的,因此如果需要,请查看:


更新1:来自本地linux控制台的更多详细信息

$ dotnet nuget -v Debug push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api-key cBwt5_hidden_ --skip-duplicate
trace: NuGet Command Line Version: 5.4.0.2
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/ 1159ms
error: 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)

$dotnet nuget-v调试推送**/*.nupkg--源代码https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api密钥cBwt5\u隐藏\u——跳过重复
trace:NuGet命令行版本:5.4.0.2
信息:正在将Sasw.TestSupport.2.0.2.nupkg推送到'https://gitlab.com/api/v4/projects/17141695/packages/nuget'...
信息:放https://gitlab.com/api/v4/projects/17141695/packages/nuget/
信息:未经授权https://gitlab.com/api/v4/projects/17141695/packages/nuget/ 1159ms
错误:响应状态代码不表示成功:401(未授权)。
跟踪:System.AggregateException:发生一个或多个错误。(响应状态代码不表示成功:401(未经授权)。)
跟踪:-->System.Net.Http.HttpRequestException:响应状态代码不表示成功:401(未经授权)。
跟踪:位于System.Net.Http.HttpResponseMessage.EnsureResccessStatusCode()处
跟踪:在NuGet.Protocol.Core.Types.PackageUpdateResource.EnsureSessAccessStatusCode处(HttpResponseMessageResponse,Nullable`1 codeNotToThrow,ILogger记录器)
跟踪:在NuGet.Protocol.Core.Types.PackageUpdateResource.c__DisplayClass23_0.b__0(HttpResponseMessage响应)
跟踪:在NuGet.Protocol.HttpSource.ProcessResponseAsync[T](HttpSourceRequest请求,Func`2 processAsync,SourceCacheContext cacheContext,ILogger日志,CancellationToken令牌)
跟踪:在NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackageToServer(字符串源、字符串apiKey、字符串pathToPackage、Int64 packageSize、布尔noServiceEndpoint、布尔skipDuplicate、TimeSpan请求超时、ILogger、CancellationToken令牌)
跟踪:在NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackageCore(字符串源、字符串apiKey、字符串packageToPush、布尔noServiceEndpoint、布尔skipDuplicate、TimeSpan请求超时、ILogger日志、CancellationToken令牌)
跟踪:在NuGet.Protocol.Core.Types.PackageUpdateResource.PushPackage(String packagePath、String source、String apiKey、Boolean noServiceEndpoint、Boolean skipDuplicate、TimeSpan requestTimeout、ILogger日志、CancellationToken令牌、Boolean isSnupkgPush)
跟踪:在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、iLog)
跟踪:在NuGet.Commands.PushRunner.Run(ISettings设置、IPackageSourceProvider sourceProvider、String packagePath、String source、String apiKey、String symbolSource、String symbolApiKey、Int32 timeoutSeconds、布尔禁用缓冲、布尔noSymbols、布尔noServiceEndpoint、布尔跳过复制、ILogger)
trace:at numget.CommandLine.XPlat.PushCommand.c_uudisplayClass0_1.d.MoveNext()
跟踪:---内部异常堆栈跟踪的结束---
跟踪:在System.Threading.Tasks.Task.ThrowifeException(布尔includeTaskCanceledException)
跟踪:在System.Threading.Tasks.Task`1.GetResultCore(布尔waitCompletionNotification)
trace:at System.Threading.Tasks.Task`1.get_Result()
跟踪:在Microsoft.Extensions.CommandLineUtils.CommandLineApplication.c__DisplayClass56_0.b__0()中
跟踪:位于Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(字符串[]args)
跟踪:位于NuGet.CommandLine.XPlat.Program.MainInternal(字符串[]args,CommandOutputLogger日志)

更新2:Alexey的答案是正确的,并且是2021年4月的最新答案。GitLab在去年改进了Nuget支持,现在可以轻松地将包推送到repo包注册表,并使用部署令牌在项目级或组级对Nuget提要进行读取访问。

我设法以一种完全不直观的方式推送Nuget。 我必须创建一个包含凭据详细信息的NuGet.Config。这是我不喜欢的,因为将api键传递给
dotnet nuget push
命令就足够了

无论如何,以下是我的步骤:
dotnet new nugetconfig——强制
在我的解决方案的根文件夹中创建一个NuGet.Config 然后对其进行编辑以添加新源(链接到特定项目。烦人..)

现在我可以看到可用的包,但没有元数据(不确定原因)。因此,如果我将相同的NuGet.Config添加到任何解决方案文件夹中,并尝试安装该包,它就会正常工作

$ dotnet add Foo/Foo.csproj package Sasw.TestSupport
  Writing C:\Users\dmsanz\AppData\Local\Temp\tmpF8D4.tmp
info : Adding PackageReference for package 'Sasw.TestSupport' into project 'Foo/Foo.csproj'.
info : Restoring packages for D:\src\sasw\sasw-test-support\Foo\Foo.csproj...
info :   CACHE https://api.nuget.org/v3-flatcontainer/sasw.testsupport/index.json
info :   CACHE https://gitlab.com/api/v4/projects/17141695/packages/nuget/download/sasw.testsupport/index.json
info : Package 'Sasw.TestSupport' is compatible with all the specified frameworks in project 'Foo/Foo.csproj'.
info : PackageReference for package 'Sasw.TestSupport' version '2.0.3' added to file 'D:\src\sasw\sasw-test-support\Foo\Foo.csproj'.
info : Committing restore...
info : Writing assets file to disk. Path: D:\src\sasw\sasw-test-support\Foo\obj\project.assets.json
log  : Restore completed in 1.13 sec for D:\src\sasw\sasw-test-support\Foo\Foo.csproj.
它是有效的。。。但我一点也不喜欢

  • 首先,我不能让我的NuGet.Config通用,他们需要一个包含特定项目的URL。最好至少有一个指向组而不是项目的nuGet提要,这样nuGet.Config就可以在不同的项目之间共享
  • 使用api键来运行命令并不直观,我需要委托一个NuGet.Config来提供
    $ dotnet nuget push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --skip-duplicate
    warn : No API Key was provided and no API Key could be found for 'https://gitlab.com/api/v4/projects/17141695/packages/nuget'. To save an API Key for a source use the 'setApiKey' command.
    info : Pushing Sasw.TestSupport.2.0.3.nupkg to 'https://gitlab.com/api/v4/projects/17141695/packages/nuget'...
    info :   PUT https://gitlab.com/api/v4/projects/17141695/packages/nuget/
    info :   Created https://gitlab.com/api/v4/projects/17141695/packages/nuget/ 1936ms
    info : Your package was pushed.
    
    $ dotnet add Foo/Foo.csproj package Sasw.TestSupport
      Writing C:\Users\dmsanz\AppData\Local\Temp\tmpF8D4.tmp
    info : Adding PackageReference for package 'Sasw.TestSupport' into project 'Foo/Foo.csproj'.
    info : Restoring packages for D:\src\sasw\sasw-test-support\Foo\Foo.csproj...
    info :   CACHE https://api.nuget.org/v3-flatcontainer/sasw.testsupport/index.json
    info :   CACHE https://gitlab.com/api/v4/projects/17141695/packages/nuget/download/sasw.testsupport/index.json
    info : Package 'Sasw.TestSupport' is compatible with all the specified frameworks in project 'Foo/Foo.csproj'.
    info : PackageReference for package 'Sasw.TestSupport' version '2.0.3' added to file 'D:\src\sasw\sasw-test-support\Foo\Foo.csproj'.
    info : Committing restore...
    info : Writing assets file to disk. Path: D:\src\sasw\sasw-test-support\Foo\obj\project.assets.json
    log  : Restore completed in 1.13 sec for D:\src\sasw\sasw-test-support\Foo\Foo.csproj.
    
    nuget:
      stage: deploy
      image: mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
      script:
        - dotnet pack -c Release -o $PWD/nuget
        - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
        - dotnet nuget push "$PWD/nuget/*.nupkg" --source gitlab
      only:
        - master
        - tags
    
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <packageSources>
            <clear />
            <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
            <add key="myfeed" value="https://gitlab.mydomain.dev/api/v4/groups/19/-/packages/nuget/index.json" />
        </packageSources>
        <packageSourceCredentials>
            <myfeed>
                <add key="Username" value="gitlab+deploy-token-14" />
                <add key="ClearTextPassword" value="thetokenvalue" />
            </myfeed>
        </packageSourceCredentials>
    </configuration>