GeWuYou 1f34928785 feat(ci): 添加发布工作流支持NuGet和GitHub Packages
- 实现自动构建和打包功能,支持标签触发
- 集成NuGet.org和GitHub Packages双重发布机制
- 添加许可证合规性检查和SBOM文件生成
- 实现GitHub Release自动创建和资产上传
- 配置OIDC身份验证和临时API密钥管理
- 添加包重复上传检测和跳过功能
2026-04-05 18:49:08 +08:00

249 lines
7.2 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 发布工作流NuGet + GitHub Packages + GitHub Release
#
# 功能:当推送标签时自动构建、打包,并将相同产物并发发布到 NuGet.org 与 GitHub Packages
# 最后创建 GitHub Release。
# 触发条件:推送任何标签(如 v1.0.0 或 1.0.0
# 权限:允许写入内容、包和使用 OIDC 身份验证
name: Publish (NuGet + GitHub Packages + GitHub Release)
on:
push:
tags:
- '*'
permissions:
contents: write
packages: write
id-token: write
jobs:
build-pack:
name: Build And Pack
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
id-token: write
outputs:
package_version: ${{ steps.tag_version.outputs.version }}
steps:
- name: Checkout repository (at tag)
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: true
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
- name: Restore dependencies
run: dotnet restore
# 从 GitHub 引用中提取标签版本。
# 提取逻辑:去除 refs/tags/ 前缀,然后去除 v/V 前缀。
- name: Determine tag version
id: tag_version
run: |
set -e
echo "GITHUB_REF = ${GITHUB_REF}"
TAG=${GITHUB_REF#refs/tags/}
VERSION=${TAG#v}
VERSION=${VERSION#V}
echo "tag='$TAG' -> version='$VERSION'"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Pack (use tag version)
run: |
set -e
echo "Packing with version=${{ steps.tag_version.outputs.version }}"
dotnet pack -c Release -o ./packages -p:PackageVersion=${{ steps.tag_version.outputs.version }} -p:IncludeSymbols=false
- name: Show packages
run: ls -la ./packages || true
# 上传 nupkg 工件,供多个发布 job 复用,避免重复打包。
- name: Upload package artifacts
uses: actions/upload-artifact@v7
with:
name: packages
path: ./packages/*.nupkg
# 上传许可证合规相关的工件文件包括通知文件、第三方许可证、SBOM 文件及验证结果。
- name: Upload compliance artifacts
uses: actions/upload-artifact@v7
with:
name: license-compliance
path: |
NOTICE
THIRD_PARTY_LICENSES.md
sbom.spdx.json
sbom.cyclonedx.json
sbom-spdx-validation.txt
sbom-cyclonedx-validation.txt
publish-nuget:
name: Publish To NuGet.org
runs-on: ubuntu-latest
needs: build-pack
permissions:
contents: read
packages: read
id-token: write
steps:
- name: Download package artifacts
uses: actions/download-artifact@v5
with:
name: packages
path: ./packages
- name: Show downloaded packages
run: ls -la ./packages || true
- name: NuGet login (OIDC → temporary API key)
id: nuget_login
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_USER }}
# 将所有生成的包推送到 nuget.org。
# 使用临时 API 密钥进行身份验证,并跳过重复包上传。
- name: Push all packages to nuget.org
env:
NUGET_API_KEY: ${{ steps.nuget_login.outputs.NUGET_API_KEY }}
run: |
set -e
echo "Found API key: ${NUGET_API_KEY:+*** present ***}"
pushed_any=false
for PKG in ./packages/*.nupkg; do
[ -f "$PKG" ] || continue
pushed_any=true
echo "Pushing $PKG to nuget.org..."
dotnet nuget push "$PKG" \
--api-key "${NUGET_API_KEY}" \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate
done
if [ "$pushed_any" = false ]; then
echo "No packages found to push."
fi
publish-github-packages:
name: Publish To GitHub Packages
runs-on: ubuntu-latest
needs: build-pack
permissions:
contents: read
packages: write
steps:
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
- name: Download package artifacts
uses: actions/download-artifact@v5
with:
name: packages
path: ./packages
- name: Show downloaded packages
run: ls -la ./packages || true
# 使用仓库内建的 GITHUB_TOKEN 配置 GitHub Packages NuGet 源。
- name: Configure GitHub Packages source
run: |
set -e
dotnet nuget add source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
--name github \
--username "${{ github.repository_owner }}" \
--password "${{ secrets.GITHUB_TOKEN }}" \
--store-password-in-clear-text
- name: Push all packages to GitHub Packages
run: |
set -e
pushed_any=false
for PKG in ./packages/*.nupkg; do
[ -f "$PKG" ] || continue
pushed_any=true
echo "Pushing $PKG to GitHub Packages..."
dotnet nuget push "$PKG" \
--source github \
--skip-duplicate
done
if [ "$pushed_any" = false ]; then
echo "No packages found to push."
fi
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs:
- build-pack
- publish-nuget
- publish-github-packages
if: ${{ always() && needs.build-pack.result == 'success' }}
permissions:
contents: write
packages: read
steps:
- name: Download package artifacts
uses: actions/download-artifact@v5
with:
name: packages
path: ./packages
- name: Download compliance artifacts
uses: actions/download-artifact@v5
with:
name: license-compliance
path: .
# 无论某一侧包源发布是否失败,都继续创建 Release并在正文中标注结果。
- name: Create GitHub Release and Upload Assets
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
name: "Release ${{ github.ref_name }}"
body: |
Release created by CI for tag ${{ github.ref_name }}
Package version: ${{ needs.build-pack.outputs.package_version }}
## Publish Status
- NuGet.org publish: ${{ needs.publish-nuget.result }}
- GitHub Packages publish: ${{ needs.publish-github-packages.result }}
## Compliance
- NOTICE
- THIRD_PARTY_LICENSES
- SPDX & CycloneDX SBOM
draft: false
prerelease: false
files: |
./packages/*.nupkg
NOTICE
THIRD_PARTY_LICENSES.md
sbom.spdx.json
sbom.cyclonedx.json
sbom-spdx-validation.txt
sbom-cyclonedx-validation.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}