Jenkins Pipeline Groovy语法指南
目录
Groovy基础语法
Pipeline声明式语法结构
流程控制语法
条件执行与判断
循环与迭代
错误处理与异常
变量与作用域
函数与方法
常用步骤命令
实战模板
一、Groovy基础语法
1.1 基本数据类型
groovy
复制代码
// 字符串
def str1 = '单引号字符串' // 单引号 - 不支持插值
def str2 = "双引号字符串 ${str1}" // 双引号 - 支持插值
def str3 = '''三引号字符串''' // 三引号 - 多行字符串
// 数字
def intNum = 123 // 整数
def doubleNum = 3.14 // 浮点数
def longNum = 100L // 长整数
def hexNum = 0xFF // 十六进制
// 布尔
def boolTrue = true
def boolFalse = false
// 列表(ArrayList)
def list = [1, 2, 3, 'four', 5.0]
// 映射(LinkedHashMap)
def map = [
name: 'Jenkins',
version: '2.x',
plugins: ['Pipeline', 'Git']
]
// 范围(Range)
def range = 1..10 // 包含10
def range2 = 1..<10 // 不包含10
1.2 运算符
groovy
复制代码
// 算术运算符
+ - * / % ++ --
// 比较运算符
== != < > <= >=
// 逻辑运算符
&& || !
// 条件运算符
?: (三元运算符)
?. (安全导航运算符)
==~ (正则匹配)
=~ (查找匹配)
// 成员运算符
in // 类似于Java的 instanceof
1.3 字符串操作
groovy
复制代码
def name = 'Jenkins'
// 字符串插值
echo "Hello ${name}"
echo "Version: ${map.version}"
// 字符串方法
name.toUpperCase() // JENKINS
name.toLowerCase() // jenkins
name.reverse() // snikreJ
name.length() // 7
name.contains('jen') // true
name.startsWith('Jen') // true
name.endsWith('ins') // true
// 多行字符串
def multiLine = '''
第一行
第二行
第三行
'''
// 字符串模板(GString)
def template = "Name: ${name}, Time: ${new Date()}"
1.4 列表操作
groovy
复制代码
def fruits = ['apple', 'banana', 'orange']
// 访问元素
fruits[0] // apple
fruits[-1] // orange(倒数第一个)
fruits[0..2] // ['apple', 'banana', 'orange']
// 添加元素
fruits << 'grape' // 左移运算符添加
fruits.add('melon')
// 移除元素
fruits.remove(0) // 按索引移除
fruits.remove('banana') // 按值移除
// 遍历
fruits.each { fruit ->
echo fruit
}
fruits.eachWithIndex { fruit, index ->
echo "${index}: ${fruit}"
}
// 映射
fruits.collect { it.toUpperCase() }
// ['APPLE', 'BANANA', 'ORANGE']
// 过滤
fruits.findAll { it.size() > 5 }
// ['banana', 'orange']
// 判断
fruits.any { it.contains('a') } // true
fruits.every { it.size() > 3 } // true
1.5 映射操作
groovy
复制代码
def person = [
name: '张三',
age: 30,
skills: ['Java', 'Groovy']
]
// 访问元素
person.name // 张三
person['name'] // 张三
person.skills[0] // Java
// 添加/修改
person.email = 'zhangsan@example.com'
person.age = 31
// 遍历
person.each { key, value ->
echo "${key}: ${value}"
}
person.eachWithIndex { entry, index ->
echo "${index}: ${entry.key} = ${entry.value}"
}
// 键值对列表
person.collect { k, v -> "${k}=${v}" }
// ['name=张三', 'age=31', ...]
1.6 正则表达式
groovy
复制代码
// 查找匹配
def text = 'Jenkins is awesome 123'
def match = text =~ /\d+/ // 返回Matcher对象
def found = text ==~ /\d+/ // 返回Boolean
// 替换
def result = text.replaceAll(/\d+/, 'NUM')
// 捕获组
def pattern = /(\w+)@(\w+)\.(\w+)/
def email = 'john@example.com'
def (full, user, domain, tld) = email =~ pattern
// user = john, domain = example, tld = com
二、Pipeline声明式语法结构
2.1 基本结构
groovy
复制代码
pipeline {
agent any // 1. 定义执行节点
options { // 2. Pipeline配置选项
timestamps() // 开启时间戳
timeout(time: 1, unit: 'HOURS') //流水线超时时间1小时
buildDiscarder(logRotator(numToKeepStr: '10')) // 保留最近10个构建记录
}
parameters { // 3. 参数定义
string(name: 'BRANCH', defaultValue: 'main', description: '代码分支')
booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '跳过测试')
choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: '部署环境')
}
environment { // 4. 环境变量
JAVA_HOME = '/usr/local/java'
MAVEN_OPTS = '-Xmx1024m'
}
stages { // 5. 阶段定义
stage('Stage 1') {
steps { // 6. 步骤执行
echo 'Hello World'
}
}
}
post { // 7. 后置处理
always {
echo '总是执行'
}
success {
echo '构建成功时执行'
}
failure {
echo '构建失败时执行'
}
}
}
2.2 agent配置详解
groovy
复制代码
// agent any - 任意可用节点
pipeline {
agent any
}
// agent none - 不分配节点,需在每个stage单独指定
pipeline {
agent none
stages {
stage('Build') {
agent { label 'build' }
}
}
}
// agent label - 指定标签的节点
pipeline {
agent { label 'windows && java' }
}
// agent kubernetes - Kubernetes集群运行
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8.1-eclipse-temurin-8
command: ["cat"]
tty: true
'''
defaultContainer 'maven'
}
}
}
// agent docker - Docker容器运行
pipeline {
agent {
docker {
image 'maven:3.8.1-eclipse-temurin-8'
label 'docker'
args '-v $HOME/.m2:/root/.m2'
}
}
}
// agent dockerfile - 从Dockerfile构建
pipeline {
agent {
dockerfile {
filename 'Dockerfile.build'
dir 'build'
additionalBuildArgs '--build-arg VERSION=1.0'
}
}
}
2.3 environment配置
groovy
复制代码
// 静态环境变量
environment {
APP_NAME = 'my-app'
APP_VERSION = '1.0.0'
}
// 动态环境变量(使用credentials)
environment {
// Secret text类型凭据
API_TOKEN = credentials('api-token-secret')
// Username and password类型凭据
NPM_CREDENTIALS = credentials('npm-credentials')
}
// 环境变量引用
environment {
BUILD_DIR = "${WORKSPACE}/build"
JAR_PATH = "${BUILD_DIR}/app.jar"
}
2.4 options配置
groovy
复制代码
options {
// 构建保持策略
buildDiscarder(logRotator(
numToKeepStr: '10', // 保持最近10个构建
daysToKeepStr: '30', // 保持最近30天的构建
artifactNumToKeepStr: '5' // 保持最近5个构建产物
))
// 超时设置
timeout(time: 1, unit: 'HOURS') // 1小时超时
timeout(time: 30, unit: 'MINUTES') // 30分钟超时
// 时间戳
timestamps()
// 并发构建控制
disableConcurrentBuilds()
// 重试次数
retry(3)
// 跳过默认Checkout
skipDefaultCheckout()
// 在代理上保存工作空间
preserveStashes()
}
2.5 parameters配置
groovy
复制代码
parameters {
// 字符串参数
string(
name: 'BRANCH',
defaultValue: 'main',
description: 'Git分支名'
)
// 多行字符串
text(
name: 'CHANGE_DESCRIPTION',
defaultValue: '',
description: '变更描述'
)
// 布尔参数
booleanParam(
name: 'SKIP_TEST',
defaultValue: false,
description: '是否跳过测试'
)
// 选择参数
choice(
name: 'ENVIRONMENT',
choices: ['dev', 'staging', 'prod'],
description: '部署环境'
)
// 文件参数
file(
name: 'CONFIG_FILE',
description: '配置文件'
)
// 密码参数
password(
name: 'API_SECRET',
defaultValue: '',
description: 'API密钥'
)
}
// 使用参数
pipeline {
stages {
stage('Build') {
steps {
echo "Branch: ${params.BRANCH}"
echo "Environment: ${params.ENVIRONMENT}"
}
}
}
}
2.6 triggers配置
groovy
复制代码
pipeline {
triggers {
// 定时触发 - Cron语法
cron('H 2 * * *') // 每天凌晨2点
cron('H/15 * * * *') // 每15分钟
cron('H(0-30) 8-18 * * 1-5') // 工作日8-18点每小时的0-30分钟
// GitHub PR触发
githubPullRequest()
// Bitbucket Pull Request触发
bitbucketPullRequest()
// GitLab MR触发
gitlabMergeRequest()
// Poll SCM - 轮询源码
pollSCM('H/5 * * * *')
// 依赖触发
upstream('job1,job2', threshold: 'SUCCESS')
}
}
2.7 post配置
groovy
复制代码
post {
// 总是执行
always {
echo '无论构建结果如何都执行'
cleanWs() // 清理工作空间
}
// 构建成功后执行
success {
echo '构建成功!'
emailext(
subject: "构建成功: ${env.JOB_NAME}",
body: "查看结果: ${env.BUILD_URL}",
to: 'team@example.com'
)
}
// 构建失败后执行
failure {
echo '构建失败!'
emailext(
subject: "构建失败: ${env.JOB_NAME}",
body: "失败原因: ${currentBuild.result}",
to: 'team@example.com'
)
}
// 标记为不稳定(测试失败)
unstable {
echo '构建不稳定'
}
// 构建被中断
aborted {
echo '构建被中断'
}
// 构建前次失败但本次成功
fixed {
echo '从失败恢复!'
}
// 构建前次成功但本次失败
regression {
echo '回归失败!'
}
// 条件执行
cleanup {
echo '清理资源'
}
}
三、流程控制语法
3.1 stage阶段
groovy
复制代码
// 基本结构
pipeline {
stages {
stage('Checkout') {
steps {
echo '拉取代码'
}
}
stage('Build') {
steps {
echo '编译项目'
}
}
stage('Test') {
steps {
echo '运行测试'
}
}
stage('Deploy') {
steps {
echo '部署应用'
}
}
}
}
3.2 steps步骤块
groovy
复制代码
stage('Example') {
steps {
// 基本命令
echo 'Hello World'
bat 'mvn clean package' // Windows
sh './build.sh' // Linux/Mac
// 执行PowerShell
powershell '''
Write-Host "PowerShell Script"
Get-Process
'''
// 设置环境变量(临时)
env.PATH = "${env.PATH}:/opt/bin"
// 返回值
def version = sh(script: 'cat version.txt', returnStdout: true).trim()
// 错误处理继续执行
sh 'git commit || true'
// 超时控制
timeout(time: 5, unit: 'MINUTES') {
sh 'long-running-command'
}
}
}
3.3 parallel并行执行
groovy
复制代码
// 基本并行
pipeline {
stages {
stage('Parallel Build') {
parallel {
stage('Windows Build') {
agent { label 'windows' }
steps {
bat 'build.bat'
}
}
stage('Linux Build') {
agent { label 'linux' }
steps {
sh './build.sh'
}
}
stage('macOS Build') {
agent { label 'macos' }
steps {
sh './build.sh'
}
}
}
}
}
}
groovy
复制代码
// 复杂并行构建矩阵,支持多个平台和构建类型,例如Windows、Linux、macOS和调试/发布构建
def platforms = ['windows', 'linux', 'macos']
def buildTypes = ['debug', 'release']
stage('Matrix Build') {
parallel {
platforms.collectEntries { platform ->
["${platform}-build" ]: {
stage("${platform} Build") {
agent { label platform }
steps {
echo "Building ${platform}"
}
}
}
}
}
}
groovy
复制代码
// 并行+顺序组合
pipeline {
stages {
stage('Build') {
parallel {
stage('Backend') {
steps {
echo 'Building backend...'
}
}
stage('Frontend') {
steps {
echo 'Building frontend...'
}
}
}
}
stage('Integration Tests') {
steps {
echo 'Running integration tests...'
}
}
stage('Deploy') {
parallel {
stage('Deploy to Staging') {
when {
expression { params.ENVIRONMENT != 'prod' }
}
steps {
echo 'Deploying to staging...'
}
}
stage('Deploy to Production') {
when {
expression { params.ENVIRONMENT == 'prod' }
}
steps {
echo 'Deploying to production...'
}
}
}
}
}
}
3.4 script脚本块
groovy
复制代码
// 在声明式Pipeline中使用脚本
pipeline {
stages {
stage('Conditional Build') {
steps {
script {
def branch = env.BRANCH_NAME
def shouldBuild = false
if (branch == 'main') {
shouldBuild = true
} else if (branch.startsWith('release/')) {
shouldBuild = true
} else if (env.CHANGE_ID) {
shouldBuild = true
}
if (shouldBuild) {
echo "Starting build for branch: ${branch}"
sh './build.sh'
} else {
echo "Skipping build for branch: ${branch}"
}
}
}
}
}
}
groovy
复制代码
// 复杂脚本逻辑
stage('Deploy') {
steps {
script {
def targetEnv = params.ENVIRONMENT
def config = [:]
switch (targetEnv) {
case 'dev':
config = [
apiUrl: 'https://dev-api.example.com',
replicas: 1
]
break
case 'staging':
config = [
apiUrl: 'https://staging-api.example.com',
replicas: 2
]
break
case 'prod':
config = [
apiUrl: 'https://api.example.com',
replicas: 5
]
break
default:
error "Unknown environment: ${targetEnv}"
}
echo "Deploying to ${targetEnv}"
echo "API URL: ${config.apiUrl}"
echo "Replicas: ${config.replicas}"
}
}
}
四、条件执行与判断
4.1 when条件块
groovy
复制代码
// 基本语法
stage('Deploy') {
when {
expression { params.DEPLOY == 'true' }
}
steps {
echo 'Deploying...'
}
}
groovy
复制代码
// 多条件组合
stage('Deploy to Production') {
when {
expression { env.BRANCH_NAME == 'main' }
expression { params.DEPLOY_TO_PROD == true }
expression { currentBuild.result == null || currentBuild.result == 'SUCCESS' }
}
steps {
echo 'Deploying to production...'
}
}
groovy
复制代码
// OR条件
stage('Deploy') {
when {
anyOf {
expression { env.BRANCH_NAME == 'main' }
expression { env.BRANCH_NAME.startsWith('release/') }
expression { params.FORCE_DEPLOY == true }
}
}
steps {
echo 'Deploying...'
}
}
groovy
复制代码
// AND条件
stage('Full Test') {
when {
allOf {
expression { env.BRANCH_NAME != 'main' }
expression { !params.SKIP_TEST }
}
}
steps {
echo 'Running full test suite...'
}
}
groovy
复制代码
// NOT条件
stage('Skip on Main') {
when {
not { expression { env.BRANCH_NAME == 'main' } }
}
steps {
echo 'This stage is skipped on main branch'
}
}
groovy
复制代码
// Branch条件
stage('Feature Branch Build') {
when {
branch 'feature/*'
}
steps {
echo 'Building feature branch...'
}
}
groovy
复制代码
// Tag条件
stage('Release Build') {
when {
buildingTag()
}
steps {
echo 'Building release tag...'
}
}
groovy
复制代码
// 环境变量条件
stage('Deploy') {
when {
environment name: 'DEPLOY_ENV', value: 'production'
}
steps {
echo 'Deploying to production...'
}
}
groovy
复制代码
// changelog条件(Git变更日志)
stage('Build') {
when {
changeset '**/*.java'
}
steps {
echo 'Java files changed, building...'
}
}
4.2 if-else条件判断
groovy
复制代码
// 基本if-else
pipeline {
stages {
stage('Check') {
steps {
script {
if (env.BRANCH_NAME == 'main') {
echo 'Main branch detected'
} else {
echo 'Other branch detected'
}
}
}
}
}
}
groovy
复制代码
// if-else if-else
script {
def status = currentBuild.result ?: 'SUCCESS'
if (status == 'SUCCESS') {
echo 'Build succeeded'
} else if (status == 'UNSTABLE') {
echo 'Build is unstable'
} else if (status == 'FAILURE') {
echo 'Build failed'
} else {
echo 'Build status: ${status}'
}
}
groovy
复制代码
// 三元运算符
script {
def message = env.BRANCH_NAME == 'main' ? 'Deploy to prod' : 'Deploy to dev'
echo message
}
4.3 switch-case选择
groovy
复制代码
script {
def envName = params.ENVIRONMENT
switch (envName) {
case 'dev':
echo 'Deploying to development environment'
break
case 'staging':
echo 'Deploying to staging environment'
break
case 'prod':
echo 'Deploying to production environment'
break
default:
error "Unknown environment: ${envName}"
}
}
groovy
复制代码
// 带表达式的switch
script {
def branch = env.BRANCH_NAME
switch (branch) {
case ~/main/:
echo 'Main branch'
break
case ~/release\/.*/:
echo 'Release branch'
break
case ~/feature\/.*/:
echo 'Feature branch'
break
default:
echo 'Other branch'
}
}
五、循环与迭代
5.1 for循环
groovy
复制代码
// 基本for循环
script {
for (int i = 0; i < 5; i++) {
echo "Iteration: ${i}"
}
}
groovy
复制代码
// for-in循环
script {
def items = ['a', 'b', 'c']
for (item in items) {
echo "Item: ${item}"
}
}
groovy
复制代码
// 遍历Map
script {
def config = [
name: 'app',
version: '1.0',
env: 'dev'
]
for (entry in config) {
echo "${entry.key} = ${entry.value}"
}
}
5.2 each迭代
groovy
复制代码
// 列表迭代
['apple', 'banana', 'orange'].each { fruit ->
echo "Fruit: ${fruit}"
}
// 带索引迭代
['apple', 'banana', 'orange'].eachWithIndex { fruit, index ->
echo "${index}: ${fruit}"
}
groovy
复制代码
// Map迭代
[name: 'John', age: 30].each { key, value ->
echo "${key} = ${value}"
}
groovy
复制代码
// 数字范围迭代
(1..5).each { num ->
echo "Number: ${num}"
}
5.3 列表操作
groovy
复制代码
// collect - 映射
def numbers = [1, 2, 3, 4, 5]
def doubled = numbers.collect { it * 2 }
// [2, 4, 6, 8, 10]
groovy
复制代码
// find/findAll - 过滤
def numbers = [1, 2, 3, 4, 5, 6]
def evens = numbers.findAll { it % 2 == 0 }
// [2, 4, 6]
groovy
复制代码
// any/every - 判断
def numbers = [1, 2, 3, 4, 5]
def hasEven = numbers.any { it % 2 == 0 } // true
def allPositive = numbers.every { it > 0 } // true
groovy
复制代码
// join - 连接
def words = ['Hello', 'World']
def sentence = words.join(' ')
// 'Hello World'
groovy
复制代码
// sort - 排序
def numbers = [3, 1, 4, 1, 5, 9, 2, 6]
def sorted = numbers.sort()
// [1, 1, 2, 3, 4, 5, 6, 9]
groovy
复制代码
// unique - 去重
def numbers = [1, 2, 2, 3, 3, 3]
def unique = numbers.unique()
// [1, 2, 3]
5.4 列表推导式
groovy
复制代码
// 基本推导式
def squares = [1, 2, 3, 4, 5].collect { it * it }
// [1, 4, 9, 16, 25]
groovy
复制代码
// 带条件的推导式
def numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def evenSquares = numbers.findAll { it % 2 == 0 }.collect { it * it }
// [4, 16, 36, 64, 100]
六、错误处理与异常
6.1 try-catch-finally
groovy
复制代码
stage('Risky Operation') {
steps {
script {
try {
echo 'Attempting risky operation...'
sh '可能出现问题的命令'
echo 'Operation succeeded'
} catch (Exception e) {
echo "Operation failed: ${e.message}"
currentBuild.result = 'FAILURE'
} finally {
echo 'Cleanup code here'
}
}
}
}
groovy
复制代码
// 捕获特定异常
script {
try {
sh 'mvn clean package'
} catch (hudson.AbortedException e) {
echo 'Build was aborted'
} catch (java.io.IOException e) {
echo 'IO error occurred'
} catch (Exception e) {
echo "Unexpected error: ${e.message}"
}
}
6.2 try-catch in Pipeline
groovy
复制代码
pipeline {
stages {
stage('Build') {
steps {
script {
try {
sh 'mvn clean package'
env.BUILD_STATUS = 'SUCCESS'
} catch (Exception ex) {
env.BUILD_STATUS = 'FAILED'
throw ex // 重新抛出以使构建标记为失败
}
}
}
}
}
}
6.3 继续执行即使出错
groovy
复制代码
// 方法1: 使用 || true
stage('Optional Step') {
steps {
sh 'git commit || true' // 如果git commit失败,继续执行
}
}
groovy
复制代码
// 方法2: 使用catchError
stage('Optional Step') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
sh '可能会失败的命令'
}
}
}
groovy
复制代码
// 方法3: 使用catchError保持结果但继续
stage('Build') {
steps {
catchError(message: 'Test failed but continuing') {
sh 'mvn test'
}
echo 'This will execute even if tests fail'
}
}
6.4 抛出异常
groovy
复制代码
script {
def value = params.ENVIRONMENT
if (!value) {
error 'ENVIRONMENT parameter is required'
}
if (value == 'prod' && !params.APPROVED) {
error 'Production deployment requires approval'
}
}
groovy
复制代码
// 抛出自定义异常
throw new Exception('Custom error message')
groovy
复制代码
// 使用return/exit提前返回
script {
if (env.BRANCH_NAME != 'main') {
echo 'Not main branch, skipping deployment'
return
}
echo 'Deploying...'
}
6.5 retry重试机制
groovy
复制代码
// 基本重试
stage('Download') {
steps {
retry(3) {
sh 'curl -O https://example.com/large-file.zip'
}
}
}
groovy
复制代码
// 重试+休眠
stage('API Call') {
steps {
retry(5) {
sleep(time: 10, unit: 'SECONDS')
sh 'curl -X POST https://api.example.com/webhook'
}
}
}
groovy
复制代码
// 条件重试
stage('Deploy') {
steps {
script {
def attempts = 0
def maxAttempts = 3
while (attempts < maxAttempts) {
try {
attempts++
echo "Attempt ${attempts} of ${maxAttempts}"
sh './deploy.sh'
if (isServerHealthy()) {
echo 'Deployment successful'
break
} else {
throw new Exception('Server not healthy')
}
} catch (Exception e) {
if (attempts >= maxAttempts) {
error "Deployment failed after ${maxAttempts} attempts"
}
echo "Attempt ${attempts} failed, retrying..."
sleep(time: 30, unit: 'SECONDS')
}
}
}
}
}
6.6 timeout超时控制
groovy
复制代码
// 基本超时
stage('Long Running Task') {
steps {
timeout(time: 1, unit: 'HOURS') {
sh './long-running-script.sh'
}
}
}
groovy
复制代码
// 超时后抛出异常
stage('Network Call') {
steps {
timeout(time: 30, unit: 'SECONDS') {
script {
def response = sh(
script: 'curl -s --max-time 25 https://api.example.com/health',
returnStdout: true
).trim()
if (response != 'OK') {
error 'Health check failed'
}
}
}
}
}
七、变量与作用域
7.1 变量类型
groovy
复制代码
// 局部变量 - 在脚本块中定义
script {
def localVar = 'Hello'
echo localVar
}
groovy
复制代码
// 环境变量 - 全局可用
environment {
MY_VAR = 'value'
}
// 通过env访问
env.MY_VAR
env['MY_VAR']
// 设置环境变量
env.BUILD_ID = '123'
groovy
复制代码
// Pipeline参数
parameters {
string(name: 'BRANCH', defaultValue: 'main')
}
// 访问参数
params.BRANCH
groovy
复制代码
// Current Build变量
currentBuild.displayName // 构建显示名称
currentBuild.result // 构建结果 SUCCESS/FAILURE/UNSTABLE
currentBuild.number // 构建编号
currentBuild.durationString // 持续时间字符串
currentBuild.id // 构建ID
currentBuild.url // 构建URL
currentBuild.buildVariables // 所有构建变量
7.2 Groovy变量与Env区别
groovy
复制代码
pipeline {
agent any
environment {
ENV_VAR = 'defined in environment block'
}
stages {
stage('Variables') {
steps {
script {
// Groovy变量 - 只在当前script块有效
def groovyVar = 'I am Groovy'
echo "Groovy var: ${groovyVar}"
// Env变量 - 全局有效
env.ENV_VAR = 'modified in script'
echo "Env var: ${env.ENV_VAR}"
// 使用env前缀访问
echo env.PATH
echo env.WORKSPACE
echo env.BUILD_NUMBER
}
}
}
stage('Another Stage') {
steps {
// groovyVar 不可访问(作用域外)
echo "Env var still available: ${env.ENV_VAR}"
}
}
}
}
7.3 变量引用与插值
groovy
复制代码
// 在字符串中引用变量
def name = 'Jenkins'
echo "Hello ${name}"
echo 'Hello ${name}' // 单引号不插值
// 在步骤中引用
sh "echo ${name}" // Groovy变量
sh 'echo ${name}' // Shell变量
// 复杂表达式
def version = '1.0'
def build = 100
echo "v${version}.${build}" // v1.0.100
7.4 变量类型转换
groovy
复制代码
// 字符串转数字
def str = '123'
def num = str.toInteger()
def num2 = str as Integer
// 数字转字符串
def num = 123
def str = num.toString()
def str2 = "${num}"
// 字符串转布尔
def str = 'true'
def bool = str.toBoolean()
// JSON解析
import groovy.json.JsonSlurper
def jsonStr = '{"name": "John", "age": 30}'
def json = new JsonSlurper().parseText(jsonStr)
echo json.name // John
八、函数与方法
8.1 方法定义
groovy
复制代码
// 基本方法
def greet(name) {
echo "Hello, ${name}!"
}
// 带返回值
def add(a, b) {
return a + b
}
// 默认参数
def greet(name = 'World') {
echo "Hello, ${name}!"
}
// 可变参数
def sum(int... numbers) {
def total = 0
for (n in numbers) {
total += n
}
return total
}
groovy
复制代码
// 在Pipeline中使用方法
def buildJar() {
sh 'mvn package -DskipTests'
}
def deployJar(String env) {
sh "./deploy.sh ${env}"
}
pipeline {
stages {
stage('Build') {
steps {
script {
buildJar()
deployJar('dev')
}
}
}
}
}
8.2 闭包
groovy
复制代码
// 基本闭包
def closure = { echo 'Hello' }
closure() // 调用闭包
// 带参数的闭包
def greet = { name -> echo "Hello, ${name}!" }
greet('World')
// it隐式参数
def double = { it * 2 }
echo double(5) // 10
// 闭包返回值
def result = { x, y ->
return x + y
}(1, 2)
echo result // 3
groovy
复制代码
// 闭包作为方法参数
def executeWithRetry(closure, maxRetries = 3) {
def attempts = 0
while (attempts < maxRetries) {
try {
return closure()
} catch (Exception e) {
attempts++
if (attempts >= maxRetries) {
throw e
}
}
}
}
// 使用
executeWithRetry({
sh 'mvn test'
}, 3)
8.3 静态方法调用
groovy
复制代码
// 使用Math类
script {
def random = Math.random() * 100
def ceiling = Math.ceil(3.14) // 4.0
def floor = Math.floor(3.14) // 3.0
def abs = Math.abs(-5) // 5
}
groovy
复制代码
// 使用Date类
script {
def now = new Date()
def timestamp = now.time
def formatted = now.format('yyyy-MM-dd HH:mm:ss')
// 日期计算
def tomorrow = now + 1
def nextWeek = now + 7
}
8.4 外部方法库
groovy
复制代码
// 在 vars/ 目录下创建共享库
// vars/buildJar.groovy
def call(String type = 'jar') {
echo "Building ${type}..."
sh "mvn package -DskipTests"
}
// 在Pipeline中调用
pipeline {
stages {
stage('Build') {
steps {
buildJar('war') // 调用共享库方法
}
}
}
}
groovy
复制代码
// vars/deploy.groovy
def call(String env, String region) {
echo "Deploying to ${env} in ${region}..."
sh "./deploy.sh -e ${env} -r ${region}"
}
// Pipeline中使用
deploy('prod', 'us-west-2')
九、常用步骤命令
9.1 基础命令
groovy
复制代码
// echo - 输出日志
echo 'Hello World'
echo "Building branch: ${env.BRANCH_NAME}"
// print - 打印输出
print variable
// error - 中断构建并报错
error 'This is an error message'
// warning - 输出警告
warning 'This is a warning'
// catchError - 捕获错误但不中断
catchError(message: 'Build failed') {
sh 'mvn package'
}
9.2 Shell执行
groovy
复制代码
// Linux/Mac - sh
sh 'ls -la'
sh 'mvn clean package'
sh '''
cd src
ls -la
'''
// 返回值
def output = sh(script: 'echo Hello', returnStdout: true).trim()
// 返回码
def result = sh(script: 'exit 0', returnStatus: true)
// Windows - bat
bat 'dir'
bat 'mvn clean package'
// PowerShell - powershell
powershell 'Get-Process'
9.3 源码管理
groovy
复制代码
// Git
git 'https://github.com/org/repo.git'
git branch: 'main',
credentialsId: 'git-credentials',
url: 'https://github.com/org/repo.git'
// 带submodules
git submodule: true,
branches: [[name: '*/main']],
credentialsId: 'git-credentials',
url: 'https://github.com/org/repo.git'
// SVN
checkout changelog: true,
poll: true,
sku: 'https://svn.example.com/repo',
workspace: 'hudson.scm.SubversionSCM'
9.4 文件操作
groovy
复制代码
// 读取文件
def content = readFile 'config.txt'
def json = readJSON file: 'package.json'
// 写入文件
writeFile file: 'output.txt', text: 'Hello World'
writeJSON file: 'package.json', json: [name: 'app', version: '1.0']
// 复制文件
copyArtifacts projectName: 'upstream-job', selector: lastSuccessful()
// 归档
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
archiveArtifacts artifacts: 'build/**/*.war', allowEmptyArchive: true
// 清理
cleanWs() // 清理工作空间
deleteDir() // 删除当前目录
9.5 字符串处理
groovy
复制代码
// 替换
def newStr = str.replace('old', 'new')
def newStr = str.replaceAll(/\d+/, 'NUM')
// 分割
def parts = 'a,b,c'.split(',')
def lines = multilineString.split('\n')
// 连接
def joined = ['a', 'b', 'c'].join(',')
// 截取
def sub = str.substring(0, 10)
// 大小写
str.toUpperCase()
str.toLowerCase()
// 去除空白
str.trim()
str.stripIndent()
9.6 通知
groovy
复制代码
// 发送邮件
emailext(
subject: "构建通知: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: '''
<html>
<body>
<h2>构建结果</h2>
<p>状态: ${currentBuild.result ?: 'SUCCESS'}</p>
<p>构建URL: <a href="${env.BUILD_URL}">点击查看</a></p>
</body>
</html>
''',
to: 'team@example.com',
mimeType: 'text/html'
)
// 企业微信/钉钉通知
discord_webhook = 'https://discord.webhook.url'
mattermost_webhook = 'https://mattermost.webhook.url'
9.7 认证和凭证
groovy
复制代码
// 使用credentials
withCredentials([string(credentialsId: 'api-token', variable: 'API_TOKEN')]) {
sh 'curl -H "Authorization: Bearer ${API_TOKEN}" https://api.example.com'
}
// SSH Agent
sshagent(credentials: ['ssh-key']) {
sh 'ssh -i key.pem user@host "command"'
}
// 获取当前用户
wrap([$class: 'BuildUser']) {
echo "Build triggered by: ${BUILD_USER}"
}
9.8 锁和资源
groovy
复制代码
// 锁定资源, 避免多个构建同时占用相同资源,例如数据库连接池
// 可以使用 lock() 方法来锁定资源,确保在构建过程中不会被其他构建占用
pipeline {
stages {
stage('Deploy') {
steps {
lock(resource: 'production-deployment') {
echo 'Deploying to production...'
}
}
}
}
}
groovy
复制代码
// 占用临时资源, 例如工作空间或临时目录
// 可以使用 ws() 方法来占用临时资源,确保在构建过程中不会被其他构建占用
pipeline {
stages {
stage('Test') {
steps {
ws('workspace') {
echo 'Using workspace'
}
}
}
}
}
十、实战模板
10.1 基础Java构建流水线
groovy
复制代码
pipeline {
agent { label 'java && maven' }
options {
timestamps()
timeout(time: 30, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: '10'))
}
parameters {
string(name: 'BRANCH', defaultValue: 'main', description: '代码分支')
choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: '部署环境')
booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '跳过测试')
}
environment {
MAVEN_OPTS = '-Xmx2048m -Xms1024m'
}
stages {
stage('Checkout') {
steps {
echo "Checking out branch: ${params.BRANCH}"
git branch: params.BRANCH,
url: 'https://github.com/your-org/your-project.git'
}
}
stage('Build') {
steps {
echo 'Building project...'
sh 'mvn clean compile'
}
}
stage('Test') {
when {
expression { !params.SKIP_TEST }
}
steps {
echo 'Running tests...'
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Package') {
steps {
echo 'Packaging...'
sh 'mvn package -DskipTests'
}
post {
always {
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
}
stage('Deploy') {
when {
expression { params.ENV != null }
}
steps {
echo "Deploying to ${params.ENV}..."
script {
deployToEnvironment(params.ENV)
}
}
}
}
post {
success {
echo 'Build completed successfully!'
}
failure {
echo 'Build failed!'
}
}
}
def deployToEnvironment(String env) {
echo "Deploying application to ${env} environment"
// 实际部署逻辑
}
10.2 多环境部署流水线
groovy
复制代码
pipeline {
agent none
parameters {
choice(name: 'TARGET_ENV', choices: ['dev', 'staging', 'prod'], description: '目标环境')
string(name: 'VERSION', defaultValue: '', description: '版本号(留空则自动生成)')
}
options {
timestamps()
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Initialize') {
steps {
script {
env.DEPLOY_VERSION = params.VERSION ?: generateVersion()
echo "Deploying version: ${env.DEPLOY_VERSION}"
}
}
}
stage('Build') {
parallel {
stage('Backend') {
agent { label 'java' }
steps {
echo 'Building backend...'
sh 'mvn clean package -DskipTests'
}
}
stage('Frontend') {
agent { label 'nodejs' }
steps {
echo 'Building frontend...'
sh 'npm run build'
}
}
}
}
stage('Deploy') {
script {
switch (params.TARGET_ENV) {
case 'dev':
deployToDev()
break
case 'staging':
deployToStaging()
break
case 'prod':
deployToProd()
break
default:
error "Unknown environment: ${params.TARGET_ENV}"
}
}
}
}
post {
always {
cleanWs()
}
success {
echo 'Deployment completed!'
}
failure {
echo 'Deployment failed!'
}
}
}
def generateVersion() {
return "v${new Date().format('yyyyMMdd-HHmmss')}"
}
def deployToDev() {
echo 'Deploying to DEV environment...'
sh './deploy.sh dev'
}
def deployToStaging() {
echo 'Deploying to STAGING environment...'
sh './deploy.sh staging'
}
def deployToProd() {
echo 'Deploying to PRODUCTION environment...'
timeout(time: 30, unit: 'MINUTES') {
input message: '确认部署到生产环境?',
ok: '确认部署',
submitter: 'admin'
}
sh './deploy.sh prod'
}
10.3 GitOps自动化流水线
groovy
复制代码
pipeline {
agent { label 'kubernetes' }
environment {
REGISTRY = 'registry.example.com'
APP_NAME = 'my-application'
}
stages {
stage('Verify Commit') {
when {
anyOf {
branch 'main'
branch 'release/*'
}
}
steps {
script {
def commitMessage = sh(
script: 'git log -1 --pretty=%B',
returnStdout: true
).trim()
echo "Commit: ${commitMessage}"
if (commitMessage.contains('[skip ci]')) {
error 'Commit message contains [skip ci], aborting pipeline'
}
}
}
}
stage('Build & Push Image') {
steps {
script {
def imageTag = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}"
env.IMAGE_TAG = imageTag
env.IMAGE_FULL = "${REGISTRY}/${APP_NAME}:${imageTag}"
sh """
docker build -t ${IMAGE_FULL} .
docker push ${IMAGE_FULL}
"""
}
}
}
stage('Update Manifest') {
steps {
sh """
sed -i 's|image:.*|image: ${IMAGE_FULL}|' k8s/deployment.yaml
git add k8s/deployment.yaml
git commit -m "Update image to ${IMAGE_FULL} [skip ci]"
git push
"""
}
}
stage('Deploy to Cluster') {
steps {
sh """
kubectl apply -f k8s/deployment.yaml
kubectl rollout status deployment/${APP_NAME}
"""
}
}
}
post {
failure {
script {
notifyFailure()
}
}
}
}
def notifyFailure() {
echo 'Sending failure notification...'
// 通知逻辑
}
10.4 矩阵构建流水线
groovy
复制代码
def buildMatrix = [
[platform: 'windows', arch: 'x64', config: 'Release'],
[platform: 'windows', arch: 'x86', config: 'Debug'],
[platform: 'linux', arch: 'x64', config: 'Release'],
[platform: 'linux', arch: 'arm64', config: 'Release'],
[platform: 'macos', arch: 'x64', config: 'Release'],
[platform: 'macos', arch: 'arm64', config: 'Release']
]
pipeline {
agent none
stages {
stage('Build Matrix') {
steps {
script {
def branches = [:]
buildMatrix.each { params ->
def buildParams = params
branches["${buildParams.platform}-${buildParams.arch}-${buildParams.config}"] = {
node("${buildParams.platform}") {
stage("Build ${buildParams.platform} ${buildParams.arch} ${buildParams.config}") {
steps {
script {
echo "Building for ${buildParams.platform} ${buildParams.arch} ${buildParams.config}"
sh "./build.sh --platform=${buildParams.platform} --arch=${buildParams.arch} --config=${buildParams.config}"
}
}
post {
always {
archiveArtifacts artifacts: "output/**/*.${getExt(buildParams.platform)}"
}
}
}
}
}
}
parallel branches
}
}
}
}
}
def getExt(String platform) {
switch (platform) {
case 'windows': return 'exe'
case 'linux': return 'bin'
case 'macos': return 'dmg'
default: return 'bin'
}
}
附录:Cheat Sheet
A.1 常用快捷语法
groovy
复制代码
// 链式调用
def result = [1, 2, 3, 4, 5]
.findAll { it > 2 }
.collect { it * 2 }
.join(', ')
// Elvis运算符,用于处理空值
def name = user.name ?: 'Anonymous'
// 安全导航,用于处理空指针异常
def city = user?.address?.city ?: 'Unknown'
//with方法,用于批量更新对象属性
def person = [:]
person.with {
name = 'John'
age = 30
city = 'New York'
}