mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 08:44:29 +08:00
- 配置CI工作流支持PR时执行代码质量检查、构建和测试 - 设置发布工作流支持标签推送时自动打包发布到NuGet和GitHub Packages - 修复源代码生成器项目的包依赖配置,统一使用GFramework.SourceGenerators.Common命名 - 配置多版本.NET SDK支持及相应的缓存策略 - 实现并行测试执行和统一的测试报告生成机制 - 添加安全扫描和代码质量检查集成
267 lines
7.9 KiB
YAML
267 lines
7.9 KiB
YAML
# 发布工作流(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:
|
||
- '*'
|
||
|
||
concurrency:
|
||
group: ${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: false
|
||
|
||
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 GFramework.sln
|
||
|
||
# 从 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 GFramework.sln \
|
||
-c Release \
|
||
--no-restore \
|
||
-o ./packages \
|
||
-p:PackageVersion=${{ steps.tag_version.outputs.version }} \
|
||
-p:IncludeSymbols=false
|
||
|
||
- name: Validate packed modules
|
||
run: |
|
||
set -euo pipefail
|
||
|
||
expected_packages=(
|
||
"GeWuYou.GFramework"
|
||
"GeWuYou.GFramework.Core"
|
||
"GeWuYou.GFramework.Core.Abstractions"
|
||
"GeWuYou.GFramework.Core.SourceGenerators"
|
||
"GeWuYou.GFramework.Cqrs"
|
||
"GeWuYou.GFramework.Cqrs.Abstractions"
|
||
"GeWuYou.GFramework.Cqrs.SourceGenerators"
|
||
"GeWuYou.GFramework.Ecs.Arch"
|
||
"GeWuYou.GFramework.Ecs.Arch.Abstractions"
|
||
"GeWuYou.GFramework.Game"
|
||
"GeWuYou.GFramework.Game.Abstractions"
|
||
"GeWuYou.GFramework.Game.SourceGenerators"
|
||
"GeWuYou.GFramework.Godot"
|
||
"GeWuYou.GFramework.Godot.SourceGenerators"
|
||
)
|
||
|
||
mapfile -t actual_packages < <(
|
||
find ./packages -maxdepth 1 -type f -name '*.nupkg' -printf '%f\n' \
|
||
| sed -E 's/\.[0-9][0-9A-Za-z.-]*\.nupkg$//' \
|
||
| sort -u
|
||
)
|
||
|
||
printf '%s\n' "${expected_packages[@]}" | sort > expected-packages.txt
|
||
printf '%s\n' "${actual_packages[@]}" | sort > actual-packages.txt
|
||
|
||
echo "Expected packages:"
|
||
cat expected-packages.txt
|
||
echo "Actual packages:"
|
||
cat actual-packages.txt
|
||
|
||
diff -u expected-packages.txt actual-packages.txt
|
||
|
||
- 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
|
||
|
||
publish-nuget:
|
||
name: Publish To NuGet.org
|
||
runs-on: ubuntu-latest
|
||
needs: build-pack
|
||
|
||
permissions:
|
||
contents: read
|
||
packages: read
|
||
id-token: write
|
||
|
||
steps:
|
||
- name: Setup .NET
|
||
uses: actions/setup-dotnet@v5
|
||
with:
|
||
dotnet-version: 10.0.x
|
||
|
||
- name: Download package artifacts
|
||
uses: actions/download-artifact@v8
|
||
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@v8
|
||
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 "${{ 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@v8
|
||
with:
|
||
name: packages
|
||
path: ./packages
|
||
|
||
# 无论某一侧包源发布是否失败,都继续创建 Release。
|
||
# 合规工件由独立 workflow 生成,当前发布流不再假设这些文件在同一次运行中可用。
|
||
- name: Create GitHub Release and Upload Assets
|
||
uses: softprops/action-gh-release@v3
|
||
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 }}
|
||
draft: false
|
||
prerelease: false
|
||
files: |
|
||
./packages/*.nupkg
|
||
env:
|
||
GITHUB_TOKEN: ${{ github.token }}
|