GitLABJenkins
GitLAB & Jenkins


目录

实践:基于Jenkins提交流水线(测试成功)-2023.4.25
目的:掌握通过触发器将GitLab和Jenkins集成,实现提交流水线。


1、触发Jenkins构建
安装Generic Webhook Trigger插件

重启后,进入一个Pipeline项目设置,已经可以选择这个触发器了…

插件文档:https://plugins.jenkins.io/generic-webhook-trigger/

Jenkins作业配置触发器
启动Generic Webhook触发器后, 相当于给Jenkins加了一个新的接口(http://JENKINS_URL/generic-webhook-trigger/invoke)。


调用的时候:这里要把 JENKINS_URL 换成自己真实的Jenkins 服务器地址,有端口就加上端口,是域名就写域名。下面是一个参考的URL:
http://192.168.1.200:8080/generic-webhook-trigger/invoke
Post content parameters: 获取调用接口传进来的数据
JsonPath语法文档: https://github.com/json-path/JsonPath

Header parameters: 获取Header中的参数


Request parameters: 获取URL中的请求参数
curl http://192.168.1.200:8080/generic-webhook-trigger/invoke?runopts=gitlab

Token: 给URL添加一个触发的认证
curl http://192.168.1.200:8080/generic-webhook-trigger/invoke?token=devops-service

打印调试信息到日志中

触发条件过滤:仅满足条件才能触发此作业

创建测试项目
- 创建一个叫做
devops-demo-service的jenkins作业(这里的作业名称和gitlab里的项目名称推荐保持一致)

- 要加一个唯一的token,不然会触发所有token一样的项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZFLY8ZF-1682425393155)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423062932520.png)]
- 把这2个选项勾选上

- 此时在postman里测试触发
触发url http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service

这里记得要加一个basic auth:



可以看到触发成功了。
- 演示将postman中的请求转换curl方式。

curl --location --request POST 'http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service' \
--header 'Authorization: Basic YWRtaW46YWRtaW4='


可以看到,也是能构建成功的。
解析GET/POST请求数据
传参注意,第一个参数使用?号连接, 后面的参数使用&符号连接。
?token=demo-pipeline-service&user=jenkins&a=1&b=2
解析GET数据
- 客户端发送Get请求, 带有两个参数
version和username。
http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service&version=1.1.1&username=jenkins

- Jenkins 配置Generic hook,获取请求参数
version和username(参数名称要一致)

- 验证测试(Jenkins日志中能够打印出获取的值,则正常)


哎,这里怎么没显示一些变量呢??

这里简单写一个pipeline把。


可以看到效果了。
- 通过jenkinsfile读取传递的参数,再次触发
currentBuild.displayName = "${version}"println("${version}")
println("${username}")pipeline {agent anystages {stage('Hello') {steps {echo 'Hello World'}}}
}
再次postman触发,观察效果:(符合预期)


解析HEADER参数数据
- 客户端发送请求(什么请求都可以,这里的header与请求类型无关), 带有两个参数 devops和 tool-name。

- Jenkins 配置Generic hook,获取请求参数devops和 tool-name 。

- 通过jenkinsfile读取传递的参数
注意,这里的pipeline代码如果打印tool-name变量的话,会报错的


这里要使用下划线来替换横杠:


再次触发,就正常了,符合预期。

解析POST数据
- 客户端发送POST请求, 参数存储在body体中(参考POSTMAN中的样例)

- Jenkins 配置触发器来获取Post参数。
删除之前测试的header参数,request参数。
$代表/,获取所有数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYZuhkun-1682425393160)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423075557421.png)]
获取name字段

- Jenkinsfile中使用参数

触发:

验证:


扩展流水线解析JSON数据
- 安装插件:
Pipeline Utility Steps

- readJSON: 处理json数据
currentBuild.displayName = "${name}"println("${Data}")NewData = readJSON text: "${Data}"
envName = NewData["envName"]
appsName = NewData["apps"]["name"]pipeline {agent anystages {stage('Hello') {steps {script {println("${envName}")println("${appsName}")}}}}
}
再次构建:
验证:(符合预期)


Rebuilder插件使用
可以直接携带原触发参数进行触发,不用重复触发(不用在重复的提交代码了)。

进入某一次构建后,可以点击rebuild。

2、获取触发参数
1.触发器配置
Jenkins开启trigger
目的: 开启trigger后,就可以实现其他系统通过一个指定的URL进行自动触发构建了;
新建一个文件夹存放对应GitLab仓库组中的流水线。这里建议用仓库组的名称作为文件夹的名称devops03;
用Gitlab项目名称与流水线命名; devops03-demo-service项目;


- 开启Generic webhook;
- 配置触发Token,例如:作业名称
devops03-demo-service(这个token是流水线触发需要传递的); - 生成的触发URL;

http://192.168.1.200:8080/generic-webhook-trigger/invoke?token=devops03-demo-service
(此时,已经生成了触发URL,接着可以使用Curl或者Postman进行触发测试了!)
自己本次的这部分配置已经配置完成了。
- 这里还原下,删除之前的变量,这里只保留Data。

- 修改下pipeline代码

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")pipeline {agent anystages {stage('Hello') {steps {script {println("${NewData}")}}}}
}
配置GitLab WebHook
进入GitLab项目设置, 进入 webhook配置页面;
-
配置要触发的URL,即Jenkins触发器接口URL;
-
选择发生哪种GitLab事件后触发此Webhook;例如:Push提交代码、Tag创建标签等等;
-
在gitlab的项目里配置好webhook
http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service


事件:
-
Push 提交事件
-
Tag Push 创建事件
-
MergeRequest 合并事件
-
Issue 问题创建更新事件
-
测试模拟触发
模拟事件触发,点击test按钮选择push事件,此时去看下Jenkins是否成功被触发。
这里稍微测试下:
点击Test

触发成功则提示: Hook executed successfully: HTTP 200, 此时可以看下Jenkins是否已经触发了一次构建;


Webhook问题排查调试
进入webhook添加页面的最下方,点击你所创建的webhook的 Edit按钮 ;

webhook历史记录: 此记录可以判断,当前动作提交是否产生了webhook。

点击 View details 可以看到此webhook发送给对端Jenkins的数据信息,和请求状态。
- 200: 表示触发Jenkins请求成功;
- Resend Request: 重新发送请求;(此处便于排查调试错误)
- RequestBody: GitLab传递给Jenkins的数据信息;

假如请求由于xxx原因导致没有触发jenkins构建, 可以在这里点击 Resend Request 按钮进行重新发送请求,而不是再次提交代码。

如果Jenkins触发成功了之后,我们可以在Jenkins的构建日志中查看效果。 这些数据就是gitlab post传递过来的。

到此:你基本上已经知道了Gitlab如何触发Jenkins的了。(多看几遍,多练习几遍)
2.提交流水线优化
过滤新建分支和tag的触发
你可能发现问题了,新建一个分支或者标签也会出现构建,这个构建是没有意义的。我们需要排除掉。没错,jenkins 的 Generic webHook 也是支持的。
参考官方的说明:https://github.com/jenkinsci/generic-webhook-trigger-plugin/blob/master/src/test/resources/org/jenkinsci/plugins/gwt/bdd/gitlab/gitlab-push-ignore-create-remove-branch.feature

添加三个变量,获取当前的提交信息 $object_kind $before $after
(此步骤一定要注意下参数名和值后面的空格,要去掉)

通过正则表达式配置触发条件:Expression ^push\s(?!0{40}).{40}\s(?!0{40}).{40}$ Text $object_kind $before $after。 push请求只有after和before的值都不是40个0的时候触发构建(为40个0的情况是删除分支或者新建分支)

本次测试过程:
- 我们在gitlab上新创建一个分支

可以看到,gitlab上新创建一个分支后,就会触发jenkins流水线,这不是我们所期望的,因此下面将进一步优化。

- 在jenlins侧如何过滤出一些构建:
before如果是40个0的话,那么可能是创建分支;
after如果是40个0的话,那么可能是合并分支;


- 这里先编辑jenkins上流水线的触发过滤条件

通过正则表达式配置触发条件:Expression ^push\s(?!0{40}).{40}\s(?!0{40}).{40}$ Text $object_kind $before $after。 push请求只有after和before的值都不是40个0的时候触发构建(为40个0的情况是删除分支或者新建分支)
\s是空格

配置完成后,保存。
gitlab上再新建分支,观察是否会触发jenkins?

可以看到gitlab上已经成功触发了,但是被jenkins过滤掉了,符合预期。😘


如何支持多个分支触发构建?
方法1:创建多个gitlab webhook, 设置不同的分支,最终指向同一个jenkins 作业;

方法2:过滤
gitlab上设置,只允许feature开头的分支才可以进行触发:

编辑gitlab上的webhook配置:

3、自动触发Pipeline
- 这里写下代码
获取项目地址:


获取分支名:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zds29h2j-1682425393170)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423214640427.png)]
下载代码:
利用片段生成器生成代码:

创建gitlab-root凭据:


生成代码:
checkout([$class: 'GitSCM', branches: [[name: 'main']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: 'srcUrl']]])
继续编写代码:
println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// current build desc
currentBuild.displayName = "${branchName}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}
}

将写好的代码保存到jekins里。
- 在gitlab任意分支做个提交:
我们先拉取下代码:

在feature-dev-01编辑README.md文件并推送。
Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ cat README.md
情出自愿-事过无悔Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ echo 佳 >> README.mdWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git add .
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches itWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git commit -m "佳"
[feature-dev-01 683b378] 佳1 file changed, 1 insertion(+)Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git push origin feature-dev-01
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 287 bytes | 287.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for feature-dev-01, visit:
remote: http://172.29.9.101:8076/devops6/devops-demo-service/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature-dev-01
remote:
To http://172.29.9.101:8076/devops6/devops-demo-service.git7cf5639..683b378 feature-dev-01 -> feature-dev-01Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$
- 此时可以看到jenkins里的流水线被触发了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqRmpjvu-1682425393171)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424063019832.png)]

- 这里再在新建一个分支,用于测试,看是否会触发jebnkins流水线
Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git checkout -b feature-003
Switched to a new branch 'feature-003'Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ ls
HELP.md README.md mvnw* mvnw.cmd pom.xml src/Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ echo "i am very hurt" > README.mdWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git add .
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches itWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git commit -m "hurt"
[feature-003 1de466b] hurt1 file changed, 1 insertion(+), 2 deletions(-)Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git push origin feature-003
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 262 bytes | 262.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for feature-003, visit:
remote: http://172.29.9.101:8076/devops6/devops-demo-service/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature-003
remote:
To http://172.29.9.101:8076/devops6/devops-demo-service.git* [new branch] feature-003 -> feature-003Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$
可以看到,jenkins流水线被触发了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uKeDH3jU-1682425393172)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424063427563.png)]
🍀 之前代码

webhookData = readJSON text: "${webhook_data}"//分支名称
env.branchName = webhookData["ref"] - "refs/heads/"
env.projectUrl = webhookData["project"]["git_http_url"]
env.userEmail = webhookData["user_email"]//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('Checkout') {steps {script{//checkout checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'd7e4e500-e5c6-4673-ae4b-d43bf4ff5d19', url: "${env.projectUrl}"]]])}}}stage('Build'){steps{script{sh "mvn clean package -DskipTests"}}}stage('test'){steps{script{sh "mvn test"}}}}post {always{script{EmailUser("${env.userEmail}",currentBuild.currentResult)}}}
}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li> <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li> <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr> </table> </body> </html> """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
- 进一步更新代码
此时,想要commitId的前8位该如何取呢?
这样处理就好:

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// Get short commit id 想要commitId的前8位
env.commitId = NewData["checkout_sha"][0..7]// current build desc
currentBuild.displayName = "${branchName}:${env.commitId}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}
}
触发测试:(符合预期)

4、手动触发流水线
很简单的,就是在jenkins项目里添加一些选项参数,把这些变量写死在选项参数里就好。
自动触发和手动触发的可以并存的,例如写一些If ……else,但是不推荐。
手动触发:例如有一些版本分支,这些分支名是会变的,因此不是很方便;但是如果不想每次提交都触发流水线,而是等到一个小版本后再触发,这个用手动触发也是可以的哦。

//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('Checkout') {steps {script{//checkout checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'd7e4e500-e5c6-4673-ae4b-d43bf4ff5d19', url: "${env.projectUrl}"]]])}}}stage('Build'){steps{script{sh "mvn clean package -DskipTests"}}}stage('test'){steps{script{sh "mvn test"}}}}
}
这里做下测试:
- jenkins上创建项目
gitlab-jenkins-service-manual,配置好选项参数。


- 编写pipeline代码
//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('CheckOut') {steps {script {println("Checkout: ${projectUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${projectUrl}"]]])sh 'ls -l'}}} stage('Build'){steps{script{println("mvn clean package -DskipTests") }}}stage('test'){steps{script{println("mvn test")}}}}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWq1xNg3-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425065947246.png)]
- 准备好一个gitlab项目就好。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jdHoDId-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425070037754.png)]
- 测试(符合预期)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4dfgOONl-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425065814820.png)]
5、Jenkins消息通知
添加邮箱
邮箱是标配吧。(钉钉机器人也是可以的)
- 默认情况可能每个Gitlab用户没有配置邮箱的, 需要Gitlab用户要配置好邮箱。

- 点击头像进入 edit profile
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oU6PqOcc-1682425393174)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424123355.png)]
添加自己邮箱:

这里需要登录到自己的邮箱去确认下:
方法1:或者按如下方式直接配置好自己的gitlab邮箱为qq邮箱:(强制更改) 本次是强制更改的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1VidOF8-1682425393174)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424204730808.png)]
点击Edit:

这里配置好自己的邮箱,点击保存:

可以看到这里的邮箱被确认了:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CTNLrvSR-1682425393175)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205009192.png)]
方法2:在自己的邮箱里确认。
- 奇怪,我这里怎么163、qq邮箱都收不到确认邮件呢??😥

- 经过百度,发现是在gitlab里的配置文件要做下配置的:
[root@devops ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11a54a1f4a2a gitlab/gitlab-ce:14.9.3-ce.0 "/assets/wrapper" 6 days ago Up 28 hours (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:2222->22/tcp devops_tutorial_gitlab
f3f039aa667a jenkins/jenkins:2.332.2-centos7-jdk8 "/sbin/tini -- /usr/…" 4 weeks ago Up 24 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp jenkins
[root@devops ~]#docker exec -it devops_tutorial_gitlab bash
root@11a54a1f4a2a:/# vi /etc/gitlab/gitlab.rb
#搜索smtp
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.163.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "onexlforyou@163.com"
gitlab_rails['smtp_password'] = "NVSMOUfffAxxxccEMXAB"
gitlab_rails['smtp_domain'] = "163.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = 'onexlforyou@163.com'root@11a54a1f4a2a:/# gitlab-ctl reconfigure



- 此时,发下就可以正常识别到自己的邮箱了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZ6LEB58-1682425393176)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20220512231531784.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QZxrlTV3-1682425393176)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20220512231618636.png)]
- 参考链接:
http://t.zoukankan.com/zgz345-p-9122146.html

- 在这个页面配置好邮箱地址,最好这几个email都配置上吧…最后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yTiQhTTT-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205222529.png)]
- 这里在gitlab上提交一次代码,确认post请求里的数据体是否含
user_email信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G0nCvZFA-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205446256.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31XOyYPn-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205511731.png)]

可以看到,这里的user_email数据是有了。
安装Email Extension插件
- Jenkins需要配置邮件通知,安装插件
Email Extension安装后重启Jenkins。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItnszpQZ-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424205619.png)]
- 然后进入系统管理->
系统设置, 先配置下全局的admin的邮箱地址。(最后配置下不然可能会出错的)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pm9S1M6c-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205904038.png)]
拿到邮箱授权码
- 登入邮箱拿到授权码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hj46fHWs-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424210549.png)]
zpnchpffffgggvnfgfeqwggzhgecef
发送短信之后获取授权码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uMNFQ6Ov-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424210610.png)]
配置Email Extension
- ->
Extended E-email Notification。设置邮件系统配置信息。
这里我使用的是QQ邮箱,填写SMTP服务器地址smtp.qq.com 和端口 465注意要开启SSL,密码为授权码。
这里写下自己的qq的授权码凭证:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yq5sxTb9-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424211243147.png)]
- 换个选项注意下: 不选择
HTML就是普通的文本,HTML可以支持html网页,更加美观。这里选择HTML
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hAAXK4j-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424211401396.png)]
编写代码
- pipeline as code , 进入片段生成器,生成邮件通知代码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmNU2xzm-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424211508.png)]
emailext body: 'hello world!....jenkins', subject: 'test.....', to: '2560350642@qq.com'
然后我们将此段代码加入到Jenkins pipeline 中运行, 可以看到效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88VOg56c-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424211545.png)]
- jenkins as code 将email 写成一个函数。这个通知信息是一个html格式的。
def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li> <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li> <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr> </table> </body> </html> """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
- 这里继续编写下代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uyXhJU4i-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424212344209.png)]
println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// Get git user email
userEmail = NewData["user_email"]// current build desc
currentBuild.displayName = "${branchName}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}post {always{script{EmailUser(userEmail,"${currentBuild.currentResult}")}}}}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li> <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li> <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr> </table> </body> </html> """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zMluC30w-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220307725.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EdJCbw0P-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220258311.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y1cjr9Vu-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220237905.png)]
触发测试
- 提交下代码,触发下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Me3WP333-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424212630637.png)]
- 自己的测试现象(符合预期)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoccgQGI-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214039852.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fM9J30cm-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214104233.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kE3BBZoj-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214122673.png)]
解决默认图片显示异常问题
- 可以看到这里的人图片显示异常,这里我们使用oss路径来存储图片就可以了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rLK47nvC-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220342128.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwsrlHfV-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425161711144.png)]
本次最新代码(测试成功)
//打印jenkins的Generic Webhook Trigger接收到的数据,默认为字符串
println("${Data}")//格式化webhook接收的数据为json格式
NewData = readJSON text: "${Data}" //$表示全量数据
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch 提交分支
branchName = NewData["ref"] - "refs/heads/"// Get git user email
userEmail = NewData["user_email"]// Get short commit id 想要commitId的前8位 commit ID
env.commitId = NewData["checkout_sha"][0..7]
//env.commitId = NewData["checkout_sha"] // 提交人
env.commitUser = NewData["user_username"] //这里为什么要使用env.定义变量呢? 因为全局变量保险些,便于后面所有阶段间的引用;// current build desc
currentBuild.displayName = "${branchName}:${env.commitId}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}// 代码构建stage("Build"){steps{script{echo "build"}}}//单元测试stage("UnitTest"){steps{script{echo "unit test"}}}//部署stage("deploy"){steps {script{echo "deploy"}}}}post {always{script{EmailUser(userEmail,"${currentBuild.currentResult}")}}}}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="https://s1.ax1x.com/2023/04/25/p9usju8.jpg"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li> <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li> <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr> </table> </body> </html> """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
相关文章:
GitLABJenkins
GitLAB & Jenkins 目录 实践:基于Jenkins提交流水线(测试成功)-2023.4.25 目的:掌握通过触发器将GitLab和Jenkins集成,实现提交流水线。 1、触发Jenkins构建 安装Generic Webhook Trigger插件 重启后,进入一个Pipeline项目设…...
互联网摸鱼日报(2023-04-26)
互联网摸鱼日报(2023-04-26) InfoQ 热门话题 神州数码:抢抓云原生发展机遇,共建共治共享 OpenNJet 应用引擎开源生态 《产业数字人才研究与发展报告(2023)》 如何写出CPU友好的代码,百倍提升…...
石化企业数字化防爆融合通信解决方案
项目背景 石化工业是我国国民经济和社会发展的基础性、战略性产业,其发展和壮大受到了党和国家的高度重视。随着石化企业厂区规模的不断扩大以及技术的快速发展,现有石化企业专网通信系统建设相对滞后,缺乏结合人员管理、安全生产、安全通信…...
NTT学习笔记(快速数论变换)
一些概念 欧拉函数 ϕ ( n ) \phi(n) ϕ(n) 欧拉函数简介 阶 若 g g g和 n n n互质,则令 g x % n 1 g^x\%n1 gx%n1的最小正整数 x x x称为 g g g模 n n n的阶。 原根 对于互质的两个正整数 g g g和 n n n,如果 g g g模 n n n的阶为 ϕ ( n ) \phi…...
Android类似微信首页的页面开发教程(Kotlin)二
前提条件 安装并配置好Android Studio Android Studio Electric Eel | 2022.1.1 Patch 2 Build #AI-221.6008.13.2211.9619390, built on February 17, 2023 Runtime version: 11.0.150-b2043.56-9505619 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 …...
PAt A1015 Reversible Primes
1015 Reversible Primes 分数 20 作者 CHEN, Yue 单位 浙江大学 A reversible prime in any number system is a prime whose "reverse" in that number system is also a prime. For example in the decimal system 73 is a reversible prime because its rever…...
解决Lemuroid识别不到蓝牙键盘的问题
Android系统基于libretro的全能游戏模拟器,目前有RetroArch,Kodi,Lemuroid。 而且这三个都是开源免费的APP。 Lemuroid相对前面两个功能比较简陋。也不能自己下载核心。但代码也是最少的。 在使用Lemuroid的时候,发现它不能检测…...
SpringBoot 使用 Sa-Token 完成权限认证
一、设计思路 所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限: 有,就让你通过。没有?那么禁止访问! 深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是…...
Spring核心与设计思想、创建与使用
文章目录 一、Spring是什么二、为什么要学习框架三、IoC和DI(一)IoC1. 认识IoC2. Spring的核心功能 (二)DI 四、Spring项目的创建(一)使用 Maven 方式创建一个 Spring 项目 五、Spring项目的使用࿰…...
mysql 备份 还原
1:备份 执行命令方案1: /usr/local/mysql/bin/mysqldump -uX -pX -h 127.0.0.1 --set-gtid-purgedOFF --skip-extended-insert --add-drop-table --add-locks --create-options --disable-keys --lock-tables --quick --set-charset -e --max_allowed_packet16777216 --net_b…...
每日学术速递4.26
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.AutoNeRF: Training Implicit Scene Representations with Autonomous Agents 标题:AutoNeRF:使用自主代理训练隐式场景表示 作者:Pierre Marz…...
RabbitMQ使用StringRedisTemplate-防止重复消费
造成重复消费的原因: MQ向消费者推送message,消费者向MQ返回ack,告知所推送的消息消费成功。但是由于网络波动等原因,可能造成消费者向MQ返回的ack丢失。MQ长时间(一分钟)收不到ack,于是会向消…...
临沂大学张继群寄语
目录 寄语 1、不能有不良睹好 2、坚毅的个性和勤奋的品质 3、会存钱...
线程学习笔记
1:Thread 线程的生命周期控制 2:Runnable 可执行的任务和程序 3:Callable 执行程序后返回结果 4:Future 收集程序返回结果 5:Executor 线程池 6:ForkJoin 默认线程池 每个线程有工作队列 工作窃取 7:RunnableFuture FutureTask 实现 Runnable 和 Future 执…...
代码随想录算法训练营第四十二天|01背包问题,你该了解这些!、01背包问题,你该了解这些! 滚动数组 、416. 分割等和子集
文章目录 01背包问题,你该了解这些!01背包问题,你该了解这些! 滚动数组416. 分割等和子集 01背包问题,你该了解这些! 题目链接:代码随想录 二维数组解决0-1背包问题 解题思路: 1.dp…...
结构体指针、数组指针和结构体数组指针
结构体指针 首先让我们定义结构体: struct stu { char name[20]; long number; float score[4]; }; 再定义指向结构体类型变量的指针变量: struct stu *student; /*定义结构体类型指针*/ student malloc(sizeof(struct stu)); /*为指针变量分…...
项目架构一些注意点
考虑系统的 稳定性 一、微服务的稳定性 1、如何解决那些不稳定的因素/问题?也是常说的如何容错。 2、一个系统的高可用取决于它本身和其强依赖的组件的高可用 3、消除单点 保活机制 健康检查 注册中心如何保障稳定性 注册中心集群 微服务本身对注册信息的本地持…...
Forefront GPT-4免费版:开启无限畅聊时代,乐享人工智能快感,无限制“白嫖”,还能和N多角色一起聊天?赶紧注册,再过些时间估计就要收费了
目录 前言注册登录方式应用体验聊天体验绘图体验 “是打算先免费后收费吗?”建议其它资料下载 前言 近期,人工智能技术迎来重大飞跃,OpenAI的ChatGPT等工具成为全球数亿人探索提高生产力和增强创造力的新方法。人们现在可以使用人工智能驱动…...
深入浅出 Compose Compiler(1) Kotlin Compiler KCP
前言 Compose 的语法简洁、代码效率非常高,这主要得益于 Compose Compiler 的一系列编译期魔法,帮开发者生成了很多样板代码。但编译期插桩也阻碍了我们对于 Compose 运行原理的认知,想要真正读懂 Compose 就必须先了解它的 Compiler。本系列…...
BatchNormalization和LayerNormalization的理解、适用范围、PyTorch代码示例
文章目录 为什么要NormalizationBatchNormLayerNormtorch代码示例 学习神经网络归一化时,文章形形色色,但没找到适合小白通俗易懂且全面的。学习过后,特此记录。 为什么要Normalization 当输入数据量级极大或极小时,为保证输出数…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
