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
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
'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])
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.'
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
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