.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/maui、dotnet/android、dotnet/macios、dotnet/android-libraries,传入其他仓库会直接抛出Repository '…' is not enabled for this release pipeline.。 - workload 推断:
ghOwner为dotnet且ghRepo是android、macios、maui之一时走 workload 路径(pack 与 manifest 分开审批和发布);其余允许的仓库(如android-libraries)走普通 NuGet 包路径。
配置 dry-run 参数
参数及其默认值以 ci-official-release.yml 的parameters段为准:
| 参数 | 类型 | 默认值 | dry-run 建议值 | 用途说明(来自文档/YAML) |
|---|---|---|---|---|
ghOwner | string | dotnet | dotnet | 用于解析 BAR 构建的 GitHub owner |
ghRepo | string | maui | 目标仓库名 | 与ghOwner组合确定 workload/非 workload 路径 |
commitHash | string | skip | BAR 构建的完整 commit SHA | skip会阻止一切准备、审批、workload-channel 与 NuGet 发布 job |
pushWorkloadSet | boolean | true | false | 是否把 BAR 构建加入 workload 发布 channel |
pushNugetOrg | boolean | true | true | 启用 NuGet.org 发布阶段 |
pushPackages | boolean | true | false | false时只准备 dry-run 工件,不发布 |
nugetIncludeFilters | string | skip | 可选 | 分号分隔的包文件名通配过滤 |
nugetExcludeFilters | string | skip | 可选 | 分号分隔的排除过滤 |
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: false,prepare_release(displayName: Prepare release artifacts)阶段完整运行,包含:
- 用 Darc 按 commit 解析 BAR 构建(取第一个匹配构建),并校验该构建确实属于请求的 GitHub 仓库;
- 执行一次
darc gather-drop,只下载 BAR 中的 NuGet 包资产——asset 过滤规则为^[^/]+$,符号包等带路径的 blob 资产不属于 NuGet.org 发布输入,不会被下载。workload 发布对 gather 失败 fail-fast;非 workload 发布加--continue-on-error,但每个未下载成功的选中包必须在 NuGet.org 上已存在其精确 ID/version,否则发布被拒绝; - 对每个收集到的包从 nuspec 读取 package ID 与 version,拒绝格式错误或重复的包(重复文件名、重复 ID/version 对都会 throw),并应用 include/exclude 过滤;
- 阶段结束报告选中的包身份与数量。
随后按路径产出不同的工件,这是 dry-run 核对的核心对象:
- workload 路径(
dotnet/maui、dotnet/android、dotnet/macios):发布两个 1ES pipeline 工件MauiPacksForNuGet与MauiManifestsForNuGet,各自包含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 的.nupkg、expected-packages.json、辅助脚本)和审计工件NuGetReleaseAudit——其中release-audit.json记录barBuildId、commit、repository、selectedPackages、stagedPackages,在人工审批之前就把"选中清单"与"实际 staged 清单"固定下来。prepare 阶段还会对 staged 目录运行FilterExisting,过滤掉 NuGet.org 上已存在的精确 ID/version 对,所以stagedPackages与selectedPackages的差集就是已存在于 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 preview | 1ES 展开、条件、任务输入、工件接线与服务连接引用有效 |
commitHash: skip | 没有任何 gather、审批、服务连接、workload-channel 或发布 job 运行 |
| Artifact dry run | 一个真实发布 commit 执行了一次 gather;两个工件中的 filters、identities、counts 和 SBOMs 正确 |
对照检查清单:
- 阶段日志:
prepare_release成功,且日志中对每个包集合打印了id/version/fileName表和计数("Workload packs: N" / "NuGet packages: N" 形式)。把它与预期发布集合比对。 - 审计工件:非 workload 下载
NuGetReleaseAudit,核对release-audit.json中 selected 与 staged 两个列表;workload 则核对MauiPacksForNuGet、MauiManifestsForNuGet中的expected-packages.json。 - skip 路径:先用
commitHash: skip跑一次,确认除skip_release外没有任何 job——这是文档证据表的第二行。 - 本地断言参考:仓库自带 Pester 测试 eng/pipelines/ci-official-release.Tests.ps1 断言了 dry-run 相关行为,例如非 workload 发布模板只有在
pushPackages为true时才被包含(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。 - 恢复过滤器仅限 workload:
nugetAlreadyAttemptedPackFilters/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),仅供参考