Esempio n. 1
0
    def raise_error(self, exc, identity=None):
        if isinstance(exc, ApiUnauthorized):
            six.reraise(
                InvalidIdentity,
                InvalidIdentity(self.message_from_error(exc),
                                identity=identity),
                sys.exc_info()[2],
            )
        elif isinstance(exc, ApiError):
            if exc.json:
                error_fields = self.error_fields_from_json(exc.json)
                if error_fields is not None:
                    six.reraise(IntegrationFormError,
                                IntegrationFormError(error_fields),
                                sys.exc_info()[2])

            six.reraise(IntegrationError,
                        IntegrationError(self.message_from_error(exc)),
                        sys.exc_info()[2])
        elif isinstance(exc, IntegrationError):
            raise
        else:
            self.logger.exception(six.text_type(exc))
            six.reraise(IntegrationError,
                        IntegrationError(self.message_from_error(exc)),
                        sys.exc_info()[2])
Esempio n. 2
0
    def after_link_issue(self, external_issue, **kwargs):
        data = kwargs["data"]
        client = self.get_client()

        repo, issue_num = external_issue.key.split("#")

        if not repo:
            raise IntegrationFormError({"repo": "Repository is required"})
        if not issue_num:
            raise IntegrationFormError({"externalIssue": "Issue ID is required"})

        comment = data.get("comment")
        if comment:
            try:
                client.create_comment(
                    repo=repo, issue_id=issue_num, data={"content": {"raw": comment}}
                )
            except ApiError as e:
                self.raise_error(e)
Esempio n. 3
0
    def raise_error(self, exc: ApiError, identity: Optional[Identity] = None) -> None:
        if isinstance(exc, ApiUnauthorized):
            raise InvalidIdentity(self.message_from_error(exc), identity=identity).with_traceback(
                sys.exc_info()[2]
            )
        elif isinstance(exc, ApiError):
            if exc.json:
                error_fields = self.error_fields_from_json(exc.json)
                if error_fields is not None:
                    raise IntegrationFormError(error_fields).with_traceback(sys.exc_info()[2])

            raise IntegrationError(self.message_from_error(exc)).with_traceback(sys.exc_info()[2])
        elif isinstance(exc, IntegrationError):
            raise
        else:
            self.logger.exception(str(exc))
            raise IntegrationError(self.message_from_error(exc)).with_traceback(sys.exc_info()[2])
Esempio n. 4
0
    def create_issue(self, data, **kwargs):
        client = self.get_client()
        if not data.get("repo"):
            raise IntegrationFormError({"repo": ["Repository is required"]})

        data["content"] = {"raw": data["description"]}
        del data["description"]

        try:
            issue = client.create_issue(data.get("repo"), data)
        except ApiError as e:
            self.raise_error(e)

        return {
            "key": issue["id"],
            "title": issue["title"],
            "description": issue["content"]["html"],  # users content rendered as html
            "repo": data.get("repo"),
        }
Esempio n. 5
0
    def create_issue(self, data, **kwargs):
        client = self.get_client()
        cleaned_data = {}
        # protect against mis-configured integration submitting a form without an
        # issuetype assigned.
        if not data.get("issuetype"):
            raise IntegrationFormError(
                {"issuetype": ["Issue type is required."]})

        jira_project = data.get("project")
        if not jira_project:
            raise IntegrationFormError(
                {"project": ["Jira project is required"]})

        meta = client.get_create_meta_for_project(jira_project)
        if not meta:
            raise IntegrationError(
                "Could not fetch issue create configuration from Jira.")

        issue_type_meta = self.get_issue_type_meta(data["issuetype"], meta)
        user_id_field = client.user_id_field()

        fs = issue_type_meta["fields"]
        for field in fs.keys():
            f = fs[field]
            if field == "description":
                cleaned_data[field] = data[field]
                continue
            elif field == "summary":
                cleaned_data["summary"] = data["title"]
                continue
            elif field == "labels" and "labels" in data:
                labels = [
                    label.strip() for label in data["labels"].split(",")
                    if label.strip()
                ]
                cleaned_data["labels"] = labels
                continue
            if field in data.keys():
                v = data.get(field)
                if not v:
                    continue

                schema = f.get("schema")
                if 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 = {user_id_field: v}
                    elif schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES.get(
                            "multiuserpicker"):
                        # custom multi-picker
                        v = [{user_id_field: v}]
                    elif schema["type"] == "array" and schema.get(
                            "items") == "option":
                        v = [{"value": vx} for vx in v]
                    elif schema["type"] == "array" and schema.get(
                            "items") == "string":
                        v = [v]
                    elif schema["type"] == "array" and schema.get(
                            "items") != "string":
                        v = [{"id": vx} for vx in v]
                    elif schema["type"] == "option":
                        v = {"value": 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)

        issue_key = response.get("key")
        if not issue_key:
            raise IntegrationError("There was an error creating the issue.")

        issue = client.get_issue(issue_key)

        return {
            "title": issue["fields"]["summary"],
            "description": issue["fields"]["description"],
            "key": issue_key,
        }
Esempio n. 6
0
    def create_issue(self, data, **kwargs):
        """
        Get the (cached) "createmeta" from Jira to use as a "schema". Clean up
        the Jira issue by removing all fields that aren't enumerated by this
        schema. Send this cleaned data to Jira. Finally, make another API call
        to Jira to make sure the issue was created and return basic issue details.

        :param data: JiraCreateTicketAction object
        :param kwargs: not used
        :return: simple object with basic Jira issue details
        """
        client = self.get_client()
        cleaned_data = {}
        # protect against mis-configured integration submitting a form without an
        # issuetype assigned.
        if not data.get("issuetype"):
            raise IntegrationFormError(
                {"issuetype": ["Issue type is required."]})

        jira_project = data.get("project")
        if not jira_project:
            raise IntegrationFormError(
                {"project": ["Jira project is required"]})

        meta = client.get_create_meta_for_project(jira_project)
        if not meta:
            raise IntegrationError(
                "Could not fetch issue create configuration from Jira.")

        issue_type_meta = self.get_issue_type_meta(data["issuetype"], meta)
        user_id_field = client.user_id_field()

        fs = issue_type_meta["fields"]
        for field in fs.keys():
            f = fs[field]
            if field == "description":
                cleaned_data[field] = data[field]
                continue
            elif field == "summary":
                cleaned_data["summary"] = data["title"]
                continue
            elif field == "labels" and "labels" in data:
                labels = [
                    label.strip() for label in data["labels"].split(",")
                    if label.strip()
                ]
                cleaned_data["labels"] = labels
                continue
            if field in data.keys():
                v = data.get(field)
                if not v:
                    continue

                schema = f.get("schema")
                if 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 = {user_id_field: v}
                    elif schema.get("custom") == JIRA_CUSTOM_FIELD_TYPES.get(
                            "multiuserpicker"):
                        # custom multi-picker
                        v = [{user_id_field: v}]
                    elif schema["type"] == "issuelink":  # used by Parent field
                        v = {"key": v}
                    elif schema.get(
                            "custom") == JIRA_CUSTOM_FIELD_TYPES["epic"]:
                        v = v
                    elif schema.get(
                            "custom") == JIRA_CUSTOM_FIELD_TYPES["sprint"]:
                        try:
                            v = int(v)
                        except ValueError:
                            raise IntegrationError(
                                f"Invalid sprint ({v}) specified")
                    elif schema["type"] == "array" and schema.get(
                            "items") == "option":
                        v = [{"value": vx} for vx in v]
                    elif schema["type"] == "array" and schema.get(
                            "items") == "string":
                        v = [v]
                    elif schema["type"] == "array" and schema.get(
                            "items") != "string":
                        v = [{"id": vx} for vx in v]
                    elif schema["type"] == "option":
                        v = {"value": 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:
            return self.raise_error(e)

        issue_key = response.get("key")
        if not issue_key:
            raise IntegrationError("There was an error creating the issue.")

        # Immediately fetch and return the created issue.
        return self.get_issue(issue_key)