版本控制系统集成

您好,本章主要我们主要学习与版本控制系统Gitlab的集成,例如:配置提交流水线和合并流水线。

目录


提交流水线

当Gitlab中触发push操作,则触发相对应的Jenkins流水线构建。实现快速反馈与验证。

  • 方式1: 使用Gitlab CI,当有push请求,在CI脚本中远程触发Jenkins项目构建。
    • 需要准备Gitlab runner
    • 编写触发Jenkins脚本
  • 方式2: 使用Gitlab WebHook,当有push请求,直接触发jenkins项目构建。【采用】
    • 需要配置Gitlab webHook
    • 需要配置Jenkins项目Hook

配置jenkins

首先我们准备一个能够构建成功的流水线项目(暂且不设置复杂的步骤,helloworld即可) images

编辑项目配置: 我们要使用Generic Webhook Trigger触发器,需要安装插件。这触发器非常灵活,推荐使用。

images

开启Generic Webhook Trigger触发器,添加一个请求参数runOpts Request parameters 。我们定义这个参数是为了对构建做个标识。辨别手动触发构建与提交构建。配置一个token默认我使用的是项目的名称,必须唯一,否则在配置了相同的token的项目都会被触发。Print post content用于展示请求日志,Print contributed variables展示我们在post中获取的变量内容。

images

配置完成后: 我们生成一个触发URL

images http://JENKINS_URL/generic-webhook-trigger/invoke?token=demo-maven-service_PUSH&runOpts=GitlabCI

配置gitlab

我们找到要配置提交触发构建的项目,设置->集成,勾选Push Events images

{{% notice info %}} 配置完成,这时候我们进行提交代码,会发现已经能够正常触发项目构建了。如果出现了问题,我们重点检查jenkins的项目触发URL和网络权限问题。 {{% /notice %}}

提交流水线优化

分支名称自动替换

当我们在任意分支提交的时候,Jenkins需要获取我们提交的分支进行构建。而不是固定的分支。

增加获取hook参数 分支名称变量 Post content parameters. $指的是在Gitlab系统中push操作触发后发送给Jenkins的数据。(这个数据包含谁提交的、提交的分支、提交的id等信息)。而$.ref是解析这个json格式的数据,获取其中的ref也就是提交的分支名称。 images

查看下面这段jenkinsfile,你会发现branch变量就是上面我们在触发器中配置的,它的原始内容是refs/heads/master,因为我们在下载代码的时候不需要前面refs/heads/内容,所以去掉了。此时可以重复在不通的分支提交代码,当在构建日志中出现了不通的分支名称,则成功了。

  1. branchName = branch - "refs/heads/"
  2. //pipeline
  3. pipeline{
  4. agent { node { label "build"}}
  5. stages{
  6. stage("CheckOut"){
  7. steps{
  8. script{
  9. println("${branchName}")
  10. }
  11. }
  12. }
  13. }
  14. }

增加构建描述信息

别忘了我们在前面构建触发器中配置了runOpts参数,这个参数我们用于区分不通的构建触发方式(手动、提交触发)。 这时候我们可以结合currendBuild.description配置。

为了更加明显我们可以在触发器中再添加一个参数,用户获取提交的用户。

images

然后我们来完善一下上面的Jenkinsfile,如下:

  1. branchName = branch - "refs/heads/"
  2. currentBuild.description = "Trigger by ${userName} ${branch}"
  3. //pipeline
  4. pipeline{
  5. agent { node { label "build"}}
  6. stages{
  7. stage("CheckOut"){
  8. steps{
  9. script{
  10. println("${branchName}")
  11. }
  12. }
  13. }
  14. }
  15. }

改好了之后,我们可以进行调试了。当你在项目的构建记录中看到下图信息,表名成功了。

images

变更commit状态

其实,Gitlab自身的GitlabCI很好用,能够根据流水线的状态设置当前提交的状态。而我们使用Jenkins也是可以完成这样的配置。这个需要我们去研究Gitlab的API。先看下效果吧! images

开始配置: 需要研究Gitlab的Pipeline接口文档 关于gitlab中pipeline的状态有:[pending, running, success, failed, canceled] 。 接口地址为projects/${projectId}/statuses/${commitSha}?state=state

搞清楚了上面这些,我们在共享库中进行封装就很简单了。 开始吧!可以看到我们还需要一些信息例如:projectIdgitlab项目的ID,commitSha提交的id。我们该如何获取呢? 对的,没错我们根据上面的操作一样获取。 首先在触发器添加两个参数projectId,commitSha,分别对应项目Id和提交Id。 $.project.id,$.checkout_sha images

ok!很好,我们接下来在共享库创建一个文件src/org/devops/gitlab.groovy,这个文件用与后续的Gitlab操作。然后我们在jenkins中添加一个凭据用户存储Gitlab的token,这里我定义的凭据名称是gitlab-token 。我们首先使用httpRequest封装请求Gitlab的API地址,然后使用withCredentials获取Jenkins中的凭据gitlab-token赋值给变量gitlabToken用于认证使用。

  1. package org.devops
  2. //封装HTTP请求
  3. def HttpReq(reqType,reqUrl,reqBody){
  4. def gitServer = "http://192.168.1.200:30088/api/v4"
  5. withCredentials([string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
  6. result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]],
  7. httpMode: reqType,
  8. contentType: "APPLICATION_JSON",
  9. consoleLogResponseBody: true,
  10. ignoreSslErrors: true,
  11. requestBody: reqBody,
  12. url: "${gitServer}/${reqUrl}"
  13. //quiet: true
  14. }
  15. return result
  16. }

{{% notice info %}} 如果上面的内容你有点看不懂了,嘿嘿,先放放。你可以去了解下关于HTTP请求相关基础知识了。 {{% /notice %}}

我们开始添加变更提交状态的方法(记住我们现在还在gitlab.groovy文件中哦),我们定义一个ChangeCommitStatus()方法,具有三个参数分别为项目ID、提交ID、提交状态 projectIdcommitSha,status。然后使用我们上面封装好的方法发送POST请求。

  1. //更改提交状态
  2. def ChangeCommitStatus(projectId,commitSha,status){
  3. commitApi = "projects/${projectId}/statuses/${commitSha}?state=${status}"
  4. response = HttpReq('POST',commitApi,'')
  5. println(response)
  6. return response
  7. }

到此我们在共享库的配置就完成了,接下来在Jenkinsfile中引用并进行调试。首先我们先加载了共享库jenkinslibrary 然后引用了gitlab.groovy。当流水线开始运行的时候我们将当前这次提交的状态为running运行中状态,当流水线构建成功我们会把状态变为success,当流水线失败了或者被取消了我们会将状态变为failedcanceled

  1. #!groovy
  2. @Library('jenkinslibrary@master') _
  3. //func from shareibrary
  4. def gitlab = new org.devops.gitlab()
  5. //branch
  6. branchName = branch - "refs/heads/"
  7. currentBuild.description = "Trigger by ${userName} ${branch}"
  8. gitlab.ChangeCommitStatus(projectId,commitSha,"running")
  9. //pipeline
  10. pipeline{
  11. agent { node { label "build"}}
  12. stages{
  13. stage("CheckOut"){
  14. steps{
  15. script{
  16. println("${branchName}")
  17. }
  18. }
  19. }
  20. }
  21. post {
  22. always{
  23. script{
  24. println("always")
  25. }
  26. }
  27. success{
  28. script{
  29. println("success")
  30. gitlab.ChangeCommitStatus(projectId,commitSha,"success")
  31. }
  32. }
  33. failure{
  34. script{
  35. println("failure")
  36. gitlab.ChangeCommitStatus(projectId,commitSha,"failed")
  37. }
  38. }
  39. aborted{
  40. script{
  41. println("aborted")
  42. gitlab.ChangeCommitStatus(projectId,commitSha,"canceled")
  43. }
  44. }
  45. }
  46. }

如果调试没有问题,那么此时你可以登录gitlab系统当前项目的分支的提交的状态了!但是你是否觉得还差点什么? 如果开发人员提交了,然后流水线自动执行了,最后失败了怎么办? 要求开发人员放下工作实时去看?我觉得发送一个通知会更好一些! 例如邮件通知。好吧,开始配置!

构建失败邮件通知

首先要为每个开发人员分配一个邮箱,并且要在Gitlab中填写好。登录个人用户进行配置哦!没错,在这里配置邮箱的意义就是方便后面我们在jenkins中过滤获取。当然如果公司邮箱具有特征:用户名@xxx.com。就不用配置了因为前面已经获取的用户名。当然很多时候不是这样的,所以我们有必要把这个配置好。

images

配置好邮箱之后,我们需要在Jenkins中配置邮件通知和项目配置。我们在项目中触发器添加一个参数userEmail

images

Jenkins需要配置邮件通知,安装插件Email Extension,然后进入系统管理-> 系统设置 ->Extended E-email Notification。这里我使用的是QQ邮箱,填写SMTP服务器地址smtp.qq.com 和端口 465注意要开启SSL,密码为授权码。

images

邮件通知的功能很重要,我们要为每条流水线都加上这个步骤,我们在共享库中封装一个toemail.groovy。 新建文件src/org/devops/toemail.groovy。在这个文件中,我们写了一段HTML代码,主要展示Jenkins的构建信息。

  1. package org.devops
  2. //定义邮件内容
  3. def Email(status,emailUser){
  4. emailext body: """
  5. <!DOCTYPE html>
  6. <html>
  7. <head>
  8. <meta charset="UTF-8">
  9. </head>
  10. <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
  11. <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png">
  12. <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
  13. <tr>
  14. <td><br />
  15. <b><font color="#0B610B">构建信息</font></b>
  16. </td>
  17. </tr>
  18. <tr>
  19. <td>
  20. <ul>
  21. <li>项目名称:${JOB_NAME}</li>
  22. <li>构建编号:${BUILD_ID}</li>
  23. <li>构建状态: ${status} </li>
  24. <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li>
  25. <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
  26. </ul>
  27. </td>
  28. </tr>
  29. <tr>
  30. </table>
  31. </body>
  32. </html> """,
  33. subject: "Jenkins-${JOB_NAME}项目构建信息 ",
  34. to: emailUser
  35. }

在流水线中引用

  1. #!groovy
  2. @Library('jenkinslibrary@master') _
  3. //func from shareibrary
  4. def gitlab = new org.devops.gitlab()
  5. def toemail = new org.devops.toemail()
  6. //branch
  7. branchName = branch - "refs/heads/"
  8. currentBuild.description = "Trigger by ${userName} ${branch}"
  9. gitlab.ChangeCommitStatus(projectId,commitSha,"running")
  10. //pipeline
  11. pipeline{
  12. agent { node { label "build"}}
  13. stages{
  14. stage("CheckOut"){
  15. steps{
  16. script{
  17. println("${branchName}")
  18. }
  19. }
  20. }
  21. }
  22. post {
  23. always{
  24. script{
  25. println("always")
  26. }
  27. }
  28. success{
  29. script{
  30. println("success")
  31. gitlab.ChangeCommitStatus(projectId,commitSha,"success")
  32. toemail.Email("流水线成功",userEmail)
  33. }
  34. }
  35. failure{
  36. script{
  37. println("failure")
  38. gitlab.ChangeCommitStatus(projectId,commitSha,"failed")
  39. toemail.Email("流水线失败了!",userEmail)
  40. }
  41. }
  42. aborted{
  43. script{
  44. println("aborted")
  45. gitlab.ChangeCommitStatus(projectId,commitSha,"canceled")
  46. toemail.Email("流水线被取消了!",userEmail)
  47. }
  48. }
  49. }
  50. }

接下来可以调试了,如果没有问题会在邮箱中看到此封邮件。 images

过滤特殊push请求

你可能发现问题了,新建一个分支或者标签也会出现构建,这个构建是没有意义的。我们需要排除掉。没错,jenkins 的 Generic webHook 也是支持的。

参考官方的说明:https://github.com/jenkinsci/generic-webhook-trigger-plugin/tree/master/src/test/resources/org/jenkinsci/plugins/gwt/bdd

images

添加三个变量,获取当前的提交信息 $object_kind $before $after images

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

images

Ok! 提交流水线配置好了,可以玩耍了~。

合并流水线

关于合并流水线的配置之前要把提交流水线配置好,当提交流水线配置好了,合并流水线只需要修改一个配置。

当流水线成功后才可以合并:会检查原分支中的最后一次提交的状态是否为success。

images

当原分支最后一次提交的状态为success,则可以合并。 images