目前支持的参数类型如下
string
:字符串类型的参数。text
:文本型参数,一般用于定义多行文本内容的变量。booleanParam
:布尔型参数。choice
:选择型参数,一般用于给定几个可选的值,然后选择其中一个进行赋值。password
:密码型变量,一般用于定义敏感型变量,在 Jenkins 控制台会输出为*。
插件 Parameters
imageTag
:镜像 tag,需要安装 Image Tag Parameter 插件后使用gitParameter
:获取 git 仓库分支,需要 Git Parameter 插件后使用
示例
pipeline { agent any parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '1') //执行构建时需要手动配置字符串类型参数,之后赋值给变量 text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '2') //执行构建时需要提供文本参数,之后赋值给变量 booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '3') //布尔型参数 choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '4') //选择形式列表参数 password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password') //密码类型参数,会进行加密 imageTag(name: 'DOCKER_IMAGE', description: '', image: 'kubernetes/kubectl', filter: '.*', defaultTag: '', registry: 'https://192.168.10.15', credentialId: 'harbor-account', tagOrder: 'NATURAL') //获取镜像名称与tag gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: '', description: 'Branch for build and deploy', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH') } //获取git仓库分支列表,必须有git引用 stages { stage('env1') { steps { sh "env" } } stage('git') { steps { git branch: "$BRANCH", credentialsId: 'gitlab-key', url: 'git@192.168.10.14:root/env.git' //使用gitParameter,必须有这个 } } } }
4.Triggers
在 Pipeline 中可以用 triggers 实现自动触发流水线执行任务,可以通过 Webhook、Cron、 pollSCM 和 upstream 等方式触发流水线。
Cron
定时构建假如某个流水线构建的时间比较长,或者某个流水线需要定期在某个时间段执行构建,可以 使用 cron 配置触发器,比如周一到周五每隔四个小时执行一次
注意:H 的意思不是 HOURS 的意思,而是 Hash 的缩写。主要为了解决多个流水线在同一时间同时运行带来的系统负载压力。
pipeline { agent any triggers { cron('H */4 * * 1-5') //周一到周五每隔四个小时执行一次 cron('H/12 * * * *') //每隔12分钟执行一次 cron('H * * * *') //每隔1小时执行一次 } stages { stage('Example') { steps { echo 'Hello World' } } } }
Upstream
Upstream 可以根据上游 job 的执行结果决定是否触发该流水线。比如当 job1 或 job2 执行成功时触发该流水线
目前支持的状态有 SUCCESS
、UNSTABLE
、FAILURE
、NOT_BUILT
、ABORTED
等。
pipeline { agent any triggers { upstream(upstreamProjects: 'env', threshold: hudson.model.Result.SUCCESS) //当env构建成功时构建这个流水线 } stages { stage('Example') { steps { echo 'Hello World' } } } }
5.Input
Input 字段可以实现在流水线中进行交互式操作,比如选择要部署的环境、是否继续执行某个阶段等。
配置 Input 支持以下选项
- message:必选,需要用户进行 input 的提示信息,比如:“是否发布到生产环境?”;
- id:可选,input 的标识符,默认为 stage 的名称;
- ok:可选,确认按钮的显示信息,比如:“确定”、“允许”;
- submitter:可选,允许提交 input 操作的用户或组的名称,如果为空,任何登录用户均可提交 input;
- parameters:提供一个参数列表供 input 使用。
假如需要配置一个提示消息为“还继续么”、确认按钮为“继续”、提供一个 PERSON 的变量的参数,并且只能由登录用户为 alice 和 bob 提交的 input 流水线
pipeline { agent any stages { stage('Example') { input { message "还继续么?" ok "继续" submitter "alice,bob" parameters { string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?') } } steps { echo "Hello, ${PERSON}, nice to meet you." } } } }
6.when
When 指令允许流水线根据给定的条件决定是否应该执行该 stage,when 指令必须包含至少 一个条件。如果 when 包含多个条件,所有的子条件必须都返回 True,stage 才能执行。
When 也可以结合 not、allOf、anyOf 语法达到更灵活的条件匹配。
目前比较常用的内置条件如下
branch
:当正在构建的分支与给定的分支匹配时,执行这个 stage。注意,branch 只适用于多分支流水线changelog
:匹配提交的 changeLog 决定是否构建,例如:when { changelog '.*^\\[DEPENDENCY\\] .+$' }
environment
:当指定的环境变量和给定的变量匹配时,执行这个 stage,例如:when { environment name: 'DEPLOY_TO', value: 'production' }
equals
:当期望值和实际值相同时,执行这个 stage,例如:when { equals expected: 2, actual: currentBuild.number }
;expression
:当指定的 Groovy 表达式评估为 True,执行这个 stage,例如:when { expression { return params.DEBUG_BUILD } }
;tag
:如果 TAG_NAME 的值和给定的条件匹配,执行这个 stage,例如:when { tag "release-" }
;not
:当嵌套条件出现错误时,执行这个 stage,必须包含一个条件,例如:when { not { branch 'master' } }
;allOf
:当所有的嵌套条件都正确时,执行这个 stage,必须包含至少一个条件,例如:when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
;anyOf
:当至少有一个嵌套条件为 True 时,执行这个 stage,例如:when { anyOf { branch 'master'; branch 'staging' } }
。
示例:当分支为 main 时执行 Example Deploy 步骤
pipeline { agent any stages { stage('Example Build') { steps { echo 'Hello World' } } stage('Example Deploy') { when { branch 'main' //多分支流水线,分支为才会执行。 } steps { echo 'Deploying' } } } }
也可以同时配置多个条件,比如分支是 production,而且 DEPLOY_TO 变量的值为 main 时,才执行 Example Deploy
pipeline { agent any environment { DEPLOY_TO = "main" } stages { stage('Example Deploy') { when { branch 'main' environment name: 'DEPLOY_TO', value: 'main' } steps { echo 'Deploying' } } } }
也可以使用 anyOf 进行匹配其中一个条件即可,比如分支为 main 或 DEPLOY_TO 为 main 或 master 时执行 Deploy
pipeline { agent any stages { stage('Example Deploy') { when { anyOf { branch 'main' environment name: 'DEPLOY_TO', value: 'main' environment name: 'DEPLOY_TO', value: 'master' } } steps { echo 'Deploying' } } } }
也可以使用 expression 进行正则匹配,比如当 BRANCH_NAME 为 main 或 master,并且 DEPLOY_TO 为 master 或 main 时才会执行 Example Deploy
pipeline { agent any stages { stage('Example Deploy') { when { expression { BRANCH_NAME ==~ /(main|master)/ } anyOf { environment name: 'DEPLOY_TO', value: 'main' environment name: 'DEPLOY_TO', value: 'master' } } steps { echo 'Deploying' } } } }
默认情况下,如果定义了某个 stage 的 agent,在进入该 stage 的 agent 后,该 stage 的 when 条件才会被评估,但是可以通过一些选项更改此选项。比如在进入 stage 的 agent 前评估 when, 可以使用 beforeAgent,当 when 为 true 时才进行该 stage
目前支持的前置条件如下
beforeAgent
:如果 beforeAgent 为 true,则会先评估 when 条件。在 when 条件为 true 时,才会进入该 stagebeforeInput
:如果 beforeInput 为 true,则会先评估 when 条件。在 when 条件为 true 时,才会进入到 input 阶段;beforeOptions
:如果 beforeInput 为 true,则会先评估 when 条件。在 when 条件为 true 时,才会进入到 options 阶段;- beforeOptions 优先级
大于
beforeInput大于
beforeAgent
示例
pipeline { agent none stages { stage('Example Build') { steps { echo 'Hello World' } } stage('Example Deploy') { when { beforeAgent true branch 'main' } steps { echo 'Deploying' } } } }
Parallel
在声明式流水线中可以使用 Parallel 字段,即可很方便的实现并发构建,比如对分支 A、B、 C 进行并行处理
pipeline { agent any stages { stage('Non-Parallel Stage') { steps { echo 'This stage will be executed first.' } } stage('Parallel Stage') { failFast true //表示其中只要有一个分支构建执行失败,就直接推出不等待其他分支构建 parallel { stage('Branch A') { steps { echo "On Branch A" } } stage('Branch B') { steps { echo "On Branch B" } } stage('Branch C') { stages { stage('Nested 1') { steps { echo "In stage Nested 1 within Branch C" } } stage('Nested 2') { steps { echo "In stage Nested 2 within Branch C" } } } } } } } }
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
Jenkinsfile 的使用
上面讲过流水线支持两种语法,即声明式和脚本式,这两种语法都支持构建持续交付流水线。并且都可以用来在 Web UI 或 Jenkinsfile 中定义流水线,不过通常将 Jenkinsfile 放置于代码仓库中(当然也可以放在单独的代码仓库中进行管理)。
创建一个 Jenkinsfile 并将其放置于代码仓库中,有以下好处
- 方便对流水线上的代码进行复查/迭代
- 对管道进行审计跟踪
- 流水线真正的源代码能够被项目的多个成员查看和编辑
环境变量
1.静态变量
Jenkins 有许多内置变量可以直接在 Jenkinsfile 中使用,可以通过 JENKINS_URL/pipeline/syntax/globals#env
获取完整列表。目前比较常用的环境变量如下
BUILD_ID
:当前构建的 ID,与 Jenkins 版本 1.597+中的 BUILD_NUMBER 完全相同BUILD_NUMBER
:当前构建的 ID,和 BUILD_ID 一致BUILD_TAG
:用来标识构建的版本号,格式为:jenkins-{BUILD_NUMBER}, 可以对产物进行命名,比如生产的 jar 包名字、镜像的 TAG 等;BUILD_URL
:本次构建的完整 URL,比如:http://buildserver/jenkins/job/MyJobName/17/%EF%BC%9BJOB_NAME
:本次构建的项目名称NODE_NAME
:当前构建节点的名称;JENKINS_URL
:Jenkins 完整的 URL,需要在 SystemConfiguration 设置;WORKSPACE
:执行构建的工作目录。
示例如果一个流水线名称为print_env,第 2 次构建,各个变量的值。
BUILD_ID:2 BUILD_NUMBER:2 BUILD_TAG:jenkins-print_env-2 BUILD_URL:http://192.168.10.16:8080/job/print_env/2/ JOB_NAME:print_env NODE_NAME:built-in JENKINS_URL:http://192.168.10.16:8080/ WORKSPACE:/bitnami/jenkins/home/workspace/print_env
上述变量会保存在一个 Map 中,可以使用 env.BUILD_ID 或 env.JENKINS_URL 引用某个内置变量
pipeline { agent any stages { stage('print env') { parallel { stage('BUILD_ID') { steps { echo "$env.BUILD_ID" } } stage('BUILD_NUMBER') { steps { echo "$env.BUILD_NUMBER" } } stage('BUILD_TAG') { steps { echo "$env.BUILD_TAG" } } } } } }
2.动态变量
动态变量是根据某个指令的结果进行动态赋值,变量的值根据指令的执行结果而不同。如下所示
returnStdout
:将命令的执行结果赋值给变量,比如下述的命令返回的是 clang,此时 CC 的值为“clang”。returnStatus
:将命令的执行状态赋值给变量,比如下述命令的执行状态为 1,此时 EXIT_STATUS 的值为 1。
//Jenkinsfile (Declarative Pipeline) pipeline { agent any environment { // 使用 returnStdout CC = """${sh( returnStdout: true, script: 'echo -n "clang"' //如果使用shell命令的echo赋值变量最好加-n取消换行 )}""" // 使用 returnStatus EXIT_STATUS = """${sh( returnStatus: true, script: 'exit 1' )}""" } stages { stage('Example') { environment { DEBUG_FLAGS = '-g' } steps { sh 'printenv' } } } }
凭证管理
Jenkins 的声明式流水线语法有一个 credentials()函数,它支持 secret text(加密文本)、username 和 password(用户名和密码)以及 secret file(加密文件)等。接下来看一下一些常用的凭证处理方法。
1.加密文本
本实例演示将两个 Secret 文本凭证分配给单独的环境变量来访问 Amazon Web 服务,需要 提前创建这两个文件的 credentials(实践的章节会有演示),Jenkinsfile 文件的内容如下
//Jenkinsfile (Declarative Pipeline) pipeline { agent any environment { AWS_ACCESS_KEY_ID = credentials('txt1') AWS_SECRET_ACCESS_KEY = credentials('txt2') } stages { stage('Example stage 1') { steps { echo "$AWS_ACCESS_KEY_ID" } } stage('Example stage 2') { steps { echo "$AWS_SECRET_ACCESS_KEY" } } } }
2.用户名密码
本示例用来演示 credentials 账号密码的使用,比如使用一个公用账户访问 Bitbucket、GitLab、 Harbor 等。假设已经配置完成了用户名密码形式的 credentials,凭证 ID 为 harbor-account
//Jenkinsfile (Declarative Pipeline) pipeline { agent any environment { BITBUCKET_COMMON_CREDS = credentials('harbor-account') } stages { stage('printenv') { steps { sh "env" } } }
上述的配置会自动生成 3 个环境变量
BITBUCKET_COMMON_CREDS
:包含一个以冒号分隔的用户名和密码,格式为 username:passwordBITBUCKET_COMMON_CREDS_USR
:仅包含用户名的附加变量BITBUCKET_COMMON_CREDS_PSW
:仅包含密码的附加变量。
3.加密文件
需要加密保存的文件,也可以使用 credential,比如链接到 Kubernetes 集群的 kubeconfig 文件等。
假如已经配置好了一个 kubeconfig 文件,此时可以在 Pipeline 中引用该文件
//Jenkinsfile (Declarative Pipeline) pipeline { agent { kubernetes { cloud 'kubernetes' slaveConnectTimeout 1200 workspaceVolume emptyDirWorkspaceVolume() yaml ''' kind: Pod metadata: name: jenkins-agent spec: containers: - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\'] image: '192.168.10.15/kubernetes/jnlp:alpine' name: jnlp imagePullPolicy: IfNotPresent - command: - "cat" image: "192.168.10.15/kubernetes/kubectl:apline" imagePullPolicy: "IfNotPresent" name: "kubectl" tty: true restartPolicy: Never ''' } } environment { MY_KUBECONFIG = credentials('kubernetes-cluster') } stages { stage('kubectl') { steps { container(name: 'kubectl') { sh """ kubectl get pod -A --kubeconfig $MY_KUBECONFIG """ } } } } }