OP-2204 - added possibility to upload or add link to review to Slack notification

This commit is contained in:
Petr Kalis 2022-01-07 12:06:33 +01:00
parent 9de27a8b04
commit 2229e19caa

View file

@ -14,6 +14,8 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin):
Project settings > Slack > Publish plugins > Notification to Slack.
If instance contains 'thumbnail' it uploads it. Bot must be present
in the target channel.
If instance contains 'review' it could upload (if configured) or place
link with {review_link} placeholder.
Message template can contain {} placeholders from anatomyData.
"""
order = pyblish.api.IntegratorOrder + 0.499
@ -23,44 +25,68 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin):
optional = True
def process(self, instance):
published_path = self._get_thumbnail_path(instance)
thumbnail_path = self._get_thumbnail_path(instance)
review_path = self._get_review_path(instance)
publish_files = set()
for message_profile in instance.data["slack_channel_message_profiles"]:
message = self._get_filled_message(message_profile["message"],
instance)
instance,
review_path)
if not message:
return
if message_profile["upload_thumbnail"] and thumbnail_path:
publish_files.add(thumbnail_path)
if message_profile["upload_review"] and review_path:
publish_files.add(review_path)
for channel in message_profile["channels"]:
if six.PY2:
self._python2_call(instance.data["slack_token"],
channel,
message,
published_path,
message_profile["upload_thumbnail"])
publish_files)
else:
self._python3_call(instance.data["slack_token"],
channel,
message,
published_path,
message_profile["upload_thumbnail"])
publish_files)
def _get_filled_message(self, message_templ, instance):
"""Use message_templ and data from instance to get message content."""
def _get_filled_message(self, message_templ, instance, review_path=None):
"""Use message_templ and data from instance to get message content.
Reviews might be large, so allow only adding link to message instead of
uploading only.
"""
fill_data = copy.deepcopy(instance.context.data["anatomyData"])
fill_pairs = (
fill_pairs = [
("asset", instance.data.get("asset", fill_data.get("asset"))),
("subset", instance.data.get("subset", fill_data.get("subset"))),
("task", instance.data.get("task", fill_data.get("task"))),
("username", instance.data.get("username",
fill_data.get("username"))),
("app", instance.data.get("app", fill_data.get("app"))),
("family", instance.data.get("family", fill_data.get("family"))),
("version", str(instance.data.get("version",
fill_data.get("version"))))
)
]
if review_path:
fill_pairs.append(("review_link", review_path))
task_on_instance = instance.data.get("task")
task_on_anatomy = fill_data.get("task")
if task_on_instance:
fill_pairs.append(("task[name]", task_on_instance.get("type")))
fill_pairs.append(("task[name]", task_on_instance.get("name")))
fill_pairs.append(("task[short]", task_on_instance.get("short")))
elif task_on_anatomy:
fill_pairs.append(("task[name]", task_on_anatomy.get("type")))
fill_pairs.append(("task[name]", task_on_anatomy.get("name")))
fill_pairs.append(("task[short]", task_on_anatomy.get("short")))
self.log.debug("fill_pairs ::{}".format(fill_pairs))
multiple_case_variants = prepare_template_data(fill_pairs)
fill_data.update(multiple_case_variants)
@ -79,39 +105,51 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin):
published_path = None
for repre in instance.data['representations']:
if repre.get('thumbnail') or "thumbnail" in repre.get('tags', []):
repre_files = repre["files"]
if isinstance(repre_files, (tuple, list, set)):
filename = repre_files[0]
else:
filename = repre_files
published_path = os.path.join(
repre['stagingDir'], filename
)
if os.path.exists(repre["published_path"]):
published_path = repre["published_path"]
break
return published_path
def _get_review_path(self, instance):
"""Returns abs url for review if present in instance repres"""
published_path = None
for repre in instance.data['representations']:
tags = repre.get('tags', [])
if (repre.get("review")
or "review" in tags
or "burnin" in tags):
if os.path.exists(repre["published_path"]):
published_path = repre["published_path"]
if "burnin" in tags: # burnin has precedence if exists
break
return published_path
def _python2_call(self, token, channel, message,
published_path, upload_thumbnail):
publish_files):
from slackclient import SlackClient
try:
client = SlackClient(token)
if upload_thumbnail and \
published_path and os.path.exists(published_path):
with open(published_path, 'rb') as pf:
for p_file in publish_files:
attachment_str = "\n\n Attachment links: \n"
with open(p_file, 'rb') as pf:
response = client.api_call(
"files.upload",
channels=channel,
initial_comment=message,
file=pf,
title=os.path.basename(published_path)
title=os.path.basename(p_file),
)
else:
response = client.api_call(
"chat.postMessage",
channel=channel,
text=message
)
attachment_str += "\n<{}|{}>".format(
response["file"]["permalink"],
os.path.basename(p_file))
if publish_files:
message += attachment_str
response = client.api_call(
"chat.postMessage",
channel=channel,
text=message
)
if response.get("error"):
error_str = self._enrich_error(str(response.get("error")),
@ -123,23 +161,27 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin):
self.log.warning("Error happened: {}".format(error_str))
def _python3_call(self, token, channel, message,
published_path, upload_thumbnail):
publish_files):
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
try:
client = WebClient(token=token)
if upload_thumbnail and \
published_path and os.path.exists(published_path):
_ = client.files_upload(
channels=channel,
initial_comment=message,
file=published_path,
)
else:
_ = client.chat_postMessage(
channel=channel,
text=message
)
attachment_str = "\n\n Attachment links: \n"
for published_file in publish_files:
response = client.files_upload(
file=published_file,
filename=os.path.basename(published_file))
attachment_str += "\n<{}|{}>".format(
response["file"]["permalink"],
os.path.basename(published_file))
if publish_files:
message += attachment_str
_ = client.chat_postMessage(
channel=channel,
text=message
)
except SlackApiError as e:
# You will get a SlackApiError if "ok" is False
error_str = self._enrich_error(str(e.response["error"]), channel)