예제 #1
0
 def POST(self):
     issue_list = self.init_bugs()
     # print issue_list
     #jira = JIRA(server='http://127.0.0.1:1194', basic_auth=('wangyang', 'qwerty123456'))
     jira = JIRA(server=jira_server, basic_auth=(user_accout, user_pass))
     issues = jira.create_issues(field_list=issue_list)
     # issue = jira.issue(issues[0]['issue'])
     # issue.update(versions=[{"Affects Version/s": 'V18'}])
     print issues
     if(issues[0]['error']):
         return issues[0]['error']
     else:
         return 0
def jira_setup(project,
               assignee,
               title,
               description,
               filename='',
               due=1,
               comment=''):
    '''This code will Create Jira ticket and return the Issue Key of the ticket Created. '''

    apiKey = '*********************'  #apiKey you will find in Jira page
    jira = JIRA(basic_auth=('*****@*****.**', apiKey),
                options={"server": 'https://abcdef.xyz.net'})
    duedate = str((datetime.date.today() +
                   datetime.timedelta(days=due)).strftime('%Y-%m-%d'))
    issue_list = [{
        'project': {
            'key': project
        },
        'summary': title,
        'description': description,
        'issuetype': {
            'name': 'Task'
        },
        'assignee': {
            'name': assignee
        },
        'priority': {
            'name': 'High'
        },
        'duedate': duedate
    }]
    issues = jira.create_issues(issue_list)
    issueKey = issues[0]['issue'].key
    print(f'{issueKey} created')
    if filename:
        with open(filename, 'rb') as f:
            jira.add_attachment(issue=issueKey, attachment=f)
    if comment:
        jira.add_comment(issue=issueKey, body=comment)
        print(f'Comment added to {issueKey}')
    return issueKey
예제 #3
0
class Main():
    """Main class for task creation"""
    def __init__(self, jsonFile=None, noRun=False):
        """Constructor for Main class."""
        self.jiraURL = ''

        if noRun == False:
            username = input('Username:'******'Password:'******'Jira login failed. Please check your username and password.'
                    )
                    sys.exit()
                else:
                    print('An error occured. Status code: %s' %
                          error.status_code)

            self.tasks = []
            self.linkedIssues = []
            self.createdIssues = []
            self.confirmedLinks = []
            self.returnStatuses = []
            self.updateLinks = []
            self.taskJson = []
            self.main()

    def loadTasks(self):
        """Loads task objects from input file."""

        print('Loading task from file...')

        schema = os.path.join(os.path.dirname(__file__),
                              'schema.json')  #Read schema JSON
        with open(schema, 'r') as fp:
            schemaJson = fp.read()
        schemaJson = json.loads(schemaJson)

        try:  #Read task JSON
            with open(self.jsonFile, 'r') as fp:
                try:
                    self.taskJson = (json.loads(fp.read()))
                except json.decoder.JSONDecodeError as err:
                    print(
                        "Task JSON Load Error: %s\nError Line: %s\nError Column: %s"
                        % (err.msg, err.lineno, err.colno))
                    sys.exit()

            for task in self.taskJson:
                try:
                    validate(task, schemaJson)
                except exceptions.ValidationError as err:
                    print("Task JSON Validation Error: %s" % err.message)
                    sys.exit()

        except FileNotFoundError as err:
            print('File \'%s\' does not exist.' % self.jsonFile)
            sys.exit()

    def buildTasks(self):
        """Creates a list of task objects from the objects read in
    from the file."""

        print('Generating tasks...')
        for task in self.taskJson:

            try:
                story_points = task['story_points']
            except KeyError:
                story_points = 1

            try:
                assignee = {'name': task['assignee']}
            except KeyError:
                assignee = {'name': ''}

            try:
                priority = {'name': task['priority']}
            except KeyError:
                priority = {'name': '2— Normal'}

            try:
                description = task['description']
            except KeyError:
                description = ''

            try:
                components = [{
                    'name': component
                } for component in task['components']]
            except KeyError:
                components = []

            issue = {
                'project': task['project'],
                'summary': task['summary'],
                'customfield_10201': task['epic_link'],
                'customfield_10300': story_points,
                'assignee': assignee,
                'priority': priority,
                'description': description,
                'components': components,
                'reporter': {
                    'name': task['reporter']
                },
                'issuetype': task['issue_type']
            }
            self.tasks.append(issue)

    def createIssues(self):
        """Creates a Jira issue for each task object in the tasks list."""

        print('Creating tasks in Jira...')
        tasks = [task for task in self.tasks]  #List of task dicts
        self.returnStatuses = self.j.create_issues(field_list=tasks)

        self.createdIssues = [
            (status['status'],
             (status['issue'].key if status['status'] == 'Success' else False),
             status['input_fields']['summary'])
            for status in self.returnStatuses
        ]

    def linkIssues(self):
        """Searches for links between issues in the specified file."""

        print('Checking for links...')

        for task in self.taskJson:  #Read links from task JSON
            try:
                link = ({
                    'issuelinks': [{
                        'type': links
                    } for links in task['linked_issues']]
                }, task['summary'])
                self.linkedIssues.append(link)
            except KeyError:
                self.linkedIssues.append(None)

        for issueLink in self.linkedIssues:
            if issueLink == None:  # No link
                pass
            else:
                issueLinks = issueLink[0]['issuelinks']
                for link in issueLinks:
                    #check Link
                    linkType = list(link['type'].keys())[0]
                    toLink = list(link['type'].values())[0]
                    baseTask = issueLink[1]
                    if self.findTask(toLink, baseTask):
                        toLinkKey = self.getKey(toLink)  # current task's id
                        baseTaskKey = self.getKey(baseTask)  # link to task id

                        self.confirmedLinks.append(
                            (linkType, baseTaskKey, toLinkKey))

    def getKey(self, summary):
        """Returns the key of an issue with specified summary from the
    list of newly generated Jira tasks or from previously created tasks."""

        #Task was created from current running JSON
        for link in self.returnStatuses:
            if link['input_fields']['summary'] == summary:
                return link['issue'].key

        #Task to be linked already exists, search Jira for its key
        try:
            result = self.j.search_issues('summary ~ \"%s\"' % summary)
            return (result[0].key)

        except JIRAError as e:
            print(e)
            print("Desired link issue %s was not found in Jira. Exiting..." %
                  summary)
            sys.exit()

    def findTask(self, toLink, baseTask):
        """Determines if the tasks to be linked were both created."""
        for task in self.createdIssues:
            if toLink in task[0] and 'Error' in task[
                    0]:  # Task to be linked to not was created
                return False
        for task in self.createdIssues:
            if baseTask in task[0] and 'Error' in task[
                    0]:  # Task was not created
                return False
        return True  # Both the task and the link to task where created

    def generateUpdateLinks(self):
        """Creates a links in proper Jira format."""
        print('Generating links...')

        for link in self.confirmedLinks:  #link types supported: blockedBy, blocks, clones, duplicates, escalates, split
            type = link[0]
            if type == 'blockedBy':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Blocks',
                            "inward": "is blocked by",
                            "outward": "blocks"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'blocks':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Blocks',
                            "inward": "is blocked by",
                            "outward": "blocks"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'clones':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Cloners',
                            "inward": "is cloned by",
                            "outward": "clones"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'clonedBy':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Cloners',
                            "inward": "is cloned by",
                            "outward": "clones"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'duplicates':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Duplicate',
                            "inward": "is duplicated by",
                            "outward": "duplicates"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'duplicatedBy':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Duplicate',
                            "inward": "is duplicated by",
                            "outward": "duplicates"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'escalates':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Escalated',
                            "inward": "Escalates",
                            "outward": "Escalated by"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'escalatedBy':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Escalated',
                            "inward": "Escalates",
                            "outward": "Escalated by"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'splitTo':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Issue split',
                            "inward": "split from",
                            "outward": "split to"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'splitFrom':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Issue split',
                            "inward": "split from",
                            "outward": "split to"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'causes':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Problem/Incident',
                            "inward": "is caused by",
                            "outward": "causes"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'causedBy':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Problem/Incident',
                            "inward": "is caused by",
                            "outward": "causes"
                        },
                        "inwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            elif type == 'relatesTo':
                self.updateLinks.append((link[1], {
                    'add': {
                        'type': {
                            "name": 'Relates',
                            "inward": "relates to",
                            "outward": "relates to"
                        },
                        "outwardIssue": {
                            "key": link[2]
                        }
                    }
                }))

            else:
                return

    def update(self):
        """Updates the task links in Jira using formatted links in updateLinks list."""

        print('Updating links in Jira...')

        for link in self.updateLinks:
            issue = self.j.issue(link[0])  # Instance of desired Jira issue

            issue.update(issuelinks=[link[1]])  # Update the issue's link

    def main(self):
        """Main program sequence."""

        self.loadTasks()  # Read task file
        self.buildTasks()  # Format tasks to Jira format
        self.createIssues()  # Create issues within Jira
        self.linkIssues()  # Check for supported task links
        self.generateUpdateLinks()  # Generate update links in Jira format
        self.update()  # Update task links in Jira
예제 #4
0
    'issuetype': {
        'name': ' Task'
    },
}, {
    'project': {
        'key': 'PROJ-1'
    },
    'summary': 'Second issue',
    'description': 'Another one',
    'issuetype': {
        'name': ' Task'
    },
}, {
    'project': {
        'key': 'PROJ-1'
    },
    'summary': 'Last issue',
    'description': 'Final issue of batch.',
    'issuetype': {
        'name': ' Task'
    },
}]
issues = jira.create_issues(field_list=issue_list)
issues_in_proj = jira.search_issues('project=PROJ')

oh_crap = jira.search_issues(
    'assignee = {0} and due < endOfWeek() order by priority desc'.format(
        'testuser1'),
    maxResults=5)
print([iss for iss in oh_crap])
예제 #5
0
def main():
    """creates tickets for a release task"""
    parser = argparse.ArgumentParser(
        description='Creates tickets for release certification')
    parser.add_argument('-u',
                        '--username',
                        help='jira username',
                        default='admin')
    parser.add_argument('-p',
                        '--password',
                        help='jira password',
                        default='admin')
    parser.add_argument('-c',
                        '--config',
                        help='path to config file',
                        default='./options.ini')
    parser.add_argument('-j',
                        '--jira',
                        help='url of jira server',
                        default='http://localhost:8080')

    args = parser.parse_args()

    jira_user = args.username
    jira_pass = args.password
    jira_server = args.jira
    config_file_path = args.config
    CONFIG.read(config_file_path)

    parent_ticket = config_map('JiraOptions')['parent_ticket']
    apprenda_version = config_map('VersionInfo')['to_version']
    jira_project = config_map('JiraOptions')['project']
    jira_issue_type = config_map('JiraOptions')['issue_type']
    jira = JIRA(jira_server, basic_auth=(jira_user, jira_pass))

    parent_issue = jira.issue(parent_ticket)
    ticket_list = []

    # create clean install tickets
    clean_strings = config_map('CleanInstallSection')
    for cloud in ['single', 'hybrid']:
        ticket_to_add = ticket.Ticket(jira_project, jira_issue_type)
        ticket_to_add.format_summary(clean_strings['summary'],
                                     apprenda_version, cloud)
        ticket_to_add.format_description(clean_strings['description'])
        ticket_list.append(ticket_to_add.__dict__)

    # create upgrade tickets
    from_versions = json.loads(config_map('VersionInfo')['from_versions'])
    upgrade_strings = config_map('UpgradeSection')

    # single cloud
    for version in from_versions:
        ticket_to_add = ticket.Ticket(jira_project, jira_issue_type)
        ticket_to_add.format_summary(upgrade_strings['summary'],
                                     apprenda_version, version, "single")
        ticket_to_add.format_description(upgrade_strings['description'])
        ticket_list.append(ticket_to_add.__dict__)

    # hybrid cloud
    for version in from_versions:
        ticket_to_add = ticket.Ticket(jira_project, jira_issue_type)
        ticket_to_add.format_summary(upgrade_strings['summary'],
                                     apprenda_version, version, "hybrid")
        ticket_to_add.format_description(upgrade_strings['description'])
        ticket_list.append(ticket_to_add.__dict__)

    # create testing tickets for other tasks
    for section in CONFIG.sections():
        if 'Ticket' in section:
            strings = config_map(section)
            ticket_to_add = ticket.Ticket(jira_project, jira_issue_type)
            ticket_to_add.format_summary(strings['summary'], apprenda_version)
            ticket_to_add.format_description(strings['description'])
            ticket_list.append(ticket_to_add.__dict__)

    print 'Created {0} tickets, now sending them to Jira'.format(
        len(ticket_list))
    # send issues to jira and create tickets and links
    issues = jira.create_issues(field_list=ticket_list)

    for item in issues:
        jira.create_issue_link(
            type="Task of Story",
            outwardIssue=item['issue'].key,
            inwardIssue=parent_issue.key,
        )

    print 'Finished linking issues, exiting.'
예제 #6
0
class JiraAdapter(AbstractAdapter):

    _connected = False
    _user_name = None
    _password = None
    _servers = None
    _max_results = 0
    _jira = None

    def __init__(self):
        options = JiraAdapter.read_jira_config()
        self._user_name = options['user_name']
        self._password = options['password']
        self._servers = options['servers']
        self._max_results = int(options['max_results'])

    @staticmethod
    def read_jira_config():
        cc = cc_klass()
        options = cc.read_jira_config()

        if options is None:
            options = {'user_name': 'demo.demo',
                       'password': '******',
                       'server': 'https://jira.billing.ru',
                       'max_results': 0,
                       }
        return options

    @staticmethod
    def issues_to_list(issues, clear=True):
        issues_list = []

        if issues is None:
            logging.warning('issues is None')
            return issues_list

        for issue in issues:
            new_issue = issue.raw;
            #new_issue['fields'].fixVersions = issue.fields.fixVersions
            issues_list.append(new_issue)

        if clear:
            issues_list = clear_issues(issues_list)
        return issues_list

    def _connect(self, url):
        self._connected = False
        if internet_on():
            try:
                self._jira = JIRA(server=url, basic_auth=(self._user_name, self._password))
                self._connected = True

            except Exception as e:
                logging.error("invalid server connection: %s", url)
        else:
            logging.warning('working OFFLINE')
        return self._connected

    def load_by_query(self, query_str, expand, url):
        new_issues = []

        if query_str is None:
            raise ValueError('nothing to load')

        issue_objs = None
        if self._connect(url=url):
            issue_objs = self._jira.search_issues(query_str, maxResults=self._max_results, expand=expand,
                                              json_result=False)

            # for i in range(1,total, 200):
            #  issues.append(jira.search_issues(search_query, maxResults=200, startAt=i))

            new_issues = JiraAdapter.issues_to_list(issue_objs)
            logging.debug('total issues: %s', len(new_issues))

        return new_issues

    def load_by_key(self, key, expand, url):
        if expand is not None:
            expands = expand.split(',') if ',' in expand else [expand]
            for item in expands:
                if item not in EXPAND_LIST:
                    raise ValueError(item + ' is not correct. Valid values: ' + str(EXPAND_LIST))

        issue = None
        if self._connect(url=url):
            try:
                issue = self._jira.issue(key, expand=expand)
                logging.debug('loaded issue %s from %s', issue, self._jira._options['server'])
            except Exception as e:
                logging.error('%s [%s]', e.text, e.status_code)

        return issue

    def get_builder(self):
        return JSQLBuilder()

    def create_issue(self, issues):

        if self._connect():
            issues = self._jira.create_issues(field_list=issues)

        return issues
예제 #7
0
class JiraWrapper:
    """
    Setting for connecting to JIRA
    """
    def __init__(self, params):
        # general settings
        self.params = params
        self.jira = None

        # Proxy settings

        if "HTTP_PROXY" not in os.environ:
            if params.get_http_proxy_url:
                os.environ["HTTP_PROXY"] = params.get_http_proxy_url

        if "HTTPS_PROXY" not in os.environ:
            if params.get_https_proxy_url:
                os.environ["HTTPS_PROXY"] = params.get_https_proxy_url

        # jira settings
        self.jira_url = self.params.get_jira_url
        self.jira_url = self.jira_url.strip("/")

        # see if we need to use a certificate
        if params.get_use_cert:
            self.jira_options = {
                "server": self.jira_url,
                "verify": True,
                "client_cert": (
                    "mycert-dn.crt",
                    "mycert-dn.key",
                )
            }
        else:
            self.jira_options = {"server": self.jira_url}

    # noinspection PyAttributeOutsideInit
    def connect(self, username, password: str):
        """
        Trigger the connection to jira
        :param username:
        :param password: user password for the connection
        :return: True on success
        """
        try:
            print('Connecting to Jira')
            self.jira = JIRA(options=self.jira_options,
                             basic_auth=(username, password),
                             max_retries=1)
            print('Connected')
            return True, None

        except Exception as e:
            print('Unable to connect')
            print(str(e))
            pass
            return False, e

    @property
    def get_components(self) -> list:
        """
        Get list of components available on the server
        :return: available compnents
        """

        components = self.jira.project_components(self.params.get_project)
        component_list = []
        for i in components:
            component_list.append(i.name)

        return component_list

    def create_components(self, components: list) -> list:
        """
        Create components if the do not already exist
        :param components: components to create
        :return: list of created components
        """
        components_avail = self.get_components
        components_todo = set(components) - set(components_avail)

        for i in components_todo:
            self.jira.create_component(i, self.params.get_project)

        return list(components_todo)

    def create_task_subtask(self, task_name: str, comment: str, reporter: str,
                            parent_assignee: str, sub_assignees: list,
                            duedate: str, labels: [str], priority: str):
        """
        Creat a task and all subtasks for the users
        :param reporter: who reports the bug
        :param priority:
        :param comment:
        :param task_name: Name of the task
        :param parent_assignee: Who is the owner of the parent task
        :param sub_assignees: List of people getting the subtasks. Needs to be jira userids
        :param duedate: what is the duedate for the parent task and the subtasks
        :param labels: Labels the tasks get added
        :return: url to the jira task for the webbrowser
        """

        # return values
        parent_url = None
        error_msg = None

        parent_component = None
        parent_assignee_id = None
        for i in sub_assignees:
            if parent_assignee == i[0]:
                parent_assignee_id = i[1]
                parent_component = i[2]
                break
        assert parent_assignee_id

        # TODO this only works if the reporter is part of the assignee list.
        reporter_id = ''
        for i in sub_assignees:
            if reporter == i[0]:
                reporter_id = i[1]
                break

        assert reporter_id

        # sub_assignees = self.get_users(sub_assignees)
        issue_dict = {
            'project': self.params.get_project,
            'summary': task_name,
            'description': comment,
            'issuetype': {
                'name': 'Task'
            },
            'assignee': {
                'name': parent_assignee_id
            },
            'duedate': duedate,
            'labels': labels,
            'priority': {
                'name': priority
            }
        }
        if parent_component:
            issue_dict['components'] = [{'name': parent_component}]

        # TODO allow change reporter
        if self.params.can_change_reporter:
            issue_dict['reporter'] = {'name': reporter_id}

        # print("Creating task")
        # print(sub_assignees)
        # print(issue_dict['assignee'])

        # for debugging set to false to no swap jira
        create = True
        parent_issue = None
        if create:
            try:
                parent_issue = self.jira.create_issue(fields=issue_dict)
                print("Created task: %s" % parent_issue.key)
            except Exception as e:
                print(e)
                parent_url = None
                error_msg = e.text
                pass

        # we were not able to create a issue. Connection error?
        if not parent_issue:
            return parent_url, error_msg

        # does your handle bulk create?
        can_bulk = True

        # now create the sub-task, linked to the parent task for all users
        child_issue_dict = []
        for val in sub_assignees:
            # val[3] is the bool if the task has to be created
            if val[3]:
                print('Creating Sub-tak for:', val[0])
                cur_issue_dict = copy.deepcopy(issue_dict)
                cur_issue_dict['summary'] = '(Subtask) ' + task_name
                cur_issue_dict['issuetype'] = {'name': 'Sub-task'}
                if create:
                    # noinspection PyUnresolvedReferences
                    # cur_issue_dict['parent'] = {"id": parent_issue.key}
                    cur_issue_dict['parent'] = {"id": parent_issue.id}
                cur_issue_dict['assignee'] = {'name': val[1]}

                # if componets for the user, add it
                if val[2]:
                    cur_issue_dict['components'] = [{'name': val[2]}]
                else:
                    cur_issue_dict['components'] = []

                if not can_bulk:
                    print('Slow call of Sub-task creation')
                    self.jira.create_issue(cur_issue_dict)
                else:
                    child_issue_dict.append(cur_issue_dict)

        if create and len(child_issue_dict) > 0:
            try:
                self.jira.create_issues(child_issue_dict)
            except Exception as e:
                print('Error creating Sub-Tasks. Message:')
                print(e)
                pass

        assert parent_issue

        parent_url = '%s/%s/%s' % (self.jira_url, 'browse', parent_issue.key)
        print(parent_url)
        return parent_url, error_msg

    def get_users(self, userlist):
        """
        For all the users in the self.full_assignee_list get the user ids from JIRA
        :return:
        """
        for i, val in enumerate(userlist):
            tmp = self.jira.search_assignable_users_for_projects(
                val[0], self.params.get_project)
            if not tmp:
                raise Exception('Could not find userid for %s' % val[0])

            userlist[i][1] = tmp[0].key
        return userlist