def __init__(self, root_id): self.root_id = root_id self.api_jira = API_Jira() self.wmap = Wardley_Map() self.link_type = 'needs' self.api_jira._jira = JIRA( server='https://ubuntu-policy.atlassian.net/')
def __init__(self, issue_id=None, channel=None, team_id=None, event=None): self.issue_id = issue_id self.channel = channel self.team_id = team_id self.event = event self.api_issues = API_Issues() self.api_jira = API_Jira() self.issue = None self.action_id = 'Jira_View_Issue' self.slack_blocks = API_Slack_Blocks()
def jira_create_issue(self): #project = self.submission.get('project') issue_type = self.submission.get('issue_type') project = issue_type.upper() summary = self.submission.get('summary') description = self.submission.get('description') if summary: summary = summary.replace('+', ' ') if description: description = description.replace('+', ' ') else: description = '' if project and issue_type and summary: self.send_message( 'Creating new `{0}` issue on project `{1}` with summary `{2}` and description `{3}`' .format(issue_type, project, summary, description)) from osbot_jira.api.jira_server.API_Jira import API_Jira try: result = API_Jira().issue_create(project, summary, description, issue_type) new_issue_id = "{0}".format(result) self.submission['issue_id'] = new_issue_id self.show_issue() #self.show_issue_screnshot() jira_link = "https://glasswall.atlassian.net/browse/{0}".format( new_issue_id) return 'Created issue: <{0}|{1}>'.format( jira_link, new_issue_id) except Exception as error: return ':red_circle: Error creating issue: {0}'.format(error) return ':red_circle: Error in Slack_Dialog_Submissions.jira_create_issue. Missing required values from submission data: `{0}`'.format( self.submission)
class Jira_Map: def __init__(self, root_id): self.root_id = root_id self.api_jira = API_Jira() self.wmap = Wardley_Map() self.link_type = 'needs' self.api_jira._jira = JIRA( server='https://ubuntu-policy.atlassian.net/') def add_node(self, issue_id, depth_delta=0): issue = self.api_jira.issue(issue_id) summary = issue['Summary'] self.wmap.add_node(issue['Summary'], issue['Status'], depth_delta) issue.get('Issue Links') summary = issue.get('Summary') issue_links = issue.get('Issue Links') for link_id in issue_links: for issue_link in issue_links[link_id]: if issue_link['Link Type'] == self.link_type: self.add_node(link_id, depth_delta + 1.5) self.wmap.add_link(summary, issue_link.get('Summary')) def create(self): self.add_node(self.root_id) return self def show(self, height=300): self.create() self.wmap.show_map(height)
def issue(team_id=None, channel=None, params=None): (text, attachments) = Jira_Commands._check_params(params, ['Issue Id']) if text: return text #, attachments issue_id, = params project = issue_id.split('-').pop(0) projects = Jira_Commands.gsbot_projects if project not in projects: return { "error": ":rec_circle: project `{0}` is currently not available. The projects currently supported are: `{1}`" .format(project, projects) } return API_Jira().issue(issue_id)
def cmd_create(self, params, team_id=None, channel=None): try: if len(params) < 3: text = ":exclamation: To create an issue you need to provide the `issue type` and `summary`. For example `jira create task abc" return {"text": text, "attachments": []} else: params.pop(0) # the create command issue_type = params.pop( 0) #.title() # todo: find a better solution for this project = issue_type.upper( ) # todo: and to address the mapping of issue types to projects summary = ' '.join(params) slack_message( ':point_right: Going to create an `{0}` issue, in project `{1}` with summary `{2}`' .format(issue_type, project, summary), [], channel, team_id) #to do, move this feature to a separate lambda (which can be called to create issues from osbot_aws.Dependencies import load_dependency load_dependency('jira') from osbot_jira.api.jira_server.API_Jira import API_Jira # create issue result = API_Jira().issue_create(project, summary, '', issue_type) issue_id = "{0}".format(result) # show issue screenshot # payload = {'issue_id': issue_id,'channel': channel,'team_id': team_id, } # Lambda('osbot_browser.lambdas.jira_web').invoke_async(payload) # show issue UI payload = {'params': ['issue', issue_id], "channel": channel} Lambda('osbot_jira.lambdas.jira').invoke_async(payload) # show link of new issue to user jira_link = "https://glasswall.atlassian.net/browse/{0}".format( issue_id) text = ':point_right: New issue created with id <{0}|{1}>'.format( jira_link, issue_id) return {"text": text, "attachments": []} except Exception as error: log_to_elk('jira create error', f'{error}') return { 'text': f':red_circle: Issue could not be created, please make sure that: \n - issue type exists\n - issue type = project type\n - Issue type CamelCase is correctly entered (you want `Task` and not `task`)', "attachments": [] }
def cmd_add_link(self, params, team_id=None, channel=None): if len(params) < 4: text = ":exclamation: Hi, to add a link, You must provide 3 params: `{from ID}` `{to ID}` `{link type}`" return {"text": text, "attachments": []} else: params.pop(0) # position 0 is the 'issue' command from_key = params.pop(0) to_key = params.pop(0) link_type = " ".join(params) try: from osbot_jira.api.jira_server.API_Jira import API_Jira API_Jira().issue_add_link(from_key, link_type, to_key) text = ':point_right: Added link: *{0}* `{1}` *{2}*'.format( from_key, link_type, to_key) except Exception as error: text = ':red_circle: Error in `add_link`: {0}'.format(error) return {"text": text, "attachments": []}
def update(team_id=None, channel=None, params=None): try: issue_data = json.loads(" ".join(params)) issue_id = issue_data.get('Key') project = issue_id.split('-').pop(0) projects = Jira_Commands.gsbot_projects if project not in projects: return ":rec_circle: project `{0}` is currently not available. The projects currently supported are: `{1}`".format( project, projects) API_Jira().issue_update(issue_data) return {"status": "ok"} except Exception as error: return { "error", ":rec_circle: error in `Jira_Commands.update` command: `{0}`". format(error) }
from flask_restplus import Namespace, Resource from osbot_jira.api.jira_server.API_Jira import API_Jira api = Namespace('jira-sync', description='JIRA issues related operations') jira_api = API_Jira() @api.route('/load-jira/<file_id>') class load_jira(Resource): def get(self, file_id): try: from pbx_gs_python_utils.api_jira.API_Jira_Sheets_Sync import API_Jira_Sheets_Sync api_sync = API_Jira_Sheets_Sync(file_id) result = api_sync.load_data_from_jira() return {'status': result} except Exception as error: return {'error': "{0}".format(error)} @api.route('/diff-sheet/<file_id>') class diff_sheet(Resource): def get(self, file_id): try: from pbx_gs_python_utils.api_jira.API_Jira_Sheets_Sync import API_Jira_Sheets_Sync api_sync = API_Jira_Sheets_Sync(file_id) result = api_sync.diff_sheet() return {'status': result} except Exception as error: return {'error': "{0}".format(error)}
class GW_Elastic_Jira: def __init__(self, index_id = 'jira', projects = None): self.secrets_id = 'gw-elastic-server-1' self.index_id = index_id self.elastic = None self.api_Jira = API_Jira() self.projects = projects #'IA, TM,GDPR' def reload_all_data_from_jira_project(self): # todo: find better location to do this (reloading of elastic data) self.re_create_index() self.send_data_from_project() def re_create_index(self): # note that this will delete the index and recreate it self.elastic.delete_index() \ .create_index() # self.elastic.delete_index() \ # .delete_index_pattern() \ # .create_index() \ # .create_index_pattern(add_time_field=False) return self def setup(self): if self.elastic is None: self.elastic = Elastic_Search(self.index_id,self.secrets_id) return self def fix_issues_for_elk(self,issues): return [self.fix_issue_for_elk(issue) for issue in issues] def fix_issue_for_elk(self,issue): items = {} #{'_all': [] } # fix issue links for key, issue_links in issue['Issue Links'].items(): #items['_all'].append(key) # capture a list of all ids for issue_link in issue_links: link_type = issue_link['Link Type'] if items.get(link_type) is None: # and index them by link_type items[link_type] = [] items[link_type].append(key) issue['Issue Links'] = items if issue['Rating'] == 'To be determined': issue['Rating']= 'TBD' if issue['Project'] == 'VULN (Vulnerability)': issue['Project'] = 'VULN' #Dev.pprint(issue) return issue def send_data_from_project(self, project=None): if project: jql = 'project={0}'.format(project) else: jql = '' # todo: find a better way to get all results from Jira api_jira_rest = API_Jira_Rest() issues = api_jira_rest.search(jql) return self.elastic.add_bulk(issues, "Key") def issue_get(self,issue_id): try: data = self.elastic.get_data(issue_id) return data['_source'] except Exception as error: log_error(str(error),'API_Elastic_Jira.issue_get') return {} def issue_update(self, issue): return self.elastic.add(issue, "Key") def reset_update_index_value(self): update_key = '_update_details' self.elastic.delete_data_by_id(update_key) return self def update_index_from_jira_changes(self): if self.projects is None: log_error("Cannot update ELK since self.projects value is not configured") return update_key = '_update_details' # code to store last updated time in the index (move this to a dedicated location) data = self.elastic.get_data(update_key) if data is None: update_key_data = { "Key": update_key, "last_updated_at": None } epoch = (datetime.datetime.now() - datetime.timedelta(0, 60 * 1440)).timestamp() # if the value is not set , go back 24 h when = strftime("%Y/%m/%d %H:%M", localtime(epoch)) else: update_key_data = data['_source'] when = update_key_data['last_updated_at'] now_epoch = time() - 120 # due to the current issue with the sync server, remove 2 minutes from the time() value (which is the current time in seconds since the Epoch) now = strftime("%Y/%m/%d %H:%M", localtime(now_epoch)) # capture this value here (as soon as possible) now_server = strftime("%Y/%m/%d %H:%M",localtime(time())) print(" > using {0} , localtime: {1}".format(now,now_server)) query = 'project in ({0}) AND updated >= "{1}"'.format(self.projects,when) changes = self.api_Jira.search_no_cache(query) if len(changes) == 0: log_info("No issues updated since: {0}".format(when),"API_Elastic_Jira.update_index_from_jira_changes") return log_info(Dev.pprint("Since {0}, there where {1} issues updated: {2}".format(when, len(set(changes)),set(changes))), "API_Elastic_Jira.update_index_from_jira_changes") issues = self.fix_issues_for_elk(changes.values()) result = self.elastic.add_bulk(issues, "Key") log_info(Dev.pprint("sent {0} issues to elk instance: {1}".format(result, self.secrets_id)), "API_Elastic_Jira.update_index_from_jira_changes") update_key_data['last_updated_at'] = now self.elastic.add(update_key_data, "Key") def add_changed_log_status(self, project, start_at=0, max =-1): jql = "Project={0}".format(project) statuses = self.api_Jira.issue_changes_log_only_status(jql, start_at, max) data = [] for key,items in statuses.items(): for entry in items: entry['Key' ] = key entry['Project'] = project data.append(entry) self.elastic.add_bulk(data, "Entry_Id") return data
def __init__(self, index_id = 'jira', projects = None): self.secrets_id = 'gw-elastic-server-1' self.index_id = index_id self.elastic = None self.api_Jira = API_Jira() self.projects = projects #'IA, TM,GDPR'
def __init__(self, grid): self.grid = grid self.api_jira = API_Jira() self.api_jira_rest = API_Jira_Rest()
class Jira_View_Issue(): def __init__(self, issue_id=None, channel=None, team_id=None, event=None): self.issue_id = issue_id self.channel = channel self.team_id = team_id self.event = event self.api_issues = API_Issues() self.api_jira = API_Jira() self.issue = None self.action_id = 'Jira_View_Issue' self.slack_blocks = API_Slack_Blocks() # refactor this to base class def message_not_supported_action(self, action=''): return { "text": ':red_circle: Sorry, action not recognized : {0}'.format(action), "attachments": [], 'replace_original': False } def message_execution_error(self, error): return { "text": ':red_circle: Sorry, there was an error executing the requested action: {0}' .format(error), "attachments": [], 'replace_original': False } def handle_action(self, event): self.send_message('aaaa') action = Misc.array_pop(event.get('actions'), 0) action_value = Misc.get_value(action, 'value') try: target = getattr(self, action_value) except: channel = event.get('channel').get('id') team_id = event.get('team').get('id') # temp code (refactor when adding full support for blocks) text = ':point_right: message not recognised: {0}'.format(action) API_Slack_Blocks().set_text(text).send_message(channel, team_id) return self.message_not_supported_action( action) # event.get('original_message')) try: return target(event) except Exception as error: return self.message_execution_error(error) def load_issue(self, issue_id=None): if issue_id: self.issue_id = issue_id self.issue = self.api_issues.issue(self.issue_id) return self def create(self): self.load_issue() if self.issue: key = self.issue.get('Key') summary = self.issue.get('Summary') latest_info = self.issue.get('Latest_Information') description = self.issue.get('Description') issue_type = self.issue.get('Issue Type') jira_link = "https://glasswall.atlassian.net/browse/{0}".format( key) # todo: put the glasswall jira url in a site config value #key_link = "{0}/browse/{1}".format(self.api_issues.server_url(), key) add_layout = self.slack_blocks.add_layout_section #text = "*{0}*:\n<{1}|{2} - {3}>".format(issue_type,key_link,key, summary) text = ":point_right: *Issue*: <{1}|{2} - {3}>".format( issue_type, jira_link, key, summary) add_layout(self.issue_id).add_text(text).render() if latest_info: add_layout().add_text( '*Latest Info:* \n{0}'.format(latest_info)).render() if description: add_layout().add_text( '*Description:* \n{0}'.format(description)).render() actions_section = self.slack_blocks.add_layout_actions( self.action_id) footer_section = self.slack_blocks.add_layout_context() #actions_section.add_button('Edit Issue Field', self.issue_id) \ actions_section.add_button('View Links' , self.issue_id) \ .add_button('Screenshot' , self.issue_id) \ .add_button('Reload Issue' , self.issue_id) \ .add_button('Raw Issue Data' , self.issue_id) # .add_button('Change Status', self.issue_id) self.add_block_actions_with_transitions(self.slack_blocks) self.add_select_with_issue_links() self.add_block_edit_issue_field(self.slack_blocks) self.slack_blocks.add_text('*Actions*') actions_section.render() self.slack_blocks.add_divider() footer_items = [ 'Status: *{0}*'.format(self.issue.get('Status')), 'Rating: *{0}*'.format(self.issue.get('Rating')), 'Priority: *{0}*'.format(self.issue.get('Priority')), 'Issue Type: *{0}*'.format(self.issue.get('Issue Type')), 'Assignee: *{0}*'.format(self.issue.get('Assignee')), 'Labels: *{0}*'.format(self.issue.get('Labels')), 'Creator: *{0}*'.format(self.issue.get('Creator')), 'Created: *{0}*'.format( self.issue.get('Created').split('T').pop(0)), 'Updated: *{0}*'.format( self.issue.get('Updated').split('T').pop(0)) ] footer_section.add_texts(footer_items).render() #issue_data = "```{0}```".format(json.dumps(self.issue,indent=4)) #self.slack_blocks.add_layout_section().add_text(issue_data).render() #self.slack_ui.text = "<{0}|{1} - {2}>".format(key_link,key, summary) #self.add_overflow('abc', 'chose one' ,[('aaaa','aaaa_1'),('bbbb','bbbb_2')]) #self.add_button('Edit Issue') #self.add_button('An Replay') self.slack_blocks.add_attachment({ 'text': 'Issue *{0}* Status: `{1}`'.format(self.issue_id, self.issue.get('Status')), 'color': 'good' }) return True else: self.slack_blocks.add_layout_section().add_text( ':red_circle: Issue not found: `{0}`'.format( self.issue_id)).render() return False def send(self): if self.channel: result = self.slack_blocks.send_message(self.channel, self.team_id) if type(result) == dict and result.get('ok') is False: error_messages = result.get('response_metadata').get( 'messages') self.send_message( ':red_circle: Error in `Jira_View_Issue.send`; ```{0}```'. format(error_messages)) return result def create_and_send(self): if self.create(): self.send_message( ':point_right: *Loading data for issue: `{0}`* :point_left:'. format(self.issue_id)) return self.send() # def an_replay(self, event): # original_message = event.get('original_message') # return { # 'text' : "{0}".format(event), #original_message.get('text'), # 'attachments' : original_message.get('attachments'), # 'replace_original': True # } def add_select_with_issue_links(self): issue_links = self.issue.get('Issue Links') if issue_links: actions = self.slack_blocks.add_layout_actions( action_id='Jira_View_Issue') option_groups = [] size = 0 for issue_type, links in issue_links.items(): options = {} for link_issue_id in links: link_issue = self.api_issues.issue(link_issue_id) if link_issue: link_summary = link_issue.get('Summary') link_issue_type = link_issue.get('Issue Type') text = "{0} - {1}".format(link_issue_type, link_summary)[0:75] if options.get(link_issue_type) is None: options[link_issue_type] = [ ] # use this to sort by link_issue_type options[link_issue_type].append((text, link_issue_id)) #options.append((text , link_issue_id)) options_sorted = [] for key, values in options.items(): for value in values: options_sorted.append(value) size += 1 option_groups.append((issue_type, options_sorted)) self.slack_blocks.add_text( '*{0} Linked issues* (select to view)'.format(size)) actions.add_select( 'Issue Links', option_groups=option_groups) #, action_id='view_issue') return actions.render() def create_ui_actions_with_transitions(self, issue_id=None, current_status=None, show_intro=True): if issue_id: self.issue_id = issue_id view = API_Slack_Blocks() self.add_block_actions_with_transitions(view, current_status, show_intro) return view.send_message(self.channel, self.team_id) def add_block_actions_with_transitions(self, view, current_status=None, show_intro=True): if self.issue is None: self.issue = self.api_issues.issue(self.issue_id) if current_status is None: # this helps with the situation when the issue has just been updated but the data has not reached out to ELK current_status = self.issue.get('Status') transitions = self.api_jira.issue_next_transitions(self.issue_id) if show_intro: view.add_text("*Change issue status to*: (click to change)") if len(transitions) > 0: actions = view.add_layout_actions(action_id='Jira_View_Issue') for key, value in transitions.items(): if key != current_status: action_id = "transition_to::{0}".format(value) value = "{0}::{1}::{2}".format(self.issue_id, value, key) actions.add_button(key, value=value, action_id=action_id) return actions.render() view.add_text('...no Transitions available...') def create_ui_edit_issue_field(self): view = API_Slack_Blocks() self.add_block_edit_issue_field(view) return view.send_message(self.channel, self.team_id) def add_block_edit_issue_field(self, view): view.add_text("*Edit Issue Field:* (select to edit)".format( self.issue_id)) self.issue = self.api_issues.issue(self.issue_id) if self.issue: #fields = set(self.issue) fields = [ 'Summary', 'Description', 'Labels' #'Assignee','Description', 'Labels', 'Latest Information','Summary', #'Priority','Rating','Email', 'Slack ID','Image_Url' ] action_id = 'Jira_View_Issue::edit_field::{0}'.format( self.issue_id) view.add_select(action_id, 'Field to edit', fields) # callback methods def send_message(self, message): if self.channel: return slack_message(message, [], self.channel, self.team_id) else: return message def edit_field(self, action): try: selected_option = action.get('selected_option') field = selected_option.get('text').get('text') issue_id = action.get('action_id').split('::').pop(3) trigger_id = self.event.get('trigger_id') slack_dialog = Jira_Edit_Issue(issue_id, field).setup().render() from gw_bot.api.API_Slack import API_Slack API_Slack(self.channel, self.team_id).slack.dialog_open(trigger_id=trigger_id, dialog=slack_dialog) except Exception as error: self.send_message( ':red_circle: Error in edit_field: {0}'.format(error)) def issue_links(self, action): self.view_issue(action) def reload_issue(self, action): self.view_issue(action) def screenshot(self, action): issue_id = action.get('value') payload = { 'params': ['screenshot', issue_id], 'channel': self.channel, 'team_id': self.team_id } Lambda('osbot_jira.lambdas.jira').invoke_async(payload) def raw_issue_data(self, action): issue_id = action.get('value') issue = API_Issues().issue(issue_id) if issue: issue_data = "```{0}```".format(json.dumps(issue, indent=4)) return self.send_message(issue_data) def view_issue(self, action): issue_id = action.get('value') if issue_id is None: selected_option = action.get('selected_option') if selected_option: issue_id = selected_option.get('value') if issue_id: payload = { 'params': ['issue', issue_id], 'channel': self.channel, 'team_id': self.team_id } Lambda('osbot_jira.lambdas.jira').invoke_async(payload) else: self.send_message( ':red_circle: Error in View Issue, no issue id found in action :{0}' .format(action)) def view_links(self, action): try: issue_id = action.get('value') self.send_message( ':point_right: Viewing all links for issue: `{0}`'.format( issue_id)) payload = { 'params': ['links', issue_id, 'all', '1'], 'channel': self.channel, 'team_id': self.team_id } Lambda('osbot_jira.lambdas.jira').invoke_async(payload) except Exception as error: self.send_message( ':red_circle: Error in View Links for issue with id `{0}`: {1}' .format(issue_id, error)) def change_status(self, action): try: self.issue_id = action.get('value') self.create_ui_actions_with_transitions() except Exception as error: self.send_message( ':red_circle: Error in change_status: {0}'.format(error)) def edit_issue_field(self, action): try: self.issue_id = action.get('value') self.create_ui_edit_issue_field() except Exception as error: self.send_message( ':red_circle: Error in change_status: {0}'.format(error)) def transition_to(self, action): value_split = action.get('value').split('::') issue_id = Misc.array_pop(value_split, 0) transition_to = Misc.array_pop(value_split, 0) transition_name = Misc.array_pop(value_split, 0) try: self.api_jira.issue_transition_to_id(issue_id, transition_to) self.send_message( ':white_check_mark: Changed `{0}` status to: *{1}*. Here are the new transitions available ' .format(issue_id, transition_name)) self.create_ui_actions_with_transitions(issue_id, transition_name, show_intro=False) except Exception as error: self.send_message( ':red_circle: Error in transition_to: {0}'.format(error))
class QGrid_To_Jira: def __init__(self, grid): self.grid = grid self.api_jira = API_Jira() self.api_jira_rest = API_Jira_Rest() def jira_update_issue_status(self, key, value): transitions = self.api_jira.issue_next_transitions(key) transitions_id = transitions.get(value) if transitions_id is None: return { 'status': 'error', 'data': 'transition not available: {0}'.format(value) } result = self.api_jira.jira().transition_issue(key, transitions_id) return {'status': 'ok', 'data': result} def jira_remove_links_to_target(self, from_id, link_type, to_id): all_issue_links = self.api_jira.issue_links(from_id) issue_links = all_issue_links.get(link_type) if issue_links: for issue_link in issue_links: if to_id == issue_link.get('Key'): link_id = issue_link.get('Id') print('deleting link', from_id, link_type, link_id) self.api_jira.issue_delete_link(link_id) return True return False #return True # to handle cases when a mistaske is made on the new issue link type def jira_update_issue_link(self, issue_id, to_id, old_link_issue, new_link_issue): removed_ok = self.jira_remove_links_to_target(issue_id, old_link_issue, to_id) if new_link_issue is '': if removed_ok: return {'status': 'ok', 'data': 'issue link removed'} else: return {'status': 'error', 'data': 'failed to remove link'} try: self.api_jira.issue_add_link(issue_id, new_link_issue, to_id) print('added link', issue_id, new_link_issue, to_id) if removed_ok: return {'status': 'ok', 'data': 'issue link edited'} else: print('Removing link failed', issue_id, old_link_issue, to_id) return { 'status': 'error', 'data': 'removing link failed BUT, adding new link worked' } except Exception as error: print('Failed to add link', issue_id, new_link_issue, to_id) print(error.text) if removed_ok: return { 'status': 'error', 'data': 'adding link failed (after removing link)' } else: return { 'status': 'error', 'data': 'adding and removing links failed' } def jira_update_field(self, key, field, value): if not value: result = {'status': 'error', 'data': 'empty values not supported'} else: value = value.strip() if field == 'Latest_Information': field = 'Latest Information' if field == 'Status': result = self.jira_update_issue_status(key, value) else: data = self.api_jira_rest.issue_update_field(key, field, value) if data is False: result = {'status': 'error', 'data': data} else: result = {'status': 'ok', 'data': data} result['key'] = key result['field'] = field result['value'] = value return result def setup(self): def on_value_change(event, qgrid_widget): key = event.get('index') field = event.get('column') value = event.get('new') print("updating field `{0}` with value `{1}` on issue `{2}".format( field, value, key)) result = self.jira_update_field(key, field, value) print(result) self.grid.on('cell_edited', on_value_change) return self
def setUp(self): self.api = API_Jira()
class Test_API_Jira(unittest.TestCase): def setUp(self): self.api = API_Jira() # check connection def test_jira_server_info(self): jira = self.api.jira() assert jira.server_info().get('version') == '7.5.0' def test_jira(self): jira = self.api.jira() assert jira.__class__.__name__ == 'JIRA' assert jira.current_user() == 'gsbot' # methods def test_covert_issue(self): raw_issue = self.api.jira().issue('TASK-502') # 'FACT-10') # issue = self.api.convert_issue(raw_issue) Dev.pprint(issue) # raw_issue = self.api.jira().issue('SEC-9195')# 'FACT-10') # # issue = self.api.convert_issue(raw_issue) # self.api.convert_issue(self.api.jira().issue('SEC-9195')) # assert issue['Labels' ] == ['SEC-9195', 'SEC-9195-CFO'] # check the fields added recently # assert issue['Priority' ] == 'Minor' # # raw_issue = self.api.jira().issue('GSOKR-900') # check epic link # issue = self.api.convert_issue(raw_issue) # assert issue['Epic Link'] == 'GSOKR-924' # # raw_issue = self.api.jira().issue('GSOKR-872') # check parent (for sub taks) # issue = self.api.convert_issue(raw_issue) # assert issue['Parent'] == 'GSOKR-279' # #Dev.pprint(issue) def test_fields(self): fields = self.api.fields() assert len(fields) > 10 # data = {} # for field in fields: # data[field['name']] = field # print() # print('|--------------------------------------------------------------------------------------------------|') # print('| name | id | custom |') # print('|--------------------------------------------------------------------------------------------------|') # for name in sorted(set(data.keys())): # field = data[name] # print('| {0:55} | {1:25} | {2:10} |'.format(field['name'], field['id'], str(field['custom']))) def test_fields_by_name(self): fields_by_name = self.api.fields_by_name() assert len(set(fields_by_name)) > 300 @unittest.skip('this needs to be fixed top reflect the latest added fields' ) def test_issue(self): issue = self.api.issue('RISK-1083') assert issue == { 'Components': [], 'Issue Type': 'Risk', 'Issue Links': [], 'Key': 'RISK-1083', 'Issue Links': { 'RISK-1060': { 'Direction': 'Inward', 'Issue Type': 'Risk', 'Link Type': 'is blocked by', 'Priority': 'Minor', 'Status': 'Fixed', 'Summary': 'Test Risk' }, 'RISK-45': { 'Direction': 'Outward', 'Issue Type': 'Risk', 'Link Type': 'is child of', 'Priority': 'High', 'Status': 'Fixed', 'Summary': 'Test issue creation' }, 'RISK-32': { 'Direction': 'Outward', 'Issue Type': 'Risk', 'Link Type': 'relates to', 'Priority': 'Medium', 'Status': 'Fixed', 'Summary': 'TEST' } }, 'Rating': 'To be determined', 'Risk Description': 'This is an description', 'Risk Owner': 'Dinis Cruz', 'Status': 'Fixed', 'Summary': 'Test risk to GS-Bot' } def test_issue_add_link__error(self): try: Dev.pprint(self.api.issue_add_link('from', 'link_type', 'to')) except Exception as error: assert error.text == "No issue link type with name 'link_type' found." @unittest.skip( 'needs to be refactored (this method will get the change log for the issues' ) def _test_issue_change_log_only_status(self): statuses = self.api.issue_changes_log_only_status("Project=VULN", 300) Dev.pprint(statuses) #Dev.pprint(list(set(types))) def test_issue_update(self): issue_data = { "Key": "RISK-12", "Summary": "new summary value", "Risk Description": "el risk description", "Description": "the description" } #"Risk Rating" : "Low" } #"Status" : "Blocked" ,} result = self.api.issue_update(issue_data) Dev.pprint(result) # def test_issues_updated_in_last_hour(self): # results = self.api.issues_updated_in_last_hour() # assert len(results) > 0 # # # results_1h = self.api.issues_updated_in_last_hour(1) # results_10h = self.api.issues_updated_in_last_hour(10) # assert results == results_1h # assert set(results_1h) == {'FACT-13', 'RISK-1597'} # assert len(set(results_10h)) == 19 # def test_issues_updated_in_last_day(self): # results = self.api.issues_updated_in_last_day() # assert len(set(results)) > 1 # #Dev.pprint(len(set(results))) def test_projects(self): results = self.api.jira().projects() assert len(results) > 100 def test_search(self): issues = self.api.search('labels=R1') assert issues['RISK-1592']['Summary'] == '6 - Risk to Brand' assert len(set(issues)) == 6 def test_search_just_return_keys(self): keys = self.api.search_just_return_keys('labels=R1') assert keys == [ 'RISK-1592', 'RISK-1534', 'RISK-1498', 'RISK-1496', 'RISK-1495', 'RISK-1494' ] #keys = self.api.search_just_return_keys('project=RISK') #assert len(set(keys)) > 100 def test_covert_issue_vuln_priority(self): assert self.api.issue('VULN-1205').get('VULN Priority') == 'P3' assert self.api.issue('VULN-1624').get('VULN Priority') is None
def api_jira(): return API_Jira()
def api_jira_qa_server(): api_jira = API_Jira() api_jira.secrets_id = 'GS_BOT_GS_JIRA_QA' return api_jira