gitlab - 由于未经授权的错误,无法使用 dotnet CLI 将 nuGet 包推送到 GitLab
问题描述
GitLab 现在支持 nuget 公共和私人提要存储库。我有一个公共项目(例如:https ://gitlab.com/sunnyatticsoftware/sasw-test-support)我为我的用户创建了一个访问令牌api
和write_repository
(例如:AAABBBCCCDDD)
我在 CI/CD: 中创建了一个组SASW_API_ACCESS_TOKEN
变量AAABBBCCCDDD
。一切正常。
然后我创建多阶段 CI/CD 脚本来构建、打包和发布。尝试使用以下内容发布 nuGet 包时:
dotnet nuget push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api-key AAABBBCCCDDD --skip-duplicate
我得到错误:
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
该文档没有提及任何特别之处,但我注意到在使用(旧版?)nuget CLI 时,它会传递一个用户名。然而,Dotnet CLI 不支持用户名,只支持 API KEY。
知道为什么这不起作用吗?
这是我的 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:该项目是公开的,所以如果需要查看:https ://gitlab.com/sunnyatticsoftware/sasw-test-support/-/jobs/451080235
更新 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)
更新 2:Alexey 的答案是正确的,并且截至 2021 年 4 月是最新的。GitLab 在去年改进了对 Nuget 的支持,现在可以轻松地将包推送到 repo 包注册表并在项目级别对 Nuget 提要进行读取访问或使用部署令牌的组级别。
解决方案
按照文档推送从当前存储库构建的 NuGet 包非常容易。您不需要NuGet.config
文件来推送包,因为可以为dotnet push
命令指定凭据。您也不需要将凭据保存在 CI 文件中,因为 CI 变量包含将包推送到项目包注册表所需的所有临时凭据。
这是我的工作文件的一个片段,我.gitlab-ci.yml
从文档中复制粘贴。所有必要的信息都来自 CI 变量,所以这个片段是完全可重用的。
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
关于安装软件包的问题,您确实需要一个令牌。但这不是您的个人访问令牌。要让人们从您的提要中安装和恢复,您真正需要的只是存储库部署令牌。如果您在一个组中有多个项目,则不必在项目级别定义它,该组包含多个已发布 NuGet 包的项目。您还可以为整个组创建部署令牌。您为此目的创建的部署令牌只需要具有read_package_registry
权限,它不会授予获得此令牌的用户任何其他权限。
创建部署令牌后,令牌名称用作用户名,令牌本身就是密码。您将这两个都放入NuGet.config
文件中,其中列出了您的项目或组提要。
例如:
<?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>
推荐阅读
- reactjs - TypeError:ionRouterOutlet.commit 不是函数
- python-3.x - 计算图子集的最短路径
- java - 通过 JNA 发送用户定义的 Windows 消息
- powershell - 如何在powershell格式表中显示行号或行号
- javascript - 如何修复“查询中接受的正文参数”?
- c# - 在 ListBox 中实现 Selectable 用户控件
- css - 使用其他框架(如 Materialise)时,如何在 Bootstrap Navbar Toggler Icon 处于活动状态时更改其背景颜色?
- odoo - Odoo 模块的菜单根目录未显示
- javascript - 尝试将 .php 页面连接到在与 PHP 页面不同的端口上运行的套接字服务器
- html - 标头 html 错误