def add_label_to_issue(jira_key, label_to_add, jira=j.setup_jira_object()): issue = jira.issue(jira_key) print 'Adding label:' + label_to_add + ' to issue: ' + jira_key + ' if its not there' current_labels = issue.fields.labels if label_to_add not in current_labels: current_labels.append(label_to_add) issue.update(fields={'labels': current_labels})
def set_bugs_with_priority_as_ready(jira_key, jira=j.setup_jira_object()): projects_to_check = ['CLD', 'PROD', 'APPS', 'CORE'] payload = generate_payload_by_id.generate_payload(jira_key) if issue_within_projects(payload, projects_to_check): if issue_is_bug(payload) and issue_has_priority( payload) and payload['status'] == 'To do': transition_to_status(payload['issue_key'], 'Ready for dev', jira)
def report_to_cs_by_slack(payload, jira=j.setup_jira_object()): reporter_user_id = slack.convert_email_to_slack_id( payload['reporter_email']) text_line = "Head's up! an issue <@" + str( reporter_user_id ) + "> worked on was just marked as " + payload['status'] message_for_channel = [{ "fallback": "", "pretext": "A Jira Issue Created By CS Was Just Closed", "title": payload['issue_key'] + ": " + payload['jira_summary'], "title_link": 'https://cloudinary.atlassian.net/browse/' + payload['issue_key'], "text": text_line, "color": "#7CD197" }] slack.message_to_channel('', 'cs-jira-updates', message_for_channel) payload['labels'].append('notified_cs_by_slack') issue = jira.issue(payload['issue_key']) issue.update(notify=False, fields={"labels": payload['labels']})
def notify_mentioned_users_in_comment(comment_body, jira_id, jira=j.setup_jira_object()): issue = jira.issue(jira_id) mentioned_users = [] if '~' in comment_body: comment_parts = toolbox.force_to_unicode(comment_body).split(' ') for word in comment_parts: if '~' in word: this_user = re.sub('(.*\s*\[~)([a-z]+\.*[a-z]*)(\]\s*.*\n*)', r'\[email protected]', word) # print "word - ", word # print "this user", this_user # this_user = this_user.encode('utf-8') if this_user not in mentioned_users: this_user = toolbox.force_to_unicode(str(this_user)) print issue.key , " - Found mentioning of: ", this_user ," in added comment" mentioned_users.append(this_user) if len(mentioned_users)>0: for user in mentioned_users: print issue.key, "notifying:", user ms = [{ "fallback": "", "pretext": "You were just mentioned in an "+issue.fields.project.key+" Jira issue", "title": str(issue.key)+": "+str(issue.fields.summary), "title_link": 'https://cloudinary.atlassian.net/browse/'+str(issue.key), "text": "Head's up! somone just mentioned you on Jira\n"+comment_body+"\n *To reply to this comment please click the link to login to jira*", "color": "#7CD197" }] slack.message_to_user(user, ms)
def return_component_lead(comp_name, project_code, jira=j.setup_jira_object()): #look for component lead for comp in jira.project_components(project_code): if comp_name == str(comp.name): if comp.lead.name: return comp.lead.name else: return False
def get_parent_issue(jira_key, jira=j.setup_jira_object()): payload = generate_payload_by_id.generate_payload(jira_key) action_issue = None if payload['linked_issue_tree']: for linked_issue in payload['linked_issue_tree']: if linked_issue['type']['inward'] == 'is caused by': action_issue = jira.issue(linked_issue['inwardIssue']['key']) return action_issue
def generate_payload(request, jira=j.setup_jira_object()): payload = {} try: data = json.loads(request.data) except Exception as e: print "json payload invalid " print e print data return "500" try: payload['action'] = data['action'] except Exception as e: payload['action'] = False try: payload['merged'] = data['pull_request']['merged'] except Exception as e: payload['merged'] = False try: payload['pr_title_string'] = data['pull_request']['title'], except Exception as e: payload['pr_title_string'] = False try: payload['github_assignee'] = data['assignee']['login'] except Exception as e: payload['github_assignee'] = False try: payload['pull_request_api_url'] = data['pull_request']['_links'][ 'self']['href'] except Exception as e: payload['pull_request_api_url'] = False try: payload['pull_request_html_url'] = data['pull_request']['html_url'] except Exception as e: payload['pull_request_html_url'] = False try: payload['branch_name'] = ( data['pull_request']['head']['label']).split(":")[1] except Exception as e: payload['branch_name'] = 'master' jira_id_found = derive_jira_id_from_payload(payload) if jira_id_found: payload['linked_jira_issue'] = jira_id_found else: payload['linked_jira_issue'] = False #Print out payload to improve debugability print "Parsing Github Hook with PR subject:", payload['pr_title_string'] print(json.dumps(payload, sort_keys=True)) return payload
def remove_label_from_issue(jira_key, label_to_remove, jira=j.setup_jira_object()): issue = jira.issue(jira_key) print 'Removing label:' + label_to_remove + ' to issue: ' + jira_key + ' if its there' current_labels = issue.fields.labels if label_to_remove in current_labels: current_labels.remove(label_to_remove) issue.update(fields={'labels': current_labels})
def transition_to_status(jira_key, desired_status, jira=j.setup_jira_object()): print "will try to transition " + jira_key + " to status:" + desired_status target_issue = jira.issue(jira_key) transitions = jira.transitions(target_issue) for t in transitions: if desired_status.lower().strip() in t['name'].lower().strip(): jira.transition_issue(target_issue, t['id']) return True return False
def doc_team_memeber_to_memeber(payload, jira=j.setup_jira_object()): #if an issue is opned by doc team member set it as ready for dev if is_member_of_team(payload['assignee'], 'Documentation') and is_member_of_team( payload['reporter'], 'Documentation'): if payload['status'] == 'To Do': print "Issue: ", payload[ 'issue_key'], "Was created by member of the doc team, and is assined to a memeber of the doc team, so will transition to ready for dev" transition_to_status(payload['issue_key'], 'Ready for dev', jira)
def manage_cs_notifications(reporter_email, jira_key, jira=j.setup_jira_object()): payload = generate_payload_by_id.generate_payload(jira_key) payload["reporter_email"] = reporter_email notify_cs_team_of_resolved_sdk_issue(payload, jira) notify_cs_team_of_deployed_cld_and_prod_issue(payload, jira) notify_cs_team_of_sol_issue(payload, jira) notify_cs_team_of_doc_issue(payload, jira)
def transition_linked_issues(linked_issues, desired_state, jira=j.setup_jira_object()): for linked_issue in linked_issues: linked_issue_obj = jira.issue(linked_issue) linked_issue_status = linked_issue_obj.raw['fields']['status']['name'] print 'Checking linked issue:', str( linked_issue), 'the status of it is:', linked_issue_status if linked_issue_status != 'Done': transition_to_status(linked_issue, desired_state, jira)
def is_all_sni_child_stories_done(parent_issue, jira=j.setup_jira_object()): linked_sni_issues = check_for_linked_issue_by_project( parent_issue.key, jira, 'SNI') all_child_stories_done = True for linked_issue_key in linked_sni_issues: linked_issue_payload = generate_payload_by_id.generate_payload( linked_issue_key) if linked_issue_payload['status'] != 'Done': all_child_stories_done = False break return all_child_stories_done
def rnd_to_rnd_set_ready_for_dev(jira_key, jira=j.setup_jira_object()): projects_to_check = ['CLD', 'PROD', 'APPS', 'CORE'] payload = generate_payload_by_id.generate_payload(jira_key) if issue_within_projects(payload, projects_to_check): if is_member_of_team(payload['assignee'], 'R&D') and is_member_of_team( payload['reporter'], 'R&D'): if payload['status'] == 'To Do': print payload[ 'issue_key'], "since the reporter is from rnd team and the issue is assigned to rnd with status todo will change to Ready for dev" transition_to_status(payload['issue_key'], 'Ready for dev', jira)
def transition_and_comment(desired_status, pr_url, jira_key, jira=j.setup_jira_object()): res = toolbox.transition_to_status(jira_key=jira_key, desired_status=desired_status) if res: print "Transition completed on issue: " + str(jira_key) comment_text = 'Status was transitioned by Yentel since PR was merged and referenced: ' + str( pr_url) print "adding comment to jira issue : " + str(comment_text) jira.add_comment(jira_key, comment_text)
def new_comment_flow(request_json_payload, jira=j.setup_jira_object()): data = json.loads(request_json_payload) # print (json.dumps(data, sort_keys=True)) jira_key = data['issue']['key'] q = Queue(connection=conn) #notify users apprearing on activating comment hook q.enqueue(notify_mentioned_by_slack.notify_mentioned_users_in_comment, data['comment']['body'], jira_key) return "200"
def derive_jira_id_from_payload(gh_payload, projects_to_check=['APPS', 'CORE'], jira=j.setup_jira_object()): #try and derive jira id from pr branch name if gh_payload['branch_name']: branch_name_upper = gh_payload['branch_name'].upper() for key in projects_to_check: if key in branch_name_upper: match = re.search('(^.*)([A-Z]{4}-\d+)(.*)', branch_name_upper) jira_key = match.group(2) issue = jira.issue(jira_key) if issue.key: return jira_key return False
def link_to_doc_issue(jira_key, jira=j.setup_jira_object()): #this function will verify that an issue with the requirment for a doc issue #has a valid doc issue with a link to it #list of project codes we act upon payload = generate_payload_by_id.generate_payload(jira_key) projects_to_check = ['SDK', 'CLD', 'PROD', 'APPS', 'CORE'] if toolbox.requires_documentation( payload) and toolbox.issue_within_projects(payload, projects_to_check): linked_doc_issues = toolbox.check_for_linked_issue_by_project( payload['issue_key'], jira, 'DOC') if not linked_doc_issues: #if false means no linked doc issues were found and will create new one new_issue_dict = { 'project': { 'key': 'DOC' }, 'summary': "Document: " + payload['jira_summary'], 'description': payload['jira_description'], 'issuetype': { 'name': 'Story' }, 'priority': { 'name': payload['jira_priority'] }, 'customfield_10900': { 'value': payload['source'] }, 'customfield_10004': payload['epic'], 'customfield_11000': payload['release_notes'] } print "will open a new DOC issue with following parameters:" print(json.dumps(new_issue_dict, sort_keys=True)) new_issue = jira.create_issue(fields=new_issue_dict) print "New jira issue created:", new_issue.key print "Will now link:", jira_key, "to:", new_issue.key jira.create_issue_link(type='Problem/Incident', inwardIssue=jira_key, outwardIssue=new_issue.key) print "Will now assign ", new_issue.key, " to Docs team" jira.assign_issue(new_issue, 'docs') else: print payload[ 'issue_key'], "Is marked as Doc Update required but already has linked DOC issue" transition_linked_doc_issues(linked_doc_issues, payload, jira) terminate_wont_do_doc_issues(linked_doc_issues, payload, jira)
def find_mentioned_commentees(jira_id, jira=j.setup_jira_object()): issue = jira.issue(jira_id) mentioned_users = [] if issue.fields.comment.comments: last_comment_text = issue.fields.comment.comments[-1].body.encode('utf-8') if '~' in last_comment_text: last_comment_parts = toolbox.force_to_unicode(str(last_comment_text)).split(' ') for word in last_comment_parts: if '~' in word: this_user = re.sub('(.*\s*\[~)([a-z]+\.*[a-z]*)(\]\s*.*\n*)', r'\[email protected]', word) this_user = this_user.encode('utf-8') if this_user not in mentioned_users: this_user = toolbox.force_to_unicode(str(this_user)) print issue.key , " - Found mentioning of: ", this_user mentioned_users.append(this_user) return mentioned_users
def mark_related_undone_tasks_with_warning_comment(jira_key, jira=j.setup_jira_object()): payload = generate_payload_by_id.generate_payload(jira_key) if is_status_done(payload): related_issues_list = check_for_related_issues(payload['issue_key'], jira) if related_issues_list: for related_issue in related_issues_list: print "checking status of related issue: " + str(related_issue) if not is_issue_key_done(related_issue, jira): print "Since " + str( related_issue ) + " is not done will add a release note remarking this issue" un_done_issue = jira.issue(related_issue) new_release_notes = "an issue related to this was marked as done, so adding release notes for notice \n" + payload[ 'release_notes'] un_done_issue.update( fields={'customfield_11000': new_release_notes})
def update_doc_trigger_status(jira_key, jira=j.setup_jira_object()): payload = generate_payload_by_id.generate_payload(jira_key) # when a doc project jira is closed, update the linked jira about it if payload['status'] == 'Done' and payload[ 'project_name'] == 'DOC' and payload['linked_issue_tree']: for linked_issue in payload['linked_issue_tree']: if linked_issue['type']['inward'] == 'is caused by': action_issue = jira.issue(linked_issue['inwardIssue']['key']) #this part will handle new projects if action_issue.fields.project.key in [ 'APPS', 'CORE', 'CLD', 'PROD', 'SDK' ]: if action_issue.fields.customfield_12043.value != 'Updated': print 'DOC issue resolved, Will try to update', action_issue.key action_issue.update( fields={'customfield_12043': { 'value': 'Updated' }})
def notify_mentioned_users(jira_id, jira=j.setup_jira_object()): issue = jira.issue(jira_id) mentioned_users = find_mentioned_commentees(issue.key) if len(mentioned_users)>0: for user in mentioned_users: print issue.key, "notifying:", user last_comment_text = issue.fields.comment.comments[-1].body.encode('utf-8') last_comment_text = toolbox.force_to_unicode(str(last_comment_text)) ms = [{ "fallback": "", "pretext": "You were just mentioned in an "+issue.fields.project.key+" Jira issue", "title": str(issue.key)+": "+str(issue.fields.summary), "title_link": 'https://cloudinary.atlassian.net/browse/'+str(issue.key), "text": "Head's up! somone just mentioned you on Jira\n"+last_comment_text+"\n *To reply to this comment please click the link to login to jira*", "color": "#7CD197" }] slack.message_to_user(user, ms)
def set_done_issues_with_fixversion_as_deployed(jira_key, jira=j.setup_jira_object()): #list of project codes we act upon projects_to_check_new = ['APPS', 'CORE'] payload = generate_payload_by_id.generate_payload(jira_key) if is_status_merged(payload) and issue_within_projects( payload, projects_to_check_new): for fv in payload['fixversion']: if 'deployed' in str(fv): print "Issue has fix version and status is done, so converting to deployed state" transition_to_status(payload['issue_key'], 'Deployed', jira) projects_to_check_old = ['SDK', 'CLD', 'PROD'] if is_status_done(payload) and issue_within_projects( payload, projects_to_check_old): for fv in payload['fixversion']: if 'deployed' in str(fv): print "Issue has fix version and status is done, so converting to deployed state" transition_to_status(payload['issue_key'], 'Deployed', jira)
def check_for_related_issues(key, jira=j.setup_jira_object()): issue = jira.issue(key) linked_issues = [] linked_obj = issue.raw print 'Checking for related issues in ' + key for x in linked_obj['fields']['issuelinks']: if 'outwardIssue' in x: if x['type']['inward'] == 'relates to': linked_issues.append(x['outwardIssue']['key']) elif 'inwardIssue' in x and linked_obj['fields']['issuetype'][ 'name'] == 'Epic': if x['type']['inward'] == 'relates to': linked_issues.append(x['inwardIssue']['key']) if len(linked_issues) == 0: print 'Could not find any related issues in: ' + key return False else: print 'Found the following related issues:', linked_issues return linked_issues
def bug_set_assignees_component_lead(jira_key, jira=j.setup_jira_object()): projects_to_check = ['CLD', 'SDK', 'CORE', 'APPS'] payload = generate_payload_by_id.generate_payload(jira_key) if 'Not set' in payload['components']: return False if toolbox.issue_within_projects(payload, projects_to_check) and ( toolbox.issue_is_bug(payload) or toolbox.issue_is_task(payload)): # print payload['issue_key'], 'Will allocate bug to component lead if component is specified' for component in payload['components']: component_lead = toolbox.return_component_lead( component, payload['project_name']) if component_lead: print 'Assigning bug issue to:' print payload[ 'issue_key'], 'Component:', component, 'lead to assign is:', component_lead issue = jira.issue(payload['issue_key']) jira.assign_issue(issue, component_lead) return True
def component_lead_auto_assign(jira_key, jira=j.setup_jira_object()): projects_to_check = ['CLD', 'SDK'] payload = generate_payload_by_id.generate_payload(jira_key) #set issue object since we will need it issue = jira.issue(payload['issue_key']) if toolbox.issue_is_security_event(payload): #handle case of security issue without component set component to Security if len(payload['components']) == 0: issue.update(fields={"components": [{'name': 'Security'}]}) payload = generate_payload_by_id.generate_payload(jira_key) for component in payload['components']: component_lead = toolbox.return_component_lead( component, payload['project_name']) if component_lead: print payload[ 'issue_key'], 'Will assign issue to product lead:', component_lead issue = jira.issue(payload['issue_key']) jira.assign_issue(issue, component_lead) return True
def set_source_by_owner(jira_key, jira=j.setup_jira_object()): #this function will run through the cloudinary team structure and #will set the owner by the reporter field #configure jira issue object payload = generate_payload_by_id.generate_payload(jira_key) def issue_source_not_defined(payload): return (payload['source'] == 'Not set' or payload['source'] == 'Unknown' or payload['source'] == 'None') if not reported_by_yentel(payload) and issue_source_not_defined(payload): issue = jira.issue(payload['issue_key']) #invoke the teams structure module cld_team = cloudinary_teams.load_team_members() for team in cld_team: if is_member_of_team(payload['reporter'], team) and payload['source'] != team: print "Since the issue was reported by a member of the:", team, "team, will set the source as", team issue.update(fields={'customfield_10900': { 'value': team }}) #set "source" to the dictionary key
def is_issue_key_done(issue_key, jira=j.setup_jira_object()): issue = jira.issue(issue_key) issue_status = issue.raw['fields']['status']['name'] return issue_status == 'Done'
def set_manual_qa_to(selection, issue_key, jira=j.setup_jira_object()): issue = jira.issue(issue_key) issue.update(fields={'customfield_12042': {'value': selection}})
def generate_payload(jira_key, jira=j.setup_jira_object()): issue = jira.issue(jira_key) #normalize variables to avoid corruption data = {} data['issue'] = issue.raw try: payload = { 'status': data['issue']['fields']['status']['name'], 'issue_key': data['issue']['key'], 'labels': data['issue']['fields']['labels'], 'project_name': data['issue']['fields']['project']['key'], 'jira_summary': data['issue']['fields']['summary'], 'jira_description': toolbox.force_to_unicode(data['issue']['fields']['description']), 'jira_priority': data['issue']['fields']['priority']['name'], } except TypeError: print "Json Body is missing required values, will stop and return 500" print(json.dumps(data, sort_keys=True)) return "json error" try: payload['reporter'] = data['issue']['fields']['reporter']['name'] except Exception as e: payload['reporter'] = '' try: payload['reporter_email'] = data['issue']['fields']['reporter'][ 'emailAddress'] except Exception as e: payload['reporter_email'] = '*****@*****.**' try: payload['assignee_email'] = data['issue']['fields']['assignee'][ 'emailAddress'] except Exception as e: payload['assignee_email'] = '*****@*****.**' try: payload['assignee'] = data['issue']['fields']['assignee']['name'] except Exception as e: payload['assignee'] = 'Nobody' try: payload['issuetype'] = data['issue']['fields']['issuetype']['name'] except Exception as e: payload['issuetype'] = 'Generic' #check if any documentation impact try: payload['docs_impact'] = data['issue']['fields']['customfield_11800'][ 'value'] except TypeError: payload['docs_impact'] = False try: payload['documentation'] = data['issue']['fields'][ 'customfield_12043']['value'] except TypeError: payload['documentation'] = False #check if any documentation impact try: payload['release_notes'] = data['issue']['fields'][ 'customfield_11000']['value'] except Exception as e: payload['release_notes'] = 'None' #try to get linked issus, if found try: payload['linked_issue_keys'] = [ issue_link['outwardIssue']['key'] for issue_link in data['issue']['fields']['issuelinks'] ] except (IndexError, KeyError): payload['linked_issue_keys'] = [] #try to get linked issus, if found try: payload['linked_issue_tree'] = data['issue']['fields']['issuelinks'] except (IndexError, KeyError): payload['linked_issue_tree'] = False #check if the new issue requires qa try: payload['qa_required'] = data['issue']['fields']['customfield_11700'][ 'value'] except Exception as e: payload['qa_required'] = False #check if the new issue requires qa try: payload['manual_qa'] = data['issue']['fields']['customfield_12042'][ 'value'] except Exception as e: payload['manual_qa'] = False #check if issue has a components list (some projects might not have it) try: payload['components'] = [ comp_name['name'] for comp_name in data['issue']['fields']['components'] ] except Exception as e: payload['components'] = 'Not set' #check the source of the jira issue try: payload['source'] = data['issue']['fields']['customfield_10900'][ 'value'] except Exception as e: payload['source'] = 'Not set' #check the sdk impact of the issue try: payload['sdk_impact'] = data['issue']['fields']['customfield_12002'][ 'value'] except Exception as e: payload['sdk_impact'] = False try: payload['sdk_link'] = data['issue']['fields']['customfield_12044'][ 'value'] except Exception as e: payload['sdk_link'] = False #check if issue has a fixversion list (some projects might not have it) try: payload['fixversion'] = [ i['name'] for i in data['issue']['fields']['fixVersions'] ] except Exception as e: payload['fixversion'] = [] # check the epic of the jira issue try: payload['epic'] = data['issue']['fields']['customfield_10004'] except Exception as e: payload['epic'] = 'Not set' #add the issues comment bodies to the payload try: payload['issue_comments'] = [ comment['body'] for comment in issue.raw['fields']['comment']['comments'] ] except Exception as e: payload['issue_comments'] = 'No comments' #check if any documentation impact try: payload['mar_cs_ops'] = data['issue']['fields']['customfield_11987'][ 'name'] except Exception as e: payload['mar_cs_ops'] = 'Not set' try: payload['it_systems_list'] = data['issue']['fields'][ 'customfield_11916'] except Exception as e: payload['it_systems_list'] = 'Not set' try: payload['parsed_components'] = toolbox.convert_components_to_set( payload['components']) except Exception as e: print e payload['parsed_components'] = [] #print out the payload to improve debugability # print "Parsing Jira issue", payload['issue_key'] # print(json.dumps(payload, sort_keys=True)) return payload # if __name__=='__main__': # print generate_payload()