目录

1、触发任务—指定流水线代码的触发事件

2、用户输入

3、构建后处理


本次,我们介绍jenkins流水线的DSL语言所提供的的用于控制流水线的不同的结构。从指定属性值触发任务和如何接收用户的输入开始。然后介绍如何灵活使用一些结构,例如超时、重试、并行的运行任务。

1、触发任务—指定流水线代码的触发事件

在web界面项目的基本配置中指定吃法条件。

如果是脚本式流水线可以在代码中指定properties代码块(常在流水线开始之前)来定义触发条件(将会和web界面定义的触发条件合并,且web定义的优先)。

如果是声明式流水线,有一个triggers指令来定义流水线的触发类型。

1.1 其他任务构建后触发

            web界面实例:

           脚本式流水线,在job1成功构建之后并且与阈值匹配时,当前的流水线就会重新构建:

properties([
    pipelineTriggers([
        upstream([
            threshold: hudson.model.Result.SUCCESS,
            upstreamProjects: 'Job1/master' 【多个任务逗号分隔】
        ])
    ])
])

1.2 周期构建

           web界面配置:

             脚本式流水线语法,任务在周一至周五上午九点              

properties([pipelineTriggers([ cron('0 9 * * 1-5') ])])

1.3 轮询SCM

          web界面设置

                

         脚本式流水线             

properties([pipelineTriggers([ pollSCM('0 9 * * 1-5') ])])

1.4 远程触发构建

2、用户输入

2.1、用户可以输入密码(password)、选项型(choice)、凭证、文件(file)、多行字符串(text)、字符串(string)

def selectFile = input message:'请选择文件',
                       parameters:[file(description:'选择文件上传',name:'local')]

参考:Pipeline Syntax 强烈推荐看一看 

实例如何获取参数和使用
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}"
            }
        }
    }
}

2.2 使用jenkins应用来参数化构建 ,可以在脚本式流水线里面引用。 ${params.<参数名称>}

还可以在流水线开头把参数定义为属性,这种方法是用于流水线和声明式,例如:

properties([
    parameters([
        upstream([
             string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
        ])
    ])
])
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo "Password: ${params.PERSON}"
            }
        }
    }
}

2.2.5 流程控制选项【略,本来写了的没有保存】

      timeout、retry、sleep、waitUntill(等待直到)。

timeout(time:60, unit:'SECONDS'){ // 代码}   默认单位秒

retry(<n>){  // 代码}

sleep time:5, until: 'MINUTES'  默认单位秒

waitUntil {  // 返回true 或者 false的过程}  第一次等待时间0.25 , 后面失败 重试*1.2的因子

2.3 并行与并发

并发实例,分支1简单的睡眠10s后输出消息,分支2睡眠5秒后,抛出异常。failFast=true表示有一个分支出现异常就结束其他所有分支。可以使用于,你需要做部署和测试时,只要部署失败了测试需要停止,测试失败了,部署需要停止。

pipeline{
    agent any
    stages{
        stage('Parallel'){
            steps{
                parallel(
                    'group1': {
                        timestamps{
                            catchError{
                                sleep 10
                                echo '完成进程1!'
                            }
                        }
                    },
                    'group2': {
                        sleep 5
                        error '进程2失败!'
                    },
                    failFast:true
                )
            }
        }
    }
}

2.4 有条件的执行功能

          Conditional BuildStep plugin条件性构建步骤插件可以让用户在自由风格类型的任务上添加一些有条件执行功能。允许选择一种方法来测试某些条件,然后基于结果执行一个或者多个步骤。

         在脚本式流水线代码中,如同使用Groovy/Java 语言的条件语言一样。实例:

node('worker_node1'){
    def responce = null
    stage('selection'){
        responce = input message:'请选择分支和构建类型', parameters:[string(defaultValue:'master', description:'选择分支', name:'BRANCH_NAME'),choice(choice:'DEBUG\nRELEASE\nTEST',description:'构建类型',name:'BUILD_TYPE')]
    }
    stage('Process'){
        if((responce.BRANCH_NAME == 'master') && (responce.BUILD_TYPE == 'RELEASE')){
            echo '启动生产'
        }
    }
}

             脚本式流水线语法如下:when 和 allOf 的意思是里面的条件都满足才执行后面的步骤。

pipeline{
    agent any
    parameters {
        string(defaultValue:'master', description:'选择分支', name:'BRANCH_NAME')
        choice(choice:'DEBUG\nRELEASE\nTEST',description:'构建类型',name:'BUILD_TYPE')
    }
    stages{
        stage('process'){
            when{
                allOf{
                    expression {responce.BRANCH_NAME == 'master'}
                    exoression {responce.BUILD_TYPE == 'RELEASE'}
                }
            }
            steps{
                echo '开始启动进程'
            }
        }
    }
}

3、构建后处理

3.1 脚本式流水线构建后处理--

A、使用try-catch-finally机制: 无论最终构建的状态如何,最终总是可以执行某些行为。      

def err = null
try{
    // 流水线代码
    node('node-name'){
        stage('stage-name'){
            ...    
        }// 最后一个阶段
    }
}catch(err){
    currentBuild.result = "FAILURE"
}finally{
    (currentBuild.result != 'Aborted'){
        // 发送邮件等操作
    }
}

B、catchError:jenkisn流水线语法支持。catchError提供了一个方法,可以探测异常改变构建状态,还能继续执行流水线进程。 

3.2 声明式流水线构建后处理

构建后操作(post),可以放在一个阶段的后面,或者流水线的结尾。下表是构建后声明式构建条件

条件描述
always总是执行
changed当前构建状态与之前构建状态不同则执行1
sucess当前构建状态成功执行
failure当前构建状态失败执行
unstable当前构建状态不稳定执行
// 阶段的末尾
post{
    always{
        echo "构建完成"
    }
    success{
        echo "构建成功"
        mail body:'构建成功', subject:'构建成功', to:'xxx@xxx.com'
    }
}

这是我最近写的一个流水线部署的方式:jekins+ansible

pipeline {
    agent any
    options {
        skipStagesAfterUnstable()
    }
    parameters {
        string(defaultValue: 'dev', description: 'Enter the GIT branch to build', name: 'branch')
    }
    environment {
        PROJECT = "futureCountry"
        TARGET_SERVER = "ltServer"
		ZIP_MNAME = "dist.tar.gz"
    }
    tools {maven 'Maven3.6.3'}
    stages {
        // 准备阶段
		stage('Preparation') { 
			steps {
			    git branch: "${params.branch}", credentialsId: 'admin', url: 'ssh://git@10.1.0.3:7999/village/futurecountry-h5.git'
			    timeout(time: 5, unit: 'MINUTES') {
        			sh 'npm install'
        			sh 'npm run build'
			    }
			}
		}
		// 构建和打包、备份
        stage('Build') {
            steps {
                sh 'npm run build'
                // 压缩
				sh 'tar -czf ${ZIP_MNAME} -C dist/ .'
				// 创建目录文件
				sh 'ansible "${TARGET_SERVER}" -m file -a "path=\\${APP_DIR}/${PROJECT}/html state=directory"'
                // 删除原有的文件
                sh 'ansible "${TARGET_SERVER}" -m shell -a "(test ! -d \\${APP_DIR}/${PROJECT}/html/ || rm -rf \\${APP_DIR}/${PROJECT}/html/*)"'
			    // 备份原有压缩包
                sh 'ansible "$TARGET_SERVER" -m shell -a "(mv \\${APP_DIR}/${PROJECT}/${ZIP_MNAME} \\${APP_DIR}/${PROJECT}/${ZIP_MNAME}.bak || true)"'
            }
        }
        // 发布
        stage('Deliver') {
            steps {
                timeout(time: 3, unit: 'MINUTES') {
					sh 'ansible "${TARGET_SERVER}" -m copy -a "src=dist.tar.gz dest=\\${APP_DIR}/${PROJECT}"'
					sh 'ansible "${TARGET_SERVER}" -m shell -a "tar -zxvf \\${APP_DIR}/${PROJECT}/dist.tar.gz -C \\${APP_DIR}/${PROJECT}/html/"'
                }
            }
        }
    }
}

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐