# What this PR does - Stops writing `SlackMessage.organization` + removes references to this field. [As we discussed](https://raintank-corp.slack.com/archives/C083TU81TCH/p1733315887463279?thread_ts=1733311105.095309&cid=C083TU81TCH), we do not need this field on this model/table, `SlackMessage._slack_team_identity` is sufficient (`organization` will be dropped in a separate PR) - Adds a data migration script which: - drops orphaned `SlackMessage` records; ie. ones which, even after the [`engine/apps/slack/migrations/0007_migrate_slackmessage_channel_id.py`](https://github.com/grafana/oncall/blob/dev/engine/apps/slack/migrations/0007_migrate_slackmessage_channel_id.py) migration, still don't have a `SlackMessage.channel` id filled in (we discussed + agreed on dropping these records [here](https://raintank-corp.slack.com/archives/C083TU81TCH/p1733329914516859?thread_ts=1733311105.095309&cid=C083TU81TCH)) - fills in empty `SlackMessage.slack_team_identity` values (from `slack_message.channel.slack_team_identity`) ### Other notes On the `organization` topic. We store records in `SlackMessage` for two purposes (AFAICT), and in both cases, we have references back to the `organization`: - alert groups - `slack_message.alert_group.channel.organization` - shift swap requests - `shift_swap_request.schedule.organization` ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes.
70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
import logging
|
|
import typing
|
|
|
|
from apps.slack.client import SlackClient
|
|
from apps.slack.errors import (
|
|
SlackAPIChannelArchivedError,
|
|
SlackAPIChannelNotFoundError,
|
|
SlackAPIInvalidAuthError,
|
|
SlackAPITokenError,
|
|
)
|
|
|
|
if typing.TYPE_CHECKING:
|
|
from apps.alerts.models import AlertGroup
|
|
from apps.slack.models import SlackTeamIdentity
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AlertGroupSlackService:
|
|
_slack_client: SlackClient
|
|
|
|
def __init__(
|
|
self,
|
|
slack_team_identity: "SlackTeamIdentity",
|
|
slack_client: typing.Optional[SlackClient] = None,
|
|
):
|
|
self.slack_team_identity = slack_team_identity
|
|
if slack_client is not None:
|
|
self._slack_client = slack_client
|
|
else:
|
|
self._slack_client = SlackClient(slack_team_identity)
|
|
|
|
def publish_message_to_alert_group_thread(
|
|
self, alert_group: "AlertGroup", attachments=None, mrkdwn=True, unfurl_links=True, text=None
|
|
) -> None:
|
|
"""
|
|
TODO: refactor this method and move it to the `SlackMessage` model, such that we can remove this class..
|
|
"""
|
|
# TODO: refactor checking the possibility of sending message to slack
|
|
# do not try to post message to slack if integration is rate limited
|
|
if alert_group.channel.is_rate_limited_in_slack:
|
|
return
|
|
|
|
slack_message = alert_group.slack_message
|
|
|
|
if attachments is None:
|
|
attachments = []
|
|
|
|
try:
|
|
result = self._slack_client.chat_postMessage(
|
|
channel=slack_message.channel.slack_id,
|
|
text=text,
|
|
attachments=attachments,
|
|
thread_ts=slack_message.slack_id,
|
|
mrkdwn=mrkdwn,
|
|
unfurl_links=unfurl_links,
|
|
)
|
|
except (
|
|
SlackAPITokenError,
|
|
SlackAPIChannelArchivedError,
|
|
SlackAPIChannelNotFoundError,
|
|
SlackAPIInvalidAuthError,
|
|
):
|
|
return
|
|
|
|
alert_group.slack_messages.create(
|
|
slack_id=result["ts"],
|
|
_slack_team_identity=self.slack_team_identity,
|
|
channel=slack_message.channel,
|
|
)
|