##// END OF EJS Templates
jira: fix jira and allow to pick issue types
ergo -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,133 +1,141 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # AppEnlight Enterprise Edition, including its added features, Support
18 # AppEnlight Enterprise Edition, including its added features, Support
19 # services, and proprietary license terms, please see
19 # services, and proprietary license terms, please see
20 # https://rhodecode.com/licenses/
20 # https://rhodecode.com/licenses/
21
21
22 import jira
22 import jira
23 from appenlight.models.integrations import (IntegrationBase,
23 from appenlight.models.integrations import (IntegrationBase,
24 IntegrationException)
24 IntegrationException)
25
25
26 _ = str
26 _ = str
27
27
28
28
29 class NotFoundException(Exception):
29 class NotFoundException(Exception):
30 pass
30 pass
31
31
32
32
33 class JiraIntegration(IntegrationBase):
33 class JiraIntegration(IntegrationBase):
34 __mapper_args__ = {
34 __mapper_args__ = {
35 'polymorphic_identity': 'jira'
35 'polymorphic_identity': 'jira'
36 }
36 }
37 front_visible = True
37 front_visible = True
38 as_alert_channel = False
38 as_alert_channel = False
39 supports_report_alerting = False
39 supports_report_alerting = False
40 action_notification = True
40 action_notification = True
41 integration_action = 'Add issue to Jira'
41 integration_action = 'Add issue to Jira'
42
42
43
43
44 class JiraClient(object):
44 class JiraClient(object):
45 def __init__(self, user_name, password, host_name, project, request=None):
45 def __init__(self, user_name, password, host_name, project, request=None):
46 self.user_name = user_name
46 self.user_name = user_name
47 self.password = password
47 self.password = password
48 self.host_name = host_name
48 self.host_name = host_name
49 self.project = project
49 self.project = project
50 self.request = request
50 self.request = request
51 try:
51 try:
52 self.client = jira.client.JIRA(options={'server': host_name},
52 self.client = jira.client.JIRA(options={'server': host_name},
53 basic_auth=(user_name, password))
53 basic_auth=(user_name, password))
54 except jira.JIRAError as e:
54 except jira.JIRAError as e:
55 raise IntegrationException(
55 raise IntegrationException(
56 'Communication problem: HTTP_STATUS:%s, URL:%s ' % (
56 'Communication problem: HTTP_STATUS:%s, URL:%s ' % (
57 e.status_code, e.url))
57 e.status_code, e.url))
58
58
59 def get_projects(self):
59 def get_projects(self):
60 projects = self.client.projects()
60 projects = self.client.projects()
61 return projects
61 return projects
62
62
63 def get_assignees(self):
63 def get_assignees(self, request):
64 """Gets list of possible assignees"""
64 """Gets list of possible assignees"""
65 users = self.client.search_assignable_users_for_issues(
65 cache_region = request.registry.cache_regions.redis_sec_30
66 None, project=self.project)
66 @cache_region.cache_on_arguments('JiraClient.get_assignees')
67 results = []
68 for user in users:
69 results.append({"id": user.name, "name": user.displayName})
70 return results
71
72 def get_metadata(self):
73 def cached(project_name):
67 def cached(project_name):
74 metadata = self.client.createmeta(
68 users = self.client.search_assignable_users_for_issues(
75 projectKeys=project_name, expand='projects.issuetypes.fields')
69 None, project=project_name)
76 assignees = self.get_assignees()
70 results = []
77 parsed_metadata = []
71 for user in users:
78 for entry in metadata['projects'][0]['issuetypes']:
72 results.append({"id": user.name, "name": user.displayName})
79 issue = {"name": entry['name'],
73 return results
80 "id": entry['id'],
74 return cached(self.project)
81 "fields": []}
82 for i_id, field_i in entry['fields'].items():
83 field = {
84 "name": field_i['name'],
85 "id": i_id,
86 "required": field_i['required'],
87 "values": [],
88 "type": field_i['schema'].get('type')
89 }
90 if field_i.get('allowedValues'):
91 field['values'] = []
92 for i in field_i['allowedValues']:
93 field['values'].append(
94 {'id': i['id'],
95 'name': i.get('name', i.get('value', ''))
96 })
97 if field['id'] == 'assignee':
98 field['values'] = assignees
99
75
100 issue['fields'].append(field)
76 def get_issue_types(self, request):
101 parsed_metadata.append(issue)
77 metadata = self.get_metadata(request)
102 return parsed_metadata
78 assignees = self.get_assignees(request)
79 parsed_metadata = []
80 for entry in metadata['projects'][0]['issuetypes']:
81 issue = {"name": entry['name'],
82 "id": entry['id'],
83 "fields": []}
84 for i_id, field_i in entry['fields'].items():
85 field = {
86 "name": field_i['name'],
87 "id": i_id,
88 "required": field_i['required'],
89 "values": [],
90 "type": field_i['schema'].get('type')
91 }
92 if field_i.get('allowedValues'):
93 field['values'] = []
94 for i in field_i['allowedValues']:
95 field['values'].append(
96 {'id': i['id'],
97 'name': i.get('name', i.get('value', ''))
98 })
99 if field['id'] == 'assignee':
100 field['values'] = assignees
101 issue['fields'].append(field)
102 parsed_metadata.append(issue)
103 return parsed_metadata
103
104
105 def get_metadata(self, request):
106 # cache_region = request.registry.cache_regions.redis_sec_30
107 # @cache_region.cache_on_arguments('JiraClient.get_metadata')
108 def cached(project_name):
109 return self.client.createmeta(
110 projectKeys=project_name, expand='projects.issuetypes.fields')
104 return cached(self.project)
111 return cached(self.project)
105
112
106 def create_issue(self, form_data):
113 def create_issue(self, form_data, request):
107 metadata = self.get_metadata()
114 issue_types = self.get_issue_types(request)
108 payload = {
115 payload = {
109 'project': {'key': form_data['project']},
116 'project': {'key': form_data['project']},
110 'summary': form_data['title'],
117 'summary': form_data['title'],
111 'description': form_data['content'],
118 'description': form_data['content'],
112 'issuetype': {'id': '1'},
119 'issuetype': {'id': form_data['issue_type']},
113 "priority": {'id': form_data['priority']},
120 "priority": {'id': form_data['priority']},
114 "assignee": {'name': form_data['responsible']},
121 "assignee": {'name': form_data['responsible']},
115 }
122 }
116 for issue_type in metadata:
123 for issue_type in issue_types:
117 if issue_type['id'] == '1':
124 if issue_type['id'] == form_data['issue_type']:
118 for field in issue_type['fields']:
125 for field in issue_type['fields']:
126 # set some defaults for other required fields
119 if field == 'reporter':
127 if field == 'reporter':
120 payload["reporter"] = {'id': self.user_name},
128 payload["reporter"] = {'id': self.user_name}
121 if field['required'] and field['id'] not in payload:
129 if field['required'] and field['id'] not in payload:
122 if field['type'] == 'array':
130 if field['type'] == 'array':
123 payload[field['id']] = [field['values'][0], ]
131 payload[field['id']] = [field['values'][0], ]
124 elif field['type'] == 'string':
132 elif field['type'] == 'string':
125 payload[field['id']] = ''
133 payload[field['id']] = ''
126 new_issue = self.client.create_issue(fields=payload)
134 new_issue = self.client.create_issue(fields=payload)
127 web_url = self.host_name + '/browse/' + new_issue.key
135 web_url = self.host_name + '/browse/' + new_issue.key
128 to_return = {
136 to_return = {
129 'id': new_issue.id,
137 'id': new_issue.id,
130 'resource_url': new_issue.self,
138 'resource_url': new_issue.self,
131 'web_url': web_url
139 'web_url': web_url
132 }
140 }
133 return to_return
141 return to_return
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now