Declarative Pipeline 语法 #

Declarative Pipeline是Jenkins 2.x引入的声明式语法,提供了更简洁、更结构化的方式来定义CI/CD流水线。

基本结构 #

groovy
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
}

顶层指令 #

pipeline #

所有Declarative Pipeline必须包含在 pipeline 块中:

groovy
pipeline {
    // 所有配置
}

agent #

指定Pipeline执行的代理节点。

agent any #

在任意可用代理上执行:

groovy
pipeline {
    agent any
}

agent none #

在各个stage中单独指定:

groovy
pipeline {
    agent none
    
    stages {
        stage('Build') {
            agent { label 'linux' }
            steps { echo 'Building on Linux' }
        }
    }
}

agent label #

指定标签的节点:

groovy
pipeline {
    agent { label 'docker && linux' }
}

agent node #

指定具体节点:

groovy
pipeline {
    agent {
        node {
            label 'linux'
            customWorkspace '/tmp/custom'
        }
    }
}

agent docker #

使用Docker容器:

groovy
pipeline {
    agent {
        docker {
            image 'maven:3.8-openjdk-11'
            label 'docker'
            args '-v $HOME/.m2:/root/.m2'
        }
    }
}

agent dockerfile #

使用项目中的Dockerfile:

groovy
pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile.build'
            dir 'docker'
            additionalBuildArgs '--build-arg VERSION=1.0'
        }
    }
}

agent kubernetes #

使用Kubernetes Pod:

groovy
pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.8-openjdk-11
    command:
    - cat
    tty: true
  - name: docker
    image: docker:latest
    command:
    - cat
    tty: true
    volumeMounts:
    - name: docker-sock
      mountPath: /var/run/docker.sock
  volumes:
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
'''
        }
    }
}

environment #

定义环境变量:

groovy
pipeline {
    agent any
    
    environment {
        APP_NAME = 'myapp'
        VERSION = "${BUILD_NUMBER}"
        JAVA_HOME = tool name: 'JDK 11', type: 'jdk'
        PATH = "${env.JAVA_HOME}/bin:${env.PATH}"
    }
    
    stages {
        stage('Build') {
            steps {
                echo "Building ${APP_NAME} version ${VERSION}"
            }
        }
    }
}

使用凭据 #

groovy
environment {
    DB_PASSWORD = credentials('db-password')
    AWS_ACCESS_KEY = credentials('aws-access-key')
    SSH_KEY = credentials('ssh-private-key')
}

Stage级环境变量 #

groovy
stages {
    stage('Deploy') {
        environment {
            DEPLOY_ENV = 'production'
        }
        steps {
            echo "Deploying to ${DEPLOY_ENV}"
        }
    }
}

options #

配置Pipeline选项:

groovy
pipeline {
    agent any
    
    options {
        timeout(time: 30, unit: 'MINUTES')
        retry(3)
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
        skipDefaultCheckout()
        timestamps()
        quietPeriod(10)
        parallelsAlwaysFailFast()
    }
}

常用选项说明 #

选项 说明
timeout 构建超时时间
retry 失败重试次数
buildDiscarder 丢弃旧构建
disableConcurrentBuilds 禁止并发构建
skipDefaultCheckout 跳过默认代码检出
timestamps 添加时间戳
quietPeriod 静默期
parallelsAlwaysFailFast 并行任务任一失败立即终止

parameters #

定义构建参数:

groovy
pipeline {
    agent any
    
    parameters {
        string(name: 'VERSION', defaultValue: '1.0.0', description: '版本号')
        booleanParam(name: 'DEPLOY', defaultValue: true, description: '是否部署')
        choice(name: 'ENVIRONMENT', choices: ['dev', 'test', 'prod'], description: '部署环境')
        password(name: 'PASSWORD', defaultValue: '', description: '密码')
        text(name: 'DESCRIPTION', defaultValue: '', description: '描述')
        file(name: 'CONFIG_FILE', description: '配置文件')
    }
    
    stages {
        stage('Build') {
            steps {
                echo "Building version ${params.VERSION}"
                echo "Deploy: ${params.DEPLOY}"
                echo "Environment: ${params.ENVIRONMENT}"
            }
        }
    }
}

triggers #

定义构建触发器:

groovy
pipeline {
    agent any
    
    triggers {
        cron('H 2 * * *')
        pollSCM('H/5 * * * *')
        upstream(upstreamProjects: 'upstream-job', threshold: hudson.model.Result.SUCCESS)
        GenericTrigger(...)
    }
}

Cron表达式 #

text
┌───────────── 分钟 (0 - 59)
│ ┌───────────── 小时 (0 - 23)
│ │ ┌───────────── 日 (1 - 31)
│ │ │ ┌───────────── 月 (1 - 12)
│ │ │ │ ┌───────────── 星期 (0 - 6)
│ │ │ │ │
* * * * *

常用示例:

groovy
triggers {
    cron('H/15 * * * *')    // 每15分钟
    cron('H 2 * * *')       // 每天凌晨2点
    cron('H 2 * * 1')       // 每周一凌晨2点
    cron('H 2 1 * *')       // 每月1日凌晨2点
}

stages #

定义构建阶段:

groovy
pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
        
        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
        
        stage('Deploy') {
            steps {
                sh 'kubectl apply -f k8s/'
            }
        }
    }
}

post #

定义构建后操作:

groovy
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
    }
    
    post {
        always {
            echo 'Always executed'
            junit '**/target/surefire-reports/*.xml'
        }
        
        success {
            echo 'Build succeeded!'
            mail to: 'team@example.com',
                 subject: "Success: ${JOB_NAME} #${BUILD_NUMBER}",
                 body: 'Build succeeded'
        }
        
        failure {
            echo 'Build failed!'
            mail to: 'team@example.com',
                 subject: "Failed: ${JOB_NAME} #${BUILD_NUMBER}",
                 body: 'Build failed'
        }
        
        unstable {
            echo 'Build unstable!'
        }
        
        aborted {
            echo 'Build aborted!'
        }
        
        cleanup {
            echo 'Cleaning up...'
            cleanWs()
        }
    }
}

Stage指令 #

基本Stage #

groovy
stage('Build') {
    steps {
        sh 'mvn clean package'
    }
}

带条件的Stage #

groovy
stage('Deploy') {
    when {
        branch 'main'
    }
    steps {
        sh 'kubectl apply -f k8s/'
    }
}

并行Stage #

groovy
stage('Test') {
    parallel {
        stage('Unit Tests') {
            steps {
                sh 'mvn test'
            }
        }
        stage('Integration Tests') {
            steps {
                sh 'mvn verify -P integration'
            }
        }
        stage('E2E Tests') {
            steps {
                sh 'npm run test:e2e'
            }
        }
    }
}

嵌套Stage #

groovy
stage('CI') {
    stages {
        stage('Build') {
            steps { echo 'Building...' }
        }
        stage('Test') {
            steps { echo 'Testing...' }
        }
    }
}

Matrix Stage #

groovy
stage('Matrix Build') {
    matrix {
        axes {
            axis {
                name 'OS'
                values 'linux', 'windows', 'macos'
            }
            axis {
                name 'JAVA_VERSION'
                values '8', '11', '17'
            }
        }
        stages {
            stage('Build') {
                steps {
                    echo "Building on ${OS} with Java ${JAVA_VERSION}"
                }
            }
        }
    }
}

Steps步骤 #

基本步骤 #

echo #

输出信息:

groovy
steps {
    echo 'Hello, Jenkins!'
    echo "Build number: ${BUILD_NUMBER}"
}

sh #

执行Shell命令:

groovy
steps {
    sh 'echo "Hello"'
    sh '''
        echo "Multi-line script"
        ls -la
        pwd
    '''
    sh(script: 'mvn clean package', returnStdout: true)
    sh(script: 'test -f file.txt', returnStatus: true)
}

bat #

执行Windows批处理命令:

groovy
steps {
    bat 'echo Hello'
    bat '''
        echo Multi-line script
        dir
    '''
}

script #

执行Groovy脚本:

groovy
steps {
    script {
        def files = findFiles(glob: '**/*.java')
        files.each { f ->
            echo "Found file: ${f.name}"
        }
    }
}

代码管理步骤 #

checkout #

检出代码:

groovy
steps {
    checkout scm
    
    checkout([
        $class: 'GitSCM',
        branches: [[name: '*/main']],
        extensions: [],
        userRemoteConfigs: [[
            url: 'https://github.com/user/repo.git',
            credentialsId: 'github-creds'
        ]]
    ])
}

git #

简化的Git检出:

groovy
steps {
    git url: 'https://github.com/user/repo.git',
        branch: 'main',
        credentialsId: 'github-creds'
}

文件操作步骤 #

archiveArtifacts #

归档构建产物:

groovy
steps {
    archiveArtifacts artifacts: 'target/*.jar',
                     fingerprint: true,
                     allowEmptyArchive: false
}

stash/unstash #

暂存和恢复文件:

groovy
stage('Build') {
    steps {
        sh 'mvn clean package'
        stash includes: 'target/*.jar', name: 'artifacts'
    }
}

stage('Deploy') {
    agent { label 'production' }
    steps {
        unstash 'artifacts'
        sh 'kubectl apply -f k8s/'
    }
}

cleanWs #

清理工作空间:

groovy
steps {
    cleanWs()
    cleanWs cleanWhenSuccess: false, cleanWhenFailure: true
}

dir #

切换目录:

groovy
steps {
    dir('subdirectory') {
        sh 'ls -la'
    }
}

writeFile #

写入文件:

groovy
steps {
    writeFile file: 'config.json',
              text: '{"key": "value"}',
              encoding: 'UTF-8'
}

readFile #

读取文件:

groovy
steps {
    def content = readFile file: 'config.json'
    echo "Content: ${content}"
}

测试相关步骤 #

junit #

发布JUnit测试报告:

groovy
steps {
    junit '**/target/surefire-reports/*.xml'
    junit testResults: '**/target/surefire-reports/*.xml',
           allowEmptyResults: true,
           healthScaleFactor: 1.0
}

publishHTML #

发布HTML报告:

groovy
steps {
    publishHTML(target: [
        allowMissing: false,
        alwaysLinkToLastBuild: true,
        keepAll: true,
        reportDir: 'target/site',
        reportFiles: 'index.html',
        reportName: 'Site Report'
    ])
}

通知步骤 #

mail #

发送邮件:

groovy
steps {
    mail to: 'team@example.com',
         subject: "Build ${BUILD_NUMBER}",
         body: "Build completed: ${BUILD_URL}",
         from: 'jenkins@example.com',
         replyTo: 'no-reply@example.com'
}

emailext #

扩展邮件通知:

groovy
steps {
    emailext(
        subject: "Build ${BUILD_NUMBER}: ${currentBuild.result}",
        body: '''${SCRIPT, template="groovy-html.template"}''',
        to: 'team@example.com',
        attachmentsPattern: '**/target/*.jar'
    )
}

输入步骤 #

input #

等待用户输入:

groovy
stage('Deploy') {
    steps {
        input message: 'Deploy to production?',
               ok: 'Yes, deploy!',
               parameters: [
                   choice(name: 'ENVIRONMENT',
                          choices: ['prod', 'staging'],
                          description: 'Select environment')
               ],
               submitter: 'admin,deploy-team',
               submitterParameter: 'APPROVER'
    }
}

等待步骤 #

waitUntil #

等待条件满足:

groovy
steps {
    waitUntil {
        script {
            def r = sh script: 'curl -s http://localhost:8080/health', returnStatus: true
            return r == 0
        }
    }
}

sleep #

暂停执行:

groovy
steps {
    sleep time: 10, unit: 'SECONDS'
    sleep 30  // 默认秒
}

retry #

重试执行:

groovy
steps {
    retry(3) {
        sh 'deploy.sh'
    }
}

timeout #

超时控制:

groovy
steps {
    timeout(time: 5, unit: 'MINUTES') {
        sh 'long-running-task.sh'
    }
}

When条件 #

分支条件 #

groovy
when {
    branch 'main'
}
when {
    branch pattern: 'release/*', comparator: 'GLOB'
}

环境变量条件 #

groovy
when {
    environment name: 'ENVIRONMENT', value: 'prod'
}

表达式条件 #

groovy
when {
    expression {
        return params.DEPLOY == true
    }
}

组合条件 #

groovy
when {
    allOf {
        branch 'main'
        environment name: 'ENVIRONMENT', value: 'prod'
    }
}

when {
    anyOf {
        branch 'main'
        branch 'develop'
    }
}

when {
    not {
        branch 'main'
    }
}

beforeAgent #

在分配代理前评估条件:

groovy
stage('Deploy') {
    when {
        beforeAgent true
        branch 'main'
    }
    agent { label 'production' }
    steps {
        sh 'deploy.sh'
    }
}

beforeInput #

在用户输入前评估条件:

groovy
stage('Deploy') {
    when {
        beforeInput true
        branch 'main'
    }
    input {
        message "Deploy to production?"
    }
    steps {
        sh 'deploy.sh'
    }
}

完整示例 #

Java项目CI/CD #

groovy
pipeline {
    agent any
    
    tools {
        maven 'Maven 3.8'
        jdk 'JDK 11'
    }
    
    environment {
        APP_NAME = 'myapp'
        VERSION = "${BUILD_NUMBER}"
    }
    
    options {
        timeout(time: 30, unit: 'MINUTES')
        buildDiscarder(logRotator(numToKeepStr: '10'))
        timestamps()
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }
        
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'mvn test'
                    }
                    post {
                        always {
                            junit '**/target/surefire-reports/*.xml'
                        }
                    }
                }
                stage('Integration Tests') {
                    steps {
                        sh 'mvn verify -P integration'
                    }
                }
            }
        }
        
        stage('SonarQube') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                timeout(time: 5, unit: 'MINUTES') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
        
        stage('Build Image') {
            steps {
                sh "docker build -t ${APP_NAME}:${VERSION} ."
            }
        }
        
        stage('Push Image') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'docker-registry',
                    usernameVariable: 'DOCKER_USER',
                    passwordVariable: 'DOCKER_PASS'
                )]) {
                    sh "docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}"
                    sh "docker push ${APP_NAME}:${VERSION}"
                }
            }
        }
        
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                input message: 'Deploy to production?',
                       ok: 'Deploy'
                sh "kubectl set image deployment/${APP_NAME} ${APP_NAME}=${APP_NAME}:${VERSION}"
            }
        }
    }
    
    post {
        always {
            cleanWs()
        }
        success {
            mail to: 'team@example.com',
                 subject: "Success: ${JOB_NAME} #${BUILD_NUMBER}",
                 body: 'Build succeeded'
        }
        failure {
            mail to: 'team@example.com',
                 subject: "Failed: ${JOB_NAME} #${BUILD_NUMBER}",
                 body: 'Build failed'
        }
    }
}

下一步学习 #

小结 #

  • Declarative语法结构清晰,易于阅读
  • 支持丰富的指令和选项
  • when条件控制Stage执行
  • post块处理构建后操作
  • 推荐使用Declarative语法
最后更新:2026-03-28