重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
nuget-trusted-publishing by dotnet/skills
npx skills add https://github.com/dotnet/skills --skill nuget-trusted-publishing在 GitHub Actions 仓库中设置 NuGet 可信发布。用基于 OIDC 的短期令牌替换长期有效的 API 密钥——无需轮换或担心密钥泄露。
在以下情况使用此技能:
secrets.NUGET_API_KEY 迁移到基于 OIDC 的发布时NuGet/login@v1 或 id-token: write 时⚠️ 退出规则 : 如果在基础设施/认证问题上尝试修复一次后,任何阶段仍然失败,请停止并询问用户。不要在环境问题上循环尝试。
⚠️ 未经确认,切勿删除或覆盖 : 移除 API 密钥机密、删除标签/发布、移除工作流步骤或更改包 ID。NuGet 包 ID 是永久性的——错误无法撤销。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
新仓库的快速路径 : 当用户设置简单(一个可打包项目,没有现有的发布工作流)时,不要在多轮评估上设卡。合并阶段:立即创建工作流,在一个响应中包含 nuget.org 策略指导、本地打包建议和文件名匹配警告。下面完整的阶段化流程适用于复杂或迁移场景。
在进行任何更改之前,检查仓库并报告发现。
查找并分类可打包项目 — 检查 .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。
在接触 nuget.org 之前,先在本地打包和验证——发布错误会浪费一个永久的版本号。
⚠️ 始终提及此步骤,即使你推迟执行它。告诉用户:"在首次发布之前,运行
dotnet pack -c Release -o ./artifacts以验证 .nupkg 是否正确创建。"
dotnet pack -c Release -o ./artifacts — 验证 .nupkg 是否创建./artifacts 安装,运行 --help,卸载.nupkg 内容(它是一个 zip 文件)此阶段需要用户在 nuget.org 上操作——用确切的值指导他们。
❌ 策略要求确切的工作流文件名(例如,
publish.yml或publish.yaml)——仅文件名,无路径前缀。匹配不区分大小写。不要使用工作流的name:字段。
前往 nuget.org/account/trustedpublishing → 添加策略
* **仓库所有者** : `{owner}` * **仓库** : `{repo}` * **工作流文件** : `{filename}.yml` * **环境** : `release` _(仅当工作流使用 `environment:` 时;否则留空)_
策略所有权:用户选择个人账户或组织。组织拥有的策略适用于该组织拥有的所有包。
对于私有仓库:策略在首次成功发布前为"临时激活"状态,持续 7 天——首次成功发布后变为永久。
仓库 设置 → 环境 → 新建环境 →
release添加环境机密:名称 =
NUGET_USER,值 = nuget.org 用户名(非电子邮件)
可选:添加必需的审查者以设置审批门控。
⚠️ 在用户确认他们已创建策略之后,再要求他们移除旧的 API 密钥/机密或尝试使用工作流运行/发布。在确认之前,起草或展示工作流文件本身是可以的。
创建或修改发布工作流。工作流必须始终在你的响应中创建或展示——即使 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 # 必需——没有此项,NuGet/login 会因 403 失败
contents: read # 显式设置——设置权限会覆盖默认值
在推送前添加 NuGet 登录步骤:
- name: NuGet login (OIDC)
id: login
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_USER }} # nuget.org 个人资料名称,非电子邮件
在推送步骤中替换 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 移到更接近推送的位置 |
| "temporarily active" 策略 | 私有仓库,首次发布待定 | 在 7 天内发布 |
推送时出现 already_exists | 重新运行相同版本 | 添加 --skip-duplicate |
| GitHub Release 422 | 标签的重复发布 | 删除冲突的发布(先确认) |
| 重新运行使用错误的 YAML | gh run rerun 重放原始提交的 YAML | 删除障碍,重新运行——切勿重新标记 |
⚠️ 如果任何阻塞问题在一次修复尝试后仍然存在,停止并询问用户。
每周安装量
48
仓库
GitHub Stars
703
首次出现
2026 年 3 月 10 日
安全审计
安装于
kimi-cli45
gemini-cli45
amp45
cline45
github-copilot45
codex45
Set up NuGet trusted publishing on a GitHub Actions repo. Replaces long-lived API keys with OIDC-based short-lived tokens — no secrets to rotate or leak.
Use this skill when:
secrets.NUGET_API_KEY to OIDC-based publishingNuGet/login@v1 or id-token: write⚠️ Bail-out rule : If any phase fails after one fix attempt on an infrastructure/auth issue, stop and ask the user. Don't loop on environment problems.
⚠️ Never delete or overwrite without confirmation : Removing API key secrets, deleting tags/releases, removing workflow steps, or changing package IDs. NuGet package IDs are permanent — mistakes can't be undone.
Fast-path for greenfield repos : When the user has a simple setup (one packable project, no existing publish workflow), don't gate on multi-turn assessment. Combine phases: create the workflow immediately, include nuget.org policy guidance, local pack recommendation, and filename-matching warning all in one response. The full phased process below is for complex or migration scenarios.
Inspect the repo and report findings before making any changes.
Find and classify packable projects — check .csproj files andDirectory.Build.props (package metadata is often set repo-wide). Classify in this order (earlier matches win):
<PackageType>Template</PackageType> → Template<PackageType>McpServer</PackageType> → MCP server (also a dotnet tool)<PackAsTool>true</PackAsTool> → Dotnet toolIsPackable=true or no OutputType) → Library<OutputType>Exe</OutputType> with → (not a tool, but still publishable)| Type | Required |
|---|---|
| All | PackageId, Version (in .csproj or Directory.Build.props) |
| Dotnet tool | PackAsTool (required); ToolCommandName (optional but recommended — defaults to assembly name) |
| MCP server | PackageType=McpServer, .mcp/server.json included in package |
| Template | PackageType=Template, under content dir |
Find existing publish workflows in .github/workflows/ — look for dotnet nuget push, nuget push, or dotnet pack.
Check version consistency — for MCP servers, verify .csproj <Version> matches both server.json version fields (root version and packages[].version). Flag any mismatch.
Report findings to the user: classification, missing properties, version mismatches, existing workflows. For multi-project repos, note whether one workflow or separate workflows per package are needed. Offer to fix gaps — use before modifying project files.
❌ See references/package-types.md for per-type details and required properties.
Pack and verify locally before touching nuget.org — publishing errors waste a permanent version number.
⚠️ Always mention this step , even if you defer running it. Tell the user: "Before your first publish, run
dotnet pack -c Release -o ./artifactsto verify the .nupkg is created correctly."
dotnet pack -c Release -o ./artifacts — verify .nupkg is created./artifacts, run --help, uninstall.nupkg contents (it's a zip)This phase requires the user to act on nuget.org — guide them with exact values.
❌ The policy requires the exact workflow filename (e.g.,
publish.ymlorpublish.yaml) — just the filename, no path prefix. Matching is case-insensitive. Don't use the workflowname:field.
Go to nuget.org/account/trustedpublishing → Add policy
* **Repository Owner** : `{owner}` * **Repository** : `{repo}` * **Workflow File** : `{filename}.yml` * **Environment** : `release` _(only if the workflow uses`environment:`; leave blank otherwise)_
Policy ownership: the user chooses individual account or organization. Org-owned policies apply to all packages owned by that org.
For private repos : policy is "temporarily active" for 7 days — becomes permanent after the first successful publish.
Repo Settings → Environments → New environment →
releaseAdd environment secret: Name =
NUGET_USER, Value = nuget.org username (NOT email)
Optional: add Required reviewers for an approval gate.
⚠️ Wait for the user to confirm they've created the policy before asking them to remove old API keys/secrets or before attempting to run/publish with the workflow. Drafting or showing the workflow file itself is OK before confirmation.
Create or modify the publish workflow. The workflow must always be created or shown in your response — you may draft/show it even if the nuget.org policy is not yet confirmed, but do not guide the user to actually run/publish or remove old secrets until after confirmation.
Greenfield : Create publish.yml from the template in references/publish-workflow.md. Adapt .NET version, project path, and environment name. Ensure your output explicitly mentions id-token: write and NuGet/login@v1.
Migration (existing workflow with API key): Modify in place —
Add OIDC permission and environment to the publishing job:
jobs:
publish:
environment: release
permissions:
id-token: write # Required — without this, NuGet/login fails with 403
contents: read # Explicit — setting permissions overrides defaults
Add the NuGet login step before push:
- name: NuGet login (OIDC)
id: login
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_USER }} # nuget.org profile name, NOT email
Replace the API key in the push step:
--api-key ${{ steps.login.outputs.NUGET_API_KEY }} --skip-duplicate
Verify : Ask the user to trigger a publish and confirm the package appears on nuget.org.
❌ Don't delete the old API key secret until trusted publishing is verified. Removing it is a one-way door — wait for confirmation.
| Problem | Cause | Fix |
|---|---|---|
NuGet/login 403 | Missing id-token: write | Add to job permissions |
| "no matching policy" | Workflow filename mismatch | Verify exact filename on nuget.org |
| Push unauthorized | Package not owned by policy account | Check policy owner on nuget.org |
| Token expired | Login step >1hr before push | Move NuGet/login closer to push |
| "temporarily active" policy | Private repo, first publish pending | Publish within 7 days |
already_exists on push |
⚠️ If any blocker persists after one fix attempt, stop and ask the user.
Weekly Installs
48
Repository
GitHub Stars
703
First Seen
Mar 10, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
kimi-cli45
gemini-cli45
amp45
cline45
github-copilot45
codex45
Azure 配额管理指南:服务限制、容量验证与配额增加方法
138,600 周安装
MCP Hub:连接1200+ MCP服务器,扩展Claude AI的文件、数据库和API集成能力
488 周安装
使用 PptxGenJS 创建专业幻灯片 - 支持 .pptx 和 .js 源文件生成,提升演示文稿开发效率
495 周安装
SaaS订阅管理全攻略:生命周期、定价策略、流失预防与收入优化
493 周安装
代码重构与整洁专家 - 提升代码质量、可维护性和性能的AI助手
492 周安装
VS Code内存泄漏审计指南:预防与修复代码泄漏的6步清单
492 周安装
模板引擎技能:自动化生成Word/Excel/PPT文档,支持Jinja2语法与批量邮件合并
490 周安装
<IsPackable>true</IsPackable><OutputType>Exe</OutputType> without PackAsTool or IsPackable → Not packable by default (ask user if they intend to publish it)Validate structure for each project's type:
.template.config/template.jsonask_user| Re-running same version |
Add --skip-duplicate |
| GitHub Release 422 | Duplicate release for tag | Delete conflicting release (confirm first) |
| Re-run uses wrong YAML | gh run rerun replays original commit's YAML | Delete obstacle, re-run — never re-tag |