jenkins声明式流水线及语法

一.流水线概念

Jenkins pipeline语法:https://www.jenkins.io/doc/book/pipeline/syntax/
中文文档:https://www.jenkins.io/zh/doc/book/pipeline/syntax/
声明式流水线和脚本式流水线对比:

1.脚本式流水线概念


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

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

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

2.声明式流水线概念


在声明式流水线语法中,流水线过程定义在 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:用于聚合测试报告。

二.声明式流水线语法

声明式流水线必须包含在一个 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 的代码区域块。

(1).Agent

Agent 表示整个流水线或特定阶段中的步骤和命令执行的位置,该部分必须在 pipeline 块的顶层被定义,也可以在 stage 中再次定义,但是 stage 级别是可选的。包含了:any、none、node、dockerfile、docker、kubernetes。
➢ 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
"""
 }
(2).pose

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..."
        }
      }
    }
  }
}
(3).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}'
      }
    }
  }
}
(4).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
        """
      }
    }
  } 
}
(5).使用示例

示例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
      """
      }
    }
  }
 } 
}

2.Directives

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

(1).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'
      }
    }
  } 
}
(2).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 字段即可:

配置示例如下,只需要添加 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'
      }
    }
  } 
}
(3).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}"
      }
    }
  } 
}
(4).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 等。

(5).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."
      }
    }
  } 
}
(6).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"
              }
            }
          }
        }
      }
    }
  }
}

三.Jenkinsfile 的使用

声明式和脚本式,这两种语法都支持构建持续交付流水线。并且都可以用来在 Web UI 或 Jenkinsfile 中定义流水线,不过通常将 Jenkinsfile 放置于代码仓库中(当然也可以放在单独的代码仓库中进行管理)。
创建一个 Jenkinsfile 并将其放置于代码仓库中,有以下好处:
➢ 方便对流水线上的代码进行复查/迭代;
➢ 对管道进行审计跟踪;
➢ 流水线真正的源代码能够被项目的多个成员查看和编辑。

1.环境变量

1.静态变量

Jenkins 有许多内置变量可以直接在 Jenkinsfile 中使用,可以通过 JENKINS_URL/pipeline-syntax/globals#env 获取完整列表。

目前比较常用的环境变量如下:
➢ BUILD_ID:当前构建的 ID,与 Jenkins 版本 1.597+中的 BUILD_NUMBER 完全相同;
➢ BUILD_NUMBER:当前构建的 ID,和 BUILD_ID 一致;
➢ BUILD_TAG:用来标识构建的版本号,格式为:jenkins-${JOB_NAME}-${BUILD_NUMBER},可以对产物进行命名,比如生产的 jar 包名字、镜像的 TAG 等;
➢ BUILD_URL:本次构建的完整 URL,比如:http://buildserver/jenkins/job/MyJobName/17/;
➢ JOB_NAME:本次构建的项目名称;
➢ NODE_NAME:当前构建节点的名称;
➢ JENKINS_URL:Jenkins 完整的 URL,需要在 System Configuration 设置;
➢ WORKSPACE:执行构建的工作目录。

上述变量会保存在一个 Map 中,可以使用 env.BUILD_ID 或 env.JENKINS_URL 引用某个内置变量:

Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example') {
      steps {
        echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
      }
    }
  } 
}

对应的脚本式流水线如下:

Jenkinsfile (Scripted Pipeline)
node {
  echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
}

除了上述默认的环境变量,也可以手动配置一些环境变量:

Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  environment { 
    CC = 'clang'
  }
  stages {
    stage('Example') {
      environment { 
          DEBUG_FLAGS = '-g'
      }
      steps {
        sh 'printenv'
      }
    }
  } 
}

上述配置了两个环境变量,一个 CC 值为 clang,另一个是 DEBUG_FLAGS 值为-g。但是两者定义的位置不一样,CC 位于顶层,适用于整个流水线,而 DEBUG_FLAGS 位于 stage 中,只适用于当前 stage。

2.动态变量

动态变量是根据某个指令的结果进行动态赋值,变量的值根据指令的执行结果而不同。如下
所示:

Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any 
  environment {
    // 使用 returnStdout
    CC = """${sh(
          returnStdout: true,
          script: 'echo "clang"'
       )}""" 
    // 使用 returnStatus
    EXIT_STATUS = """${sh(
          returnStatus: true,
          script: 'exit 1'
       )}"""
  }
  stages {
    stage('Example') {
      environment {
        DEBUG_FLAGS = '-g'
      }
      steps {
        sh 'printenv'
      }
    }
  }
}

➢ returnStdout:将命令的执行结果赋值给变量,比如上述的命令返回的是 clang,此时 CC的值为“clang ”。注意后面多了一个空格,可以用.trim()将其删除;
➢ returnStatus:将命令的执行状态赋值给变量,比如上述命令的执行状态为 1,此时EXIT_STATUS 的值为 1。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇