关于 nuget-trusted-publishing
一项指导通过 GitHub Actions 使用 OIDC 配置 NuGet 可信发布的技能,以短期令牌取代长期 API 密钥。内容涵盖仓库评估、本地包验证、nuget.org 策略设置及工作流创建或迁移。
主要功能
- 01评估包类型和项目配置
- 02使用 dotnet pack 验证包
- 03指导配置 nuget.org 策略
- 04创建或迁移 GitHub Actions 工作流
- 05排查 OIDC 发布问题
适用场景
- 01为 NuGet 包配置可信发布
- 02将工作流从 API 密钥发布迁移
- 03创建新的 NuGet 发布工作流
- 04发布 dotnet 工具或 MCP 服务
MCP 相关
该技能涵盖 MCP 服务的 NuGet 包发布,但没有描述 MCP 服务或客户端。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dotnet/ skills --skill nuget-trusted-publishing安装后在 Claude Code 中输入/nuget-trusted-publishing确认已加载。
附带文件references/package-types.mdreferences/publish-workflow.md
详细介绍
NuGet 可信发布设置
在 GitHub Actions 仓库上设置 NuGet 可信发布。用基于 OIDC 的短期令牌替代长期有效的 API 密钥——无需轮换或担心泄露密钥。
前提条件
- GitHub Actions — 本技能仅涵盖 GitHub Actions 设置
- nuget.org 账户 — 用户需要有权限创建可信发布策略
何时使用此技能
在以下情况下使用此技能:
- 为 NuGet 包设置可信发布
- 从
secrets.NUGET_API_KEY迁移到基于 OIDC 的发布 - 询问无密钥或安全的 NuGet 发布
- 从头开始创建新的 NuGet 发布工作流
- 被要求“移除 NuGet API 密钥”或“使用 NuGet/login”
- 为 dotnet 工具、MCP 服务或模板包设置发布
- 询问
NuGet/login@v1或id-token: write
安全规则
⚠️ 停止规则:如果基础设施或身份验证问题在尝试修复一次后仍导致任何阶段失败,请停止并询问用户。不要反复尝试解决环境问题。
⚠️ 未经确认,绝不删除或覆盖:移除 API 密钥机密、删除标签/发行版、移除工作流步骤或更改包 ID。NuGet 包 ID 是永久的——错误无法撤销。
流程
全新仓库的快速路径:如果用户的设置简单(一个可打包项目,没有现有发布工作流),不要要求经过多轮评估。合并各阶段:立即创建工作流,并在同一条回复中提供 nuget.org 策略指导、本地打包建议和文件名匹配警告。以下完整分阶段流程适用于复杂场景或迁移场景。
阶段 1:评估
检查仓库,并在进行任何更改前报告发现的问题。
-
查找并分类可打包项目 — 检查
.csproj文件和Directory.Build.props(包元数据通常在整个仓库范围内设置)。按以下顺序分类(越靠前的匹配优先级越高):<PackageType>Template</PackageType>→ 模板<PackageType>McpServer</PackageType>→ MCP 服务(也是 dotnet 工具)<PackAsTool>true</PackAsTool>→ Dotnet 工具- 类库(
IsPackable=true或没有OutputType)→ 库 <OutputType>Exe</OutputType>且包含<IsPackable>true</IsPackable>→ 应用程序包(不是工具,但仍可发布)<OutputType>Exe</OutputType>且不包含PackAsTool或IsPackable→ 默认不可打包(询问用户是否打算发布)
-
验证结构,检查每种项目类型:
类型 必需项 全部 PackageId、Version(位于 .csproj 或 Directory.Build.props 中)Dotnet 工具 PackAsTool(必需);ToolCommandName(可选但建议设置 — 默认值为程序集名称)MCP 服务 PackageType=McpServer,包中包含.mcp/server.json模板 PackageType=Template,内容目录下包含.template.config/template.json -
查找现有发布工作流:在
.github/workflows/中查找dotnet nuget push、nuget push或dotnet pack。 -
检查版本一致性 — 对于 MCP 服务,验证
.csproj中的<Version>是否与server.json的两个版本字段(根级version和packages[].version)一致。标记任何不匹配之处。 -
向用户报告发现的问题:分类、缺失的属性、版本不匹配和现有工作流。对于多项目仓库,说明需要一个工作流还是为每个包分别设置工作流。提出修复缺失项——修改项目文件前使用
ask_user。
❌ 按类型查看详情和必需属性,请参阅 references/package-types.md。
阶段 2:本地验证
在操作 nuget.org 之前,先在本地打包并验证——发布错误会浪费一个无法挽回的版本号。
⚠️ 务必提及此步骤,即使你暂缓执行。告诉用户:“首次发布前,请运行
dotnet pack -c Release -o ./artifacts,以验证.nupkg是否已正确创建。”
dotnet pack -c Release -o ./artifacts— 验证.nupkg已创建- 对于工具/MCP 服务:从
./artifacts安装,运行--help,然后卸载 - 对于库:检查
.nupkg的内容(它是一个 zip 文件)
阶段 3:nuget.org 策略
此阶段需要用户在 nuget.org 上进行操作——请提供准确的值。
-
确定将执行发布的 仓库所有者、仓库名称和工作流文件名。
❌ 策略要求提供确切的工作流文件名(例如,
publish.yml或publish.yaml)——仅文件名,不含路径前缀。匹配时不区分大小写。不要使用工作流的name:字段。 -
引导用户创建受信任发布策略:
前往 nuget.org/account/trustedpublishing → Add policy
- Repository Owner:
{owner} - Repository:
{repo} - Workflow File:
{filename}.yml - Environment:
release(仅当工作流使用environment:时填写;否则留空)
策略归属:用户可选择个人账户或组织。归属于组织的策略适用于该组织拥有的所有包。
对于私有仓库:策略会“暂时激活”7 天——首次成功发布后转为永久有效。
- Repository Owner:
-
引导用户创建 GitHub Environment(推荐但非必需——可限定机密的作用范围并设置审批关卡):
仓库 Settings → Environments → New environment →
release添加环境机密:Name =
NUGET_USER,Value = nuget.org 用户名(不是邮箱)可选:添加 Required reviewers 以设置审批关卡。
⚠️ 在要求用户删除旧 API 密钥/机密或尝试使用工作流运行/发布之前,请先等待用户确认已创建策略。确认前可以起草或展示工作流文件。
阶段 4:工作流设置
创建或修改发布工作流。必须始终在回复中创建或展示工作流——即使 nuget.org 策略尚未确认,也可以起草或展示工作流,但在确认后才能引导用户实际运行/发布或删除旧机密。
从零开始:根据 references/publish-workflow.md 中的模板创建 publish.yml。调整 .NET 版本、项目路径和环境名称。确保输出明确提及 id-token: write 和 NuGet/login@v1。
迁移(现有工作流使用 API 密钥):在原有工作流中修改 —
-
向发布作业添加 OIDC 权限和环境:
jobs: publish: environment: release permissions: id-token: write # Required — without this, NuGet/login fails with 403 contents: read # Explicit — setting permissions overrides defaults -
在推送之前添加 NuGet 登录步骤:
- name: NuGet login (OIDC) id: login uses: NuGet/login@v1 with: user: ${{ secrets.NUGET_USER }} # nuget.org profile name, NOT email -
在推送步骤中替换 API 密钥:
--api-key ${{ steps.login.outputs.NUGET_API_KEY }} --skip-duplicate -
验证:请用户触发一次发布,并确认该包已显示在 nuget.org 上。
❌ 在验证受信任发布之前,不要删除旧的 API 密钥机密。删除后无法撤销——请等待用户确认。
故障排查
| 问题 | 原因 | 解决方法 |
|---|---|---|
NuGet/login 403 | 缺少 id-token: write | 在作业权限中添加 |
| "no matching policy" | 工作流文件名不匹配 | 在 nuget.org 上核对准确的文件名 |
| 推送未授权 | 包不归策略账户所有 | 在 nuget.org 上检查策略所有者 |
| 令牌已过期 | 登录步骤在推送前超过 1 小时执行 | 将 NuGet/login 步骤移近推送步骤 |
| 策略处于“暂时激活”状态 | 私有仓库,首次发布尚未完成 | 在 7 天内发布 |
推送时出现 already_exists | 重复运行同一版本 | 添加 --skip-duplicate |
| GitHub Release 返回 422 | 此标签已有 Release | 删除冲突的 Release(请先确认) |
| 重新运行时使用了错误的 YAML | gh run rerun 会重放原始提交中的 YAML | 删除障碍,然后重新运行——切勿重新打标签 |
⚠️ 如果尝试修复一次后问题仍未解决,请停止并询问用户。
参考资料
- 包类型详情:references/package-types.md — 检测逻辑、必需属性、最精简的 .csproj 示例
- 发布工作流模板:references/publish-workflow.md — 可直接调整的完整标签触发工作流
- Microsoft 文档:NuGet Trusted Publishing