hugo-teek is loading...

Jira自动化实践

最后更新于:

Jira自动化实践

image-20230712071753069

目录

[toc]

推荐文章

https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》

image-20230624094222589

1、Jira简介

image-20230712071158183

中文官网: https://www.atlassian.com/zh/software/jira

tstmp_20230709214731

==Jira可以做什么?==

规划

创建项目,用户需求和事务、规划 Sprint 并跨团队分配开发任务。

跟踪

全面了解项目进度情况,安排整个团队工作的优先级排序并进行讨论。

image-20230709214858649

2、Jira使用实践

创建一个项目

注意: 一个Jira 项目对应一个GitLab项目组;

image-20230710071324180

image-20230710071342437

image-20230710071421815

image-20230710071527852

为项目添加模块

注意: 一个Jira模块对应一个GitLab项目;

image-20230710071710949

配置WebHook

系统, 网络钩子(webhook)

tstmp_20230710071735

需求/任务管理

创建需求

这里在Jira上面把这个需求add login page, 类型为任务 关联到devops6-maven-service模块;

image-20230710072634191

image-20230710072658373

发布Release

课程中把 发布对应为GitLab项目代码库中的版本分支;

image-20230710072750413

issue关联发布: 可以想象成GitLab特性分支合并到版本分支;

image-20230710072904046

image-20230710072922424

3、Jira自动化实践

工作流

image-20230711094720883

工具链集成

image-20230711094833711

  • 实验环境
1gitlab-ce:15.0.3-ce.0
2jenkins:2.346.3-2-lts-jdk11
3atlassian-jira-software-9.4.8-x64
  • 实验软件

pipeline见正文。

==gitlab上模拟手动创建分支,提交代码==

  • 创建DEVOPS6-1特性分支

image-20230710073225129

提交一次代码。

  • 创建版本分支RELEASE-10.1.1

image-20230710073348020

  • 将特性分支合并到版本分支

image-20230710073432996

这个是手动操作,接下来,我们就利用Jira,jenkins,gitlab来完成操作。

1、需求与代码关联

image-20230711095313949

1.创建Jenkins作业并配置webhook

image-20230711095634664

  • 配置Generic Webhook Trigger

webhookData: 这个变量存放的是Jira 传递的数据。

image-20230711100047538

image-20230711100120530

image-20230711100133187

2.为Jira配置一个系统级别的webhook

image-20230711100550141

选项解释:

  1. 指定Jenkins的webhook触发器地址;
  2. 通过JQL指定,允许devops6这个项目进行触发;
  3. 勾选动作,触发事件;(我在jira做了什么操作之后能够触发)
  • 此时,我们来测试下

在jira上创建一个需求,看是否会触发jenkins作业?

image-20230711100900876

可以看到jenkins作业被成功触发了。

image-20230711100929592

我们再来打印下这个${webhookData}变量:

编辑下pipeline代码,重新构建:

image-20230711101201728

  • 我们把json数据拿到在线json解析下

image-20230711101905585

image-20230711101338622

image-20230711101419150

image-20230711102033403

3.Jenkins流水线配置

  • 解析Jira传递过来的数据;
 1webhookData = readJSON text: "${webhookData}"
 2
 3
 4// Jira事件
 5jiraEvent = webhookData.webhookEvent
 6jiraProjectName = webhookData.issue.fields.project.name
 7
 8// 获取gitlab参数
 9gitlabProjects = []
10gitlabBranchName = webhookData.issue.key
11gitlabGroupName = jiraProjectName
12
13for (i in webhookData.issue.fields.components){
14    gitlabProjects.add(i["name"])
15}
16
17currentBuild.description = "Trigger by ${jiraEvent} \n project: ${gitlabProjects} \n branch: ${gitlabBranchName}"

把此部分代码放到流水线里,重新构建下,可看到如下效果:

image-20230711102313235

  • 封装GitLab API接口

https://docs.gitlab.com/ee/api/branches.html#create-repository-branch

 1// 创建分支
 2def CreateBranch(projectId, newBranchName, sourceBranchName){
 3    try {
 4        apiUrl = "projects/${projectId}/repository/branches?branch=${newBranchName}&ref=${sourceBranchName}"
 5        response = HttpReq('POST', apiUrl, "")
 6    }
 7    catch(Exception e) {
 8        println(e)
 9        
10    }
11}
12
13// 获取所有项目的id
14def GetProjectsId(gitlabGroupName, gitlabProjects){
15    gitlabProjectIds = []
16    for (project in gitlabProjects){
17        id = GetProjectId(gitlabGroupName, project)
18        println(id)
19        if (id != 0){
20            gitlabProjectIds.add(id)
21        }
22    }
23    return gitlabProjectIds
24}
25
26// 根据项目名称获取项目id
27def GetProjectId(groupName, projectName){
28    apiUrl = "projects?search=${projectName}"
29    response = HttpReq('GET', apiUrl, "")
30    response = readJSON text: response.content - "\n"
31
32    if (response.size() > 1){
33        for (i in response){
34            println(i["path_with_namespace"])
35            println(groupName + projectName)
36            if (i["path_with_namespace"] == "${groupName}/${projectName}"){
37                println(i["id"])
38                return i["id"]
39            }
40        }
41    } else {
42        return response[0]["id"]
43    }
44}
45
46
47// 封装HTTP
48def HttpReq(reqType, reqUrl,reqBody ){
49    def gitServer = "http://192.168.1.200/api/v4"
50    withCredentials([string(credentialsId: '058b7907-ebe2-4d14-9b91-1ac72e071c59', variable: 'GITLABTOKEN')]) {
51        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8', 
52                          consoleLogResponseBody: true, 
53                          contentType: 'APPLICATION_JSON_UTF8', 
54                          customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]], 
55                          httpMode: "${reqType}", 
56                          url: "${gitServer}/${reqUrl}", 
57                          wrapAsMultipart: false,
58                          requestBody: "${reqBody}"
59
60    }
61    return response
62}
  • Pipeline主程序
 1pipeline {
 2    agent { label "build" }
 3
 4    stages{
 5        stage("Process"){
 6            steps{
 7                script{
 8                    println(gitlabProjects)
 9                    println(gitlabBranchName)
10                    projectIds = GetProjectsId(gitlabGroupName, gitlabProjects)
11                    
12                    switch(jiraEvent) {
13                        case "jira:issue_created":
14                            println(projectIds)
15                            for (id in projectIds){
16                                CreateBranch(id, gitlabBranchName, "main")
17                            }
18                            break
19                        default:
20                            println("error...")
21                            break
22                    }
23                }
24            }
25        }
26    }
27}
  • 完整代码
  1webhookData = readJSON text: "${webhookData}"
  2
  3
  4// Jira事件
  5jiraEvent = webhookData.webhookEvent
  6jiraProjectName = webhookData.issue.fields.project.name
  7
  8// 获取gitlab参数
  9gitlabProjects = []
 10gitlabBranchName = webhookData.issue.key
 11gitlabGroupName = jiraProjectName
 12
 13for (i in webhookData.issue.fields.components){
 14    gitlabProjects.add(i["name"])
 15}
 16
 17currentBuild.description = "Trigger by ${jiraEvent} \n project: ${gitlabProjects} \n branch: ${gitlabBranchName}"
 18
 19
 20pipeline {
 21    agent { label "build" }
 22
 23    stages{
 24        stage("Process"){
 25            steps{
 26                script{
 27                    println(gitlabProjects)
 28                    println(gitlabBranchName)
 29                    projectIds = GetProjectsId(gitlabGroupName, gitlabProjects)
 30                    
 31                    switch(jiraEvent) {
 32                        case "jira:issue_created":
 33                            println(projectIds)
 34                            for (id in projectIds){
 35                                CreateBranch(id, gitlabBranchName, "main")
 36                            }
 37                            break
 38                        default:
 39                            println("error...")
 40                            break
 41                    }
 42                }
 43            }
 44        }
 45    }
 46}
 47
 48
 49// 创建分支
 50def CreateBranch(projectId, newBranchName, sourceBranchName){
 51    try {
 52        apiUrl = "projects/${projectId}/repository/branches?branch=${newBranchName}&ref=${sourceBranchName}"
 53        response = HttpReq('POST', apiUrl, "")
 54    }
 55    catch(Exception e) {
 56        println(e)
 57        
 58    }
 59}
 60
 61// 获取所有项目的id
 62def GetProjectsId(gitlabGroupName, gitlabProjects){
 63    gitlabProjectIds = []
 64    for (project in gitlabProjects){
 65        id = GetProjectId(gitlabGroupName, project)
 66        println(id)
 67        if (id != 0){
 68            gitlabProjectIds.add(id)
 69        }
 70    }
 71    return gitlabProjectIds
 72}
 73
 74// 根据项目名称获取项目id
 75def GetProjectId(groupName, projectName){
 76    apiUrl = "projects?search=${projectName}"
 77    response = HttpReq('GET', apiUrl, "")
 78    response = readJSON text: response.content - "\n"
 79
 80    if (response.size() > 1){
 81        for (i in response){
 82            println(i["path_with_namespace"])
 83            println(groupName + projectName)
 84            if (i["path_with_namespace"] == "${groupName}/${projectName}"){
 85                println(i["id"])
 86                return i["id"]
 87            }
 88        }
 89    } else {
 90        return response[0]["id"]
 91    }
 92}
 93
 94
 95// 封装HTTP
 96def HttpReq(reqType, reqUrl,reqBody ){
 97    def gitServer = "http://172.29.9.101/api/v4"
 98    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'GITLABTOKEN')]) {
 99        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8', 
100                          consoleLogResponseBody: true, 
101                          contentType: 'APPLICATION_JSON_UTF8', 
102                          customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]], 
103                          httpMode: "${reqType}", 
104                          url: "${gitServer}/${reqUrl}", 
105                          wrapAsMultipart: false,
106                          requestBody: "${reqBody}"
107
108    }
109    return response
110}

将次代码放到pipeline里。

4.效果验证

  • 在Jira里面创建一个issue, 关联 项目;

image-20230711103206398

  • Jenkins 流水线运行;

image-20230711103508529

  • 验证Gitlab中多了分支;

image-20230711103537620

符合预期。

2、代码自动化合并

image-20230712064825091

1. 更新配置Jira Webhook

image-20230712065003182

2. Issue关联版本

  • 这里有2个待关联版本的问题

image-20230712065513067

  • 创建11.1.1发布版本

image-20230712065205538

同时可以看下devops6-maven-service仓库是没有这个11.1.1版本分支的。

image-20230712065455878

3. Jenkins Pipeline

  • 分析Jira Webhook传递的数据
 1jira event : 
 2webhookEvent: jira:issue_updated
 3
 4
 5args
 61. gitlab 项目名称   issue.fields.components    []
 72. 分支名称  issue.key
 83. gitlab 项目组名称  issue.fields.project.name
 94. fixversion   版本分支  issue.fields.fixVersions   []
10
11
12action:
131.根据项目名称获取项目的id
142.根据项目id,基于master分支创建一个版本分支
153.根据fixversion 拿到所有的特性分支;
164.根据项目id,将该项目的特性分支合并版本分支;
  • 编写Jenkinsfile
  1webhookData = readJSON text: "${webhookData}"
  2
  3// Jira事件
  4jiraEvent = webhookData.webhookEvent
  5jiraProjectName = webhookData.issue.fields.project.name
  6
  7// 获取gitlab参数
  8gitlabProjects = []
  9gitlabBranchName = webhookData.issue.key
 10gitlabGroupName = jiraProjectName
 11
 12for (i in webhookData.issue.fields.components){
 13    gitlabProjects.add(i["name"])
 14}
 15
 16currentBuild.description = "Trigger by ${jiraEvent} \n project: ${gitlabProjects} \n branch: ${gitlabBranchName}"
 17
 18pipeline {
 19    agent { label "build" }
 20
 21    stages{
 22        stage("Process"){
 23            steps{
 24                script{
 25                    println(gitlabProjects)
 26                    println(gitlabBranchName)
 27                    projectIds = GetProjectsId(gitlabGroupName, gitlabProjects)
 28                    switch(jiraEvent) {
 29                        case "jira:issue_created":
 30                            println(projectIds)
 31                            for (id in projectIds){
 32                                CreateBranch(id, gitlabBranchName, "main")
 33                            }
 34                            break
 35                        case "jira:issue_updated":
 36                            if (webhookData.issue.fields.fixVersions.size() >= 1){
 37                                jiraFixVersion = webhookData.issue.fields.fixVersions[0]["name"]
 38                                // 获取fixversion关联的所有issues
 39                                issues = GetIssuesByFixVersion(jiraProjectName, jiraFixVersion)
 40                                
 41                                // 在issue关联的所有项目创建版本分支
 42                                for (id in projectIds){
 43                                    CreateBranch(id, "RELEASE-${jiraFixVersion}", "master")   //RELEASE-1.1.6
 44
 45                                    // 创建合并请求  特性分支 > 版本分支  
 46                                    for(issue in issues) {
 47                                        CreateMergeRequest(id, issue, "RELEASE-${jiraFixVersion}" )
 48                                    } 
 49                                }
 50                                break
 51                            }
 52                        default:
 53                            println("error...")
 54                            break
 55                    }
 56                }
 57            }
 58        }
 59    }
 60}
 61
 62//创建合并请求
 63def CreateMergeRequest(projectId, sourceBranch, targetBranch ){
 64    try {
 65        apiUrl = "projects/${projectId}/merge_requests"
 66        reqBody = """{"source_branch": "${sourceBranch}","target_branch":"${targetBranch}","title": "${sourceBranch}>>>${targetBranch}byJenkins"}"""
 67        println(reqBody)
 68        response = HttpReq('POST',apiUrl,reqBody)
 69    }
 70    catch(Exception e) {
 71        println(e)
 72    }
 73}
 74
 75// 查询JiraReleaseissue
 76def GetIssuesByFixVersion(projectName, fixVersion){
 77    jql = "project%20=%20${projectName}%20AND%20fixVersion%20=%20${fixVersion}" 
 78    response = sh returnStdout: true, script: """
 79        curl  \
 80        -u admin:Admin@123 \
 81        -H "Content-Type: application/json" \
 82        --request GET "http://172.29.9.101:8066/rest/api/2/search?jql=${jql}" -s
 83    """
 84    response = readJSON text: """ ${response - "\n"} """
 85    issues = []
 86    for (i in response["issues"]){
 87        issues.add(i["key"])
 88    }
 89    
 90    return issues
 91}
 92
 93// 创建分支
 94def CreateBranch(projectId, newBranchName, sourceBranchName){
 95    try {
 96        apiUrl = "projects/${projectId}/repository/branches?branch=${newBranchName}&ref=${sourceBranchName}"
 97        response = HttpReq('POST', apiUrl, "")
 98    }
 99    catch(Exception e) {
100        println(e)
101        
102    }
103}
104
105// 获取所有项目的id
106def GetProjectsId(gitlabGroupName, gitlabProjects){
107    gitlabProjectIds = []
108    for (project in gitlabProjects){
109        id = GetProjectId(gitlabGroupName, project)
110        println(id)
111        if (id != 0){
112            gitlabProjectIds.add(id)
113        }
114    }
115    return gitlabProjectIds
116}
117
118// 根据项目名称获取项目id
119def GetProjectId(groupName, projectName){
120    apiUrl = "projects?search=${projectName}"
121    response = HttpReq('GET', apiUrl, "")
122    response = readJSON text: response.content - "\n"
123
124    if (response.size() > 1){
125        for (i in response){
126            println(i["path_with_namespace"])
127            println(groupName + projectName)
128            if (i["path_with_namespace"] == "${groupName}/${projectName}"){
129                println(i["id"])
130                return i["id"]
131            }
132        }
133    } else {
134        return response[0]["id"]
135    }
136}
137
138
139// 封装HTTP
140def HttpReq(reqType, reqUrl,reqBody ){
141    def gitServer = "http://172.29.9.101:8076/api/v4"
142    withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'GITLABTOKEN')]) {
143        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8', 
144                          consoleLogResponseBody: true, 
145                          contentType: 'APPLICATION_JSON_UTF8', 
146                          customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]], 
147                          httpMode: "${reqType}", 
148                          url: "${gitServer}/${reqUrl}", 
149                          wrapAsMultipart: false,
150                          requestBody: "${reqBody}"
151
152    }
153    return response
154}

4. 效果验证

  • jira上关联问题到发布版本

image-20230712070029427

image-20230712070822965

可以看到触发了jenkins流水线:

image-20230712070908063

gitlab上也能看到有mr请求了:

image-20230712070918429

jira付费插件也能支持这样的效果。

测试结束。😘

FAQ

ones

image-20230712071443572

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码 x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号 《云原生架构师实战》

image-20230107215126971

🍀 语雀

https://www.yuque.com/xyy-onlyone

image-20230624093747671

🍀 csdn https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎 https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

推荐使用微信支付
微信支付二维码
推荐使用支付宝
支付宝二维码
最新文章

文档导航