云原生

二十 持续集成/持续部署入门

2022-06-12  本文已影响0人  負笈在线

持续集成:帮助开发人员更加频繁的将代码合并到共享分支或主干中,合并之后会自动触发 构建应用,运行不同级别的代码扫描(sonarqube)和自动化测试(单元和集成测试)。
持续交付:将通过集成测试的代码合并到一个可以随时部署到生产环境的代码库。
持续部署:持续交付的延伸,就是将代码自动发布到生产环境中。 k8s中一个正常的流水线设计图如下:


一般的步骤如下:
  1. 在 GitLab 中创建对应的项目;
  2. 配置 Jenkins 集成 Kubernetes 集群,后期 Jenkins 的 Slave 将为在 Kubernetes 中动态创 建的 Slave;
  3. Jenkins 创建对应的任务(Job),集成该项目的 Git 地址和 Kubernetes 集群;
  4. 开发者将代码提交到 GitLab;
  5. 如有配置钩子,推送(Push)代码会自动触发 Jenkins 构建,如没有配置钩子,需要手 动构建;
  6. Jenkins 控制 Kubernetes(使用的是 Kubernetes 插件)创建 Jenkins Slave(Pod 形式); 7) Jenkins Slave 根据流水线(Pipeline)定义的步骤执行构建;
  7. 通过 Dockerfile 生成镜像;
  8. 将镜像提送(Push)到私有 Harbor(或者其它的镜像仓库);
  9. Jenkins 再次控制 Kubernetes 进行最新的镜像部署;
  10. 流水线结束删除 Jenkins Slave。

(一) 什么是流水线

1.声明式流水线

在声明式流水线语法中,流水线过程定义在Pipeline{}中,Pipeline块定义了整个流水线中完成的所有工作,比如:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any 
    stages {
        stage('Build') { 
            steps {
                // 
            }
        }
        stage('Test') { 
            steps {
                // 
            }
        }
        stage('Deploy') { 
            steps {
                // 
            }
        }
    }
}

参数说明:
Ø agent any:在任何可用的代理上执行流水线或它的任何阶段,也就是执行流水线过程的位置,也可以指定到具体的节点;
Ø stage:定义流水线的执行过程(相当于一个阶段),比如上文所示的Build、Test、Deploy,但是这个名字是根据实际情况进行定义的,并非固定的名字;
Ø steps:执行某阶段具体的步骤。

一个以声明式流水线的语法编写的Jenkinsfile文件如下:

Jenkinsfile (Declarative Pipeline)
pipeline { 
    agent any 
    stages {
        stage('Build') { 
            steps { 
                sh 'make' 
            }
        }
        stage('Test'){
            steps {
                sh 'make check'
                junit 'reports/**/*.xml' 
            }
        }
        stage('Deploy') {
            steps {
                sh 'make publish'
            }
        }
    }
}

常用参数说明:
Ø pipeline:声明式流水线的一种特定语法,定义了包含执行整个流水线的所有内容和指令,也是声明式流水线的开始;
Ø agent:声明式流水线的一种特定语法,指示Jenkins为整个流水线分配一个执行器和工作区,也就是在流水线中的步骤在哪个Agent上执行,该参数同样可以在stage中配置;
Ø stage:描述流水线阶段的语法块,在脚本式流水线语法中,stage(阶段)块是可选的;
Ø steps:声明式流水线的一种特定语法,它描述了在这个stage中要运行的步骤;
Ø sh:执行一个shell命令;
Ø junit:用于聚合测试报告。

2.脚本化流水线

在脚本化流水线语法中,会有一个或多个Node(节点)块在整个流水线中执行核心工作,比如:

Jenkinsfile (Scripted Pipeline)
node {  
    stage('Build') { 
        // 
    }
    stage('Test') { 
        // 
    }
    stage('Deploy') { 
        // 
    }
}

参数说明:
Ø node:在任何可用的代理上执行流水线或它的任何阶段,也可以指定到具体的节点;
Ø stage:和声明式的含义一致,定义流水线的阶段。Stage块在脚本化流水线语法中是可选的,然而在脚本化流水线中实现stage块,可以清楚地在Jenkins UI界面中显示每个stage的任务子集。
上一小节的声明式流水线也可以用以下脚本式流水线替代:

Jenkinsfile (Scripted Pipeline)
node { 
    stage('Build') { 
        sh 'make' 
    }
    stage('Test') {
        sh 'make check'
        junit 'reports/**/*.xml' 
    }
    stage('Deploy') {
        sh 'make publish'
    }
}

(二) 声明式Pipeline语法

声明式流水线必须包含在一个Pipeline块中,比如以下是一个Pipeline块的格式:

pipeline {
 /* insert Declarative Pipeline here */
}

在声明式流水线中有效的基本语句和表达式遵循与Groovy的语法同样的规则,但有以下例外:
Ø 流水线顶层必须是一个block,即pipeline{};
Ø 分隔符可以不需要分号,但是每条语句都必须在自己的行上;
Ø 块只能由Sections、Directives、Steps或assignment statements组成;
Ø 属性引用语句被当做是无参数的方法调用,比如input会被当做input()。

1.Sections

声明式流水线中的Sections不是一个关键字或指令,而是包含一个或多个Agent、Stages、post、Directives和Steps的代码区域块。
Agent
Agent表示整个流水线或特定阶段中的步骤和命令执行的位置,该部分必须在pipeline块的顶层被定义,也可以在stage中再次定义,但是stage级别是可选的。
Ø any:在任何可用的代理上执行流水线,配置语法:

pipeline {
 agent any
}

Ø none:表示该Pipeline脚本没有全局的agent配置。当顶层的agent配置为none时,每个stage部分都需要包含它自己的agent。配置语法:

pipeline {
 agent none
 stages {
 stage('Stage For Build'){
 agent any
 }
 }
} 

Ø label:选择某个具体的节点执行Pipeline命令,例如:agent { label 'my-defined-label' }。配置语法:

pipeline {
 agent none
 stages {
 stage('Stage For Build'){
 agent { label 'my-slave-label' }
 }
 }
}

Ø node:和label配置类似,只不过是可以添加一些额外的配置,比如customWorkspace;
Ø dockerfile:使用从源码中包含的Dockerfile所构建的容器执行流水线或stage。此时对应的agent写法如下:

agent {
 dockerfile {
 filename 'Dockerfile.build'
 dir 'build'
 label 'my-defined-label'
 additionalBuildArgs '--build-arg version=1.0.2'
 }
}

Ø docker:相当于dockerfile,可以直接使用docker字段指定外部镜像即可,可以省去构建的时间。比如使用maven镜像进行打包,同时可以指定args:

agent{
 docker{
 image 'maven:3-alpine'
 label 'my-defined-label'
 args '-v /tmp:/tmp'
 }
}

Ø kubernetes:Jenkins也支持使用Kubernetes创建Slave,也就是常说的动态Slave。配置示例如下:

agent {
    kubernetes {
        label podlabel
        yaml """
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:debug
    imagePullPolicy: Always
    command:
    - /busybox/cat
    tty: true
    volumeMounts:
      - name: aws-secret
        mountPath: /root/.aws/
      - name: docker-registry-config
        mountPath: /kaniko/.docker
  restartPolicy: Never
  volumes:
    - name: aws-secret
      secret:
        secretName: aws-secret
    - name: docker-registry-config
      configMap:
        name: docker-registry-config
"""
   }

配置示例
示例1:假设有一个Java项目,需要用mvn命令进行编译,此时可以使用maven的镜像作为agent。配置如下:

Jenkinsfile (Declarative Pipeline) // 可以不要此行
pipeline {
 agent { docker 'maven:3-alpine' }
 stages {
 stage('Example Build') {
 steps {
 sh 'mvn -B clean verify'
 }
 }
 }
}

示例2:本示例在流水线顶层将agent定义为none,那么此时stage部分就需要必须包含它自己的agent部分。在stage('Example Build')部分使用maven:3-alpine执行该阶段步骤,在stage('Example Test')部分使用openjdk:8-jre执行该阶段步骤。此时Pipeline如下:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent none 
    stages {
        stage('Example Build') {
            agent { docker 'maven:3-alpine' } 
            steps {
                echo 'Hello, Maven'
                sh 'mvn --version'
            }
        }
        stage('Example Test') {
            agent { docker 'openjdk:8-jre' } 
            steps {
                echo 'Hello, JDK'
                sh 'java -version'
            }
        }
    }
}

示例3:上述的示例也可以用基于Kubernetes的agent实现。比如定义具有三个容器的Pod,分别为jnlp(负责和Jenkins Master通信)、build(负责执行构建命令)、kubectl(负责执行Kubernetes相关命令),在steps中可以通过containers字段,选择在某个容器执行命令:

pipeline {
  agent {
    kubernetes {
      cloud 'kubernetes-default'
      slaveConnectTimeout 1200
      yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
    - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
      image: 'registry.cn-beijing.aliyuncs.com/citools/jnlp:alpine'
      name: jnlp
      imagePullPolicy: IfNotPresent      
    - command:
        - "cat"
      image: "registry.cn-beijing.aliyuncs.com/citools/maven:3.5.3"
      imagePullPolicy: "IfNotPresent"
      name: "build"
      tty: true
    - command:
        - "cat"
      image: "registry.cn-beijing.aliyuncs.com/citools/kubectl:self-1.17"
      imagePullPolicy: "IfNotPresent"
      name: "kubectl"
      tty: true
''' 
}
}

  stages {
    stage('Building') {
      steps {
        container(name: 'build') {
        sh """
          mvm clean install
         """
        }

      }
    }
    stage('Deploy') {
      steps {
      container(name: 'kubectl') {
        sh """
            kubectl get node
        """
        }

      }
    }

  }
}

Post
Post一般用于流水线结束后的进一步处理,比如错误通知等。Post可以针对流水线不同的结果做出不同的处理,就像开发程序的错误处理,比如Python语言的try catch。Post可以定义在Pipeline或stage中,目前支持以下条件:
Ø always:无论Pipeline或stage的完成状态如何,都允许运行该post中定义的指令;
Ø changed:只有当前Pipeline或stage的完成状态与它之前的运行不同时,才允许在该post部分运行该步骤;
Ø fixed:当本次Pipeline或stage成功,且上一次构建是失败或不稳定时,允许运行该post中定义的指令;
Ø regression:当本次Pipeline或stage的状态为失败、不稳定或终止,且上一次构建的状态为成功时,允许运行该post中定义的指令;
Ø failure:只有当前Pipeline或stage的完成状态为失败(failure),才允许在post部分运行该步骤,通常这时在Web 界面中显示为红色;
Ø success:当前状态为成功(success),执行post步骤,通常在Web界面中显示为蓝色或绿色;
Ø unstable:当前状态为不稳定(unstable),执行post步骤,通常由于测试失败或代码违规等造成,在Web 界面中显示为黄色;
Ø aborted:当前状态为终止(aborted),执行该post步骤,通常由于流水线被手动终止触发,这时在Web 界面中显示为灰色;
Ø unsuccessful:当前状态不是success时,执行该post步骤;
Ø cleanup:无论pipeline或stage的完成状态如何,都允许运行该post中定义的指令。和always的区别在于,cleanup会在其它执行之后执行。

示例:一般情况下post部分放在流水线的底部,比如本实例,无论stage的完成状态如何,都会输出一条I will always say Hello again!信息:

Jenkinsfile (Declarative Pipeline) // 可以不写该行
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

也可以将post写在stage:

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                sh 'EXECUTE_TEST_COMMAND'
            }
            post {
                failure {
                    echo "Pipeline Testing failure..."
                }
            }
        }
    }
}

Stages
Stages包含一个或多个stage指令,同时可以在stage中的steps块中定义真正执行的指令。
比如创建一个流水线,stages包含一个名为Example的stage,该stage执行echo 'Hello World'命令输出Hello World字符串:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages { 
        stage('Example') {
            steps {
                echo 'Hello World ${env.BUILD_ID}'
            }
        }
    }
}

Steps
Steps部分在给定的stage指令中执行的一个或多个步骤, 比如在steps定义执行一条shell命令:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps { 
                echo 'Hello World'
            }
        }
    }
}

或者是使用sh字段执行多条指令:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps { 
                sh """
                  echo 'Execute building...'
                  mvn clean install
                """
            }
        }
    }
}

2.Directives

Directives可用于一些执行stage时的条件判断或预处理一些数据,和Sections一致,Directives不是一个关键字或指令,而是包含了environment、options、parameters、triggers、stage、tools、input、when等配置。

Environment
Environment主要用于在流水线中配置的一些环境变量,根据配置的位置决定环境变量的作用域。可以定义在pipeline中作为全局变量,也可以配置在 stage中作为该stage的环境变量。

该指令支持一个特殊的方法credentials(),该方法可用于在Jenkins环境中通过标识符访问预定义的凭证。对于类型为Secret Text的凭证,credentials()可以将该Secret中的文本内容赋值给环境变量。对于类型为标准的账号密码型的凭证,指定的环境变量为username和password,并且也会定义两个额外的环境变量,分别为MYVARNAME_USR和MYVARNAME_PSW。

假如需要定义个变量名为CC的全局变量和一个名为AN_ACCESS_KEY的局部变量,并且用credentials读取一个Secret文本,可以通过以下方式定义:

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    environment {  // Pipeline中定义,属于全局变量
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment {  // 定义在stage中,属于局部变量
                AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
            }
            steps {
                sh 'printenv'
            }
        }
    }
}

Options
Jenkins流水线支持很多内置指令,比如retry可以对失败的步骤进行重复执行n次,可以根据不同的指令实现不同的效果。比较常用的指令如下:
Ø buildDiscarder:保留多少个流水线的构建记录。 比如:options { buildDiscarder(logRotator(numToKeepStr: '1')) };
Ø disableConcurrentBuilds:禁止流水线并行执行,防止并行流水线同时访问共享资源导致流水线失败。比如:options { disableConcurrentBuilds() };
Ø disableResume:如果控制器重启,禁止流水线自动恢复。比如:options { disableResume() };
Ø newContainerPerStage:agent为docker或dockerfile时,每个阶段将在同一个节点的新容器中运行,而不是所有的阶段都在同一个容器中运行。比如:options { newContainerPerStage () };
Ø quietPeriod:流水线静默期,也就是触发流水线后等待一会在执行。比如:options { quietPeriod(30) };
Ø retry:流水线失败后重试次数。比如:options { retry(3) };
Ø timeout:设置流水线的超时时间,超过流水线时间,job会自动终止。比如:options { timeout(time: 1, unit: 'HOURS') };
Ø timestamps:为控制台输出时间戳。比如:options { timestamps() }。

配置示例如下,只需要添加options字段即可:

pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') 
        timestamps()
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

Option除了写在Pipeline顶层,还可以写在stage中,但是写在stage中的option仅支持retry、timeout、timestamps,或者是和stage相关的声明式选项,比如skipDefaultCheckout。处于stage级别的options写法如下:

pipeline {
    agent any
    stages {
        stage('Example') {
            options {
                timeout(time: 1, unit: 'HOURS') 
            }
            steps {
                echo 'Hello World'
            }
        }
    }
}

Parameters
Parameters提供了一个用户在触发流水线时应该提供的参数列表,这些用户指定参数的值可以通过params对象提供给流水线的step(步骤)。

目前支持的参数类型如下:
Ø string:字符串类型的参数,例如:parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') },表示定义一个名为DEPLOY_ENV的字符型变量,默认值为staging;
Ø text:文本型参数,一般用于定义多行文本内容的变量。例如parameters { text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '') },表示定义一个名为DEPLOY_TEXT的变量,默认值是'One\nTwo\nThree\n';
Ø booleanParam:布尔型参数,例如: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') };
Ø choice:选择型参数,一般用于给定几个可选的值,然后选择其中一个进行赋值,例如:parameters { choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '') },表示定义一个名为CHOICES的变量,可选的值为one、two、three;
Ø password:密码型变量,一般用于定义敏感型变量,在Jenkins控制台会输出为*。例如:parameters { password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password') },表示定义一个名为PASSWORD的变量,其默认值为SECRET。

Parameters用法如下:

pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')

        text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')

        booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')

        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')

        password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"

                echo "Biography: ${params.BIOGRAPHY}"

                echo "Toggle: ${params.TOGGLE}"

                echo "Choice: ${params.CHOICE}"

                echo "Password: ${params.PASSWORD}"
            }
        }
    }
}

Triggers
在Pipeline中可以用triggers实现自动触发流水线执行任务,可以通过Webhook、Cron、pollSCM 和 upstream等方式触发流水线。

假如某个流水线构建的时间比较长,或者某个流水线需要定期在某个时间段执行构建,可以使用cron配置触发器,比如周一到周五每隔四个小时执行一次:

pipeline {
    agent any
    triggers {
        cron('H */4 * * 1-5')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

注意:H的意思不是HOURS的意思,而是Hash的缩写。主要为了解决多个流水线在同一时间同时运行带来的系统负载压力。

使用cron字段可以定期执行流水线,如果代码更新想要重新触发流水线,可以使用pollSCM字段:

pipeline {
    agent any
    triggers {
        pollSCM('H */4 * * 1-5')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

Upstream可以根据上游job的执行结果决定是否触发该流水线。比如当job1或job2执行成功时触发该流水线:

pipeline {
    agent any
    triggers {
        upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS)
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

目前支持的状态有SUCCESS、UNSTABLE、FAILURE、NOT_BUILT、ABORTED等。

Input
Input字段可以实现在流水线中进行交互式操作,比如选择要部署的环境、是否继续执行某个阶段等。

配置Input支持以下选项:
Ø message:必选,需要用户进行input的提示信息,比如:“是否发布到生产环境?”;
Ø id:可选,input的标识符,默认为stage的名称;
Ø ok:可选,确认按钮的显示信息,比如:“确定”、“允许”;
Ø submitter:可选,允许提交input操作的用户或组的名称,如果为空,任何登录用户均可提交input;
Ø parameters:提供一个参数列表供input使用。

假如需要配置一个提示消息为“还继续么”、确认按钮为“继续”、提供一个PERSON的变量的参数,并且只能由登录用户为alice和bob提交的input流水线:

pipeline {
    agent any
    stages {
        stage('Example') {
            input {
                message "还继续么?"
                ok "继续"
                submitter "alice,bob"
                parameters {
                    string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
                }
            }
            steps {
                echo "Hello, ${PERSON}, nice to meet you."
            }
        }
    }
}

When
When指令允许流水线根据给定的条件决定是否应该执行该stage,when指令必须包含至少一个条件。如果when包含多个条件,所有的子条件必须都返回True,stage才能执行。

When也可以结合not、allOf、anyOf语法达到更灵活的条件匹配。

目前比较常用的内置条件如下:
Ø branch:当正在构建的分支与给定的分支匹配时,执行这个stage,例如:when { branch 'master' }。注意,branch只适用于多分支流水线;
Ø changelog:匹配提交的changeLog决定是否构建,例如:when { changelog '.^\[DEPENDENCY\] .+$' };
Ø environment:当指定的环境变量和给定的变量匹配时,执行这个stage,例如:when { environment name: 'DEPLOY_TO', value: 'production' };
Ø equals:当期望值和实际值相同时,执行这个stage,例如:when { equals expected: 2, actual: currentBuild.number };
Ø expression:当指定的Groovy表达式评估为True,执行这个stage,例如:when { expression { return params.DEBUG_BUILD } };
Ø tag:如果TAG_NAME的值和给定的条件匹配,执行这个stage,例如:when { tag "release-
" };
Ø not:当嵌套条件出现错误时,执行这个stage,必须包含一个条件,例如:when { not { branch 'master' } };
Ø allOf:当所有的嵌套条件都正确时,执行这个stage,必须包含至少一个条件,例如:when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } };
Ø anyOf:当至少有一个嵌套条件为True时,执行这个stage,例如:when { anyOf { branch 'master'; branch 'staging' } }。

示例1:当分支为production时,执行Example Deploy步骤:

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

也可以同时配置多个条件,比如分支是production,而且DEPLOY_TO变量的值为production时,才执行Example Deploy

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
                environment name: 'DEPLOY_TO', value: 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

也可以使用anyOf进行匹配其中一个条件即可,比如分支为production,DEPLOY_TO为production或staging时执行Deploy:

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
                anyOf {
                    environment name: 'DEPLOY_TO', value: 'production'
                    environment name: 'DEPLOY_TO', value: 'staging'
                }
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

也可以使用expression进行正则匹配,比如当BRANCH_NAME为production或staging,并且DEPLOY_TO为production或staging时才会执行Example Deploy:

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                expression { BRANCH_NAME ==~ /(production|staging)/ }
                anyOf {
                    environment name: 'DEPLOY_TO', value: 'production'
                    environment name: 'DEPLOY_TO', value: 'staging'
                }
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

默认情况下,如果定义了某个stage的agent,在进入该stage的agent后,该stage的when条件才会被评估,但是可以通过一些选项更改此选项。比如在进入stage的agent前评估when,可以使用beforeAgent,当when为true时才进行该stage。

目前支持的前置条件如下:
Ø beforeAgent:如果beforeAgent为true,则会先评估when条件。在when条件为true时,才会进入该stage;
Ø beforeInput:如果beforeInput为true,则会先评估when条件。在when条件为true时,才会进入到input阶段;
Ø beforeOptions:如果beforeInput为true,则会先评估when条件。在when条件为true时,才会进入到options阶段;

注意:beforeOptions优先级大于beforeInput大于beforeAgent

配置一个beforeAgent示例如下:

pipeline {
    agent none
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            agent {
                label "some-label"
            }
            when {
                beforeAgent true
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

配置一个beforeInput示例如下:

pipeline {
    agent none
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                beforeInput true
                branch 'production'
            }
            input {
                message "Deploy to production?"
                id "simple-input"
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

配置一个beforeOptions示例如下:

pipeline {
    agent none
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                beforeOptions true
                branch 'testing'
            }
            options {
                lock label: 'testing-deploy-envs', quantity: 1, variable: 'deployEnv'
            }
            steps {
                echo "Deploying to ${deployEnv}"
            }
        }
    }
}

3.Parallel

在声明式流水线中可以使用Parallel字段,即可很方便的实现并发构建,比如对分支A、B、C进行并行处理:

pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            failFast true
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
                stage('Branch C') {
                    agent {
                        label "for-branch-c"
                    }
                    stages {
                        stage('Nested 1') {
                            steps {
                                echo "In stage Nested 1 within Branch C"
                            }
                        }
                        stage('Nested 2') {
                            steps {
                                echo "In stage Nested 2 within Branch C"
                            }
                        }
                    }
                }
            }
        }
    }
}

设置failFast 为true表示并行流水线中任意一个stage出现错误,其它stage也会立即终止。也可以通过options配置在全局:

pipeline {
    agent any
    options {
        parallelsAlwaysFailFast()
    }
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
                stage('Branch C') {
                    agent {
                        label "for-branch-c"
                    }
                    stages {
                        stage('Nested 1') {
                            steps {
                                echo "In stage Nested 1 within Branch C"
                            }
                        }
                        stage('Nested 2') {
                            steps {
                                echo "In stage Nested 2 within Branch C"
                            }
                        }
                    }
                }
            }
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读