1. 从“点鼠标”到 Pipeline as Code
Freestyle job 把逻辑藏在服务器配置里,难以 diff;Pipeline 把构建、测试、发布写成 Groovy 脚本,通常命名为仓库根目录的 Jenkinsfile,由 Multibranch Pipeline 或 Pipeline job 从 SCM 拉取。 这样流水线变更与业务代码走同一套评审流程——CI/CD 本身也进入变更管理。
2. Declarative Pipeline:结构即文档
顶层必须是 pipeline {}。常用块:agent(在哪跑)、options(超时、重试、构建丢弃)、 environment(键值与凭据绑定)、stages(阶段树)、post(always / success / failure 等收尾)。 when 控制阶段是否执行;steps 里放 sh、bat、checkout scm 等。
pipeline {
agent { label 'linux && docker' }
options {
timeout(time: 45, unit: 'MINUTES')
timestamps()
}
environment {
CI = 'true'
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
post {
always {
junit 'reports/**/*.xml'
}
failure {
echo 'Build failed — notify on-call'
}
}
}
3. Scripted Pipeline:自由编排的 Groovy
Scripted 以 node 包裹,内部用 stage 组织;你可以写任意 Groovy 控制流(循环、函数、库调用)。 代价是更难静态分析,新人上手曲线陡,且更容易写出非 CPS 友好的代码导致诡异挂起——需要理解 Pipeline 的 Continuation-Passing Style 执行模型。
node('linux') {
stage('Checkout') {
checkout scm
}
stage('Build') {
sh 'mvn -B -DskipTests clean package'
}
}
4. 在 Declarative 中使用 script {}
当 Declarative 的固定块不够用(例如动态决定并行矩阵),可在 steps 里嵌 script { } 写 Groovy。 这是官方支持的逃生舱:保持外层结构清晰,内层处理脏活。
stage('Matrix-ish') {
steps {
script {
def langs = ['en', 'zh']
langs.each { lang ->
echo "Testing locale: ${lang}"
}
}
}
}
5. 并行与 post:把时间掰成并行流
parallel 可在 Scripted 或 Declarative 的 script 中使用(Declarative 也有 parallel stage 模式,依版本与习惯)。 post 块统一处理通知、归档、清理 workspace,避免每个 stage 复制粘贴。
6. 对照表:怎么选?
| 场景 | 更倾向 |
|---|---|
| 团队刚 Pipeline 化,需要可读模板 | Declarative 为主 |
| 复杂动态矩阵、重度 Groovy 抽象 | Scripted 或 Declarative + shared lib |
| 需要 UI / linter 强约束 | Declarative |
| 遗留大量 Scripted,迁移成本高 | 渐进封装进共享库(下一章) |
CPS 与沙箱(挂起时该查什么)
Pipeline 使用 Continuation-Passing Style:许多步骤不是“普通同步调用”,而是可被序列化、恢复的执行块。 若在 Pipeline 里滥用某些 Java API,可能遇到不允许的方法或看似死锁的挂起。 script {} 仍在沙箱规则之下——需要特权时走管理员审批的脚本批准或把逻辑挪到普通构建脚本(shell、maven)里执行。
7. 本章清单
- 新建 Multibranch Pipeline,从仓库读取 Jenkinsfile,跑通 Declarative 最小示例。
- 对比同一流水线的 Scripted 写法,体会 node / stage 差异。
- 为失败场景配置 post 通知与报告归档。
- 阅读官方文档中 CPS / sandbox 章节,遇到挂起时知道往哪查。
- 预告:把重复 Groovy 抽进 Shared Library(下一章)。