18.3.2 Declarative与Scripted Pipeline对比与选型
Declarative Pipeline 与 Scripted Pipeline 是 Jenkins 流水线的两种核心范式:前者强调结构化与治理,后者强调脚本化与灵活编排。选型时建议以团队协作、流程规范、复杂度与可维护性为核心指标。
原理草图(执行流对比)
安装与环境准备(Pipeline 运行依赖)
- Jenkins LTS 推荐安装 Pipeline 插件与 Blue Ocean(可视化):
# 检查 Jenkins 是否已安装 Pipeline 插件
# 在 Jenkins 服务器上执行(需要管理员权限与Jenkins CLI配置)
java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar \
-s http://127.0.0.1:8080 \
-auth admin:admin \
list-plugins | grep -E "workflow-|blueocean"
# 若未安装,安装 Pipeline 相关插件
java -jar /var/jenkins_home/war/WEB-INF/jenkins-cli.jar \
-s http://127.0.0.1:8080 \
-auth admin:admin \
install-plugin workflow-aggregator blueocean -restart
- 预期效果:Jenkins 重启后,可在“新建任务”中创建 Pipeline 项目并识别 Jenkinsfile。
Declarative Pipeline 示例(规范化团队模板)
文件路径:/var/lib/jenkins/workspace/demo/Jenkinsfile
pipeline {
agent any
options {
timestamps()
buildDiscarder(logRotator(numToKeepStr: '30'))
}
environment {
APP_NAME = "demo-app"
}
stages {
stage('Checkout') {
steps {
git url: 'https://github.com/example/demo.git', branch: 'main'
}
}
stage('Build') {
steps {
sh 'mvn -v'
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
}
post {
success {
echo "✅ ${env.APP_NAME} build success"
}
failure {
echo "❌ ${env.APP_NAME} build failed"
}
}
}
命令说明
- mvn clean package -DskipTests:构建并跳过测试,加速构建。
- mvn test:执行单元测试,失败将中断流水线。
- buildDiscarder:控制历史构建数量,防止磁盘占满。
Scripted Pipeline 示例(复杂逻辑与动态阶段)
文件路径:/var/lib/jenkins/workspace/demo/Jenkinsfile
node('linux') {
def modules = ['api', 'worker']
stage('Checkout') {
checkout([$class: 'GitSCM', branches: [[name: '*/main']],
userRemoteConfigs: [[url: 'https://github.com/example/demo.git']]])
}
stage('Build & Test') {
modules.each { m ->
stage("Build-${m}") {
sh "mvn -pl ${m} clean package -DskipTests"
}
stage("Test-${m}") {
sh "mvn -pl ${m} test"
}
}
}
}
命令说明
- node('linux'):指定标签为 linux 的节点执行。
- mvn -pl ${m}:按模块构建与测试,适合多模块项目。
对比与选型建议(落地标准)
- 需要规范化、可审计与可视化:优先 Declarative。
- 复杂流程(动态阶段、条件分支多、脚本复用强):选 Scripted 或 Declarative + script {}。
- 平台化推广:主干用 Declarative,复杂逻辑下沉共享库。
混合策略示例(Declarative 内嵌 Scripted)
pipeline {
agent any
stages {
stage('Dynamic Build') {
steps {
script {
def targets = ['api','worker']
targets.each { t ->
sh "mvn -pl ${t} clean package -DskipTests"
}
}
}
}
}
}
排错与常见问题
- 报错:WorkflowScript: Expected a step
说明:Declarative 中写了 Scripted 语法。
处理:将脚本逻辑包裹在 script {} 内。
- 报错:No such DSL method 'stage'
说明:Scripted 中调用 Declarative 风格的阶段。
处理:确保使用 node { stage('x'){...} } 结构。
- 报错:java.io.IOException: Cannot run program "mvn"
说明:构建节点缺少 Maven。
处理:
# 在构建节点安装 Maven
sudo yum install -y maven
mvn -v
练习(建议在测试 Jenkins 中完成)
1. 用 Declarative 写一个包含 Checkout/Build/Test/Post 的流水线,并触发一次构建。
2. 将 Test 阶段改为 Scripted 动态遍历 2 个模块。
3. 制造一次构建失败(如 exit 1),观察 post { failure { ... } } 行为。
实践要点
- 制定统一模板与阶段命名,避免各团队风格不一致。
- Scripted 逻辑尽量封装为共享库函数,减少脚本散落。
- 通过 options { timestamps() } 与 post 统一日志与失败处理策略。