Django订阅Jira Webhook事件数据的实战教程

总体思路:

1、配置django URL、View、Model、Serializer

2、编写工厂函数,处理数据逻辑

3、配置Jira webhook


1、配置django

1.1 router配置

# 1. router配置
path('pm/issues/', views.JiraView.as_view()), # jira
  • 1.
  • 2.

1.2 View配置

# Jira data
class JiraView(views.APIView):

def __init__(self):
self.logger = logging.getLogger("cmweb")
self.resp_msg = ResponseMsg()
self.permission_classes = []

def post(self, request):
data = request.data

# receive from jira webhook and handle
webhookEvent = data['webhookEvent']
issue_event_type_name = data['issue_event_type_name']
if webhookEvent == "jira:issue_created":
NewIssueCreate().handleIssue(data)
elif webhookEvent == "jira:issue_updated":
if "comment" not in issue_event_type_name:
NewIssueUpdate().handleIssue(data)
elif webhookEvent == "jira:issue_deleted":
NewIssueDelete().handleIssue(data)
else:
pass
return JsonResponse(self.resp_msg.ok_withmsg("ok"))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

1.3 Model(cmapp/models.py)

1.4 Serializers(cmapp/serializers.py)


2、编写工厂函数

2.1 ​ ​Factory.py​​

import abc
from subscribe.jira.issue_create import parseIssueCreate
from subscribe.jira.issue_update import parseIssueUpdate, parseIssueDelete

class AbstractFactory(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def handleIssue(self, data):
pass


class NewIssueCreate(AbstractFactory):

def handleIssue(self, data):
parseIssueCreate(data)

class NewIssueUpdate(AbstractFactory):

def handleIssue(self, data):
parseIssueUpdate(data)

class NewIssueDelete(AbstractFactory):

def handleIssue(self, data):
parseIssueDelete(data)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

2.2 issue_create.py

import json
import datetime
from subscribe.jira.sync_to_db import create_issue_to_db
import logging

logger = logging.getLogger("subscribe")

def parseIssueCreate(data):
components_list = []
issue = data['issue']
labels = issue['fields']['labels']
resolution = None if issue['fields']['resolution'] is None else issue['fields']['resolution']['name']
issue_id = issue['id']
issue_name = issue['key']
issue_type = issue['fields']['issuetype']['name']
project = issue['fields']['project']['name']
summary = issue['fields']['summary']
status = issue['fields']['status']['name']
priority = issue['fields']['priority']['name']
reporter = issue['fields']['reporter']['displayName']
assignee = '' if not issue['fields']['assignee'] else issue['fields']['assignee']['displayName']
description = '' if not issue['fields'].get('description') else issue['fields']['description']
resolved_date = issue['fields']['resolutiondate']
close_date = issue['fields']['customfield_11231']
plan_start_date = issue['fields']['customfield_10421']
plan_end_date = issue['fields']['customfield_10422']
act_start_date = issue['fields']['customfield_10423']
act_end_date = issue['fields']['customfield_10424']
due_date = issue['fields']['duedate']
estimate_due_date = issue['fields']['customfield_10933']
comp_lists = issue['fields']['components']
platform = ''
if issue['fields']['customfield_11301']:
platform = issue['fields']['customfield_11301']['value']
milestone_flag = ''
if issue['fields']['customfield_11118']:
milestone_flag = issue['fields']['customfield_11118']['value']
for component in comp_lists:
components_list.append(component['name'])
if issue['fields']['issuetype']['name'] == "Bug" and issue['fields']['customfield_10603'] is not None:
reproduce_radio = issue['fields']['customfield_10603']['value']
else:
reproduce_radio = None
create_date = issue['fields']['created']
update_date = issue['fields']['updated']

# change to Asia/Shanghai time format
up_tmp_date = datetime.datetime.strptime(update_date, "%Y-%m-%dT%H:%M:%S.%f+0800")
update_date = datetime.datetime.strftime(up_tmp_date, "%Y-%m-%d %H:%M:%S")
cr_tmp_date = datetime.datetime.strptime(create_date, "%Y-%m-%dT%H:%M:%S.%f+0800")
create_date = datetime.datetime.strftime(cr_tmp_date, "%Y-%m-%d %H:%M:%S")
if resolved_date is not None:
rs_tmp_date = datetime.datetime.strptime(resolved_date, "%Y-%m-%dT%H:%M:%S.%f+0800")
resolved_date = datetime.datetime.strftime(rs_tmp_date, "%Y-%m-%d %H:%M:%S")

combine_res = {
"issue_name": issue_name,
"issue_type": issue_type,
"project": project,
"summary": summary,
"status": status,
"priority": priority,
"reporter": reporter,
"assignee": assignee,
"description": description,
"create_date": create_date,
"update_date": update_date,
"issue_id": issue_id,
"resolved_date": resolved_date,
"close_date": close_date,
"plan_start_date": plan_start_date,
"plan_end_date": plan_end_date,
"act_start_date": act_start_date,
"act_end_date": act_end_date,
"due_date": due_date,
"estimate_due_date": estimate_due_date,
"components": json.dumps(components_list),
"platform": platform,
"milestone_flag": milestone_flag,
"reproduce_radio": reproduce_radio,
"labels": json.dumps(labels),
"resolution": resolution
}
logger.info("prehandle create data %s" % combine_res)
create_issue_to_db(combine_res)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.

2.3 issue_update.py

from subscribe.jira.sync_to_db import update_issue_to_db, delete_issue_from_db
import logging

logger = logging.getLogger("subscribe")

def parseIssueUpdate(data):
"""
创建时间 created
更新时间 updated
计划开始时间 customfield_10421
计划结束时间 customfield_10422
实际开始时间 customfield_10423
实际结束时间 customfield_10424
解决时间 resolutiondate
关闭时间 customfield_10939
截止时间 duedate
预估截止时间 customfield_10933
"""

fmap = {
"issue_name": "issue_name",
"issue_type": "issue_type",
"project": "project",
"summary": "summary",
"status": "status",
"priority": "priority",
"reporter": "reporter",
"assignee": "assignee",
"description": "description",
"Created": "create_date",
"Updated": "update_date",
"Resolved": "resolved_date",
"Close Date": "close_date",
"Planned Start Date": "plan_start_date",
"Planned End Date": "plan_end_date",
"Actual Start Date": "act_start_date",
"Actual End Date": "act_end_date",
"Due": "due_date",
"Estimated Due Date": "estimate_due_date",
"components": "components",
"platform": "platform",
"milestone_flag": "milestone_flag",
"reproduce_radio": "reproduce_radio",
"labels": "labels",
"resolution": "resolution"
}

datefield = ["Close Date", "Planned Start Date", "Planned End Date", "Actual Start Date", "Actual End Date", "Due", "Estimated Due Date"]
supfield = list(fmap.keys())

predata = {
"issue_name": "",
"issue_type": "",
"project": "",
"summary": "",
"status": "",
"priority": "",
"reporter": "",
"assignee": "",
"description": "",
"create_date": "",
"update_date": "",
"issue_id": "",
"resolved_date": "",
"close_date": "",
"plan_start_date": "",
"plan_end_date": "",
"act_start_date": "",
"act_end_date": "",
"due_date": "",
"estimate_due_date": "",
"components": "",
"platform": "",
"milestone_flag": "",
"reproduce_radio": "",
"labels": "",
"resolution": ""
}

issue = data['issue']
predata['issue_name'] = issue['key']
changelog = data['changelog']
items = changelog['items']
for item in items:
if item['field'] in supfield:
logger.info(item['field'])
if item['field'] == "status":
if item['toString'] != "Integrated":
predata[fmap[item['field']]] = item['toString'].upper()
else:
predata[fmap[item['field']]] = item['toString']
elif item['field'] in datefield:
if item['toString'] == "":
predata[fmap[item['field']]] = None
else:
predata[fmap[item['field']]] = item['toString'].split(" ")[0]
else:
if item['toString'] is None:
predata[fmap[item['field']]] = ""
else:
predata[fmap[item['field']]] = item['toString']
update_issue_to_db(predata)

def parseIssueDelete(data):
issue = data['issue']
issue_name = issue['key']
delete_issue_from_db(issue_name)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.

2.4 sync_to_db.py

from cmapp.models import Jira
import logging
from cmapp.serializers import JiraSerializer

logger = logging.getLogger("subscribe")

def create_issue_to_db(data):
jira_serial = JiraSerializer(data=data)
if jira_serial.is_valid():
jira_serial.save()
logger.info("create issue %s to db ok" % data['issue_name'])
else:
logger.error("create issue failed: %s" % jira_serial.errors)

def update_issue_to_db(data):
try:
updict = {}
hasvaluecount = 0
for k, v in data.items():
if v != "" and k != "issue_name":
updict[k] = v
hasvaluecount += 1
if hasvaluecount > 0:
logger.info("receive data %s" % data)
check_exist = Jira.objects.filter(issue_name=data['issue_name'])
if check_exist.exists():
check_exist.update(**updict)
logger.info("ok jira update %s" % updict)
else:
logger.warning("%s not exist" % data['issue_name'])
except Exception as e:
logger.error("error jira update: %s" % e)

def delete_issue_from_db(issue_name):
try:
Jira.objects.filter(issue_name=issue_name).delete()
logger.info("ok jira delete %s" % issue_name)
except Exception as e:
logger.error("error delete %s, : %s" % (issue_name, e))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

3、配置Jira web-hook

jira管理员,system -> webhook ->新建

URL指向:http://xxx.example.com/api/v1/pm/issues/

触发事件为:issue_created issue_updated
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

测试

http://xxx.example.com/api/v1/pm/issues/
  • 1.
QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空