def create_issue(self, request, group, form_data, **kwargs): json_data = { 'story_type': 'bug', 'name': force_text(form_data['title'], encoding='utf-8', errors='replace'), 'description': force_text(form_data['description'], encoding='utf-8', errors='replace'), 'labels': ['sentry'], } try: _url = self.build_api_url(group, 'stories') req = self.make_api_request(group.project, _url, json_data=json_data) body = safe_urlread(req) except requests.RequestException as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) try: json_resp = json.loads(body) except ValueError as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) if req.status_code > 399: raise PluginError(json_resp['error']) return json_resp['id']
def create_issue(self, request, group, form_data, **kwargs): json_data = { "story_type": "bug", "name": force_text(form_data["title"], encoding="utf-8", errors="replace"), "description": force_text(form_data["description"], encoding="utf-8", errors="replace"), "labels": ["sentry"], } try: _url = self.build_api_url(group, "stories") req = self.make_api_request(group.project, _url, json_data=json_data) body = safe_urlread(req) except requests.RequestException as e: msg = str(e) raise PluginError(f"Error communicating with Pivotal: {msg}") try: json_resp = json.loads(body) except ValueError as e: msg = str(e) raise PluginError(f"Error communicating with Pivotal: {msg}") if req.status_code > 399: raise PluginError(json_resp["error"]) return json_resp["id"]
def link_issue(self, request, group, form_data, **kwargs): comment = form_data.get("comment") if not comment: return _url = "%s/%s/comments" % (self.build_api_url(group, "stories"), form_data["issue_id"]) try: req = self.make_api_request(group.project, _url, json_data={"text": comment}) body = safe_urlread(req) except requests.RequestException as e: msg = str(e) raise PluginError("Error communicating with Pivotal: %s" % (msg,)) try: json_resp = json.loads(body) except ValueError as e: msg = str(e) raise PluginError("Error communicating with Pivotal: %s" % (msg,)) if req.status_code > 399: raise PluginError(json_resp["error"])
def link_issue(self, request, group, form_data, **kwargs): comment = form_data.get('comment') if not comment: return _url = '%s/%s/comments' % (self.build_api_url( group, 'stories'), form_data['issue_id']) try: req = self.make_api_request(group.project, _url, json_data={"text": comment}) body = safe_urlread(req) except requests.RequestException as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) try: json_resp = json.loads(body) except ValueError as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) if req.status_code > 399: raise PluginError(json_resp['error'])
def create_issue(self, request, group, form_data, **kwargs): cleaned_data = {} # protect against mis-configured plugin submitting a form without an # issuetype assigned. if not form_data.get("issuetype"): raise PluginError("Issue Type is required.") jira_project_key = self.get_option("default_project", group.project) client = self.get_jira_client(group.project) meta = client.get_create_meta_for_project(jira_project_key) if not meta: raise PluginError( "Something went wrong. Check your plugin configuration.") issue_type_meta = self.get_issue_type_meta(form_data["issuetype"], meta) fs = issue_type_meta["fields"] for field in fs.keys(): f = fs[field] if field == "description": cleaned_data[field] = form_data[field] continue elif field == "summary": cleaned_data["summary"] = form_data["title"] continue if field in form_data.keys(): v = form_data.get(field) if v: schema = f["schema"] if schema.get( "type") == "string" and not schema.get("custom"): cleaned_data[field] = v continue if schema["type"] == "user" or schema.get( "items") == "user": v = {"name": v} elif schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES.get( "multiuserpicker"): # custom multi-picker v = [{"name": v}] elif schema["type"] == "array" and schema.get( "items") != "string": v = [{"id": vx} for vx in v] elif schema["type"] == "array" and schema.get( "items") == "string": v = [v] elif schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES.get( "textarea"): v = v elif (schema["type"] == "number" or schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES["tempo_account"]): try: if "." in v: v = float(v) else: v = int(v) except ValueError: pass elif (schema.get("type") != "string" or (schema.get("items") and schema.get("items") != "string") or schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES.get("select")): v = {"id": v} cleaned_data[field] = v if not (isinstance(cleaned_data["issuetype"], dict) and "id" in cleaned_data["issuetype"]): # something fishy is going on with this field, working on some JIRA # instances, and some not. # testing against 5.1.5 and 5.1.4 does not convert (perhaps is no longer included # in the projectmeta API call, and would normally be converted in the # above clean method.) cleaned_data["issuetype"] = {"id": cleaned_data["issuetype"]} try: response = client.create_issue(cleaned_data) except Exception as e: self.raise_error(e) return response.get("key")
def get_new_issue_fields(self, request, group, event, **kwargs): fields = super().get_new_issue_fields(request, group, event, **kwargs) jira_project_key = self.get_option("default_project", group.project) client = self.get_jira_client(group.project) try: meta = client.get_create_meta_for_project(jira_project_key) except ApiError as e: raise PluginError( "JIRA responded with an error. We received a status code of {}" .format(e.code)) except ApiUnauthorized: raise PluginError( "JIRA returned: Unauthorized. " "Please check your username, password, " "instance and project in your configuration settings.") if not meta: raise PluginError("Error in JIRA configuration, no projects " "found for user %s." % client.username) # check if the issuetype was passed as a GET parameter issue_type = None if request is not None: if request.method == "POST": issue_type = request.data.get("issuetype") else: issue_type = request.GET.get("issuetype") if issue_type is None: issue_type = self.get_option("default_issue_type", group.project) issue_type_meta = self.get_issue_type_meta(issue_type, meta) issue_type_choices = self.make_choices(meta["issuetypes"]) # make sure default issue type is actually # one that is allowed for project if issue_type: if not any(c for c in issue_type_choices if c[0] == issue_type): issue_type = issue_type_meta["id"] fields = ([{ "name": "project", "label": "Jira Project", "choices": ((meta["id"], jira_project_key), ), "default": meta["id"], "type": "select", "readonly": True, }] + fields + [{ "name": "issuetype", "label": "Issue Type", "default": issue_type or issue_type_meta["id"], "type": "select", "choices": issue_type_choices, }]) # title is renamed to summary before sending to JIRA standard_fields = [f["name"] for f in fields] + ["summary"] ignored_fields = (self.get_option("ignored_fields", group.project) or "").split(",") # apply ordering to fields based on some known built-in JIRA fields. # otherwise weird ordering occurs. anti_gravity = { "priority": -150, "fixVersions": -125, "components": -100, "security": -50 } dynamic_fields = list(issue_type_meta.get("fields").keys()) dynamic_fields.sort(key=lambda f: anti_gravity.get(f) or 0) # build up some dynamic fields based on required shit. for field in dynamic_fields: if field in standard_fields or field in [ x.strip() for x in ignored_fields ]: # don't overwrite the fixed fields for the form. continue mb_field = self.build_dynamic_field( group, issue_type_meta["fields"][field]) if mb_field: mb_field["name"] = field fields.append(mb_field) for field in fields: if field["name"] == "priority": # whenever priorities are available, put the available ones in the list. # allowedValues for some reason doesn't pass enough info. field["choices"] = self.make_choices(client.get_priorities()) field["default"] = self.get_option("default_priority", group.project) or "" elif field["name"] == "fixVersions": field["choices"] = self.make_choices( client.get_versions(jira_project_key)) return fields
def create_issue(self, request, group, form_data, **kwargs): cleaned_data = {} # protect against mis-configured plugin submitting a form without an # issuetype assigned. if not form_data.get('issuetype'): raise PluginError('Issue Type is required.') jira_project_key = self.get_option('default_project', group.project) client = self.get_jira_client(group.project) meta = client.get_create_meta_for_project(jira_project_key) if not meta: raise PluginError( 'Something went wrong. Check your plugin configuration.') issue_type_meta = self.get_issue_type_meta(form_data['issuetype'], meta) fs = issue_type_meta['fields'] for field in fs.keys(): f = fs[field] if field == 'description': cleaned_data[field] = form_data[field] elif field == 'summary': cleaned_data['summary'] = form_data['title'] if field in form_data.keys(): v = form_data.get(field) if v: schema = f['schema'] if schema.get('type') == 'string' and not schema.get( 'custom') == JIRA_CUSTOM_FIELD_TYPES['select']: continue # noop if schema['type'] == 'user' or schema.get( 'items') == 'user': v = {'name': v} elif schema.get('custom') == JIRA_CUSTOM_FIELD_TYPES.get( 'multiuserpicker'): # custom multi-picker v = [{'name': v}] elif schema['type'] == 'array' and schema.get( 'items') != 'string': v = [{'id': vx} for vx in v] elif schema['type'] == 'array' and schema.get( 'items') == 'string': v = [v] elif schema.get('custom') == JIRA_CUSTOM_FIELD_TYPES.get( 'textarea'): v = v elif schema['type'] == 'number' or \ schema.get('custom') == JIRA_CUSTOM_FIELD_TYPES['tempo_account']: try: if '.' in v: v = float(v) else: v = int(v) except ValueError: pass elif (schema.get('type') != 'string' or schema.get('items') != 'string' or schema.get('custom') == JIRA_CUSTOM_FIELD_TYPES.get('select')): v = {'id': v} cleaned_data[field] = v if not (isinstance(cleaned_data['issuetype'], dict) and 'id' in cleaned_data['issuetype']): # something fishy is going on with this field, working on some JIRA # instances, and some not. # testing against 5.1.5 and 5.1.4 does not convert (perhaps is no longer included # in the projectmeta API call, and would normally be converted in the # above clean method.) cleaned_data['issuetype'] = {'id': cleaned_data['issuetype']} try: response = client.create_issue(cleaned_data) except Exception as e: self.raise_error(e) return response.json.get('key')
def raise_error(self, exc): # TODO(jess): switch this from JIRAError to the standard # shared exeption classes if not isinstance(exc, JIRAError): self.logger.exception(six.text_type(exc)) raise PluginError(self.message_from_error(exc))
def get_new_issue_fields(self, request, group, event, **kwargs): fields = super(JiraPlugin, self).get_new_issue_fields(request, group, event, **kwargs) jira_project_key = self.get_option('default_project', group.project) client = self.get_jira_client(group.project) try: meta = client.get_create_meta_for_project(jira_project_key) except JIRAUnauthorized: raise PluginError( 'Something went wrong. Please check your configuration.') if not meta: raise PluginError('Error in JIRA configuration, no projects ' 'found for user %s.' % client.username) # check if the issuetype was passed as a GET parameter issue_type = None if request is not None: issue_type = request.GET.get('issue_type') if issue_type is None: issue_type = self.get_option('default_issue_type', group.project) issue_type_meta = self.get_issue_type_meta(issue_type, meta) issue_type_choices = self.make_choices(meta['issuetypes']) # make sure default issue type is actually # one that is allowed for project if issue_type: if not any((c for c in issue_type_choices if c[0] == issue_type)): issue_type = issue_type_meta['id'] fields = [{ 'name': 'project', 'label': 'Jira Project', 'choices': ((meta['id'], jira_project_key), ), 'default': meta['id'], 'type': 'select', 'readonly': True }] + fields + [{ 'name': 'issuetype', 'label': 'Issue Type', 'default': issue_type or issue_type_meta['id'], 'type': 'select', 'choices': issue_type_choices }] # title is renamed to summary before sending to JIRA standard_fields = [f['name'] for f in fields] + ['summary'] ignored_fields = (self.get_option('ignored_fields', group.project) or '').split(',') # apply ordering to fields based on some known built-in JIRA fields. # otherwise weird ordering occurs. anti_gravity = { "priority": -150, "fixVersions": -125, "components": -100, "security": -50 } dynamic_fields = issue_type_meta.get('fields').keys() dynamic_fields.sort(key=lambda f: anti_gravity.get(f) or 0) # build up some dynamic fields based on required shit. for field in dynamic_fields: if field in standard_fields or field in [ x.strip() for x in ignored_fields ]: # don't overwrite the fixed fields for the form. continue mb_field = self.build_dynamic_field( group, issue_type_meta['fields'][field]) if mb_field: mb_field['name'] = field fields.append(mb_field) for field in fields: if field['name'] == 'priority': # whenever priorities are available, put the available ones in the list. # allowedValues for some reason doesn't pass enough info. field['choices'] = self.make_choices( client.get_priorities().json) field['default'] = self.get_option('default_priority', group.project) or '' elif field['name'] == 'fixVersions': field['choices'] = self.make_choices( client.get_versions(jira_project_key).json) return fields