jenkins 多分枝流水线(pipeline)及 美化通知消息
之前 我们已经通过 Jenkinsfile 完成了最简单的项目的构建和部署(部署这里暂时没有更新文章),那么我们来思考目前的方式:
- 目前都是在项目的单一分支下进行操作,企业内一般会使用feature、develop、release、master 等多个分支来管理整个代码提交流程,如何根据不同的分支来做构建?
- 构建视图中如何区分不同的分支?
- 如何不配置webhook的方式实现构建?
- 如何根据不同的分支选择发布到不同的环境(开发、测试、生产)?
多分枝流水线
我们简化一下流程,假如使用develop分支作为开发分支,master分支作为集成测试分支,看一下如何 使用多分支流水线来管理。
多分支流水线的使用
-
提交develop分支:
# 直接创建分枝并提交 git checkout -b dev git push --set-upstream origin dev
-
jenkins 创建一个多分支项目
-
增加git分支源
-
发现标签、分支
-
根据名称过滤,develop|master|v.*
可以根据正则表达式,选择哪些分支可以去构建jenkins任务
-
高级克隆,设置浅克隆
浅克隆深度为2,表示只拉取最近两次的变更记录;节约磁盘;
保存后,会自动检索项目中所有存在Jenkinsfile文件的分支和标签,若匹配我们设置的过滤正则表达 式,则会添加到多分支的构建视图中。所有添加到视图中的分支和标签,会默认执行一次构建任务。
-
上图表示,这次匹配的分支中带有jenkinsfile 的分支。继续形成构建视图;往下走;没有jenkinsfile 的分支被丢弃;不参与构建任务;
表示 创建一个触发器,每分钟去扫描符合上述条件的分支;
这样的话,就不需要去配置触发器了;这里使用jenkins自己的扫描来做;这就可能会带来延迟;并且给jenkins带来一些额外的扫描压力;
当我们保存项目后,默认jenkins会自动去扫描一次;识别到匹配的扫描,jenkins就会触发构建任务;
保存后如下图:
识别了两个分支,一个为 dev 另外一个为 main;
因为我们没有为测试代码打标签;所以没有扫描到标签;
美化通知消息
因为以前是单分支,现在是多分枝;
所以推送的消息也应该做一些格式上的修改;
- 增加分支消息;
- 将推送消息写成markdown格式(支持加粗、等)
- 增加 gitlog 输出
如下:
// # Jekinsfile 中调用
// # cat Jenkinsfile
pipeline {
agent { label '10.23.1.33'}
environment {
IMAGE_REPO = "myblog"
//顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
// 获取 dingTalk 的密文
DINGTALK_CREDS = credentials('97bd1f06-a2c7-48fa-83aa-b10de2c6a2fd')
// 做了个换行
TAB_STR = "\n \n "
}
stages {
stage('printenv') {
steps {
script{
sh "git log --oneline -n 1 > gitlog.file"
env.GIT_LOG = readFile("gitlog.file").trim()
}
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout scm
script{
// 每个 stage 环节都更新了一个 env.BUILD_TASKS 环境变量
// 在哪个 stage 中,该环境变量就是谁,在该stage中 该变量 == check
env.BUILD_TASKS = env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('build-image') {
steps {
// 重试两次
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('push-image') {
steps {
// 因为这里咱们没有做 容器仓库,所以这里不 push ,写出来只为了线上可以参考
// retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('deploy') {
steps {
// 同样这里没有部署的环节,写出来只为了线上参考
// sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' deploy/*"
// timeout(time: 1, unit: 'MINUTES') {
// sh "kubectl apply -f deploy/"
// }
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "🐮 构建成功 🐮 \n**项目关键字**:jenkins-hk \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**:${RUN_DISPLAY_URL} \n**构建任务**:${BUILD_TASKS}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "😖❌ 构建失败 ❌😖 \n**项目关键字**:jenkins-hk \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**:${RUN_DISPLAY_URL} \n**构建任务**:${BUILD_TASKS}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
消息通知界面:
通知gitlab构建状态
Jenkins端做了构建,可以通过gitlab的api将构建状态通知过去,作为开发人员发起Merge Request或者合并Merge Request的依据之一。
注意一定要指定 gitLabConnection (gitlab),不然没法认证到 Gitlab 端
gitlab 配置
需要用的如下的 gitlab 名称:gitlab-hk
系统管理 -> 系统配置 -> gitlab
// # Jekinsfile 中调用
// # cat Jenkinsfile
pipeline {
agent { label '10.23.1.33'}
options {
// 构建历史 保留 10 条
buildDiscarder(logRotator(numToKeepStr: '10'))
disableConcurrentBuilds()
timeout(time: 20, unit: 'MINUTES')
// gitlab connection
gitLabConnection('gitlab-hk')
}
environment {
IMAGE_REPO = "myblog"
//顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
// 获取 dingTalk 的密文
DINGTALK_CREDS = credentials('97bd1f06-a2c7-48fa-83aa-b10de2c6a2fd')
// 做了个换行
TAB_STR = "\n \n "
}
stages {
stage('printenv') {
steps {
script{
sh "git log --oneline -n 1 > gitlog.file"
env.GIT_LOG = readFile("gitlog.file").trim()
}
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout scm
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
// 每个 stage 环节都更新了一个 env.BUILD_TASKS 环境变量
// 在哪个 stage 中,该环境变量就是谁,在该stage中 该变量 == check
env.BUILD_TASKS = env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('build-image') {
steps {
// 重试两次
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('push-image') {
steps {
// 因为这里咱们没有做 容器仓库,所以这里不 push ,写出来只为了线上可以参考
// retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
stage('deploy') {
steps {
// 同样这里没有部署的环节,写出来只为了线上参考
// sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' deploy/*"
// timeout(time: 1, unit: 'MINUTES') {
// sh "kubectl apply -f deploy/"
// }
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "🐮 构建成功 🐮 \n**项目关键字**:jenkins-hk \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**:${RUN_DISPLAY_URL} \n**构建任务**:${BUILD_TASKS}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "😖❌ 构建失败 ❌😖 \n**项目关键字**:jenkins-hk \n**Git log**: ${GIT_LOG} \n**构建分支**: ${GIT_BRANCH} \n**构建地址**:${RUN_DISPLAY_URL} \n**构建任务**:${BUILD_TASKS}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
构建之后,会有一个这样的状态;
提交merge request,也可以查看到相关的任务状态,可以作为项目owner合并代码的依据之一:
本文来自博客园, 作者:Star-Hitian, 转载请注明原文链接:https://www.cnblogs.com/Star-Haitian/p/16521575.html