作者:木烟
在 YAML 化配置流水线时,你是否会遇到以下问题?
- 单流水线中批量执行类似任务场景时,YAML 中需要定义多个类似逻辑的 Job,Job 越多,流水线 YAML 配置的越长,YAML 中的重复代码越多,代码复用性低,可读性差;
- 管理员统一管理多流水线,多应用技术架构和研发流程类似,仅些许构建、部署参数不一致时,每条流水线都需要单独修改差异化参数,配置成本高;各流水线独立配置时,又无法统一管控,可维护性差;
- 流水线 YAML 为静态文件,流水线保存时任务执行逻辑已固定,但部分研发场景流水线执行流程需要等到运行时才能明确,无法提前配置。该场景普通的流水线 YAML 无法满足。
对此,云效 Flow 流水线 YAML 引入了 template 语法,支持使用模板语言来动态渲染流水线 YAML,满足多个相同或类似逻辑的 Job 批量配置场景,满足多 Job 按需动态生成场景,帮助降低流水线 YAML 重复代码,灵活编排多任务。
什么是 template 语法
template 是一种用于定义和渲染文本的模板语言,它可以结合变量、条件语句、循环结构等,使得 YAML 文件能够根据上下文或外部数据源生成多样化的配置输出,运行时动态渲染生成流水线 YAML。
云效流水线引入 template 模板引擎,通过流水线 YAML 首行注释 template=true
指定 template 模式,支持使用 {{ }}
定义模板语言,遵循 go template
原生语法;支持使用 variables
定义的变量作为参数渲染流水线。典型适用场景如下。
template 语法核心使用场景
场景 1:多操作系统、多 SDK 版本兼容性测试场景
在某些兼容性测试场景,如你需要在 n 个不同的操作系统、m 个不同 SDK 版本测试你的代码,那么你的流水线里需要定义 n m 个 Job,每个 Job 的执行逻辑其实是一样的。该场景下,当需要兼容测试的场景很多时,流水线 YAML 将非常长,有大量重复代码,难以维护;且当 Job 执行逻辑有一处修改时,则要修改 n m 次。
引入 template 语法后,可将兼容性场景抽取成变量,使用 range 语法循环遍历场景,批量生成多个 Job,大大降低 YAML 代码量;当 Job 执行逻辑有修改时也仅需一处修改即可。
例如,在下面的代码中,我们遍历了 ["linux", "windows"] 2 个操作系统、["10", "11", "17"] 3 个 JDK 版本,使用 template 的 range 循环,很方便地就生成了 6 个相同逻辑的 Job。
# template=true
variables:
- key: osList
type: Object
value: ["linux", "windows"]
- key: jdkVersionList
type: Object
value: ["10", "11", "17"]
stages:
build_stage:
name: 兼容性测试
jobs: # 双层循环,生成 2*3 个Job
{{ range $os := .osList}}
{{ range $jdk := $.jdkVersionList}}
{{ $os }}_JDK{{ $jdk }}_job:
name: 测试-{{ $os }}-JDK{{ $jdk }}
my_step:
name: 执行命令
step: Command
with:
run: |
echo 'test on {{ $os }}-JDK{{ $jdk }}"
{{ end }}
{{ end }}
流水线的运行效果如下:
场景 2:多应用动态按需构建部署
一个系统下多应用联合发布场景,一次业务需求的修改仅会涉及系统下的部分应用,每次发布上线仅需触发部分应用的构建部署。这种情况下,使用静态 YAML 文件配置方式无法满足动态生成应用构建、部署 Job 场景。
引入 template 语法后,可将应用抽取成变量,使用 range 语法循环遍历配置,根据流水线运行时输入的应用列表,动态按需生成多个应用构建、部署任务。
如下述示例所示,我们根据应用配置了多个应用代码源、多个应用构建任务、多个应用部署任务,可根据运行时输入环境变量 appnames 动态决定部署几个应用。
# template=true
variables:
- key: appnames
type: Object
value: ["app1", "app2", "app3"]
sources:
{{ range $app := .appnames }}
repo_{{ $app }}:
type: codeup
name: 代码源名称-{{ $app }}
endpoint: https://yunxiao-test.devops.aliyun.com/codeup/07880db8-fd8d-4769-81e5-04093aaf7b2b/c{{ $app }}.git
branch: master
certificate:
type: serviceConnection
serviceConnection: wwnbrqpihykbiko4
{{ end }}
defaultWorkspace: repo_app1
stages:
build_stage:
name: 构建阶段
jobs:
{{ range $app := .appnames }}
build_job_{{ $app }}:
name: 构建任务-{{ $app }}
sourceOption: ['repo_{{ $app }}']
steps:
build_{{ $app }}:
step: Command
name: 构建-{{ $app }}
with:
run: "echo start build {{ $app }}\n"
{{ end }}
deploy_stage:
name: 部署阶段
jobs:
{{ range $app := .appnames }}
deploy_job_{{ $app }}:
name: 部署任务-{{ $app }}
needs: build_stage.build_job_{{ $app }}
steps:
build_{{ $app }}:
step: Command
name: 部署-{{ $app }}
with:
run: "echo start deploy {{ $app }}\n"
{{ end }}
流水线运行效果如下:
如何在云效内使用 template 语法
1)进入流水线 YAML 编辑页,通过首行注释 # template=true,切换至 template 模式。
2)切换至 template 模式后,支持 {{ }} 模板语言定义流水线。
- 使用 variables 定义的环境变量作为渲染参数:使用 variables 定义的环境变量作为 template 渲染参数,支持字符串 String、数字 Number、布尔值 Boolean、支持对象 Object 多种环境变量类型。支持运行时同名环境变量覆盖。
- 遵循 go template 原生语法:云效 Flow 流水线 template 模式遵循原生 go template 语法,详见:https://pkg.go.dev/text/template。常用语法如下:
{{/* a comment */}} // 注释
{{pipeline}} // 引用
{{if pipeline}} T1 {{end}} // 条件判断
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
{{range pipeline}} T1 {{end}} // 循环
{{range pipeline}} T1 {{else}} T0 {{end}}
{{break}}
{{continue}}
- 此外,云效 Flow 流水线 template 语法支持以下扩展函数,以满足更多灵活编排场景。
# add:整数相加函数,参数接收两个及两个以上 Integer
{{ add 1 2 }} // 示例返回:3
{{ add 1 2 2 }} // 示例返回:5
# addf:浮点数相加函数,参数接收两个及两个以上 Number
{{ add 1.2 2.3 }} // 示例返回:3.5
{{ add 1.2 2.3 5 }} // 示例返回:8.5
# replace:字符串替换函数,接收三个参数:源字符串、待替换字符串、替换为字符串
{{ "Hallo World" | replace "a" "e" }} // 示例返回:Hello World
{{ "I Am Henry VIII" | replace " " "-" }} // 示例返回:I-Am-Henry-VIII
3)配置流水线运行时的环境变量,用于流水线运行前动态渲染 YAML。
4)点击「预览模式」,支持使用变量进行预渲染校验流水线是否符合预期。
5)确认无误后,保存并触发流水线运行。可按需修改运行时变量,根据运行时环境变量动态渲染流水线 YAML,动态生成 Job。如修改 JDK 版本为 ["17","21"] ,操作系统保持 ["linux", "windows"],则动态生成 4 个 Job。
点击此处,免费使用云效流水线 Flow 或了解更多信息。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。