예제 #1
0
    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')
예제 #2
0
    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')
예제 #3
0
    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"])
예제 #4
0
    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')
예제 #5
0
    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')
예제 #6
0
    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')
예제 #7
0
    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')
예제 #8
0
    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')