oncall-engine/engine/apps/slack/alert_group_slack_service.py
Joey Orlando e115617528
chore: drop usage of SlackMessage.organization + drop orphaned SlackMessages (#5330)
# 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.
2024-12-06 11:43:40 -05:00

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,
)