Aspire 仓库的 Arcade 工程模板使用指南:eng/common 下 templates 与 templates-official 的选择、配置与源码机制解析
【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire
本篇指南围绕 Aspire 仓库中 eng/common/template-guidance.md 的核心主题展开,系统讲解 .NET Arcade 工程体系下两套 CI 模板(templates与templates-official)的适用场景、templateIs1ESManaged参数语义、1ES 多输出(Multiple Outputs)发布优化实践,以及 shim / logic / redirect 三层模板架构的源码级实现原理。读完本文,你将能够在 Aspire 这类 Arcade 化仓库中正确选择并引用工程模板、配置 1ES 兼容的制品发布,并理解模板文件之间的转发与参数传递关系,为自定义或调试 CI 流水线提供可落地的依据。
一、Overview:为什么存在两套模板
Arcade(.NET Core 公共工程系统)为使用其基础设施的仓库提供了两套 Azure DevOps 模板:
eng/common/templates:面向普通(非 1ES 管理)流水线场景,任何不要求由 1ES Pipeline Templates 托管的流水线都可以引用。eng/common/templates-official:面向 1ES Pipeline Templates 与 1ES Microbuild 场景,凡是被要求由 1ES 流水线模板托管的流水线,都应引用该目录;所有内部生产级(internal production-graded)流水线也应使用这套模板。
在 Aspire 仓库中,两套模板均真实存在,目录结构见:
- eng/common/templates:
job/、jobs/、steps/、variables/四个子目录。 - eng/common/templates-official:同样包含
job/、jobs/、steps/、variables/四个子目录,其中variables/额外提供sdl-variables.yml。
仓库内实际使用的流水线文件可以作为对照示例:
- 内部生产流水线(templates-official 风格)参考 eng/pipelines/azure-pipelines.yml。
- 公共构建流水线参考 eng/pipelines/azure-pipelines-public.yml。
二、How to use:如何选择与引用模板
基础使用规则可以归纳为两条:
- 1ES Pipeline Template / 1ES Microbuild 托管的流水线:引用
eng/common/templates-official。任何内部生产级流水线都应使用该套模板。 - 其余所有流水线运行:引用
eng/common/templates。
引用方式是在流水线的template:或extends:中直接使用仓库相对路径,例如:
- template: /eng/common/templates/jobs/jobs.yml@self或:
- template: /eng/common/templates-official/jobs/jobs.yml@self注意路径前的/表示仓库根目录,@self表示引用当前仓库中的模板(而非外部 Arcade 源)。
2.1 参数templateIs1ESManaged
大多数模板都开放了templateIs1ESManaged参数,它决定嵌套模板到底走两套模板中的哪一套(详见下文「Development notes」)。
- 对于
job/、jobs/、steps、post-build/目录下的模板,该参数必须显式设置,不能依赖默认值,否则嵌套模板可能被解析到错误的一套模板,导致 1ES 安全扫描注入策略失效。
从当前仓库源码看,templates/jobs/jobs.yml与templates-official/jobs/jobs.yml这两个 shim 文件正是通过硬编码is1ESPipeline参数(false/true)来实现模板选择的:
- eng/common/templates/jobs/jobs.yml:
is1ESPipeline: false - eng/common/templates-official/jobs/jobs.yml:
is1ESPipeline: true
2.2templateIs1ESManaged与is1ESPipeline的关系
从源码结构看,templateIs1ESManaged是 Arcade 模板对外暴露的用户参数,而is1ESPipeline是 shim 层内部用于向core-templates传递的状态标记。二者指向同一事实——本次运行是否处于 1ES 托管流水线中。shim 在转发参数时会把用户的选择固化到is1ESPipeline,core-templates中的逻辑层则据此决定具体实现分支。
三、Multiple outputs:减少 1ES 安全扫描注入的制品发布实践
1ES Pipeline Templates 实施一项策略:每一次执行publish artifact都会向流水线注入额外的安全扫描任务。对于制品发布点很多的流水线,这会导致安全扫描任务被重复注入、构建时间膨胀。
Arcade 的应对方案是:在使用templates-official/jobs/jobs.yml时,将所有发布产物先汇总到$(Build.ArtifactStagingDirectory),然后借助 1ES Pipeline Templates 的outputParentDirectory/outputs特性,把所有输出合并为一次发布声明,从而把安全扫描的注入次数压到最低。
实现要点:
- 确保流水线中所有要发布的制品都落在
$(Build.ArtifactStagingDirectory)下; - 使用 1ES 提供的
templateContext.outputs声明制品输出; - 这样 1ES 就能以「多个输出」的方式统一发布,避免每个制品各自触发一次安全扫描注入。
3.1 完整示例:通过 templateContext.outputs 发布日志
以下是文档给出的完整配置(已按标准 YAML 缩进整理),适用于azure-pipelines.yml中基于 1ES MicroBuild 模板的extends结构:
# azure-pipelines.yml extends: template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate parameters: stages: - stage: build jobs: - template: /eng/common/templates-official/jobs/jobs.yml@self parameters: # 1ES makes use of outputs to reduce security task injection overhead templateContext: outputs: - output: pipelineArtifact displayName: 'Publish logs from source' continueOnError: true condition: always() targetPath: $(Build.ArtifactStagingDirectory)/artifacts/log artifactName: Logs jobs: - job: Windows steps: - script: echo "friendly neighborhood" > artifacts/marvel/spiderman.txt # copy build outputs to artifact staging directory for publishing - task: CopyFiles@2 displayName: Gather build output inputs: SourceFolder: '$(System.DefaultWorkingDirectory)/artifacts/marvel' Contents: '**' TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel'关键点说明:
templateContext.outputs中的每一项对应一个 1ES 输出声明,这里以pipelineArtifact类型发布构建日志;targetPath必须位于$(Build.ArtifactStagingDirectory)之内,这是「多输出」合并生效的前提;- 常规构建产物(如
artifacts/marvel下的文件)先通过CopyFiles@2复制到$(Build.ArtifactStagingDirectory)/artifacts/marvel,保证所有内容从统一根目录发布; condition: always()与continueOnError: true用于确保即使构建部分失败也能收集到日志制品。
3.2 适用边界
Multiple outputs 仅适用于 1ES Pipeline Templates 的制品发布(即只有引用templates-official时可用)。普通templates场景没有 1ES 的安全扫描注入机制,无需(也无法)使用该特性。
四、Development notes:三层模板架构(shim / logic / redirect)
4.1 目录 / 文件结构总览
Arcade 模板的逻辑主体存放在core-templates文件夹,templates与templates-official则提供 shim 入口。文档给出的完整结构如下(当前仓库实际以eng/为前缀,例如eng/common/):
eng\common\ [templates || templates-official]\ job\ job.yml (shim + artifact publishing logic) onelocbuild.yml (shim) publish-build-assets.yml (shim) source-build.yml (shim) source-index-stage1.yml (shim) jobs\ codeql-build.yml (shim) jobs.yml (shim) source-build.yml (shim) post-build\ post-build.yml (shim) common-variabls.yml (shim) setup-maestro-vars.yml (shim) steps\ publish-build-artifacts.yml (logic) publish-pipeline-artifacts.yml (logic) component-governance.yml (shim) publish-logs.yml (shim) retain-build.yml (shim) send-to-helix.yml (shim) source-build.yml (shim) variables\ pool-providers.yml (logic + redirect) sdl-variables.yml (logic) core-templates\ job\ job.yml (logic) onelocbuild.yml (logic) publish-build-assets.yml (logic) source-build.yml (logic) source-index-stage1.yml (logic) jobs\ codeql-build.yml (logic) jobs.yml (logic) source-build.yml (logic) post-build\ common-variabls.yml (logic) post-build.yml (logic) setup-maestro-vars.yml (logic) steps\ component-governance.yml (logic) publish-build-artifacts.yml (redirect) publish-logs.yml (logic) publish-pipeline-artifacts.yml (redirect) retain-build.yml (logic) send-to-helix.yml (logic) source-build.yml (logic) variables\ pool-providers.yml (redirect)注:上表为 Arcade 模板的完整蓝图;当前 Aspire 仓库实际只落地了其中的子集,真实存在的文件见 eng/common/templates、eng/common/templates-official 与 eng/common/core-templates 三个目录。
4.2 三种文件类型的定义
上表中每个文件被标记为三类之一:
- shim(垫片):处于流水线逻辑与 .NET Core Engineering 模板(
core-templates)之间的中间层 YAML 文件,其核心职责是定义is1ESPipeline参数的值。- 若 shim 被
templates引用,is1ESPipeline设为false; - 若 shim 被
templates-official引用,is1ESPipeline设为true。
- 若 shim 被
- logic(逻辑):真正的基础模板逻辑实现。
- redirect(重定向):位于
core-templates中、将请求转发回templates或templates-official中对应 logic 文件的转发文件。
4.3 源码级印证:shim 如何工作
以jobs/jobs.yml为例,两个 shim 文件都极为精简——引用core-templates中同名模板、硬编码is1ESPipeline、并把所有用户参数原样透传:
# eng/common/templates/jobs/jobs.yml jobs: - template: /eng/common/core-templates/jobs/jobs.yml parameters: is1ESPipeline: false ${{ each parameter in parameters }}: ${{ parameter.key }}: ${{ parameter.value }}# eng/common/templates-official/jobs/jobs.yml jobs: - template: /eng/common/core-templates/jobs/jobs.yml parameters: is1ESPipeline: true ${{ each parameter in parameters }}: ${{ parameter.key }}: ${{ parameter.value }}对应的逻辑文件 eng/common/core-templates/jobs/jobs.yml 接收is1ESPipeline后,对每个 job 按条件分发回对应的一套模板:
- ${{ each job in parameters.jobs }}: - ${{ if eq(parameters.is1ESPipeline, 'true') }}: - template: /eng/common/templates-official/job/job.yml ... - ${{ else }}: - template: /eng/common/templates/job/job.yml ...也就是说:core-templates不直接实现两套逻辑,而是在少数依赖 shim 入口的场景中,把请求重定向回templates或templates-official的对应逻辑文件。
4.4 逻辑的存放位置与例外
- Arcade 模板的逻辑主要存放在
core-templates文件夹; - 例外是制品发布(artifact publishing):因为 1ES Pipeline Templates 与标准模板对制品发布的处理方式不同,这部分逻辑放在
templates/templates-official各自的steps/publish-*.yml中,而不是core-templates; templates与templates-official中,stages 层与 jobs / job 层的模板已被替换为 shim;而steps 层与 variables 层的模板粒度太细,不适合用 shim 替代,因此这些层级保留着直接适用于各自场景的逻辑。
4.5 redirect 实例:pool-providers 与制品发布
(1)variables/pool-providers.yml的重定向
eng/common/core-templates/variables/pool-providers.yml 是典型的 redirect 文件——根据is1ESPipeline选择转发目标:
parameters: is1ESPipeline: false variables: - ${{ if eq(parameters.is1ESPipeline, 'true') }}: - template: /eng/common/templates-official/variables/pool-providers.yml - ${{ else }}: - template: /eng/common/templates/variables/pool-providers.yml而 eng/common/templates/variables/pool-providers.yml 本身又带一层「逻辑 + 重定向」:当System.TeamProject为internal时,直接转发到templates-official/variables/pool-providers.yml;否则根据目标/源分支名计算公共与内部构建池变量(DncEngPublicBuildPool、DncEngInternalBuildPool,含-Svc服务池分支)。这与文档中「templates/variables/pool-providers.yml在内部项目中会重定向到templates-official/variables/pool-providers.yml」的描述完全一致。
(2)steps/publish-build-artifacts.yml的重定向
eng/common/core-templates/steps/publish-build-artifacts.yml 展示了制品发布这类「例外」的转发方式:根据is1ESPipeline把发布任务分发给templates/steps/publish-build-artifacts.yml或templates-official/steps/publish-build-artifacts.yml,因为两套模板对制品发布的实现不同(1ES 侧配合templateContext.outputs做多输出合并)。同理,publish-pipeline-artifacts.yml也采用 redirect 模式。
五、实践建议与常见陷阱
- 新流水线先定身份再选模板:内部生产级流水线直接引用
templates-official;临时、实验或非内部运行才考虑templates。混用会导致制品发布与安全扫描行为不一致。 jobs/job/steps/post-build层级必须显式传templateIs1ESManaged:Arcade 不会替你推断嵌套模板的目标,缺省值可能把 1ES 场景解析到标准模板。- 制品发布优先走
$(Build.ArtifactStagingDirectory)汇总:结合templateContext.outputs声明多输出,可显著减少 1ES 安全扫描注入次数;但请记住该优化只在templates-official下生效。 - 理解三层结构后再做自定义:不要直接修改
core-templates中的两套差异逻辑(制品发布除外),正确做法是在templates/templates-official对应位置扩展 shim 或 logic,并保持is1ESPipeline语义不变。 - 以仓库实际文件为准:Arcade 模板随版本演进,结构可能略有差异;定制前先核对 eng/common/templates、eng/common/templates-official、eng/common/core-templates 三处真实文件,再对照本文的结构图进行定位。
六、延伸阅读
- 流水线模板的实际消费方式:eng/pipelines/azure-pipelines.yml(templates-official 场景)与 eng/pipelines/azure-pipelines-public.yml
- 模板参考入口:eng/common/template-guidance.md
- shim 参数转发实现:eng/common/templates/jobs/jobs.yml 与 eng/common/templates-official/jobs/jobs.yml
- 逻辑分发实现:eng/common/core-templates/jobs/jobs.yml
- 池变量重定向:eng/common/core-templates/variables/pool-providers.yml 与 eng/common/templates/variables/pool-providers.yml
- 制品发布重定向:eng/common/core-templates/steps/publish-build-artifacts.yml
【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考