1 Pipeline
1.1 Pipeline定义
Pipeline是通过Jenkinsfile描述的流水线,安装声明式插件Pipeline:Declarative
Jenkensfile的组成:
- 指定node节点/workspace
- 指定运行选项
- 指定stages阶段
- 指定构建后操作
1.2 Pipeline语法
1.2.1 agent指定node节点/workspace
可选参数:
- any表示任何可用的节点上执行pipeline
- none为agent的默认值
- label表示在指定节点上运行
- node表示允许额外的选项
agent {
node {
label "master" // 指定运行节点的标签或名称
customWorkspace "${workspace}" // 指定运行的工作目录(可选)
}
}
复制代码
1.2.2 options指定运行选项
options指令允许从流水线内部配置特定的流水线选项,也可以由插件提供:
- buildDiscarder:为最近的流水线运行的特定数量保存组件和控制台输出
- disableConcurrentBuilds:不允许同时执行流水线,可防止同时访问共享资源
- overriderIndexTriggers:允许覆盖分支索引触发器的默认处理
- timeout:设置超时时间
- retry:失败后重新尝试的次数
- skipStagesAfterUnstable:一旦构建状态变为UNSTABLE,就跳过该阶段
options {
timestamps() // 在日志中打印时间
skipDefaultCheckout() // 删除隐式的checkout scm 语句
disableCouncurrentBuilds() // 禁止并行
timeout(time:1, unit:'HOURS') // 流水线超时设置为1H
}
复制代码
1.2.3 stages指定stages阶段
包含了一个或多个stage指令,用于连接交付过程中每个离散的部分
stages{
stage("PullCode") { // 阶段名称
steps { // 步骤
timeout(time:5, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("获取代码")
}
}
}
}
stage("Build") { // 阶段名称
steps { // 步骤
timeout(time:20, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("应用打包")
}
}
}
}
stage("CodeScan") { // 阶段名称
steps { // 步骤
timeout(time:30, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("代码扫描")
}
}
}
}
}
复制代码
1.2.4 post指定构建后操作
post-condition块:
- always{}:总是执行
- success{}:成功后执行
- failure{}:失败后执行
- aborted{}:取消后执行
- changed{}:当流水线或阶段完成状态和之前不同时执行
- unstable{}:当流水线或阶段状态为unstable时执行
post {
always {
println("总是执行")
}
success {
script {
// currentBuild是一个全局变量
// description是构建描述
currentBuild.description += "\n 构建成功!"
}
}
failure {
script {
currentBuild.description += "\n 构建失败!"
}
}
aborted {
script {
currentBuild.description += "\n 构建取消!"
}
}
}
复制代码
1.2.5 enviroment环境变量
用于指定一个键值对序列,用于定义所有/特定阶段步骤的环境变量,取决于environment定义的位置。支持credentials()方法,用于通过标识符访问jenkins预定义的凭证。相当于定义一个变量,可以在后续使用
pipeline {
agent any
enviroment {
CC = 'clang'
}
stages {
stage("example") {
enviroment {
ACC_KEY = credentails("my-secret-text")
}
steps {
sh 'printenv'
}
}
}
}
复制代码
1.2.6 parameter参数
为流水线运行时设置项目相关的参数
parameters {
string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '')
booleanParam(name: 'DEBUG_BUILD', defaultValue: true, descrptio: '')
}
复制代码
1.2.7 trigger触发器
构建触发器:
- cron计划任务定期执行构建:
triggers{cron('H */4 * * 1-5')}
- pollSCM与cron类型,由jenkins定期检测源码变化:
triggers{pollSCM('H */4 * * 1-5')}
- upstream接受都好分割的工作字符串和阈值,当字符串中任何作业以最小阈值结束时,流水线被重新触发
1.2.8 input人工确认
input由人工确认是否继续进行
- message:呈现给用户的提示信息
- id可选默认为stage名称
- ok默认表单的ok文本
- submitter:可选,逗号分隔的用户列表或允许提交的外部组名,默认允许任何用户
- parameter:提示提交者提供一个可选的参数列表
示例:
pipeline {
agent any
stages {
stage('SayHello') {
input {
message "Should we continue"
ok "Yes, we should"
submitter "xd1998"
parameters {
string(name: "PERSON", defaultValue: "JXD", description: "Who are you?")
}
}
steps {
echo "Hello ${PERSON}"
}
}
}
}
复制代码
1.2.9 when语法
放置在stage中,条件为true,stage执行。
- branch:构建的分支和给定的分支匹配则执行,适用于多分支流水线:
when {branch 'master'}
- environment:指定环境变量是给定值执行:
when {environment name: 'DEPLOY_TO', value:'prooduction'}
- expression:当指定的Groovy表达式评估为true时才执行:
when {expression {return params.DEBUG_BUILD}}
when语法根据参数值跳过执行的阶段
- not:当嵌套条件为false时执行:
when {not {branch 'master'}}
- allOf:当所有嵌套条件都为true才执行:
when {allOf {branch 'master'; environment name: 'DEPLOY_TO, value: 'production}}
- anyOf:当至少有一个嵌套条件为true时执行
pipeline {
agent any
parameters {
string(name: "PERSON", defaultValue: "JXD", description: "Who are you?")
}
stages{
stage('SayHello') {
input {
message "Should we continue"
ok "Yes, we should"
submitter "xd1998"
}
steps {
echo "Hello ${PERSON}"
}
}
stage("PullCode") { // 阶段名称
steps { // 步骤
timeout(time:5, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("获取代码")
}
}
}
}
stage("Build") { // 阶段名称
steps { // 步骤
timeout(time:20, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("应用打包")
}
}
}
}
stage("CodeScan") { // 阶段名称
when {
environment name: "PERSON",
value: 'JXD'
}
steps { // 步骤
timeout(time:30, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("代码扫描")
}
}
}
}
}
}
复制代码
2 Jenkins Share Library
src目录类似于标准的Java src目录结构,执行流水线时,将这个目录添加到类路径,vars目录托管脚本文件,这些脚本文件在管道中作为变量公开。resource目录允许libraryResource从外部库使用步骤来加载相关联的非Groovy文件。
(root)
- src # Groovy源文件
| -org
| -foo
| -Bar.groovy # org.foo.Bar 类
- vars
| -foo.groovy # 全局的foo变量
| -foo.txt # foo变量的help
- resources # 源文件(外部库)
| -org
| -foo
| -bar.json # org.foo.Bar的静态helper数据
复制代码
2.1 创建自己的共享库
在github中新建仓库,在src/org/devops下创建文件,定义共享方法
package org.devops
// 打印内容
def PrintMes(content) {
println(content)
}
复制代码
2.2 在Jenkins中配置共享库
先设置共享库的名称,后续在pipeline中通过@Library或者Library{}指定共享库。根据github的分支名称指定默认的版本
设置共享库中的源码管理
2.3 在流水线中使用共享库
#!groovy
@Library('jenkinslib') _
def tools = new org.devops.tools()
String workspace = "/opt/jenkins/workspace"
pipeline {
agent {
node {
label "master"
customWorkspace "${workspace}"
}
}
parameters {
string(name: "PERSON", defaultValue: "JXD", description: "Who are you?")
}
stages{
stage('SayHello') {
input {
message "Should we continue"
ok "Yes, we should"
submitter "xd1998"
}
steps {
echo "Hello ${PERSON}"
}
}
stage("PullCode") { // 阶段名称
steps { // 步骤
timeout(time:5, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("获取代码")
}
}
}
}
stage("Build") { // 阶段名称
steps { // 步骤
timeout(time:20, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("应用打包")
}
}
}
}
stage("CodeScan") { // 阶段名称
when {
environment name: "PERSON",
value: 'JXD'
}
steps { // 步骤
timeout(time:30, unit:'MINUTES') { // 指定步骤的超时时间
script { // 指定运行的脚本
println("代码扫描")
tools.PrintMes('this is mylib')
}
}
}
}
}
}
复制代码
3 Groovy
Groovy是功能强大可选类型的动态语言,支持Java平台,可以与Java集成,提供脚本编写、特定领域语言编写、运行时和编译时元编程及函数式编程。
3.1 安装Groovy
- 下载Groovy安装包
- 解压安装包
- 获取bin目录
- 将bin写入/etc/profile文件
export GROOVY_HOME=/opt/groovy
export PATH=$PATH:$GROOVY_HOME/bin
复制代码
- 生效:source /etc/profile
- 启动Groovy IDE:
groovyconsole
3.2 Groovy基础
数据类型String常用方法:
- contains()是否包含特定内容
- size() length()字符串长度
- toString()转为string类型
- indexOf()元素索引
- endWith()是否指定字符结尾
- minus() plus() 增加去掉字符串
- reverse() 反向排序
- substring(1,2)取子字符串
- toUpperCase() toLowerCase() 大小写转换
- split() 切分字符串
单引号引用普通字符串,双引号相当于模板字符串可以使用${}
引用变量
数据类型List常用方法:
- + – += -= 增删元素
- add() 添加元素
- isEmpty() 判空
- intersect() disjoint() 取交集、判断是否有交际
- flatten() 扁平化列表
- unique() 去重
- reverse() sort() 反转 排序
- count() 个数
- join() 连接
- sum() min() max() 求和、最值
- contains() 包含特定元素
- remove() removeAll()
- each() 遍历
定义函数
def PrintMessage(message) {
println(message)
}
复制代码
补充:常用的Pipeline DSL
- readJSON
- checkout
- publishHTML
- input
- credentials
- httpRequest
4 Jenkins工具集成
4.1 Maven集成
集成Maven、Gradle、Ant过程类似:下载压缩包,解压缩,找到bin目录,配置环境变量,让环境变量生效。在全局工具配置中配置home的位置(如果没找到配置的地方就安装插件),在pipeline中定义一个变量等于tool + “name” ,后续使用变量即可。
在github中新增jenkinsfile
pipeline {
agent {
node {
label "master"
}
}
stages {
stage("build") {
steps {
script {
mvnHome = tool "maven3.6.3"
sh "${mvnHome}/bin/mvn -v"
}
}
}
}
}
复制代码
从SCM中配置流水线
执行流水线,执行成功
4.2 NPM集成
- 安装node
- 在全局工具配置中配置home的位置
- 遇到一个报错:
/usr/bin/env: node: No such file or directory
,解决方法:添加软连接ln -s /usr/local/NODEJS_HOME/bin/node /usr/bin/node
4.3 使用共享库整合构建工具
4.4 Ansible集成
- 安装ansible
- 配置ssh
- 配置servers
将Ansible添加到流水线中
#!groovy
@Library('jenkinslib') _
def build = new org.devops.build()
def deploy = new org.devops.deploy()
String buildShell = "${env.buildShell}"
String buildType = "${env.buildType}"
String deployHosts = "${env.deployHosts}"
pipeline {
agent {
node {
label "master"
}
}
stages {
stage("build") {
steps {
script {
build.Build(buildType, buildShell)
deploy.AnsibleDeploy("${deployHosts}", "-m ping")
}
}
}
}
}
复制代码
引入的共享库:@Library('jenkinslib') _
package org.devops
def AnsibleDeploy(hosts, func) {
sh "ansible ${func} ${hosts}"
}
复制代码