name: publish
on:
push:
tags: [ v* ]
workflow_dispatch:
# 必须同时声明:缺 packages: write 会让 GitHub Packages 推送 403,缺 contents: write 无法创建 Release
permissions:
contents: write
packages: write
jobs:
build-publish:
# 优先 Ubuntu:打包与发包均为纯托管流程,无需 Windows 专属工具链
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup dotNET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.x
7.x
8.x
9.x
10.x
- name: Resolve version
id: version
# tag 发布时以 tag 为准(去掉 v 前缀),保证包版本与 tag 完全一致;
# 手工触发时不传 Version,沿用 csproj 中「主.次.当天」的默认版本
run: |
if [ "${{ github.ref_type }}" = "tag" ]; then
VERSION="${GITHUB_REF_NAME#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "pack_args=-p:Version=$VERSION" >> "$GITHUB_OUTPUT"
else
echo "version=(csproj default)" >> "$GITHUB_OUTPUT"
echo "pack_args=" >> "$GITHUB_OUTPUT"
fi
- name: Build
run: |
dotnet pack -c Release -o out ${{ steps.version.outputs.pack_args }} NewLife.RocketMQ/NewLife.RocketMQ.csproj
ls -l out
- name: Publish to GitHub Packages
id: ghpackages
# 备用镜像渠道,失败只告警,不阻断 NuGet.org 正式发布
continue-on-error: true
run: |
dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://nuget.pkg.github.com/NewLifeX/index.json --api-key ${{ github.token }}
- name: Publish to NuGet.org
id: nuget
run: |
dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nugetKey }}
- name: Create GitHub Release
id: release
# 仅 tag 推送时创建;手工触发(无 tag)只发包
if: startsWith(github.ref, 'refs/tags/')
# 观察期:失败只告警,不影响已完成的发包;结尾 Publish Summary 会显式标红
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
tag="$GITHUB_REF_NAME"
# 幂等:同 tag 已有 Release 就直接跳过,失败重跑不会报错
if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "Release $tag 已存在,跳过"
exit 0
fi
# 发布说明优先取 ChangeLog.md 中当前版本段落(标题形如 "## v3.3.2026.1024 (2026-10-24)")
version="${tag#v}"
escaped=$(printf '%s' "$version" | sed 's/[.]/\\./g')
start=$(grep -nE "^## v?${escaped}([ (]|\$)" ChangeLog.md | head -1 | cut -d: -f1 || true)
args=(release create "$tag" --repo "$GITHUB_REPOSITORY" --title "$tag" --verify-tag)
if [ -n "$start" ]; then
end=$(awk -v s="$start" 'NR>s && /^## /{print NR; exit}' ChangeLog.md)
[ -n "$end" ] || end=$(( $(wc -l < ChangeLog.md) + 1 ))
sed -n "${start},$((end - 1))p" ChangeLog.md > release-notes.md
args+=(--notes-file release-notes.md)
echo "发布说明取自 ChangeLog.md 的 $version 段落($((end - start)) 行)"
else
args+=(--generate-notes)
echo "ChangeLog.md 未找到 $version 段落,改用自动生成说明"
fi
shopt -s nullglob
assets=(out/*.nupkg out/*.snupkg)
args+=("${assets[@]}")
gh "${args[@]}"
echo "已创建 Release $tag,附加资产 ${#assets[@]} 个"
- name: Publish Summary
if: always()
run: |
summary="$GITHUB_STEP_SUMMARY"
echo "### 发布结果" >> "$summary"
echo "" >> "$summary"
echo "| 渠道 | 结果 |" >> "$summary"
echo "| --- | --- |" >> "$summary"
for row in \
"GitHub Packages|${{ steps.ghpackages.outcome }}" \
"NuGet.org|${{ steps.nuget.outcome }}" \
"GitHub Release|${{ steps.release.outcome }}"
do
name="${row%%|*}"
outcome="${row##*|}"
case "$outcome" in
success) mark="✅" ;;
failure) mark="⚠️" ;;
skipped) mark="⏭" ;;
cancelled) mark="⛔" ;;
*) mark="❔" ;;
esac
echo "| $name | $mark $outcome |" >> "$summary"
done
echo "" >> "$summary"
echo "> GitHub Release 仅 tag 推送时创建;手工触发只发包。" >> "$summary"
|