8.1 Pipeline概述

什么是Pipeline

Pipeline定义:

Jenkins Pipeline是一套插件,支持在Jenkins中实现和集成持续交付管道。
Pipeline提供了一套可扩展的工具,用于将简单到复杂的交付管道建模为代码。

核心特性:
- 代码化:Pipeline以代码形式定义,可以版本控制
- 持久性:Pipeline可以在Jenkins重启后继续执行
- 可暂停:Pipeline可以暂停并等待人工输入或批准
- 多功能:支持复杂的现实世界CD需求
- 可扩展:支持自定义扩展的DSL和多个选项

Pipeline优势:

传统Job vs Pipeline:

传统Job:
- 通过UI配置
- 难以版本控制
- 复杂流程难以实现
- 重用性差
- 维护困难

Pipeline:
- 代码即配置(Infrastructure as Code)
- 版本控制友好
- 支持复杂的工作流
- 高度可重用
- 易于维护和调试
- 支持并行执行
- 内置错误处理

Pipeline类型:

声明式Pipeline(Declarative Pipeline):
- 更简单、更结构化的语法
- 更容易学习和使用
- 内置错误检查
- 推荐的Pipeline语法

脚本式Pipeline(Scripted Pipeline):
- 基于Groovy的DSL
- 更灵活、更强大
- 适合复杂的自定义逻辑
- 需要更多的编程知识

Pipeline架构

Pipeline执行模型:

Pipeline执行流程:

1. Pipeline定义
   ├── Jenkinsfile(推荐)
   ├── Pipeline脚本
   └── 共享库

2. Pipeline解析
   ├── 语法检查
   ├── 步骤验证
   └── 资源分配

3. Pipeline执行
   ├── 阶段执行
   ├── 步骤执行
   ├── 并行处理
   └── 错误处理

4. Pipeline监控
   ├── 执行状态
   ├── 日志输出
   ├── 性能指标
   └── 结果报告

Pipeline组件:

核心组件:

Pipeline:
- 整个CD流程的定义
- 包含所有阶段和步骤

Node:
- Pipeline执行的环境
- 可以是主节点或代理节点

Stage:
- Pipeline的逻辑分组
- 如构建、测试、部署

Step:
- 单个任务或命令
- Pipeline的最小执行单元

Agent:
- 执行Pipeline的节点
- 可以指定特定的代理

Workspace:
- Pipeline的工作目录
- 存储源码和构建产物

8.2 声明式Pipeline

基本语法

Pipeline结构:

// 声明式Pipeline基本结构
pipeline {
    // 指定执行代理
    agent any
    
    // 定义环境变量
    environment {
        // 全局环境变量
    }
    
    // 定义工具
    tools {
        // 构建工具配置
    }
    
    // 定义参数
    parameters {
        // 构建参数
    }
    
    // 定义触发器
    triggers {
        // 构建触发器
    }
    
    // 定义选项
    options {
        // Pipeline选项
    }
    
    // 定义阶段
    stages {
        stage('阶段名称') {
            // 阶段配置
            steps {
                // 执行步骤
            }
        }
    }
    
    // 后置操作
    post {
        // 清理和通知
    }
}

简单示例:

// 简单的声明式Pipeline示例
pipeline {
    agent any
    
    stages {
        stage('Checkout') {
            steps {
                echo '检出源码...'
                git branch: 'main', url: 'https://github.com/company/myapp.git'
            }
        }
        
        stage('Build') {
            steps {
                echo '构建应用...'
                sh 'mvn clean compile'
            }
        }
        
        stage('Test') {
            steps {
                echo '运行测试...'
                sh 'mvn test'
            }
        }
        
        stage('Package') {
            steps {
                echo '打包应用...'
                sh 'mvn package'
            }
        }
    }
    
    post {
        always {
            echo 'Pipeline执行完成'
        }
        success {
            echo 'Pipeline执行成功'
        }
        failure {
            echo 'Pipeline执行失败'
        }
    }
}

Agent配置

Agent类型:

// 1. 任意可用代理
pipeline {
    agent any
    // ...
}

// 2. 无代理(手动指定)
pipeline {
    agent none
    stages {
        stage('Build') {
            agent any
            steps {
                // 步骤
            }
        }
    }
}

// 3. 指定标签
pipeline {
    agent {
        label 'linux && docker'
    }
    // ...
}

// 4. Docker代理
pipeline {
    agent {
        docker {
            image 'maven:3.8.1-jdk-11'
            args '-v /tmp:/tmp'
        }
    }
    // ...
}

// 5. Dockerfile代理
pipeline {
    agent {
        dockerfile {
            filename 'Dockerfile.build'
            dir 'docker'
            additionalBuildArgs '--build-arg version=1.0'
        }
    }
    // ...
}

// 6. Kubernetes代理
pipeline {
    agent {
        kubernetes {
            yaml """
                apiVersion: v1
                kind: Pod
                spec:
                  containers:
                  - name: maven
                    image: maven:3.8.1-jdk-11
                    command:
                    - cat
                    tty: true
                  - name: docker
                    image: docker:latest
                    command:
                    - cat
                    tty: true
                    volumeMounts:
                    - mountPath: /var/run/docker.sock
                      name: docker-sock
                  volumes:
                  - name: docker-sock
                    hostPath:
                      path: /var/run/docker.sock
            """
        }
    }
    // ...
}

阶段级Agent:

pipeline {
    agent none
    
    stages {
        stage('Build') {
            agent {
                docker 'maven:3.8.1-jdk-11'
            }
            steps {
                sh 'mvn clean compile'
            }
        }
        
        stage('Test') {
            agent {
                docker 'maven:3.8.1-jdk-11'
            }
            steps {
                sh 'mvn test'
            }
        }
        
        stage('Docker Build') {
            agent {
                label 'docker'
            }
            steps {
                script {
                    docker.build('myapp:latest')
                }
            }
        }
    }
}

环境变量

环境变量定义:

pipeline {
    agent any
    
    environment {
        // 全局环境变量
        APP_NAME = 'myapp'
        APP_VERSION = '1.0.0'
        DOCKER_REGISTRY = 'registry.company.com'
        
        // 使用凭据
        DOCKER_CREDENTIALS = credentials('docker-registry-credentials')
        DATABASE_URL = credentials('database-url')
        
        // 动态环境变量
        BUILD_TIMESTAMP = sh(
            script: 'date +"%Y%m%d%H%M%S"',
            returnStdout: true
        ).trim()
        
        // 条件环境变量
        DEPLOY_ENV = "${env.BRANCH_NAME == 'main' ? 'production' : 'staging'}"
    }
    
    stages {
        stage('Build') {
            environment {
                // 阶段级环境变量
                MAVEN_OPTS = '-Xmx1024m'
                JAVA_HOME = '/usr/lib/jvm/java-11-openjdk'
            }
            steps {
                echo "构建应用: ${APP_NAME} v${APP_VERSION}"
                echo "构建时间: ${BUILD_TIMESTAMP}"
                echo "部署环境: ${DEPLOY_ENV}"
                
                sh 'mvn clean compile'
            }
        }
        
        stage('Docker Build') {
            steps {
                script {
                    // 使用环境变量
                    def imageName = "${DOCKER_REGISTRY}/${APP_NAME}:${APP_VERSION}-${BUILD_TIMESTAMP}"
                    
                    docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') {
                        def image = docker.build(imageName)
                        image.push()
                        image.push('latest')
                    }
                }
            }
        }
    }
}

环境变量使用:

pipeline {
    agent any
    
    environment {
        // 定义环境变量
        SERVICE_NAME = 'user-service'
        SERVICE_PORT = '8080'
    }
    
    stages {
        stage('Environment Info') {
            steps {
                // 在shell中使用
                sh 'echo "Service: $SERVICE_NAME on port $SERVICE_PORT"'
                
                // 在Groovy中使用
                echo "Service: ${env.SERVICE_NAME} on port ${env.SERVICE_PORT}"
                
                // 使用内置环境变量
                echo "Job: ${env.JOB_NAME}"
                echo "Build: ${env.BUILD_NUMBER}"
                echo "Workspace: ${env.WORKSPACE}"
                echo "Node: ${env.NODE_NAME}"
                echo "Branch: ${env.BRANCH_NAME}"
                
                // 设置动态环境变量
                script {
                    env.DYNAMIC_VAR = "value-${env.BUILD_NUMBER}"
                }
                
                echo "Dynamic: ${env.DYNAMIC_VAR}"
            }
        }
    }
}

工具配置

工具定义:

pipeline {
    agent any
    
    tools {
        // Maven工具
        maven 'Maven-3.8.1'
        
        // JDK工具
        jdk 'JDK-11'
        
        // Gradle工具
        gradle 'Gradle-7.0'
        
        // Node.js工具
        nodejs 'NodeJS-16'
        
        // Git工具
        git 'Git-2.30'
    }
    
    stages {
        stage('Build Info') {
            steps {
                // 工具会自动添加到PATH
                sh 'java -version'
                sh 'mvn -version'
                sh 'gradle -version'
                sh 'node -version'
                sh 'npm -version'
                sh 'git --version'
            }
        }
        
        stage('Maven Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        
        stage('Gradle Build') {
            steps {
                sh 'gradle clean build'
            }
        }
        
        stage('Node.js Build') {
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }
    }
}

阶段级工具:

pipeline {
    agent any
    
    stages {
        stage('Java Build') {
            tools {
                jdk 'JDK-11'
                maven 'Maven-3.8.1'
            }
            steps {
                sh 'java -version'
                sh 'mvn clean compile'
            }
        }
        
        stage('Node.js Build') {
            tools {
                nodejs 'NodeJS-16'
            }
            steps {
                sh 'node -version'
                sh 'npm install'
                sh 'npm run build'
            }
        }
        
        stage('Python Build') {
            agent {
                docker 'python:3.9'
            }
            steps {
                sh 'python --version'
                sh 'pip install -r requirements.txt'
                sh 'python -m pytest'
            }
        }
    }
}

参数化构建

参数类型:

pipeline {
    agent any
    
    parameters {
        // 字符串参数
        string(
            name: 'BRANCH_NAME',
            defaultValue: 'main',
            description: '要构建的分支名称'
        )
        
        // 选择参数
        choice(
            name: 'DEPLOY_ENV',
            choices: ['dev', 'staging', 'production'],
            description: '部署环境'
        )
        
        // 布尔参数
        booleanParam(
            name: 'SKIP_TESTS',
            defaultValue: false,
            description: '是否跳过测试'
        )
        
        // 文本参数
        text(
            name: 'RELEASE_NOTES',
            defaultValue: '',
            description: '发布说明'
        )
        
        // 密码参数
        password(
            name: 'API_KEY',
            defaultValue: '',
            description: 'API密钥'
        )
        
        // 文件参数
        file(
            name: 'CONFIG_FILE',
            description: '配置文件'
        )
    }
    
    stages {
        stage('Parameter Info') {
            steps {
                echo "分支: ${params.BRANCH_NAME}"
                echo "环境: ${params.DEPLOY_ENV}"
                echo "跳过测试: ${params.SKIP_TESTS}"
                echo "发布说明: ${params.RELEASE_NOTES}"
                
                script {
                    if (params.CONFIG_FILE) {
                        echo "配置文件已上传"
                    }
                }
            }
        }
        
        stage('Checkout') {
            steps {
                git branch: "${params.BRANCH_NAME}", 
                    url: 'https://github.com/company/myapp.git'
            }
        }
        
        stage('Test') {
            when {
                not { params.SKIP_TESTS }
            }
            steps {
                echo '运行测试...'
                sh 'mvn test'
            }
        }
        
        stage('Deploy') {
            steps {
                script {
                    switch(params.DEPLOY_ENV) {
                        case 'dev':
                            echo '部署到开发环境'
                            break
                        case 'staging':
                            echo '部署到测试环境'
                            break
                        case 'production':
                            echo '部署到生产环境'
                            break
                    }
                }
            }
        }
    }
}

动态参数:

pipeline {
    agent any
    
    parameters {
        // 动态选择参数
        activeChoice(
            name: 'PROJECT',
            description: '选择项目',
            choiceType: 'SINGLE_SELECT',
            script: [
                $class: 'GroovyScript',
                script: [
                    classpath: [],
                    sandbox: false,
                    script: '''
                        def projects = []
                        def jenkins = Jenkins.instance
                        jenkins.getAllItems(Job.class).each { job ->
                            if (job.name.startsWith('project-')) {
                                projects.add(job.name)
                            }
                        }
                        return projects.sort()
                    '''
                ]
            ]
        )
        
        // 级联参数
        cascadeChoiceParameter(
            name: 'ENVIRONMENT',
            description: '选择环境',
            referencedParameters: 'PROJECT',
            choiceType: 'SINGLE_SELECT',
            script: [
                $class: 'GroovyScript',
                script: [
                    classpath: [],
                    sandbox: false,
                    script: '''
                        if (PROJECT.startsWith('project-web')) {
                            return ['dev', 'staging', 'production']
                        } else if (PROJECT.startsWith('project-api')) {
                            return ['dev', 'test', 'prod']
                        } else {
                            return ['development']
                        }
                    '''
                ]
            ]
        )
    }
    
    stages {
        stage('Deploy') {
            steps {
                echo "部署项目 ${params.PROJECT} 到环境 ${params.ENVIRONMENT}"
            }
        }
    }
}

触发器

触发器类型:

pipeline {
    agent any
    
    triggers {
        // 定时触发(Cron表达式)
        cron('H 2 * * *')  // 每天凌晨2点左右
        
        // SCM轮询
        pollSCM('H/5 * * * *')  // 每5分钟检查一次SCM变化
        
        // 上游项目触发
        upstream(
            upstreamProjects: 'upstream-project',
            threshold: hudson.model.Result.SUCCESS
        )
        
        // GitHub webhook触发
        githubPush()
        
        // GitLab webhook触发
        gitlab(
            triggerOnPush: true,
            triggerOnMergeRequest: true,
            branchFilterType: 'All'
        )
    }
    
    stages {
        stage('Triggered Build') {
            steps {
                echo "构建触发原因: ${currentBuild.getBuildCauses()}"
                echo "构建时间: ${new Date()}"
            }
        }
    }
}

条件触发:

pipeline {
    agent any
    
    triggers {
        // 仅在工作日触发
        cron(env.BRANCH_NAME == 'main' ? 'H 2 * * 1-5' : '')
        
        // 根据分支设置不同的轮询频率
        pollSCM(env.BRANCH_NAME == 'main' ? 'H/5 * * * *' : 'H/15 * * * *')
    }
    
    stages {
        stage('Build') {
            when {
                anyOf {
                    branch 'main'
                    branch 'develop'
                    changeRequest()
                }
            }
            steps {
                echo '执行构建...'
            }
        }
    }
}

选项配置

Pipeline选项:

pipeline {
    agent any
    
    options {
        // 构建保留策略
        buildDiscarder(logRotator(
            numToKeepStr: '10',
            daysToKeepStr: '30',
            artifactNumToKeepStr: '5',
            artifactDaysToKeepStr: '14'
        ))
        
        // 禁用并发构建
        disableConcurrentBuilds()
        
        // 构建超时
        timeout(time: 1, unit: 'HOURS')
        
        // 重试次数
        retry(3)
        
        // 跳过默认检出
        skipDefaultCheckout()
        
        // 保留构建日志
        preserveStashes(buildCount: 5)
        
        // 时间戳
        timestamps()
        
        // ANSI颜色输出
        ansiColor('xterm')
        
        // 检出到子目录
        checkoutToSubdirectory('src')
        
        // 新构建中止旧构建
        disableResume()
        
        // 静默期
        quietPeriod(5)
    }
    
    stages {
        stage('Build with Options') {
            options {
                // 阶段级超时
                timeout(time: 30, unit: 'MINUTES')
                
                // 阶段级重试
                retry(2)
            }
            steps {
                echo '带选项的构建阶段'
                sh 'sleep 10'  // 模拟耗时操作
            }
        }
    }
}

高级选项:

pipeline {
    agent any
    
    options {
        // 自定义工作空间
        ws("/custom/workspace/${env.JOB_NAME}/${env.BUILD_NUMBER}")
        
        // 锁定资源
        lock(resource: 'shared-database', quantity: 1)
        
        // 节流构建
        throttle(['category1', 'category2'])
        
        // 构建名称
        buildName("#${BUILD_NUMBER}-${BRANCH_NAME}")
        
        // 构建描述
        buildDescription("Build for ${BRANCH_NAME} branch")
        
        // 跳过阶段
        skipStagesAfterUnstable()
        
        // 并行阶段失败快速失败
        parallelsAlwaysFailFast()
    }
    
    stages {
        stage('Advanced Options Demo') {
            steps {
                echo "当前工作空间: ${env.WORKSPACE}"
                echo "构建名称: ${currentBuild.displayName}"
                echo "构建描述: ${currentBuild.description}"
            }
        }
    }
}

8.3 脚本式Pipeline

基本语法

脚本式Pipeline结构:

// 脚本式Pipeline基本结构
node {
    try {
        // 阶段1
        stage('Checkout') {
            // 检出代码
        }
        
        // 阶段2
        stage('Build') {
            // 构建代码
        }
        
        // 阶段3
        stage('Test') {
            // 运行测试
        }
        
        // 阶段4
        stage('Deploy') {
            // 部署应用
        }
        
    } catch (Exception e) {
        // 错误处理
        currentBuild.result = 'FAILURE'
        throw e
    } finally {
        // 清理工作
    }
}

简单示例:

// 简单的脚本式Pipeline示例
node {
    def mvnHome
    
    stage('Preparation') {
        // 获取Maven工具
        mvnHome = tool 'Maven-3.8.1'
        
        // 检出代码
        git 'https://github.com/company/myapp.git'
    }
    
    stage('Build') {
        // 设置Maven环境
        withEnv(["MVN_HOME=$mvnHome"]) {
            if (isUnix()) {
                sh '"$MVN_HOME/bin/mvn" -Dmaven.test.failure.ignore clean compile'
            } else {
                bat(/"$MVN_HOME\bin\mvn" -Dmaven.test.failure.ignore clean compile/)
            }
        }
    }
    
    stage('Test') {
        withEnv(["MVN_HOME=$mvnHome"]) {
            if (isUnix()) {
                sh '"$MVN_HOME/bin/mvn" test'
            } else {
                bat(/"$MVN_HOME\bin\mvn" test/)
            }
        }
        
        // 发布测试结果
        junit '**/target/surefire-reports/TEST-*.xml'
    }
    
    stage('Package') {
        withEnv(["MVN_HOME=$mvnHome"]) {
            if (isUnix()) {
                sh '"$MVN_HOME/bin/mvn" package'
            } else {
                bat(/"$MVN_HOME\bin\mvn" package/)
            }
        }
        
        // 归档构建产物
        archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
    }
}

节点和工作空间

节点选择:

// 1. 任意节点
node {
    echo "运行在节点: ${env.NODE_NAME}"
}

// 2. 指定标签
node('linux') {
    echo "运行在Linux节点"
}

// 3. 多个标签
node('linux && docker') {
    echo "运行在支持Docker的Linux节点"
}

// 4. 排除标签
node('!windows') {
    echo "运行在非Windows节点"
}

// 5. 动态节点选择
def nodeLabel = env.BRANCH_NAME == 'main' ? 'production' : 'development'
node(nodeLabel) {
    echo "运行在 ${nodeLabel} 节点"
}

工作空间管理:

node {
    // 当前工作空间
    echo "工作空间: ${env.WORKSPACE}"
    
    // 自定义工作空间
    ws("/custom/workspace/${env.JOB_NAME}") {
        echo "自定义工作空间: ${pwd()}"
        
        // 在自定义工作空间中工作
        git 'https://github.com/company/myapp.git'
        sh 'ls -la'
    }
    
    // 返回原工作空间
    echo "回到原工作空间: ${pwd()}"
}

// 多个工作空间
node {
    // 主工作空间
    stage('Main Workspace') {
        git 'https://github.com/company/main-app.git'
        sh 'mvn clean compile'
    }
    
    // 临时工作空间
    ws('temp-workspace') {
        stage('Temp Workspace') {
            git 'https://github.com/company/config-repo.git'
            sh 'cp config.properties ${WORKSPACE}/src/main/resources/'
        }
    }
    
    // 继续在主工作空间
    stage('Continue Main') {
        sh 'mvn package'
    }
}

流程控制

条件语句:

node {
    def branchName = env.BRANCH_NAME
    def buildNumber = env.BUILD_NUMBER.toInteger()
    
    stage('Conditional Logic') {
        // if-else语句
        if (branchName == 'main') {
            echo '主分支构建'
            sh 'mvn clean package'
        } else if (branchName.startsWith('feature/')) {
            echo '功能分支构建'
            sh 'mvn clean compile'
        } else {
            echo '其他分支构建'
            sh 'mvn clean test'
        }
        
        // switch语句
        switch (branchName) {
            case 'main':
                echo '生产环境部署'
                break
            case 'develop':
                echo '开发环境部署'
                break
            case ~/^release\/.*$/:
                echo '预发布环境部署'
                break
            default:
                echo '跳过部署'
        }
        
        // 三元运算符
        def deployEnv = (branchName == 'main') ? 'production' : 'staging'
        echo "部署环境: ${deployEnv}"
        
        // 条件执行
        if (buildNumber % 10 == 0) {
            echo '每10次构建执行特殊操作'
            sh 'mvn clean'
        }
    }
}

循环语句:

node {
    stage('Loops') {
        // for循环
        for (int i = 1; i <= 3; i++) {
            echo "循环 ${i}"
            sh "echo 'Step ${i}'"
        }
        
        // for-each循环
        def environments = ['dev', 'staging', 'production']
        for (env in environments) {
            echo "处理环境: ${env}"
        }
        
        // while循环
        def counter = 0
        while (counter < 3) {
            echo "计数器: ${counter}"
            counter++
        }
        
        // 遍历文件
        def files = sh(
            script: 'find . -name "*.java" | head -5',
            returnStdout: true
        ).trim().split('\n')
        
        for (file in files) {
            echo "处理文件: ${file}"
        }
    }
}

异常处理:

node {
    try {
        stage('Risky Operation') {
            echo '执行可能失败的操作'
            
            // 模拟可能失败的操作
            def result = sh(
                script: 'exit 1',  // 故意失败
                returnStatus: true
            )
            
            if (result != 0) {
                throw new Exception('操作失败')
            }
        }
        
    } catch (Exception e) {
        echo "捕获异常: ${e.getMessage()}"
        
        // 设置构建状态
        currentBuild.result = 'FAILURE'
        
        // 发送通知
        emailext (
            subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
            body: "构建失败,错误信息: ${e.getMessage()}",
            to: 'team@company.com'
        )
        
        // 重新抛出异常
        throw e
        
    } finally {
        echo '清理工作'
        
        // 清理临时文件
        sh 'rm -f temp_*'
        
        // 发布测试结果(即使失败也要发布)
        publishTestResults testResultsPattern: '**/target/surefire-reports/*.xml'
    }
}

函数和变量

变量定义:

node {
    // 局部变量
    def appName = 'myapp'
    def version = '1.0.0'
    def buildTime = new Date().format('yyyyMMdd-HHmmss')
    
    // 全局变量(在node外定义)
    env.GLOBAL_VAR = 'global_value'
    
    // 动态变量
    def gitCommit = sh(
        script: 'git rev-parse HEAD',
        returnStdout: true
    ).trim()
    
    def gitBranch = sh(
        script: 'git rev-parse --abbrev-ref HEAD',
        returnStdout: true
    ).trim()
    
    stage('Variable Usage') {
        echo "应用名称: ${appName}"
        echo "版本: ${version}"
        echo "构建时间: ${buildTime}"
        echo "Git提交: ${gitCommit}"
        echo "Git分支: ${gitBranch}"
        echo "全局变量: ${env.GLOBAL_VAR}"
    }
    
    // 条件变量
    def deployTarget = (gitBranch == 'main') ? 'production' : 'staging'
    echo "部署目标: ${deployTarget}"
    
    // 集合变量
    def servers = ['server1', 'server2', 'server3']
    def config = [
        database: 'mysql',
        cache: 'redis',
        queue: 'rabbitmq'
    ]
    
    echo "服务器列表: ${servers.join(', ')}"
    echo "数据库: ${config.database}"
}

函数定义:

// 在node外定义函数
def buildApplication(appName, version) {
    echo "构建应用: ${appName} v${version}"
    sh "mvn clean package -Dapp.name=${appName} -Dapp.version=${version}"
}

def deployToEnvironment(environment, artifact) {
    echo "部署 ${artifact} 到 ${environment} 环境"
    
    switch (environment) {
        case 'development':
            sh "scp ${artifact} dev-server:/opt/apps/"
            break
        case 'staging':
            sh "scp ${artifact} staging-server:/opt/apps/"
            break
        case 'production':
            sh "scp ${artifact} prod-server:/opt/apps/"
            break
        default:
            error "未知环境: ${environment}"
    }
}

def runTests(testType) {
    switch (testType) {
        case 'unit':
            sh 'mvn test'
            break
        case 'integration':
            sh 'mvn verify -P integration-tests'
            break
        case 'e2e':
            sh 'mvn verify -P e2e-tests'
            break
        default:
            error "未知测试类型: ${testType}"
    }
}

def sendNotification(status, message) {
    def color = (status == 'SUCCESS') ? 'good' : 'danger'
    
    slackSend(
        channel: '#ci-cd',
        color: color,
        message: "${status}: ${message}"
    )
}

// 使用函数
node {
    def appName = 'myapp'
    def version = '1.0.0'
    def artifact = "target/${appName}-${version}.jar"
    
    try {
        stage('Build') {
            buildApplication(appName, version)
        }
        
        stage('Test') {
            runTests('unit')
            runTests('integration')
        }
        
        stage('Deploy') {
            def environment = (env.BRANCH_NAME == 'main') ? 'production' : 'staging'
            deployToEnvironment(environment, artifact)
        }
        
        // 成功通知
        sendNotification('SUCCESS', "${appName} v${version} 构建部署成功")
        
    } catch (Exception e) {
        // 失败通知
        sendNotification('FAILURE', "${appName} v${version} 构建失败: ${e.getMessage()}")
        throw e
    }
}

高级函数:

// 返回值函数
def getGitInfo() {
    def gitInfo = [:]
    
    gitInfo.commit = sh(
        script: 'git rev-parse HEAD',
        returnStdout: true
    ).trim()
    
    gitInfo.branch = sh(
        script: 'git rev-parse --abbrev-ref HEAD',
        returnStdout: true
    ).trim()
    
    gitInfo.author = sh(
        script: 'git log -1 --pretty=format:"%an"',
        returnStdout: true
    ).trim()
    
    gitInfo.message = sh(
        script: 'git log -1 --pretty=format:"%s"',
        returnStdout: true
    ).trim()
    
    return gitInfo
}

// 闭包函数
def withDockerContainer(imageName, closure) {
    def containerId = sh(
        script: "docker run -d ${imageName} sleep 3600",
        returnStdout: true
    ).trim()
    
    try {
        closure(containerId)
    } finally {
        sh "docker stop ${containerId}"
        sh "docker rm ${containerId}"
    }
}

// 并行执行函数
def runParallelTasks(tasks) {
    def parallelTasks = [:]
    
    tasks.each { taskName, taskClosure ->
        parallelTasks[taskName] = {
            node {
                taskClosure()
            }
        }
    }
    
    parallel parallelTasks
}

// 使用高级函数
node {
    stage('Git Info') {
        def gitInfo = getGitInfo()
        echo "提交: ${gitInfo.commit}"
        echo "分支: ${gitInfo.branch}"
        echo "作者: ${gitInfo.author}"
        echo "消息: ${gitInfo.message}"
    }
    
    stage('Docker Test') {
        withDockerContainer('maven:3.8.1-jdk-11') { containerId ->
            sh "docker exec ${containerId} mvn --version"
        }
    }
    
    stage('Parallel Tasks') {
        def tasks = [
            'Unit Tests': {
                sh 'mvn test'
            },
            'Code Quality': {
                sh 'mvn sonar:sonar'
            },
            'Security Scan': {
                sh 'mvn dependency-check:check'
            }
        ]
        
        runParallelTasks(tasks)
    }
}

本章小结

本章详细介绍了Jenkins Pipeline的基础知识,包括:

  1. Pipeline概述:了解Pipeline的概念、优势和架构
  2. 声明式Pipeline:学习声明式Pipeline的语法和各种配置
  3. 脚本式Pipeline:掌握脚本式Pipeline的编写和高级用法

Pipeline是Jenkins的核心功能,它将持续集成和持续部署流程代码化,提供了强大的自动化能力。

下一章预告

下一章我们将深入学习Pipeline的高级特性,包括并行执行、条件执行、共享库等内容。

练习与思考

理论练习

  1. Pipeline类型比较

    • 比较声明式和脚本式Pipeline的优缺点
    • 分析不同场景下的适用性
    • 设计Pipeline选择策略
  2. Pipeline设计

    • 为一个Web应用设计完整的CI/CD Pipeline
    • 考虑不同环境的部署策略
    • 设计错误处理和回滚机制

实践练习

  1. 声明式Pipeline实践

    • 创建一个包含构建、测试、部署的声明式Pipeline
    • 配置参数化构建和环境变量
    • 实现条件执行和错误处理
  2. 脚本式Pipeline实践

    • 将声明式Pipeline转换为脚本式Pipeline
    • 添加自定义函数和复杂逻辑
    • 实现动态Pipeline生成

思考题

  1. Pipeline最佳实践

    • 如何设计可维护的Pipeline?
    • 如何平衡Pipeline的复杂性和可读性?
    • 如何实现Pipeline的重用和标准化?
  2. 性能优化

    • 如何优化Pipeline的执行时间?
    • 如何减少资源消耗?
    • 如何实现Pipeline的并行化?