0. 参考文档

pipeline 官方文档
使用Jenkins Pipeline自动化构建发布Java项目
Jenkins高级篇之Pipeline方法篇

1. pipline 模式

声明性限制了用户具有更严格和预定义结构的可用性,使其成为更简单连续输送Pipeline的理想选择。

脚本化提供了极少的限制,因为Groovy本身只能对结构和语法进行限制,而不是任何Pipeline专用系统,使其成为高级用户和具有更复杂要求的用户的理想选择。

2. Declarative pipline

下面是一段示例代码,可直接运行。

  1. pipeline {
  2. agent { docker 'maven:3.3.3' }
  3. stages {
  4. stage('build') {
  5. steps {
  6. sh 'mvn --version'
  7. }
  8. }
  9. }
  10. }

pipline 通过 jenkins 的 master/slave 模式运行, agent 指定要执行 pipline 代码的 slave 机器(即所谓的代理机器)
pipline {…} 的下一层,必须要有一个 agent, agent部分主要作用就是告诉Jenkins,选择那台节点机器去执行Pipeline代码。

2.1 agent 参数介绍:

any

在任何可用的代理上执行Pipeline或stage

  1. pipeline {
  2. agent any
  3. }
  4. // 如果你Jenkins平台环境只有一个master,那么这种写法就最省事情.

none

不为 整个pipline运行分配代理, 并且每个stage 部分要有自己的agent

  1. pipeline {
  2. agent none
  3. stages {
  4. stage('Build'){
  5. agent {
  6. label '具体的节点名称'
  7. }
  8. }
  9. }
  10. }

label

在指定的 label 标签上 运行 pipline

jenkins 在配置 从节点时,会指定 label
./
image.png

  1. pipeline {
  2. agent {
  3. label 'mylabel-1' // 指定要在哪些标签上运行
  4. }
  5. }

node

和上面label功能类似,但是node运行其他选项,例如customWorkspace

下面是一段完整的pipline 代码:

  1. pipeline {
  2. agent {
  3. node {
  4. label 'test'
  5. customWorkspace "${env.JOB_NAME}/${env.BUILD_NUMBER}" // 指定工作空间
  6. }
  7. }
  8. stages {
  9. stage ('build') {
  10. steps{
  11. sh "pwd"
  12. }
  13. }
  14. stage ('test') {
  15. steps{
  16. sh "echo ${JAVA_HOME}"
  17. }
  18. }
  19. }
  20. }

2.2 post 参数介绍

post 参数,构建状态相关。用来指定 当 pipline运行完成后,后续的一些操作。如: 测试完后对数据库的恢复,运行成功或失败后发送邮件等。
基本的代码布局如下:

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. stages {
  6. stage ('test') {
  7. steps {
  8. sh "echo hello ..."
  9. }
  10. }
  11. }
  12. post {
  13. //写相关post部分代码
  14. // ......
  15. }
  16. }
  17. - - - -
  18. https://blog.csdn.net/u011541946/article/details/83278531

always

无论Pipeline运行的完成状态如何,都会执行这段代码

一般 always 参数用来写相关清除、恢复环境 等操作代码。如: 测试完了,对数据库进行恢复操作,恢复到测试之前的环境。

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. stages {
  6. stage ('test') {
  7. steps {
  8. sh "echo hello ... test ..."
  9. println "this is a test ... " // 这个是Groovy风格的语法
  10. }
  11. }
  12. }
  13. post {
  14. always {
  15. script {
  16. echo "清除... 恢复..."
  17. }
  18. }
  19. }
  20. }

changed (不常用)

当本次构建的结果状态与上次的不一样时,触发 changed。

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. stages {
  6. stage ('test') {
  7. steps {
  8. sh "echo hello ... test ..."
  9. }
  10. }
  11. }
  12. post {
  13. changed {
  14. script {
  15. echo "与上次的构建状态发生了变化......"
  16. echo "已发邮件通知 ..."
  17. }
  18. }
  19. }
  20. }

failure

当本次构建失败时触发。

success

当本次构建成功后触发。

aborted

只有当前Pipeline处于“中止”状态时,才会运行,通常是由于Pipeline被手动中止。通常在具有灰色指示的Web UI中表示。

unstable

构建的不稳定状态。通常由测试失败,代码违例等引起,才能运行。通常在具有黄色指示的Web UI中表示。

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. stages {
  6. stage ('test') {
  7. steps {
  8. sh "echo hello ... test ..."
  9. }
  10. }
  11. }
  12. post {
  13. success {
  14. script {
  15. echo "success ..."
  16. echo "send mail ... "
  17. }
  18. }
  19. failure {
  20. script {
  21. echo "构建失败 ..."
  22. echo "已发邮件通知 ..."
  23. }
  24. }
  25. }
  26. }

2.3 指令

environment

用来定义一些环境变量。可以在 pipline层, stage层来定义变量。

  1. // def NAME="mmm" // def 定义的变量的优先级最高
  2. pipeline {
  3. agent {
  4. label 'test'
  5. }
  6. environment {
  7. NAME="all-evn"
  8. }
  9. stages {
  10. stage ('test') {
  11. environment {
  12. NAME="step-env"
  13. }
  14. steps {
  15. println NAME
  16. script {
  17. def browsers = ['chrome', 'firefox']
  18. for (int i = 0; i < browsers.size(); ++i) {
  19. echo "Testing the ${browsers[i]} browser"
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }

options

  • buildDiscarder

pipeline保持构建的最大个数。例如:options { buildDiscarder(logRotator(numToKeepStr: ‘1’)) }

  • disableConcurrentBuilds

不允许并行执行Pipeline,可用于防止同时访问共享资源等。例如:options { disableConcurrentBuilds() }

  • skipDefaultCheckout

默认跳过来自源代码控制的代码。例如:options { skipDefaultCheckout() }

  • skipStagesAfterUnstable

一旦构建状态进入了“Unstable”状态,就跳过此stage。例如:options { skipStagesAfterUnstable() }

  • timeout

设置Pipeline运行的超时时间。例如:options { timeout(time: 1, unit: ‘HOURS’) }

  • retry

失败后,重试整个Pipeline的次数。例如:options { retry(3) }

  • timestamps

预定义由Pipeline生成的所有控制台输出时间。例如:options { timestamps() }

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. options {
  6. timeout(time: 1, unit: 'HOURS')
  7. retry(3)
  8. }
  9. stages {
  10. stage ('test') {
  11. steps {
  12. sh "echo retry ..."
  13. sh "echo1 test ..."
  14. }
  15. }
  16. }
  17. }

parameters (参数化构建)

  • string

A parameter of a string type, for example: parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }

  • booleanParam

A boolean parameter, for example: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }

  • choice

choice(name: 'ENV_TYPE', choices: ['test', 'dev', 'product'], description: 'test means test env,….')

  • text

text(name: 'Welcome_text', defaultValue: 'One\nTwo\nThree\n', description: '')

  • file

parameters { file(name: 'FILE', description: 'Some file to upload') }

  • password

password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password')

目前只支持[ booleanParam, choice, credentials, file, text, password, run, string ]这几种参数类型,其他高级参数化类型还需等待社区支持。

  1. // 这里的 pipline 参数化,只要将pipline写代码即可, 不需要手动的去配置参数化构建。
  2. pipeline{
  3. agent {
  4. label 'test'
  5. }
  6. parameters {
  7. string(name: 'user', defaultValue: 'yang', description: 'please give a name')
  8. // 这里choice 这么写有问题, 使用下面的那个写法。
  9. // choice(name: 'version', choices: ['1.1', '1.2', '1.3'], description: 'select the version to test')
  10. choice(name: 'version', choices: '1.1\n1.2\n1.3', description: 'select the version to test')
  11. booleanParam(name: 'is_boy', defaultValue: true, description: 'you is boy or not')
  12. }
  13. stages {
  14. stage('test') {
  15. steps{
  16. echo "${params.user}"
  17. echo "${params.version}"
  18. echo "${params.is_boy}"
  19. }
  20. }
  21. }
  22. }
  23. // 保存之后,你会发现,菜单是Build now,而并不是Build with Parameters
  24. // 这个是正常,你先点击Build now,先完成第一个构建,Jenkins第二个构建才会显示代码中的三个参数。
  25. // 刷新之后,就可以看到参数化构建这个菜单。

UI 界面
image.png
image.png
image.png

triggers (定时触发器)

  • cron

    1. 接受一个cron风格的字符串来定义Pipeline应重新触发的常规间隔,例如: `triggers { cron('H 4/* 0 0 1-5') }`
  • pollSCM

    1. 接受一个cron风格的字符串来定义Jenkins应该检查新的源更改的常规间隔。如果存在新的更改,则Pipeline将被重新触发。例如: `triggers { pollSCM('H 4/* 0 0 1-5') }`
  • upstream

接受逗号分隔的作业字符串和阈值。 当字符串中的任何作业以最小阈值结束时,将重新触发pipeline。例如: triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) } // 当job1或job2运行成功的时,自动触发。

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. triggers {
  6. pollSCM('H * * * *')
  7. }
  8. stages {
  9. stage('test') {
  10. steps{
  11. echo "定时1分钟..."
  12. }
  13. }
  14. }
  15. }

tools

定义自动安装和放置工具的部分PATH。如果agent none指定,这将被忽略。
只支持定义 maven,jdk, gradle 三种工具的环境变量。

  1. pipeline{
  2. agent {
  3. label 'test'
  4. }
  5. tools {
  6. jdk 'jdk8'
  7. }
  8. stages {
  9. stage('test') {
  10. steps{
  11. sh 'java -version'
  12. }
  13. }
  14. }
  15. }

注意:工具名称必须在Jenkins 管理Jenkins全局工具配置中配置。例如,上面代码我写了jdk,那么我必须在jenkins管理的全局工具配置中有jdk配置。
image.png

when

内置条件
  • branch

当正在构建的分支与模式给定的分支匹配时,执行这个阶段, 例如: when { branch 'master' }。注意,这只适用于多分支流水线。

  • environment

当指定的环境变量是给定的值时,执行这个步骤, 例如: when { environment name: 'DEPLOY_TO', value: 'production' }

  • expression

当指定的Groovy表达式评估为true时,执行这个阶段, 例如: when { expression { return params.DEBUG_BUILD } }

  • not

当嵌套条件是错误时,执行这个阶段,必须包含一个条件,例如: when { not { branch 'master' } }

  • allOf

当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如: when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }

  • anyOf

当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch 'master'; branch 'staging' } }

在进入 stageagent 前评估 when

默认情况下, 如果定义了某个阶段的代理,在进入该stageagent 后该 stagewhen 条件将会被评估。但是, 可以通过在 when 块中指定 beforeAgent 选项来更改此选项。 如果 beforeAgent 被设置为 true, 那么就会首先对 when 条件进行评估 , 并且只有在 when 条件验证为真时才会进入 agent

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. environment {
  6. quick_test = true
  7. }
  8. stages {
  9. stage('Example Build') {
  10. steps {
  11. script {
  12. echo 'Hello World'
  13. }
  14. }
  15. }
  16. stage('Example Deploy') {
  17. when {
  18. expression {
  19. return (quick_test == "true")
  20. }
  21. }
  22. steps {
  23. echo 'Deploying'
  24. }
  25. }
  26. }
  27. }

2.4 并行

在声明式 pipeline 版本 1.2 之前,这是唯一的并行方式

  1. pipeline {
  2. agent {
  3. label 'test'
  4. }
  5. stages {
  6. stage('run-parallel') {
  7. steps {
  8. parallel(
  9. a: {
  10. echo "task 1"
  11. },
  12. b: {
  13. echo "task 2"
  14. }
  15. )
  16. }
  17. }
  18. }
  19. }

声明式流水线的阶段可以在他们内部声明多隔嵌套阶段, 它们将并行执行。 注意,一个阶段必须只有一个 stepsparallel 的阶段。 嵌套阶段本身不能包含进一步的 parallel 阶段, 但是其他的阶段的行为与任何其他 stage 相同。任何包含 parallel 的阶段不能包含 agenttools 阶段, 因为他们没有相关 steps
另外, 通过添加 failFast true 到包含 parallelstage 中, 当其中一个进程失败时,你可以强制所有的 parallel 阶段都被终止。

  1. pipeline {
  2. agent any
  3. stages {
  4. stage('Non-Parallel Stage') {
  5. steps {
  6. echo 'This stage will be executed first.'
  7. }
  8. }
  9. stage('Parallel Stage') {
  10. when {
  11. branch 'master'
  12. }
  13. failFast true
  14. parallel {
  15. stage('Branch A') {
  16. agent {
  17. label "for-branch-a"
  18. }
  19. steps {
  20. echo "On Branch A"
  21. }
  22. }
  23. stage('Branch B') {
  24. agent {
  25. label "for-branch-b"
  26. }
  27. steps {
  28. echo "On Branch B"
  29. }
  30. }
  31. }
  32. }
  33. }
  34. }

scripted

stage, node 没有明确的层级限制, 使用比较灵活。

  1. stage('Example') {
  2. node('A01') {
  3. if (env.BRANCH_NAME == 'master') {
  4. echo 'I only execute on the master branch'
  5. } else {
  6. echo 'I execute elsewhere'
  7. }
  8. sh label: 'A01', script: 'echo A01 > /tmp/a.txt'
  9. }
  10. }

问题

  1. 1. pipline pipline{...} 中可以写多个agent ?
  2. 不可以。 最外层的 agent 是全局的。 每个 stage 中的 agent 也只能有一个。