公司通过gitlab托管代码,采用jira作为敏捷实践的管理工具,每次发布的时候拉出当前迭代的所有故事做发布计划.

然而实际上因为某些原因,基本上无法实现每次迭代的所有故事都能发布.只有在分支上测试完成合并到 master上的故事才会被发布.

那么就想着能不能在分支合并到master的时候在jira上打个标签,这样在jira上一筛选就知道哪些故事是可以发布的了

好在gitlab有webhook功能,能够在触发某些操作的时候调用自定义的接口传输相关操作的信息,而jira也提供了相应的api来方便读写,那么只需要发布一个服务提供接口给webhook调用,解析传过来的参数,符合条件的情况下去调用jira的api修改标签,这个方案也就实现了.

本文相关版本信息

GitLab Community Edition 11.1.4

JIRA v7.13.5

python 3.5.4

Flask 1.1.2

requests 2.24.0

提前约定

在git创建分支时分支名称需要包含jiraId

我们项目组是直接以jiraId+故事标题命名分支

编写程序

图快速方便所以用python写的,结果后面部署费了不少事

webhook调用接口传递参数解析

文档: https://docs.gitlab.com/ee/user/project/integrations/webhooks.html

参数是json形式的

主要取出其中3个参数

  • object_attributes.state

    gitlab设置的trigger是合并事件,实际上会在申请(opened),关闭(closed)和完成合并(merged)3个情况触发,所以要判断是否是完成合并的调用

  • object_attributes.target_branch

    target_branch 是为了确认是合并到master的请求,合并到其他分支的请求不处理

  • object_attributes. source_branch

    source_branch 是为了取出jiraId以进行后续操作

jira接口调用

文档: https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/#editing-an-issue-examples

从source_branch利用正则截取出jiraId,拼装并调用接口地址

附三个修改标签的传参,第一个是追加,后两种是覆盖设置

#增加
{
    "update" : {
        "labels" : [{"add" : "标签内容"}]
    }
}
#设置
{
    "fields" : {
        "labels": ["标签内容"]
        
        
    }
}
{
    "update" : {
        "labels" : [{"set" : ["标签内容"]}]
    }
}

PS:

建议先用postman之类的工具先调试一下jira的接口,如果报错

Field 'labels' cannot be set. It is not on the appropriate screen, or unknown.

那就需要联系jira管理员,在项目的screens(项目管理->界面)中开启相关字段的api读写权限

完整源码如下:

# -*- coding: utf-8 -*-

from flask import Flask,request
import requests
import re

baseUrl = 'http://jira.sunjianbo.com:8080/rest/api/2/issue/'
app = Flask(__name__)

@app.route("/", methods=["GET", "POST"])
def test():
    # addTag2Jira("DB19236-2398 324扥矿赛肯")
    return "hello world"

@app.route("/merged", methods=["GET", "POST"])
def merged():
    # print(request.headers)
    # print(request.json)
    # print('---')
    body = request.json
    object_attributes = body['object_attributes']
    state = object_attributes['state']  # opened,closed,merged
    source_branch = object_attributes['source_branch']
    target_branch = object_attributes['target_branch']
    if state == 'merged' and target_branch == 'master':
        # 已合并到master
        print('是已合并到master的请求,开始修改jira标签')
        addTag2Jira(source_branch)
    else:
        print('不是合并到master的成功请求,而是合并到['+target_branch+']的['+state+"]请求")
    return ""

def addTag2Jira(source_branch):
    # 取得分支jira id
    matchObj = re.search(r"DB\d+-\d+", source_branch)
    if matchObj:
        print("匹配出的jiraId: ", matchObj.group())
        jiraId = matchObj.group()
        # 去相应jira故事中打一个uat标签
        url = baseUrl + jiraId
        messagebody = '''
            {
                "update" : {
                    "labels" : [{"add" : "UAT"}]
                }
            }
            '''
        result = fun_put(url, messagebody)
        print(result)
        if result.status_code == 204:
            print('修改成功: ' + url)
        else:
            print('修改失败: ' + source_branch)
    else:
        print("分支名称上找不到jiraId: " + source_branch)

def fun_put(url, messagebody):
    headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
    r = requests.put(url, data=messagebody, headers=headers, auth=('username', 'passwd'))
    print(r.status_code)
    return r

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

部署

部署这里有个插曲

公司服务器是离线的,所以我先离线安装了python3,然后打算安装virtualenv时报了一个ssl的错误,明明是离线安装,为毛会涉及到ssl,咱也不知道,咱也不敢问,推测是python3安装的有点问题,依赖的openssl之类的在测试机上不太全吧

折腾了半天没搞定,考虑到是测试服务器我就瞎搞了一把

用了

pip3 install -r requirements.txt --proxy=代理服务器IP:端口号

代理走了我本地电脑在线安装了Flask和 requests,瞬间就解决了(给机智的我点个赞(◔◡◔))

设置gitlab上的webhook

settings->integrations->填写url->Trigger勾选Merge request events->嫌麻烦我禁用了ssl,没有实际测试一下行不行->保存

set-integrations)