如何在GitHub Actions中推送NuGet包

48

我正在尝试使用GitHub操作从我的项目生成NuGet包,并将其推送到(私有)GitHub注册表。

我的脚本([NAME]字段已过滤):

name: Update NuGet

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    name: Update NuGet 
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-dotnet@v1
        with:
          dotnet-version: '2.2.105'
      - name: Package Release
        run: |  
          cd [SOLUTION_FOLDER]
          dotnet pack -c Release -o out
      - name: Publish Nuget to GitHub registry
        run: dotnet nuget push ./[SOLUTION_FOLDER]/[PROJECT_FOLDER]/out/$(ls ./[SOLUTION_FOLDER]/[PROJECT_FOLDER]/out) -s https://nuget.pkg.github.com/[USERNAME]/index.json -k ${GITHUB_TOKEN}  
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 

日志输出:

info : Pushing [PROJECT_FOLDER].3.4.23.nupkg to 'https://nuget.pkg.github.com/[USERNAME]'...
info :   PUT https://nuget.pkg.github.com/[USERNAME]/
info : An error was encountered when fetching 'PUT https://nuget.pkg.github.com/[USERNAME]/'. The request will now be retried.
info : An error occurred while sending the request.
info :   The server returned an invalid or unrecognized response.
info :   PUT https://nuget.pkg.github.com/[USERNAME]/
info : An error was encountered when fetching 'PUT https://nuget.pkg.github.com/[USERNAME]/'. The request will now be retried.
info : An error occurred while sending the request.
info :   The server returned an invalid or unrecognized response.
info :   PUT https://nuget.pkg.github.com/[USERNAME]/
error: An error occurred while sending the request.
error:   The server returned an invalid or unrecognized response.
##[error]Process completed with exit code 1.

以下是对应的 GitHub 问题(带有解决方案选项):https://github.com/NuGet/Home/issues/8580


请添加说明,您如何使用“dotnet nuget push”命令修复了“错误:请指定软件包路径”的问题。 - Konard
@Konard 那是我的错。我没有在环境变量中获取文件名。我通过直接添加命令 dotnet nuget push /path/$(ls ..) 解决了这个问题。 - jwillmer
你成功地解决了这个问题吗?我也在尝试同样的事情,但是遇到了困难。 - Justus Burger
@JustusBurger 我正在联系GitHub支持。如果他们能帮我解决问题,我会发布答案。 - jwillmer
为什么不使用发布NuGet操作 - Alexan
7个回答

42

第二次更新: 我在GitHub问题中得到了jcansdale的答复,他说(我还没有测试):

现在GitHub Packages支持使用dotnet nuget push --api-key选项。由于某种原因,这个选项一直能够稳定工作,但是使用基本身份验证(在nuget.config文件中添加密码)会随机失败!

例子:

  - name: Publish Nuget to GitHub registry
    run: dotnet nuget push ./<project>/out/*.nupkg -k ${GITHUB_TOKEN} -s https://nuget.pkg.github.com/<organization>/index.json --skip-duplicate --no-symbols 
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

更新: 根据GitHub上Dids的回答,现在我的配置如下:

name: NuGet Generation

on:
  push:
    branches:
      - master
  pull_request:
    types: [closed]
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-18.04
    name: Update NuGet package
    steps:

      - name: Checkout repository
        uses: actions/checkout@v1

      - name: Setup .NET Core @ Latest
        uses: actions/setup-dotnet@v1
        with:
          source-url: https://nuget.pkg.github.com/<organization>/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}        
          
      - name: Build solution and generate NuGet package
        run: |  
          cd <project>
          dotnet pack -c Release -o out  

      - name: Push generated package to GitHub registry
        run: dotnet nuget push ./<project>/out/*.nupkg --skip-duplicate --no-symbols true

注意: 在撰写本文时,我需要使用--no-symbols true而非--no-symbols以防止dotnet NuGet客户端出现异常。


原来的回答:

我切换到Windows镜像,并按照@anangaur的示例成功运行了代码。这是我的最终代码:

name: NuGet Generation

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: windows-latest
    name: Update NuGet 
    steps:

      - name: Checkout repository
        uses: actions/checkout@master

#  latest image has .NET already installed!
#      - name: Setup .NET environment
#        uses: actions/setup-dotnet@v1
#        with:
#          dotnet-version: '2.2.105' 
          
      - name: Build solution and generate NuGet package
        run: |  
          cd SOLUTION_FOLDER
          dotnet pack -c Release -o out  

      - name: Install NuGet client
        uses: warrenbuckley/Setup-Nuget@v1
        
      - name: Add private GitHub registry to NuGet
        run: nuget sources add -name "GPR" -Source https://nuget.pkg.github.com/ORGANIZATION_NAME/index.json -Username ORGANIZATION_NAME -Password ${{ secrets.GITHUB_TOKEN }}
        
      - name: Push generated package to GitHub registry
        run: nuget push .\SOLUTION_FOLDER\PROJECT_FOLDER\out\*.nupkg -Source "GPR" -SkipDuplicate


2
请确保在您的 csproj 文件中设置 RepositoryUrl 值。 - ctyar
我曾经有其他的评论,但已删除。我现在遇到了这个问题: 警告:未检测到目标存储库。请确保源项目定义了'RepositoryUrl'属性。如果您正在使用nuspec文件,请确保它具有所需的'repository'元素和'type'和'url'属性。 BadRequest https://nuget.pkg.github.com/myOrganization/ 25ms 错误:响应状态代码表明操作失败:400(错误请求)。 我从URL中删除了我的组织实际名称。 - John Demetriou
如果我使用GitHub Actions的source-url,那么是否会阻止我也推送到NuGet.org? 其次,我相信--no-symbols标志现在已经修复了。 - Muhammad Rehan Saeed
1
有人知道如何在 .Net Framework 项目中指定 RepositoryUrl 吗?直到 .Net Standard 或 Core 才添加了该元素。 - JasonDWilson
--no-symbols true 会导致 error: File does not exist (true).。不再支持传递 --no-symbols 的值。因此应该将 true 删除。 - Steven T. Cramer
如何增加NuGet版本? - user1034912

6
你可以使用 dotnet nuget add source 命令进行操作:(链接)
    - name: NuGet push
      run: |
        dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --name github --username ${{ github.repository_owner }} --password ${{ github.token }} --store-password-in-clear-text
        dotnet nuget push **/*.nupkg --source github

在 Linux 环境中运行时,我需要使用 --store-password-in-clear-text 选项。

通过这种方法,无需修改 actions/setup-dotnet 任务。此方法还允许您根据需要推送到多个 NuGet 流。


1
完美的,谢谢,正是我所需要的。也可以在末尾加上“--skip-duplicate”来组合使用。 - Marfu

6

这里有一个解决方案,适用于所有平台:

name: prerelease NuGet

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    # also works with windows-latest and macos-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v1
    - name: Build with dotnet
      run: dotnet build --configuration Release --version-suffix prerelease-$(date +%Y%m%d%H%M%S)
      shell: bash
    - name: Publish nuget
      run: |
           for f in ./[repository]/bin/Release/*.nupkg
           do
             curl -vX PUT -u "[user]:${{ secrets.GHPackagesToken }}" -F package=@$f https://nuget.pkg.github.com/[user]/
           done
      shell: bash

注意事项:

  • 此操作会为每次 Git push 创建带有日期时间戳的预发布版本,并将其上传到 NuGet。
    • 要使后缀生效,您需要在 .csproj 中设置 <VersionPrefix> 而不是 <Version>
    • 如果您不想要预发布后缀,请删除 --version-suffix 参数。
  • Shell 明确设置为 bash,以便兼容 Windows 上的构建。
  • 您需要将上面的 [user] 和 [repository] 替换为您自己的特定值。
    • 您需要创建一个具有 write:packages 权限的个人访问令牌
    • 然后创建一个名为 GHPackagesToken 的GitHub 机密,并将上面创建的令牌放入其中。
    • 使用 GitHub 机密可消除包含您的令牌的单独文件的需求。
  • 这假设您在 .csproj 中有 <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    • 如果没有,则需要运行一个额外的步骤来运行 dotnet pack
  • 请确保在您的 .csproj 中指定 <RepositoryUrl>...</RepositoryUrl>
  • 如果您无法使上述代码工作,请参阅此处的工作示例,该示例会将代码推送到 https://github.com/vslee/IEXSharp/packages(请忽略我所有多余的注释)。
    • 我发布了这篇文章,因为我尝试了 jwillmer 和 GH 问题线程上的 @anangaur 和 @marza91 的两个示例,但在任何平台上都无法正常工作。
  • 一旦 GitHub 解决了无法直接在 dotnet nuget push 命令中使用 API 密钥的问题(请参见GH 问题的初始帖子),我们就不再需要这个解决方法了。

没有看到你的仓库,很难说。但是听起来curl可能难以读取文件(nupkg)? - vlee
1
好的,实际上你并没有创建一个nupkg。所以你可以取消注释你的Pack步骤,或者在你的.csproj中添加<GeneratePackageOnBuild>true</GeneratePackageOnBuild>。 - vlee
GHPackagesToken 是你的 Nuget Api 密钥吗? - Emil
不,这是GitHub Packages令牌。您可以在GitHub Secrets中生成它(请参见我的回答中的链接)。NuGet API密钥在此处未使用,因为此操作不会上传到官方NuGet网站。 - vlee
啊,好的,我误读了问题。我以为他想要推送到 NuGet。谢谢。 - Emil
显示剩余3条评论

4

其他的回答太长了,我也不知道为什么。这是我的做法:

针对 NuGet.org:

- name: Push Package to NuGet.org
  run: dotnet nuget push *.nupkg -k ${{ secrets.NUGET_ORG_API_KEY }} -s https://api.nuget.org/v3/index.json

对于GitHub.com:

- name: Push Package to GitHub.com
  run: dotnet nuget push *.nupkg -k ${{ secrets.GITHUB_TOKEN }} -s https://nuget.pkg.github.com/USERNAME/index.json

如果您阅读了最初的问题,您会发现您的解决方案过去并不起作用。今天这可能非常正确。 - jwillmer

4

请确保您的项目文件包含以下内容

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <OutputType>Library</OutputType>
    <PackageId>Example.PackageName</PackageId>
    <Version>1.0.0</Version>
    <Authors>Author Engineering</Authors>
    <Company>Company Inc</Company>
    <PackageDescription>This package for ...!</PackageDescription>
    <RepositoryUrl>
https://github.com/YOUR_ACCOUNT/Example.PackageName</RepositoryUrl>
  </PropertyGroup>

这应该是你的main.yaml文件,用于构建、打包、发布和版本控制:
name: Continuous Integration

on:
  push:
    branches:
      - master

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Setup Dotnet Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 3.1.100
        source-url: https://nuget.pkg.github.com/YOUR_ACCOUNT/index.json
      env:
        NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

    - name: Setup Nuget Config
      run: sed 's/GITHUB_TOKEN/${{ secrets.GITHUB_TOKEN }}/g' .nuget.config > nuget.config

    - name: Build
      run: dotnet build --configuration Release

    - name: Version and Tag
      id: bump_version
      uses: mathieudutour/github-tag-action@v1
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}

    - name: Prep Version String
      run: echo ::set-env name=VERSION_NUMBER::$(echo ${{ steps.bump_version.outputs.new_tag }} | sed 's/[v]//g')

    - name: Define Package Name
      run: echo ::set-env name=PACKAGE_NAME::$"Example.PackageName/bin/Release/Example.PackageName.${{ env.VERSION_NUMBER }}.nupkg"

    - name: Set Nuget Package Version
      uses: roryprimrose/set-vs-sdk-project-version@v1
      with:
        version: ${{ env.VERSION_NUMBER }}

    - name: Pack
      run: dotnet pack --configuration Release Example.PackageName

    - name: Publish Package
      run: dotnet nuget push Example.PackageName/bin/Release/*.nupkg --source https://nuget.pkg.github.com/YOUR_ACCOUNT/index.json

    - name: Create Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ steps.bump_version.outputs.new_tag }}
        release_name: Release ${{ github.ref }}


设置环境变量已更改:docs.github.com/en/actions/reference/…. 例如:运行:echo "VERSION_NUMBER=$(echo ${{ steps.bump_version.outputs.new_tag }} | sed 's/[v]//g')" >> $GITHUB_ENV 和运行:echo 'PACKAGE_NAME=$"Example.PackageName/bin/Release/Example.PackageName.${{ env.VERSION_NUMBER }}.nupkg" ' >> $GITHUB_ENV - roeland
值得注意的是,<RepositoryUrl>https://github.com/YOUR_ACCOUNT/Example.PackageName</RepositoryUrl> 需要识别存储库而不是包,就像 <RepositoryUrl>https://github.com/YOUR_ACCOUNT/YOUR_REPOSITORY</RepositoryUrl> 一样。通常情况下,存储库名称和包ID将匹配,但这并非必须。 - Mike Schenk

1

我的工作解决方案:

  • 将“usernamecompanyname”替换为您的存储库的有效值
  • 我将构建和打包分开,以便在出现问题时更容易进行调试
  • 您可以在github secrets中设置变量为,以允许更详细的调试
  • 将更改为所需的dotnet-sdk版本
  • 不需要在github repo secrests中指定,该令牌默认存在

build_and_publish_nuget.yml:

name: Build and publish package

# Controls when the action will run. Triggers the workflow on push or pull request 
# events but only for the master branch
on:
  push:
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@master

      - name: Setup .NET environment
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: '3.1.102'
          source-url: https://nuget.pkg.github.com/usernamecompanyname/index.json
        env:
          NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

      - name: Build project
        run: dotnet build -c Release

      - name: Generate a NuGet package
        run: dotnet pack --no-build -c Release -o .

      - name: Push to GitHub package registry
        run: dotnet nuget push *.nupkg

有没有想过如何从同一组织的另一个存储库中使用此软件包? - Pradeep

1
GitHub在将NuGet Packages发布到GitHub Packages时出现间歇性问题。我联系了支持团队,他们给了我两个选项。
选项1:使用CURL。
curl -vX PUT -u "<username>:<TOKEN>" -F package=@PATH-TO-PKG-FILE.nupkg https://nuget.pkg.github.com/<OWNER>/

选项2:DOTNET GPR工具
https://github.com/jcansdale/gpr

dotnet tool install gpr -g
gpr push PATH-TO-PKG-FILE.nupkg -k <TOKEN>

在我的 GitHub Action 工作流中,我选择了选项2

$file = Get-ChildItem -Path <where I output my nupkg file to> -Recurse -Filter *.nupkg | Select -First 1
gpr push $file.FullName -k ${{secrets.GITHUB_TOKEN}}          

或者您可以使用 nuget.exe 而不是 dotnet nuget 来推送到 GPR。这样应该能够保持一致性。 - Pieterjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接