.NET MAUI 如何用 pushPackages:false 对 NuGet 发布流水线做 dry-run 验证?
2026/9/14 19:45:58 网站建设 项目流程

.NET MAUI 如何用 pushPackages:false 对 NuGet 发布流水线做 dry-run 验证?

【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui

在把 .NET MAUI(或相关 dotnet 仓库)的 NuGet 包正式推送到 NuGet.org 之前,release owner 需要先确认"BAR 构建解析 → 包收集 → 过滤 → 身份校验 → 审计工件"这一整条链路是正确的,而不希望真的推出去任何包。.NET MAUI 的唯一发布流水线 eng/pipelines/ci-official-release.yml 提供了pushPackages参数,其 displayName 为"If false, prepare a dry-run artifact without publishing":设为false时,流水线只收集和发布发布工件,不做 workload 构建提升、不执行审批、也不请求生产 NuGet 服务连接。下面按实际操作顺序说明如何配置并核对这次 dry-run。

前提:该流水线在内部 Azure DevOps 的dnceng/internal项目中手动运行,构建与发布环境是内部镜像https://dev.azure.com/dnceng/internal/_git/dotnet-maui(公共 GitHub 仓库仍是开发源,镜像与已发布源码保持一致),因此 dry-run 需要在内部项目环境中执行。

适用流水线与前置条件

  • 流水线eng/pipelines/ci-official-release.yml是唯一的 release 流水线,手动触发,无 trigger/PR 触发。
  • BAR 构建已注册:待发布的 commit 必须已经过内部azure-pipelines-internal.yml完成构建、签名、打包,并把产物注册到 Maestro 的 Build Asset Registry(BAR)。BAR 记录与源 commit 共同标识本次发布使用的不可变资产。dry-run 传入的commitHash就是这个 commit。
  • 仓库白名单:prepare 阶段只接受dotnet/mauidotnet/androiddotnet/maciosdotnet/android-libraries,传入其他仓库会直接抛出Repository '…' is not enabled for this release pipeline.
  • workload 推断ghOwnerdotnetghRepoandroidmaciosmaui之一时走 workload 路径(pack 与 manifest 分开审批和发布);其余允许的仓库(如android-libraries)走普通 NuGet 包路径。

配置 dry-run 参数

参数及其默认值以 ci-official-release.yml 的parameters段为准:

参数类型默认值dry-run 建议值用途说明(来自文档/YAML)
ghOwnerstringdotnetdotnet用于解析 BAR 构建的 GitHub owner
ghRepostringmaui目标仓库名ghOwner组合确定 workload/非 workload 路径
commitHashstringskipBAR 构建的完整 commit SHAskip会阻止一切准备、审批、workload-channel 与 NuGet 发布 job
pushWorkloadSetbooleantruefalse是否把 BAR 构建加入 workload 发布 channel
pushNugetOrgbooleantruetrue启用 NuGet.org 发布阶段
pushPackagesbooleantruefalsefalse时只准备 dry-run 工件,不发布
nugetIncludeFiltersstringskip可选分号分隔的包文件名通配过滤
nugetExcludeFiltersstringskip可选分号分隔的排除过滤

docs/ReleaseProcess.md 给出的官方 dry-run 示例输入(非 workload 路径):

ghOwner: dotnet ghRepo: android-libraries commitHash: <FULL_COMMIT_SHA> pushWorkloadSet: false pushNugetOrg: true pushPackages: false

其中<FULL_COMMIT_SHA>是文档中的占位符,替换为你要验证的那个 BAR 构建的完整 commit SHA。

两点参数语义需要注意:

  • commitHash: skip时流水线只会运行skip_release阶段(输出一行 "No release operations were requested."),不执行任何 gather 或发布。要验证真实发布 commit 的 dry-run,必须传实际 SHA。
  • 流水线还有一个短路条件:pushNugetOrg: false且(非 workload,或 workload 仓库同时pushWorkloadSet: false)时同样直接进入skip_release。所以示例里保留pushNugetOrg: true,让prepare_release阶段真正跑起来。

pushPackages:false 时哪些步骤会执行

pushPackages: falseprepare_release(displayName: Prepare release artifacts)阶段完整运行,包含:

  1. 用 Darc 按 commit 解析 BAR 构建(取第一个匹配构建),并校验该构建确实属于请求的 GitHub 仓库;
  2. 执行一次darc gather-drop,只下载 BAR 中的 NuGet 包资产——asset 过滤规则为^[^/]+$,符号包等带路径的 blob 资产不属于 NuGet.org 发布输入,不会被下载。workload 发布对 gather 失败 fail-fast;非 workload 发布加--continue-on-error,但每个未下载成功的选中包必须在 NuGet.org 上已存在其精确 ID/version,否则发布被拒绝;
  3. 对每个收集到的包从 nuspec 读取 package ID 与 version,拒绝格式错误或重复的包(重复文件名、重复 ID/version 对都会 throw),并应用 include/exclude 过滤;
  4. 阶段结束报告选中的包身份与数量。

随后按路径产出不同的工件,这是 dry-run 核对的核心对象:

  • workload 路径dotnet/mauidotnet/androiddotnet/macios):发布两个 1ES pipeline 工件MauiPacksForNuGetMauiManifestsForNuGet,各自包含expected-packages.json和包可用性辅助脚本 nuget_release_packages.ps1。prepare 阶段会记录该脚本的 SHA-256,后续每个生产步骤执行前先校验这个哈希。过滤必须同时选中 pack 和 manifest 集合(否则报 "Package filtering must select workload packs and manifests."),且全部 manifest 只能属于同一个 workload 主版本号(当前映射了 .NET 8/9/10/11 的 channel 与 feed)。
  • 非 workload 路径(如android-libraries):产出NuGetPackagesForRelease(staged 的.nupkgexpected-packages.json、辅助脚本)和审计工件NuGetReleaseAudit——其中release-audit.json记录barBuildIdcommitrepositoryselectedPackagesstagedPackages,在人工审批之前就把"选中清单"与"实际 staged 清单"固定下来。prepare 阶段还会对 staged 目录运行FilterExisting,过滤掉 NuGet.org 上已存在的精确 ID/version 对,所以stagedPackagesselectedPackages的差集就是已存在于 NuGet.org 的包。

以下部分在pushPackages: false时全部不会运行(这些 stage 的启用条件都显式要求pushPackages: true):

  • workload channel 提升(publish_maestro阶段的darc add-build-to-channel);
  • 所有人工会签点(ManualValidation@0,包括 non-workload-publish.yml 中"Review NuGetReleaseAudit, then press Resume"的审批);
  • 通过1ES.PublishNuget@1请求nuget.org (dotnetframework)服务连接的生产发布 job;
  • 发布后 30 分钟窗口内轮询 NuGet.org 可见性的Verify步骤。

文档明确给出的边界:dry-run 会产出上述工件,但不验证服务连接授权、外部 NuGet.org 认证或网络出向(egress)。

如何判断 dry-run 成功

docs/ReleaseProcess.md 的 "Required internal validation" 表格为 dry-run 给出了明确的证据要求:

阶段要求证据
YAML preview1ES 展开、条件、任务输入、工件接线与服务连接引用有效
commitHash: skip没有任何 gather、审批、服务连接、workload-channel 或发布 job 运行
Artifact dry run一个真实发布 commit 执行了一次 gather;两个工件中的 filters、identities、counts 和 SBOMs 正确

对照检查清单:

  1. 阶段日志prepare_release成功,且日志中对每个包集合打印了id/version/fileName表和计数("Workload packs: N" / "NuGet packages: N" 形式)。把它与预期发布集合比对。
  2. 审计工件:非 workload 下载NuGetReleaseAudit,核对release-audit.json中 selected 与 staged 两个列表;workload 则核对MauiPacksForNuGetMauiManifestsForNuGet中的expected-packages.json
  3. skip 路径:先用commitHash: skip跑一次,确认除skip_release外没有任何 job——这是文档证据表的第二行。
  4. 本地断言参考:仓库自带 Pester 测试 eng/pipelines/ci-official-release.Tests.ps1 断言了 dry-run 相关行为,例如非 workload 发布模板只有在pushPackagestrue时才被包含(eq(parameters.pushPackages, true).*non-workload-publish.yml)、审计工件先于审批存在。可以在本地参考这些断言核对流水线门禁行为。

限制与后续步骤

  • dry-run 不能替代生产验证:NuGet.org 上的包不可变,生产发布无法被普通 dry-run 完全测出。文档要求在首次生产发布前按证据表逐项记录:YAML preview、commitHash: skip、artifact dry run、test-feed run(把同样的1ES.PublishNuget@1形态发布到批准的非生产 feed)、duplicate/recovery run、production preflight,最后才是受控的 planned release。内部 Azure Artifacts feed 只能证明任务机制,不能证明外部 feed 的精确认证与出向路径;如果没有有代表性的外部测试 feed,要在投产前记录这一限制。
  • 所有权检查:任何仓库首次推送前,先确认现有nuget.org (dotnetframework)服务连接拥有审计工件中所有 package ID。
  • 恢复过滤器仅限 workloadnugetAlreadyAttemptedPackFilters/nugetAlreadyAttemptedManifestFilters只用于 workload 发布中"上一次任务已提交给 NuGet.org、仍在验证窗口"的包;非 workload 发布会直接拒绝这两个参数("Non-workload releases do not support workload recovery filters")。
  • android-libraries 的特殊性:其 BAR 构建是逐构建增量而非 channel 资产并集,要按 commit 顺序逐个发布挂起的构建。

dry-run 通过上述核对后,按文档证据表顺序进入 test-feed run 与 duplicate/recovery run,再谈真正的生产发布;不要跳过这些阶段直接从 dry-run 结论跳到 scheduled release。

【免费下载链接】maui.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.项目地址: https://gitcode.com/GitHub_Trending/ma/maui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询