Jenkins流水线pipelinle用法

官网地址:

https://www.jenkins.io/zh/doc/book/pipeline/syntax/

Pipeline支持两种语法: Declarative Pipeline(声明式pipeline,在pipeline2.5中引入,结构化方式)和Scripted Pipeline(脚本式pipeline),两者都支持建立连续输送的Pipeline,建议使用声明式Pipeline的方式进行编写,声明式pipeline必须包含在固定格式的pipeline{}内注意在pipeline{}中所有模块的大括号都要是英文状态下的,否则报错

声明式pipeline一般定义在jenkinsfile中(此名字可自定义的,但是要与Jenkins中配置的一致),然后将jenkinsfile放在gitlab中,可与代码放在一起或者单独放一个同一个仓库下的不同分支中(建议放在不同分支下,拉取推送代码对它没影响)

流水线的大致工作流程为:

  • jenkins连接gitlab来获取代码与jenkinsfile文件
  • jenkins根据定义的Jenkinsfile文件来执行Jenkinsfile中的pipeline流水线

本例子演示的是将Jenkinsfile与源代码分开存放,Jenkinsfile放在dev分支下,源代码放在main分支下

演示

1、首先在dev分支下新建文件,如图:

2、输入文件名以及文件内容,点击下方的Commit changes,如图:

  • 第4行的括号里只是说明作用,内容可自定义

3、打开Jenkins,创建流水线项目,如图:

在定义位置选择声明式流水线,然后配置git地址和凭据,如图:

选择Jenkinsfile所在的分支,Jenkinsfile名称要与gitlab中定义的要一致,如图:

注:此处的主要目的是从dev分支来拉取Jenkinsfile文件,然后根据Jenkinsfile内容才开始正式的构建过程

4、构建Jenkins,可以看到构建成功,一个简单的流水线完成了,如图:

agent模块

agent指定了pipeline脚本在哪台机器或者容器或者pod中运行,因为jenkins的工作模式有master-slave模式,因此pipeline可以放到其他slave中执行,如果agent后面写着any,则表示可以在任意节点执行,如果master或者slave配置了标签,那么pipeline可以在执行标签的节点上运行,语法如下:

pipeline {
   agent {
      node {label: 'hello'}
   }
}

agent也可以写到stage里,表示特定的stage模块在指定的标签节点运行,如下:

pipeline {
  agent any
  stages {
     stage('hello') {
        agent {
           node {label: 'hello'}
        }
     }
  }
}

注:agent模块不可省略

stages、stage、steps模块

stages模块由多个stage组成,一个stage表示一个阶段,一个阶段又由多个步骤组成,每个步骤使用steps表示,steps中只要用于执行具体的命令,例如,执行echo命令,如下:

pipeline {
   agent any
   stages {
       stage("echo") {
         steps {
            echo "100000"
         }
       }
   }
}

注:stage后面的括号内容是注释作用,可自定义的

steps模块下可定义script部分,然后在里面可执行各种shell命令或者脚本,如图:

sh 后面使用”’ ”’或者””” “””都可以,但是三引号里面就不用使用//来注释了,否则报错

post模块

在stages或者单个stage模块后定义post模块,用来表示整个stages或者单个stage完成后需要执行的动作,比如配置钉钉告警或者微信告警

修改上述Jenkins文件,添加post模块,上图在stage和stages后都添加了,如图:

从打印结果来看,在steps和stages执行后都调用了post,如图:

post可以定义多个条件块,条件里写要执行的步骤,条件块如下:

  • always:无论当前执行结果是什么状态都执行
  • changed:当前完成状态和上一步完成状态不同则执行
  • fixed:上一步状态失败或者不稳定(unstable),当前状态为成功时
  • regression:上一次成功,当前失败,不稳定或者中止(aborted)时执行
  • aborted:当前执行结果是中止状态时执行(一般人为中止)
  • failure:当前状态为失败时执行
  • success:当前状态为成功时执行
  • unstable :当前状态为不稳定时执行
  • cleanup:清理条件块,不论当前状态是什么,其他条件块执行完成后都执行

post中定义多个条件块语法如下:

post {
  success {
    echo "hello"
  }
  failure {
     echo "world"
  }
  .............
}

environment模块

environment模块用于设置环境变量,可定义在pipeline或stage部分

继续修改Jenkinsfile文件,添加环境变量,如图:

Jenkins执行结果如下,环境变量已经打印出来,如图:

tools模块

tools会自动下载并安装我们指定的工具,并将其加入PATH变量中,可定义在pipeline或stage中

例如如果构建java应用需要maven,但是机器没有安装,此时就可以执行,如下:

pipeline {
  agent any
  tools {
    maven 'apache-maven-3.0.1'
  }
}

input模块

定义在stage部分,会暂停pipeline,提示你输入内容

options模块

用于配置Jenkins pipeline本身的选项,options指令可定义在stage或pipeline部分,如下:

options {
  retry(3)                        //执行失败时尝试3次
  timeout(time: 1, unit: 'HOURS') //超时1小时停止,MINUTES表示分
}

更多用法查看官方文档

parallel

并行执行多个step。在pipeline插件1.2版本后,parallel开始支持对多个阶段(stage)进行并行执行,注意,一个阶段必须只有一个 stepsparallel 的阶段,嵌套阶段本身不能包含进一步的 parallel 阶段, 但是其他的阶段的行为与任何其他 stage 相同。任何包含 parallel 的阶段不能包含 agenttools 阶段, 因为他们没有相关 steps

下面是一段简单的并行执行的代码,如图:

注:通过添加 failFast true 到包含 parallel`的 `stage 中, 当其中一个进程失败时,你可以强制所有的 parallel 阶段都被终止

triggers模块

triggers 指令定义了流水线被重新触发的自动化方法,可用触发器为cron,pollSCM,upstream

  • cron:接收 cron 样式的字符串来定义要重新触发流水线的常规间隔 ,比如: triggers { cron('H */4 * * 1-5') }
  • pollSCM:接收 cron 样式的字符串来定义一个固定的间隔,在这个间隔中,Jenkins 会检查新的源代码更新。如果存在更改, 流水线就会被重新触发。例如: triggers { pollSCM('H */4 * * 1-5') }
  • upstream:接受逗号分隔的工作字符串和阈值。 当字符串中的任何作业以最小阈值结束时,流水线被重新触发。例如: triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) }
pipeline {
  agent any
  triggers {
     cron('H */4 * * 1-5')
  }
}

when模块

when 指令允许流水线根据给定的条件决定是否应该执行阶段。 when 指令必须包含至少一个条件,如果 when 指令包含多个条件, 所有的子条件必须返回True,阶段才能执行。 这与子条件在 allOf 条件下嵌套的情况相同

内置条件有:branch、environment、not、allOf、anyOf

branch:当正在构建的分支与模式给定的分支匹配时,执行这个阶段, 例如: when { branch 'master' }。注意,只有多分支流水线的时候才会生效,配置方法如下:

environment:当指定的环境变量是给定的值时,执行这个步骤

下面例子定义了两个环境变量height和age,然后在when中进行判断,如图:

  • name:对应的就是环境变量中的变量名,固定格式
  • value:对应的就是环境变量中的变量值,固定格式

查看Jenkins执行结果,如图:

从上图看出,dev分支部分条件不符合,因此不执行,main分支符合,所以执行

expression:当指定的Groovy表达式评估为true时,执行这个阶段

下面例子修改jenkinsfile,添加表达式,如图:

执行Jenkins,结果如下:

从上图看出,因为第一个expression为true,因此执行了main分支内容

not:当嵌套条件是错误时,执行这个阶段,必须包含一个条件

下面例子定义环境变量值为100kg,在stage中出现了错误引用为50kg,如图:

环境变量引用错误,因此not条件匹配,将执行steps,jenkins中执行结果如下:

allOf:当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件

下面例子第一个stage中两个条件都正确,第二个只有一个正确,如图:

第一个stage两个条件都正确,因此会打印main分支内容,查看jenkins结果,如图:

anyOf:当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件

下面例子中有个条件为真,一个为假,那么steps将会被执行,如图:

查看jenkins的执行结果,如图:

parameters模块

parameters 指令提供了一个用户在触发流水线时应该提供的参数列表。这些用户指定参数的值可通过 params 对象提供给流水线步骤,可用参数为字符串类型和布尔类型

1、下面例子是字符串类型的参数定义,如图:

通过jenkins第一次构建完,第二次构建的时候就可以看到分支选项,如果多个分支可以选择,如图:

Jenkins运行结果如下:

2、下面例子是布尔类型的参数定义,定义了两个,如图:

在Jenkins界面,第二次构建的时候就可以看到参数选项,可根据需要勾选,如图:

注:parameters里面也可以嵌套gitParameter模块,但是次模块需要安装Git parameter插件

构建前端vue项目

Jenkins按照文章开始的那样配置,Jenkinsfile定义在dev中,代码在main中

涉及插件:

  • Git parameter #定义分支,在构建时会显示分支选择
  • NodeJS Plugin #执行node命令
  • SSH Agent #管理SSH凭据,用于安全的连接远程机器,不支持密码,只能用key
  • Publish Over ssh #推送构建结果到远程机器 (好像不装也行)

1、在dev分支中定义Jenkinsfile文件,内容如下:

pipeline {
    agent any
    tools {
        nodejs 'nodejs_10_15_3'
    }
    environment {
        repo = 'git@192.168.238.130:test-project/test-demo.git'    //代码位置
        //npmrepo = 'https://registry.npmjs.org'                   //官方npm仓库
        npmrepo = 'https://registry.npmmirror.com'                 //淘宝的npm仓库
        GIT_AUTH = 'connect_gitlab'                                //jenkins连接gitlab的凭据
    }
    parameters {
        gitParameter(
            branchFilter: 'origin/(.*)',                           //过滤以origin开头分支(连接gitlab后会获取全部分支)
            defaultValue: 'main',                                  //默认分支
            name: 'branch',                                        //参数名,在jenkins界面显示
            sortMode: 'NONE',                                      //不对分支进行排序
            type: 'PT_BRANCH',                                     //参数类型为分支选择参数
            description: ''                                        //分支描述,可不写
        )
    }
    stages {
        stage('拉取代码') {
            steps {
                echo "开始拉取代码"
                git (
                    url: "${env.repo}",                            //代码仓库,使用evn来获取environment中的值
                    changelog: true,                               //是否记录拉取代码时的变更历史,设置为true和false都可以
                    branch: "${branch}",                           //制定要拉取的分支
                    credentialsId: "${env.GIT_AUTH}"               //连接gitlab的认证凭据,使用env获取environment的变量
                )
            }
        }
        stage('使用node构建'){
            steps {
                 script {
                    echo '开始构建.....'
                    sh """
                      node -v
                      npm -v
                      echo "开始执行npm命令构建"
                      cd "${env.WORKSPACE}"                        //进入项目目录,固定写法,如果项目为a,那么进入的就是workspace/a目录下
                      rm -rf node_modules                          //可选,删不删都行
                      rm -rf package-lock.json
                      sudo npm config set registry "${env.npmrepo}"     //配置仓库
                      sudo npm install autoprefixer@latest caniuse-lite@latest browserslist@latest --save-dev //非必须,如果提示版本低就执行这条
                      sudo npm install  --prefer-offline   //优先使用本地缓存
                      sudo npm run build                   //构建
                    """
                   }
                 
            }
        }
        stage('推送到远程机器上'){
            steps {
                script {
                    //sshagent提供一个认证凭据,不支持密码,只支持秘钥
                    sshagent(credentials: ['66642ff9-35e4-492f-bfdb-bfd84ad984ec']){
                        sh """
                            scp -r dist/* root@192.168.238.130:/root           //将构建后的推送到远程机器
                            sleep 1 
                            ssh root@192.168.238.130 "systemctl restart nginx" //执行远程机器重启中间件命令
                        """
                    }
                }
            }
        }
    }
}

tools:此次构建使用的工具为nodejs,后面单引号中的nodejs_10_15_3要与Jenkins中配置的一致,查看jenkins中配置,系统管理–全局工具配置–nodejs,如图:

GIT_AUTH:对应的值是jenkins连接gitlab的凭据名称,系统管理–凭据–系统–全局凭据–Add crendentials可添加凭据,选择秘钥,如图:

jenkins所在服务器的公钥要放在gitlab上(头像–>Edit profile–>SSH Keys),如果是docker容器部署的,那就要去容器里获取公钥私钥

注:配置完成后如何Jenkins项目页面还是提示连接gitlab异常,此时可以去Jenkins所在机器(docker部署的就去容器里)使用git clone测试拉取一次,一般测试成功后jenkins界面就可以连接了

gitParameter:需要安装Git parameter插件才能使用

sshagent:用于提供连接远程服务器的认证凭据,不支持密码,只支持秘钥,在jenkins的系统管理–>凭据里配置,将jenkins所在服务器的公钥发送到远程服务器(ssh-copy-id),然后将私钥配置到凭据中(如果是docker部署的就要获取容器中的公钥私钥),配置后如图:

注:sshagent中只能配置凭据ID,不能使用凭据名称,会提示找不到,如果构建后报错内容为:

java.lang.NoSuchMethodError: No such DSL method 'sshagent' found among steps

此错误说明Jenkins的ssh agent插件没有安装,安装下即可

通过http的方式获取代码:

上面的Jenkinsfile使用的是SSH方式获取git代码(git@192.168.2…….git),需要配置公私钥,如果要通过http的方式来获取代码(http://192.168.2…….git),此时就需要使用access tokens了

1、登录gitlab–>头像–>Edit profile–>access token,如图:

填写token名字,勾选权限,如图:

点击创建后即可获取到个人access token,如图:

注:此token要保存好,关闭页面后可能就看不到了

2、登录Jenkins–>系统管理–>凭据–>添加凭据,在密码位置输入token,如图:

配置完成后,页面如图:

在项目界面中连接git的凭据位置,选择刚配置的access_token凭据,如图:

Jenkinsfile中拉取代码的仓库地址要改为http方式的,然后修改凭据为上面配置access_token凭据,如图:

问题:

如果jenkin界面可以看到node版本,但是还是提示node: command not found,可能是权限不足,在npm 命令前面加上sudo即可,如:sudo npm install && sudo npm run build,或者使用绝对路径试试,比如/usr/bin/npm

标签