def _add_label_to_tracker(self, story_id, label): method = '_add_label_to_tracker' commons.printMSG(Tracker.clazz, method, 'begin') label_to_post = Object() label_to_post.name = label.lower() tracker_url = "{url}/services/v5/projects/{projid}/stories/{storyid}/labels".format(url=Tracker.tracker_url, projid=Tracker.project_id, storyid=story_id) headers = {'Content-type': 'application/json', 'Accept': 'application/json', 'X-TrackerToken': Tracker.token} commons.printMSG(Tracker.clazz, method, tracker_url) commons.printMSG(Tracker.clazz, method, label_to_post.to_JSON()) try: resp = requests.post(tracker_url, label_to_post.to_JSON(), headers=headers, timeout=self.http_timeout) except requests.ConnectionError: commons.printMSG(Tracker.clazz, method, 'Request to Tracker timed out.', 'WARN') except Exception as e: commons.printMSG(Tracker.clazz, method, "Unable to tag story {story} with label {lbl}".format( story=story_id, lbl=label), 'WARN') commons.printMSG(Tracker.clazz, method, e, 'WARN') if resp.status_code != 200: commons.printMSG(Tracker.clazz, method, "Unable to tag story {story} with label {lbl} \r\n " "Response: {response}".format(story=story_id, lbl=label, response=resp.text), 'WARN') else: commons.printMSG(Tracker.clazz, method, resp.text) commons.printMSG(Tracker.clazz, method, 'end')
def _create_version(self, version, released=False): method = '_create_version' commons.print_msg(Jira.clazz, method, 'begin') new_version = Object() new_version.description = "Generated from pipeline" new_version.name = version if released: new_version.userReleaseDate = datetime.datetime.now().strftime( "%-d/%b/%Y") new_version.project = Jira.project_id new_version.released = released jira_url = "{}/rest/api/2/version".format(Jira.jira_url) headers = {'Content-type': 'application/json'} commons.print_msg(Jira.clazz, method, jira_url) commons.print_msg(Jira.clazz, method, new_version.to_JSON()) try: # TODO: Remove auth from below... resp = requests.post(jira_url, new_version.to_JSON(), headers=headers, auth=(os.getenv('JIRA_USER'), os.getenv('JIRA_PWD')), timeout=self.http_timeout) if resp.status_code != 201: commons.print_msg( Jira.clazz, method, "Unable to add version {version} \r\n " "Response: {response}".format(version=version, response=resp.text), 'WARN') else: commons.print_msg(Jira.clazz, method, resp.text) except requests.ConnectionError as e: commons.print_msg(Jira.clazz, method, 'Connection error. ' + str(e), 'WARN') except Exception as e: commons.print_msg( Jira.clazz, method, "Unable to add version {verions}".format(version=version), 'WARN') commons.print_msg(Jira.clazz, method, e, 'WARN') commons.print_msg(Jira.clazz, method, 'end')
def create_chg(self, story_details=None): servicenow_create_chg_url = ServiceNow.servicenow_url + '/api/now/table/change_request' cr = Object() cr.category = "Software" cr.description = self._format_release_notes(story_details) cr.short_description = "Deployment of {app}-{version} to {env}".format( app=BuildConfig.project_name, version=BuildConfig.version_number, env=os.getenv('NEXT_ENVIRONMENT')) cr.assignment_group = 'CAB Approval' cr.work_start = '2018-08-10 23:59:59' cr.work_end = '2018-08-11 23:59:59' cr.cmdb_ci = 'Cloud Foundry' cr.start_date = '2018-08-10 23:59:59' cr.end_date = '2018-08-11 23:59:59' cr.reason = 'Continuous Deployment' # headers = {'Content-type': 'application/json', 'Accept': 'application/json', # 'Authorization': "Bearer {}".format(os.getenv('SERVICENOW_TOKEN'))} headers = { 'Content-type': 'application/json', 'Accept': 'application/json' } print(servicenow_create_chg_url) resp = requests.post( servicenow_create_chg_url, cr.to_JSON(), headers=headers, auth=(os.getenv('SERVICENOW_USER'), os.getenv('SERVICENOW_PWD')), ) resp_obj = json.loads(resp.text) print(resp) print(resp.text) print(resp_obj["result"]["number"])
def publish_custom_message(self, message, channel=None, user='******', icon=None, emoji=None, attachment_color=None, slack_url=None, button_text=None, button_link=None): method = 'publish_custom_message' commons.print_msg(Slack.clazz, method, 'begin') slack_message = Object() if slack_url is not None: Slack.slack_url = slack_url if slack_url is None and Slack.slack_url is None and BuildConfig.settings.has_section('slack') and \ BuildConfig.settings.has_option('slack', 'generic_message_slack_url'): Slack.slack_url = BuildConfig.settings.get('slack', 'generic_message_slack_url') elif slack_url is None and Slack.slack_url is None: commons.print_msg(Slack.clazz, method, 'No Slack URL was found in the environment or settings.ini. Failed to send message', 'ERROR') exit(1) if emoji is None and 'slack' in BuildConfig.json_config and 'emoji' in BuildConfig.json_config['slack']: emoji = BuildConfig.json_config['slack']['emoji'] slack_message.icon_emoji = emoji elif emoji is None and BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'emoji'): emoji = BuildConfig.settings.get('slack', 'emoji') slack_message.icon_emoji = emoji if icon is None and 'slack' in BuildConfig.json_config and 'icon' in BuildConfig.json_config['slack']: icon = BuildConfig.json_config['slack']['icon'] slack_message.icon_url = icon elif icon is None and BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'icon'): icon = BuildConfig.settings.get('slack', 'icon') slack_message.icon_url = icon if channel is None and 'slack' in BuildConfig.json_config and 'channel' in BuildConfig.json_config['slack']: slack_channel = BuildConfig.json_config['slack']['channel'] slack_message.channel = slack_channel elif channel is None and BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'channel'): slack_channel = BuildConfig.settings.get('slack', 'channel') slack_message.channel = slack_channel if user is None and 'slack' in BuildConfig.json_config and 'botName' in BuildConfig.json_config['slack']: user = BuildConfig.json_config['slack']['botName'] elif user is None and BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'bot_name'): user = BuildConfig.settings.get('slack', 'bot_name') app_version = BuildConfig.version_number environment = BuildConfig.build_env app_name = BuildConfig.json_config['projectInfo']['name'] slack_message.username = user slack_message.attachments = [] # Application information attachment = Object() attachment.pretext = attachment.fallback = message if attachment_color is not None: attachment.color = attachment_color elif (BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'release_note_attachment_color')): attachment.color = BuildConfig.settings.get('slack', 'release_note_attachment_color') else: attachment.color = '#0000ff' attachment.author_name = app_name + ' ' + environment + " " + (str(app_version) if str(app_version) is not None else 'Uknown Version') if 'github' in self.config.json_config and 'org' in self.config.json_config['github']: attachment.author_name = "{msg} \n org: {org} \n repo: {repo}".format(msg=attachment.author_name, org=self.config.json_config['github']['org'], repo=self.config.json_config['github']['repo']) # attachment.title = app_name attachment.title_link = (os.environ.get('BUILD_URL') if os.environ.get('BUILD_URL') is not None else '') attachment.footer = 'Flow' # attachment.text = message slack_message.attachments.append(attachment) commons.print_msg(Slack.clazz, method, slack_message.to_JSON()) headers = {'Content-type': 'application/json', 'Accept': 'application/json'} commons.print_msg(Slack.clazz, method, Slack.slack_url) try: resp = requests.post(Slack.slack_url, slack_message.to_JSON(), headers=headers, timeout=Slack.http_timeout) if resp.status_code == 200: commons.print_msg(Slack.clazz, method, "Successfully sent to slack. \r\n resp: {}".format(resp.text), "DEBUG") else: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url} \r\n Resp: {resp} \r\n " "Status: {stat}".format(url=Slack.slack_url, resp=resp.text, stat=resp.status_code), "WARN") except requests.ConnectionError: commons.print_msg(Slack.clazz, method, "Request to Slack timed out.", "ERROR") except Exception as e: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url} with exception {ex}" .format(url=Slack.slack_url, ex=e)) commons.print_msg(Slack.clazz, method, 'end')
def publish_deployment(self, story_details): method = 'publish_deployment' commons.print_msg(Slack.clazz, method, 'begin') if Slack.slack_url is None: commons.print_msg(Slack.clazz, method, 'No Slack URL was found in the environment. Did you set ' 'SLACK_WEBHOOK_URL in your pipeline?', 'ERROR') exit(1) commons.verify_version(self.config) icon = None emoji = None slack_channel = None user_name = None if 'slack' in self.config.json_config and 'emoji' in self.config.json_config['slack']: emoji = self.config.json_config['slack']['emoji'] elif self.config.settings.has_section('slack') and self.config.settings.has_option('slack', 'emoji'): emoji = self.config.settings.get('slack', 'emoji') if 'slack' in self.config.json_config and 'icon' in self.config.json_config['slack']: icon = self.config.json_config['slack']['icon'] elif self.config.settings.has_section('slack') and self.config.settings.has_option('slack', 'icon'): icon = self.config.settings.get('slack', 'icon') if 'slack' in self.config.json_config and 'channel' in self.config.json_config['slack']: slack_channel = self.config.json_config['slack']['channel'] elif self.config.settings.has_section('slack') and self.config.settings.has_option('slack', 'channel'): slack_channel = self.config.settings.get('slack', 'channel') if 'slack' in self.config.json_config and 'botName' in self.config.json_config['slack']: user_name = self.config.json_config['slack']['botName'] elif self.config.settings.has_section('slack') and self.config.settings.has_option('slack', 'bot_name'): user_name = self.config.settings.get('slack', 'bot_name') app_version = self.config.version_number environment = self.config.build_env app_name = self.config.json_config['projectInfo']['name'] slack_message = Object() if icon: slack_message.icon_url = icon else: slack_message.icon_emoji = emoji if slack_channel: slack_message.channel = slack_channel slack_message.username = user_name slack_message.attachments = [] # Application information attachment = Object() attachment.mrkdwn_in = ['pretext', 'fields'] attachment.fallback = "{name} {version} has been deployed to {env}".format(name=app_name, version=app_version, env=environment) attachment.pretext = ":package: *{app}* _{version}_ has been deployed to *{env}*".format(app=app_name, version=app_version, env=environment) attachment.fields = [] manual_deploy_environment_links = self._get_manual_deploy_links() # deploy links for key, value in enumerate(manual_deploy_environment_links): attachment_field = Object() attachment_field.value = "Deploy to <{link}|{title}>".format(link=manual_deploy_environment_links[value], title=value) attachment.fields.append(attachment_field) slack_message.attachments.append(attachment) # no stories defined if len(story_details) == 0: attachment = Object() attachment.mrkdwn_in = ['pretext', 'fields'] attachment.pretext = '*No Release Notes*' slack_message.attachments.append(attachment) # story details for i, story in enumerate(story_details): if story.story_type == 'release': story_emoji = ':checkered_flag:' elif story.story_type == 'bug': story_emoji = ':beetle:' elif story.story_type == 'chore': story_emoji = ':wrench:' else: story_emoji = ':star:' attachment = Object() attachment.fallback = story.name attachment.mrkdwn_in = ['pretext', 'fields'] if (BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'release_note_attachment_color')): attachment.color = BuildConfig.settings.get('slack', 'release_note_attachment_color') else: attachment.color = '#0000ff' attachment.footer = 'Flow' if (BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'footer_icon_url')): attachment.footer_icon = BuildConfig.settings.get('slack', 'footer_icon_url') if i == 0: attachment.pretext = '*Release Notes*' attachment.fields = [] attachment_field = Object() attachment_field.value = "*" + str(story.id) + "* " + story_emoji + ' _' + story.story_type + "_" attachment_field.short = True attachment.fields.append(attachment_field) attachment_field = Object() attachment_field.value = '*<' + story.url + '|' + story.name + '>*' attachment.fields.append(attachment_field) attachment_field = Object() if story.description is None or len(story.description.strip()) == 0: attachment_field.value = '_No description_' else: attachment_field.value = (story.description[:150] + '..') if len(story.description) > 150 else story.description attachment.fields.append(attachment_field) attachment_field = Object() # TODO: Put this back # attachment_field.value = '*Status*: ' + story.description attachment_field.short = True attachment.fields.append(attachment_field) slack_message.attachments.append(attachment) headers = {'Content-type': 'application/json', 'Accept': 'application/json'} commons.print_msg(Slack.clazz, method, Slack.slack_url) commons.print_msg(Slack.clazz, method, slack_message.to_JSON()) resp = None # instantiated so it can be logged outside of the try below the except try: resp = requests.post(Slack.slack_url, slack_message.to_JSON(), headers=headers, timeout=self.http_timeout) except requests.ConnectionError: commons.print_msg(Slack.clazz, method, "Request to Slack timed out.", "ERROR") exit(1) except Exception as e: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url}. {exception}".format( url=Slack.slack_url, exception=e)) # has to be defined here too in order to exit properly during the exception but still log appropriate # messages when there is a status code available if hasattr('resp', 'status_code') and resp.status_code != 200: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url}. \r\n Response: {resp}" .format(url=Slack.slack_url, resp=resp.text)) exit(1) if hasattr('resp', 'status_code') and resp.status_code != 200: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url}. \r\n Response: {resp}" .format(url=Slack.slack_url, resp=resp.text)) exit(1) commons.print_msg(Slack.clazz, method, 'end')
def publish_error(sender, message, class_name, method_name): method = 'publish_error' commons.print_msg(Slack.clazz, method, 'begin') if Slack.slack_url is None: commons.print_msg(Slack.clazz, method, 'No Slack URL was found in the environment. Did you set SLACK_WEBHOOK_URL in your pipeline?', 'WARN') else: icon = None emoji = None slack_channel = None user_name = None if 'slack' in BuildConfig.json_config and 'emoji' in BuildConfig.json_config['slack']: emoji = BuildConfig.json_config['slack']['emoji'] elif BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'emoji'): emoji = BuildConfig.settings.get('slack', 'emoji') if 'slack' in BuildConfig.json_config and 'icon' in BuildConfig.json_config['slack']: icon = BuildConfig.json_config['slack']['icon'] elif BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'icon'): icon = BuildConfig.settings.get('slack', 'icon') if 'slack' in BuildConfig.json_config and 'channel' in BuildConfig.json_config['slack']: slack_channel = BuildConfig.json_config['slack']['channel'] elif BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'channel'): slack_channel = BuildConfig.settings.get('slack', 'channel') if 'slack' in BuildConfig.json_config and 'botName' in BuildConfig.json_config['slack']: user_name = BuildConfig.json_config['slack']['botName'] elif BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'bot_name'): user_name = BuildConfig.settings.get('slack', 'bot_name') app_version = BuildConfig.version_number environment = BuildConfig.build_env app_name = BuildConfig.json_config['projectInfo']['name'] slack_message = Object() if icon: slack_message.icon_url = icon else: slack_message.icon_emoji = emoji if slack_channel: slack_message.channel = slack_channel slack_message.username = user_name slack_message.attachments = [] # Application information attachment = Object() attachment.pretext = attachment.fallback = "CI/CD for {} has failed".format(app_name) if (BuildConfig.settings.has_section('slack') and BuildConfig.settings.has_option('slack', 'error_attachment_color')): attachment.color = BuildConfig.settings.get('slack', 'error_attachment_color') else: attachment.color = '#ff0000' attachment.author_name = environment + " " + (str(app_version) if str(app_version) is not None else 'Uknown Version') attachment.title = "Build " + (os.environ.get('BUILD_ID') if os.environ.get('BUILD_ID') is not None else 'Uknown') attachment.title_link = (os.environ.get('BUILD_URL') if os.environ.get('BUILD_URL') is not None else '') attachment.footer = 'Flow' attachment.text = message attachment.fields = [] attachment_field = Object() attachment_field.value = class_name attachment_field.title = 'Class' attachment.fields.append(attachment_field) attachment_field = Object() attachment_field.value = method_name attachment_field.title = 'Method' attachment.fields.append(attachment_field) slack_message.attachments.append(attachment) commons.print_msg(Slack.clazz, method, slack_message.to_JSON()) headers = {'Content-type': 'application/json', 'Accept': 'application/json'} commons.print_msg(Slack.clazz, method, Slack.slack_url) try: resp = requests.post(Slack.slack_url, slack_message.to_JSON(), headers=headers, timeout=Slack.http_timeout) if resp.status_code == 200: commons.print_msg(Slack.clazz, method, "Successfully sent to slack. \r\n resp: {}".format(resp.text), "DEBUG") else: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url} \r\n Resp: {resp} \r\n " "Status: {stat}".format(url=Slack.slack_url, resp=resp.text, stat=resp.status_code), "WARN") except requests.ConnectionError: commons.print_msg(Slack.clazz, method, "Request to Slack timed out.", "ERROR") except Exception as e: commons.print_msg(Slack.clazz, method, "Failed sending slack message to {url} with exception {ex}" .format(url=Slack.slack_url, ex=e)) commons.print_msg(Slack.clazz, method, 'end')
def add_tag_and_release_notes_to_github(self, new_version_tag_array, release_notes=None): # TODO this needs to be split out and better unit testing added. # testing is hard because json attributes are not ordered. method = 'add_tag_and_release_notes_to_github' commons.print_msg(GitHub.clazz, method, 'begin') me = Object() me.tag_name = self.convert_semver_tag_array_to_semver_string(new_version_tag_array) me.target_commitish = self.config.build_env_info['associatedBranchName'] me.name = self.convert_semver_tag_array_to_semver_string(new_version_tag_array) if release_notes is not None and len(release_notes) > 0: me.body = release_notes else: me.body = 'No Release Notes' me.draft = False me.prerelease = True # release builds will have a build index of 0. if self._is_semver_tag_array_release_or_snapshot(new_version_tag_array) == 'release': me.prerelease = False tag_and_release_note_payload = me.to_JSON() url_params = {'org': self.org, 'repo': self.repo} commons.print_msg(GitHub.clazz, method, self.url) commons.print_msg(GitHub.clazz, method, self.org) commons.print_msg(GitHub.clazz, method, self.repo) release_url = self.url + '/' + self.org + '/' + self.repo + '/releases' commons.print_msg(GitHub.clazz, method, release_url) commons.print_msg(GitHub.clazz, method, tag_and_release_note_payload) commons.print_msg(GitHub.clazz, method, ("?", url_params)) if self.token is not None: headers = {'Content-type': cicommons.content_json, 'Accept': cicommons.content_json, 'Authorization': ('token ' + self.token)} else: headers = {'Content-type': cicommons.content_json, 'Accept': cicommons.content_json} try: resp = requests.post(release_url, tag_and_release_note_payload, headers=headers, params=url_params, timeout=self.http_timeout) except requests.ConnectionError: commons.print_msg(GitHub.clazz, method, 'Request to GitHub timed out.', 'ERROR') exit(1) except: commons.print_msg(GitHub.clazz, method, "The github add release notes call failed to {} has failed".format( release_url), 'ERROR') exit(1) # noinspection PyUnboundLocalVariable if resp.status_code != 200 and resp.status_code != 201: commons.print_msg(GitHub.clazz, method, "The github add release notes call failed to {url}\r\n Response: {rsp}" .format(url=release_url, rsp=resp.text), 'ERROR') exit(1) else: commons.print_msg(GitHub.clazz, method, resp.text) commons.print_msg(GitHub.clazz, method, 'end')
def _add_version_to_jira_story(self, story_id, label): method = '_add_version_to_jira_story' commons.print_msg(Jira.clazz, method, 'begin') detail = self._retrieve_story_detail(story_id) versions = detail.versions versions.append(label) add_version_story = Object() add_version_story.update = Object() add_version_story.update.fixVersions = [] set_version = Object() set_version.set = [] for current_version in versions: version = Object() version.name = current_version set_version.set.append(version) add_version_story.update.fixVersions.append(set_version) jira_url = "{url}/rest/api/2/issue/{storyid}".format(url=Jira.jira_url, storyid=story_id) headers = { 'Content-type': 'application/json', 'Accept': 'application/json' } commons.print_msg(Jira.clazz, method, jira_url) commons.print_msg(Jira.clazz, method, add_version_story.to_JSON()) try: # TODO: Remove auth from below... resp = requests.put(jira_url, add_version_story.to_JSON(), auth=(os.getenv('JIRA_USER'), os.getenv('JIRA_PWD')), headers=headers, timeout=self.http_timeout) if resp.status_code != 204: commons.print_msg( Jira.clazz, method, "Unable to tag story {story} with label {lbl} \r\n " "Response: {response}".format(story=story_id, lbl=label, response=resp.text), 'WARN') else: commons.print_msg(Jira.clazz, method, resp.text) except requests.ConnectionError as e: commons.print_msg(Jira.clazz, method, 'Connection error. ' + str(e), 'WARN') except Exception as e: commons.print_msg( Jira.clazz, method, "Unable to tag story {story} with label {lbl}".format( story=story_id, lbl=label), 'WARN') commons.print_msg(Jira.clazz, method, e, 'WARN') commons.print_msg(Jira.clazz, method, 'end')