问题描述
GitLab 现在支持 nuget 公共和私人提要存储库.我有一个公共项目(例如:https://gitlab.com/sunnyatticsoftware/sasw-测试支持)我使用 api
和 write_repository
为我的用户创建访问令牌(例如:AAABBBCCCDDD)
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)
我在 CI/CD 中创建了一个组变量:SASW_API_ACCESS_TOKEN
:AAABBBCCCDDD
.一切正常.
I create a group variable in my CI/CD: SASW_API_ACCESS_TOKEN
: AAABBBCCCDDD
. All normal.
然后我创建多阶段 CI/CD 脚本来构建、打包和发布.尝试使用以下内容发布 nuGet 包时:dotnet nuget push **/*.nupkg --source https://gitlab.com/api/v4/projects/17141695/packages/nuget/index.json --api-key AAABBBCCCDDD --skip-duplicate代码>
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
我得到错误:
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.
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?
这是我的 CI/CD 脚本:
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_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
PS: The project is public, so in case it's needed have a look at: https://gitlab.com/sunnyatticsoftware/sasw-test-support/-/jobs/451080235
更新 1:来自本地 linux 控制台的更多详细信息
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-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 提要上拥有读取权限使用部署令牌的项目级别或组级别.
UPDATE 2: Alexey's answer is the proper one and up to date as per April 2021. GitLab has improved Nuget support in the last year and now it's possible to easily push packages to the repo package registry and have readacces on Nuget feed at project level or group level using deploy tokens.
推荐答案
推送从当前存储库构建的 NuGet 包非常简单,遵循 文档.您不需要 NuGet.config
文件来推送包,因为可以为 dotnet push
命令指定凭据.您也不需要将凭据保存在 CI 文件中,因为 CI 变量包含将包推送到项目包注册表所需的所有临时凭据.
Pushing NuGet packages built from the current repository is quite easy, following the documentation. You do not need a NuGet.config
file to push packages, as the credentials can be specified for the dotnet push
command. You also don't need to keep the credentials in the CI file, as the CI variables contain all the necessary temporary credentials to push packages to the project package registry.
这是我的工作 .gitlab-ci.yml
文件中的一个片段,我从文档中复制粘贴了该文件.所有必要的信息都来自 CI 变量,所以这个片段是完全可重用的.
This is a fragment from my working .gitlab-ci.yml
file, which I literally copy-pasted from the docs. All the necessary information comes from CI variables, so this snippet is totally reusable.
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
权限,它不会授予获得此令牌的用户任何其他权限.
Concerning the question about installing the package, you would, indeed, need a token. But it is not your personal access token. All you need really to let people install and restore from your feed is the repository deploy token. It doesn't have to be defined on the project level if you have multiple projects in a group, which contains several projects that have NuGet packages published. You can also create a deploy token for the whole group. The deploy token you create for this purpose only needs to have the read_package_registry
permissions and it doesn't give any other rights to the users who get this token.
创建部署令牌后,令牌名称作为用户名,令牌本身就是密码.您将这两个文件都放在 NuGet.config
文件中,在该文件中列出了您的项目或组供稿.
After creating a deploy token, the token name is used as the username, and the token itself is the password. You put both of those to the NuGet.config
file, where you have your project or group feed listed.
例如:
<?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>
这篇关于由于未经授权的错误,无法使用 dotnet CLI 将 nuGet 包推送到 GitLab的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!