def run_pipeline_and_notify(pipeline: pipelines.Pipeline, nodes: {pipelines.Node} = None): if config.slack_token(): import requests, os message = ( ':hatching_chick: *' + (os.environ.get('SUDO_USER') or os.environ.get('USER') or os.getlogin()) + '* manually triggered run of ' + ('pipeline <' + config.base_url() + '/' + '/'.join(pipeline.path()) + '|' + '/'.join(pipeline.path()) + ' >' if pipeline.parent else 'root pipeline')) if nodes: message += ', nodes ' + ', '.join( [f'`{node.id}`' for node in nodes]) requests.post('https://hooks.slack.com/services/' + config.slack_token(), json={'text': message}) if not run_pipeline(pipeline, nodes): requests.post('https://hooks.slack.com/services/' + config.slack_token(), json={'text': ':baby_chick: failed'}) sys.exit(-1) requests.post('https://hooks.slack.com/services/' + config.slack_token(), json={'text': ':hatched_chick: succeeded'})
def send_task_failed_message(self, event: pipeline_events.NodeFinished): path = '/'.join(event.node_path) text = '\n:baby_chick: Ooops, a hiccup in ' + '_ <' + config.base_url() + '/' + path \ + ' | ' + path + ' > _' attachments = [] key = tuple(event.node_path) if self.node_output[key][False]: attachments.append({ 'text': self._format_output(self.node_output[key][False]), 'mrkdwn_in': ['text'] }) if self.node_output[key][True]: attachments.append({ 'text': self._format_output(self.node_output[key][True]), 'color': '#eb4d5c', 'mrkdwn_in': ['text'] }) self._send_message({'text': text, 'attachments': attachments})
def handle_event(self, event: events.Event): """ Send the output of a node to Slack when the node failed. Args: event: The current event of interest """ if isinstance(event, events.Output): key = tuple(event.node_path) if not self.node_output: self.node_output = {} if not key in self.node_output: self.node_output[key] = {True: [], False: []} self.node_output[key][event.is_error].append(event) elif isinstance(event, events.NodeFinished): key = tuple(event.node_path) if not event.succeeded and event.is_pipeline is False: message = { 'text': '\n:baby_chick: Ooops, a hiccup in ' + '_ <' + config.base_url() + flask.url_for('data_integration.node_page', path='/'.join(event.node_path)) + ' | ' + '/'.join(event.node_path) + ' > _', 'attachments': [] } if (self.node_output[key][False]): message['attachments'].append({ 'text': self.format_output(self.node_output[key][False]), 'mrkdwn_in': ['text'] }) if (self.node_output[key][True]): message['attachments'].append({ 'text': self.format_output(self.node_output[key][True]), 'color': '#eb4d5c', 'mrkdwn_in': ['text'] }) response = requests.post('https://hooks.slack.com/services/' + config.slack_token(), json=message) if response.status_code != 200: raise ValueError( 'Request to slack returned an error %s. The response is:\n%s' % (response.status_code, response.text))
def send_run_started_interactively_message( self, event: pipeline_events.RunStarted): text = ('<font size="4">🐣</font> ' + event.user + ' manually triggered run of ' + ('pipeline [_' + '/'.join(event.node_path).replace("_", "\\_") + '_]' + '(' + (config.base_url() + '/' + '/'.join(event.node_path) + ')' if not event.is_root_pipeline else 'root pipeline'))) if event.node_ids: text += ', nodes ' + ', '.join( [f'`{node}`' for node in event.node_ids]) self._send_message({'text': text})
def send_run_started_interactively_message( self, event: pipeline_events.RunStarted): text = (':hatching_chick: *' + event.user + '* manually triggered run of ' + ('pipeline <' + config.base_url() + '/' + '/'.join(event.node_path) + '|' + '/'.join(event.node_path) + ' >' if not event.is_root_pipeline else 'root pipeline')) if event.node_ids: text += ', nodes ' + ', '.join( [f'`{node}`' for node in event.node_ids]) self._send_message({'text': text})
def send_task_failed_message(self, event: pipeline_events.NodeFinished): text = '<font size="4">🐤</font> Ooops, a hiccup in [_' + '/'.join(event.node_path).replace("_", "\\_") \ + '_](' + config.base_url() + '/' + '/'.join(event.node_path) + ')' key = tuple(event.node_path) if self.node_output[key][False]: text += self._format_output(self.node_output[key][False]) if self.node_output[key][True]: text += self._format_output(self.node_output[key][True]) # Shortening message to 2000 because Teams does not display message greater than 28 KB. # https://docs.microsoft.com/en-us/microsoftteams/limits-specifications-teams#chat if len(text) > 2000: text = text[:2000] + '</pre>' self._send_message({'text': text})
def handle_event(self, event: events.Event): """ Send the output of a node to Slack when the node failed. Args: event: The current event of interest """ import requests if isinstance(event, pipeline_events.Output): key = tuple(event.node_path) if not self.node_output: self.node_output = {} if not key in self.node_output: self.node_output[key] = {True: [], False: []} self.node_output[key][event.is_error].append(event) elif isinstance(event, pipeline_events.NodeFinished): key = tuple(event.node_path) if not event.succeeded and event.is_pipeline is False: message = { 'text': '\n:baby_chick: Ooops, a hiccup in ' + '_ <' + config.base_url() + '/' + '/'.join(event.node_path) + ' | ' + '/'.join(event.node_path) + ' > _', 'attachments': [] } if (self.node_output[key][False]): message['attachments'].append({ 'text': self.format_output(self.node_output[key][False]), 'mrkdwn_in': ['text'] }) if (self.node_output[key][True]): message['attachments'].append({ 'text': self.format_output(self.node_output[key][True]), 'color': '#eb4d5c', 'mrkdwn_in': ['text'] }) response = requests.post('https://hooks.slack.com/services/' + config.slack_token(), json=message) if response.status_code != 200: raise ValueError( 'Request to slack returned an error %s. The response is:\n%s' % (response.status_code, response.text)) elif isinstance(event, pipeline_events.RunStarted): # default handler only handles interactively started runs if event.interactively_started: message = f':hatching_chick: *{event.user}* manually triggered run of ' message += ('pipeline <' + config.base_url() + '/' + '/'.join(event.node_path) + '|' + '/'.join(event.node_path) + ' >' if not event.is_root_pipeline else 'root pipeline') if event.node_ids: message += ', nodes ' + ', '.join( [f'`{id_}`' for id_ in event.node_ids]) requests.post('https://hooks.slack.com/services/' + config.slack_token(), json={'text': message}) elif isinstance(event, pipeline_events.RunFinished): # default handler only handles interactively started runs if event.interactively_started: if event.succeeded: msg = ':hatched_chick: succeeded' else: msg = ':baby_chick: failed' requests.post('https://hooks.slack.com/services/' + config.slack_token(), json={'text': msg})