程序猿进阶(四)--Jenkins篇(pipeline语法)

脚本式流水线和声明式流水线

脚本式流水线

node('name'){
	stage('Source'){
		git '[email protected]'
	}
	stage('Compile'){
		pwd()
		do something()
	}
}

优点:

  • 更少的代码段落和弱规范要求
  • 更强大的程序代码能力
  • 更像编程代码程序
  • 传统的流水线即代码模型,用户熟悉并向后兼容性
  • 更灵活的自定义代码操作
  • 能够构建更复杂的工作流和流水线

缺点:

  • 要求更高编程水平
  • 首先与Groovy语言和环境
  • 和传统Jenkins模型有很大差异
  • 与声明式流水线相比,同一工作流会更复杂

声明式流水线

pipeline{
	agent{label 'name'}
	stages{
		stage('Source'){
			steps{
				git '[email protected]'
			}
		}
		stage('Compile'){
			steps{
				pwd()
				do something()
			}
		}
	}
}

优点:

  • 结构化,贴近Jenkins Web的表单形式
  • 高可读性
  • 可以通过图形化界面自动生成
  • 段落可以映射到常见的Jenkins概念,比如通知
  • 更友好的语法检查和错误识别
  • 提升流水线间的一致性

缺点:

  • 迭代较弱
  • 开发不完善
  • 结构严格
  • 难以处理复杂的任务

说明

声明式流水线的agent和脚本式流水线的node都是指运行的节点,对于没有配置节点(默认只有master节点),使用node{}(把label省略掉)和agent any即可
修改节点需要在工作台->系统管理->节点管理处进行

构建配置

配置示例

proprties([
	pipelineTriggers([
		upstream(
			threshold:hudson.model.Result.SUCCESS,
			upstreamProjects:'name'
		)
	])#在名为name的项目构建成功后构建
	pipelineTriggers([cron('0 9 * * 1-5')])
	#这里表示每周一到周五,上午9点的定时任务
	pipelineTriggers([cron('*\20 * * * *')])
	#*/表示每隔,这里表示每隔20分钟
	pipelineTriggers([cron('*H H(0-7) * * *')])
	#H(s,e)随机选择从s到e的任意值,这里表示0点到7点的任意时间
	#定时任务
	#五个参数分别表示分钟、小时、每月第几天、第几个月、每周第几天(0和7表示周日)
	pipelineTriggers([pollSCM('H H 1,15 1-11 *')])
	#除了12月之外,每个月的第1,15天扫描一次SCM变化
	pipelineTriggers([cron('H H(9-16)/2 * * 1-5')])
	#每两小时一次,每个工作日上午9点到下午5点
	pipelineTriggers([githubPush()])
])

指令列表

input

可以再流水线中等待用户相应,默认表单为选项为Proceed和Abort

input id:'name',message:'msg',ok:'Yes',submitter:'user1,user2',parameters:[]
#id不给也会默认生成唯一标识符
#message为显示给输入者的消息
#submitter指定哪些人可用
#paramaters为带的参数

parameters

#类型有boolean,choice,credential,file,subversion,password,run,string
parameters:[(booleanParam (defaultValue:true,description:'description',name:'name')]
#返回值为java.lang.boolean

parameters:[choice(choices:"choice1\nchoice2\nchoice3\n",description:'description',name:'name')]
#使用\n分割选项

parameters:[[$class:'CredentialsParameterDefinition',
credentialType:'com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey',
defaultValue:'jenkins2-ssh',description:'description',
name:'name',required:true]]
#ssh秘钥

parameters:[[$class:'CredentialsParameterDefinition',
credentialType:'com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl',
defaultValue:'',description:'description',
name:'name',required:true]]
#使用用户名密码

parameters:[file(description:'description',name:'name')]
#返回类型为hudson.FilePath

parameters:[[$class:'ListSubversionTagsParameterDefinition',credentialsId:'jenkins2-ssh',
defaultValue:'',maxTags:'',name:'name',reverseByDate:false,reverseByName:false,
tagsDir:'path/to/directory',tagsFilter:'*']]
#提供下拉列表框和过滤器

parameters:[text(defaultValue:'''line1
line2
line3''',description:'',name:'')]
#'''用于跨越多行

parameters:[password(defaultValue:'',description:'description',name:'name']
#输入时文本会被隐藏

parameters:[run(description:'description',filter:'ALL',name:'name',projectName:'pipeName')]
#选择使用已经执行过的构建

parameters:[string(defaultValue:'',description:'description',name:'name',trim:false)]
#输入字符串,trim表示是否清空字符串开头结尾的空格换行等字符

这里有两个坑

pipeline {
   agent any
    stages{
        stage('Start') {
            steps {
                echo 'Hello World. Starting!'
            }
        }
		stage('Source'){
			steps{
				echo "Start"
        	    input "Continue?"
        		
			}
		}
		stage('Compile'){
			steps{
			    script{//必须要用script把这一块包装起来,不然报错
			        def info = input message: 'login', parameters: [string(defaultValue: 'id', description: 'desc id', name: 'id', trim: false), password(defaultValue: 'pwd', description: 'desc pwd', name: 'pwd')]
				    echo info['id']
        		    echo "${info['pwd']}"
        		    //echo info['pwd'] 会出错,原因可能是password字段,我也不确定
			    }
				
			}
		}
	}
}

还可以定义parameters块

pipeline{
	agent any
	parameters{
		string(defaultValue:'',
		description:'',
		name:'name')
		choice(choices:'c1\nc2\nc3',
		description:'',
		name:'c')
	}
	stages{
		stage('stage'){
		 	......
		 	#调用相应参数时使用 params.name , params.c
		}
	}
}

script说明

声明式的风格不支持一些功能,所以需要使用script来使用非声明式语法,上述代码和下面的代码等价

node {
    stage('Start') {
        echo 'Hello World. Starting!'
    }
	stage('Source'){
		echo "Start"
        input "Continue?"
		}
	stage('Compile'){
		def info = input message: 'login', parameters: [string(defaultValue: 'id', description: 'desc id', name: 'id', trim: false), password(defaultValue: 'pwd', description: 'desc pwd', name: 'pwd')]
		echo info['id']
        echo "${info['pwd']}"
	}
}

timeout

对于需要限时的任务进行包装

stage('name'){
	try{
		timeout(time:10,unit:'SECONDS'){
			do something()
		}
	}
	catch(err){
		do something()
	}
}

retry

retry(){do something()}

当有异常发生时重试n次

sleep

sleep time:t , unit:'MINUTES'

WaitUntil

使用timeout封装WaitUntil避免死循环

timeout(time:10,unit:'SECONDS'){
	WaitUntil {
		def ret = sh returnStatus:true, script: ''
		return (ret == 0)
	}
}

lock

lock (node_label){
	do something()
}

lock是为了处理并发情况下的问题,比如有的在安装编译,而有的正在调用,就会出问题
lock不允许多个构建同时使用一个节点

milestone

和lock一样用于处理并发的问题

milestone label:'After bild',ordinal:1

第一个参数是标签,用来标识这个里程碑,第二个参数是序列号,不显式声明会自动生成
里程碑的处理规则:

  • 按照构建标号依次通过
  • 新的构建通过里程碑时,老的构建中止运行
  • 当一个构件通过了一个里程碑,Jenkins会中止那些已经通过了前一个里程碑但还没有到达该里程碑的构建
  • 如果较旧的构件通过了某个里程碑,还没有通过该里程碑的较新的构建不会被终止
    简而言之,保证构建进度相对一致,新的跑得慢,旧的跑的快
    可以保证构建在执行时需求的资源不被其他构建修改

并发限制

限制多分支流水线只能构建一个分支
脚本式:

properties([disableConcurrentBuilds()])

声明式:

options{
	disableConcurentBuilds()
}

并行

pipeline{
	agent any
	stages{
		stage ('Parallel'){
			steps{
				paralle{
					'group1':{
						do something()
					},
					'group2':{
						do something()
					},
					failFast:true
				}
			}
		}
	}
}

failFast值为true意味着如果某个分支因为错误等原因终止,整个测试都会停止

条件执行

when中指定给定的条件,最终结果为true才会执行,和其他语言的if类似

pipeline{
	agent any
	parameters{
		string(defaultValue:'',
		description:'',
		name:'name')
		choice(choices:'c1\nc2\nc3',
		description:'',
		name:'c')
	}
	stages{
		stage('Process1'){
			when{
				allOf{
					expression {params.name == 'n'}
					expression {params.c == 'c2'}
				}
				/*
				anyOf{
					expression {params.name == 'name'}
					expression {params.c == 'c2'}
				}//替换后会被执行
				*/			
			}
			steps{
				echo 'P1'
				//不会被执行
			}
		}
	}
}

构建后处理

用于错误处理,场景恢复等,在构建结束后添加一些操作

脚本式流水线

主要有两种方法,一个是try-catch-finally,和python非常接近,另一个是catchError

def err = null
try{
	node ('node-name'){
		stage('stag-name'){
			do something()
		}
	}
}
catch(err){
	currentBuild.result='FAILURE'
}
finally{
	(currentBuild.result != 'ABORTED'){
		do something()
		//失败时做什么
		//如果想传播错误可以继续抛出异常 error 'err msg'
	}
}
node ('node-name'){
	catchError{
		stage('stag-name'){
			do something()
		}
	}
}

catchError会自动捕捉异常、输出异常并标记currentBuild.result为FAILURE,但是不提供finally块

声明式流水线

使用专门的部分用于构建后处理

post{
	always{
	//总是执行
	}
	failure{
	//构建失败执行
	}
	success{
	//构建成功执行
	}
	changed{
	//当前构建状态与之前构建状态不同
	}
	unstable{
	//构建状态不稳定时执行
	//不稳定指的是服务器内存不足等问题,和代码本身无关
	}
}

参考:
《Jenkins2 权威指南》
Jenkins高级篇之Pipeline语法篇-8-Declarative Pipeline指令:input/when
Jenkins基础:Jenkinsfile使用实例:5:使用when进行条件分支处理
Jenkins构建项目的时候出现构建不稳定异常UNSTABLE

你可能感兴趣的:(程序猿进阶)