jenkins的groovy语法

Jenkins Pipeline Groovy语法指南

目录

  1. Groovy基础语法
  2. Pipeline声明式语法结构
  3. 流程控制语法
  4. 条件执行与判断
  5. 循环与迭代
  6. 错误处理与异常
  7. 变量与作用域
  8. 函数与方法
  9. 常用步骤命令
  10. 实战模板

一、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'
}
相关推荐
橙露2 小时前
Nginx 反向代理与负载均衡:配置详解与高可用方案
运维·nginx·负载均衡
赵庆明老师2 小时前
宝塔Linux面板Bug修复:添加反向代理出错
linux·运维·bug
藤谷性能2 小时前
Ubuntu 22.04:制作Ubuntu 22.04安装U盘
linux·运维·ubuntu
华科大胡子2 小时前
Workstation避坑指南:网络总连不上?
运维·服务器·网络
AzusaFighting2 小时前
llama.cpp CUDA with Gemma4-E4B(Ubuntu 24.04)部署
linux·运维·ubuntu
运维行者_2 小时前
网络监控告警设置指南:如何配置智能告警规避“告警风暴”?
linux·运维·服务器·网络·后端
DeepHacking2 小时前
Ubuntu上面加速下载文件
linux·运维·ubuntu
EAIReport2 小时前
深入浅出理解Token技术计算方式:从原理到实战
linux·运维·服务器
EasyGBS3 小时前
录像备份太麻烦?国标GB28181视频平台EasyGBS平台SyncRecord云端录像同步备份支持S3
linux·运维·音视频