|
@@ -1,12 +1,12 @@
|
|
|
from __future__ import annotations
|
|
|
|
|
|
import logging
|
|
|
-from typing import Any, Iterable, Mapping, MutableMapping, Optional
|
|
|
+from typing import Any, Iterable, Mapping, MutableMapping, Optional, Sequence, TypedDict
|
|
|
|
|
|
import pytz
|
|
|
|
|
|
from sentry.db.models import Model
|
|
|
-from sentry.models import Release, Team, User, UserOption
|
|
|
+from sentry.models import Release, ReleaseCommit, Team, User, UserOption
|
|
|
from sentry.notifications.notifications.base import ProjectNotification
|
|
|
from sentry.notifications.types import ActionTargetType, NotificationSettingTypes
|
|
|
from sentry.notifications.utils import (
|
|
@@ -22,6 +22,7 @@ from sentry.notifications.utils.participants import get_send_to
|
|
|
from sentry.plugins.base.structs import Notification
|
|
|
from sentry.types.integrations import ExternalProviders
|
|
|
from sentry.utils import metrics
|
|
|
+from sentry.utils.http import absolute_uri
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
@@ -159,6 +160,12 @@ class AlertRuleNotification(ProjectNotification):
|
|
|
}
|
|
|
|
|
|
|
|
|
+class CommitData(TypedDict):
|
|
|
+ author: User
|
|
|
+ subject: str
|
|
|
+ key: str
|
|
|
+
|
|
|
+
|
|
|
class ActiveReleaseAlertNotification(AlertRuleNotification):
|
|
|
message_builder = "ActiveReleaseIssueNotificationMessageBuilder"
|
|
|
metrics_key = "release_issue_alert"
|
|
@@ -172,8 +179,14 @@ class ActiveReleaseAlertNotification(AlertRuleNotification):
|
|
|
target_identifier: int | None = None,
|
|
|
last_release: Optional[Release] = None,
|
|
|
) -> None:
|
|
|
+ from sentry.rules.conditions.active_release import ActiveReleaseEventCondition
|
|
|
+
|
|
|
super().__init__(notification, target_type, target_identifier)
|
|
|
- self.last_release = last_release
|
|
|
+ self.last_release = (
|
|
|
+ last_release
|
|
|
+ if last_release
|
|
|
+ else ActiveReleaseEventCondition.latest_release(notification.event)
|
|
|
+ )
|
|
|
|
|
|
def get_notification_title(self, context: Mapping[str, Any] | None = None) -> str:
|
|
|
from sentry.integrations.slack.message_builder.issues import build_rule_url
|
|
@@ -190,6 +203,56 @@ class ActiveReleaseAlertNotification(AlertRuleNotification):
|
|
|
return title_str
|
|
|
|
|
|
def get_context(self) -> MutableMapping[str, Any]:
|
|
|
- ctx = super().get_context()
|
|
|
- ctx["last_release"] = self.last_release
|
|
|
- return ctx
|
|
|
+ environment = self.event.get_tag("environment")
|
|
|
+ enhanced_privacy = self.organization.flags.enhanced_privacy
|
|
|
+ rule_details = get_rules(self.rules, self.organization, self.project)
|
|
|
+ context = {
|
|
|
+ "project_label": self.project.get_full_name(),
|
|
|
+ "group": self.group,
|
|
|
+ "event": self.event,
|
|
|
+ "link": get_group_settings_link(self.group, environment, rule_details),
|
|
|
+ "rules": rule_details,
|
|
|
+ "has_integrations": has_integrations(self.organization, self.project),
|
|
|
+ "enhanced_privacy": enhanced_privacy,
|
|
|
+ "last_release": self.last_release,
|
|
|
+ "last_release_link": self.release_url(self.last_release),
|
|
|
+ "commits": self.get_release_commits(self.last_release),
|
|
|
+ "environment": environment,
|
|
|
+ "slack_link": get_integration_link(self.organization, "slack"),
|
|
|
+ "has_alert_integration": has_alert_integration(self.project),
|
|
|
+ }
|
|
|
+
|
|
|
+ # if the organization has enabled enhanced privacy controls we don't send
|
|
|
+ # data which may show PII or source code
|
|
|
+ if not enhanced_privacy:
|
|
|
+ context.update({"tags": self.event.tags, "interfaces": get_interface_list(self.event)})
|
|
|
+
|
|
|
+ return context
|
|
|
+
|
|
|
+ def get_release_commits(self, release: Release) -> Sequence[CommitData]:
|
|
|
+ if not release:
|
|
|
+ return []
|
|
|
+
|
|
|
+ release_commits = (
|
|
|
+ ReleaseCommit.objects.filter(release_id=release.id)
|
|
|
+ .select_related("commit", "commit__author")
|
|
|
+ .order_by("-order")
|
|
|
+ )
|
|
|
+
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ "author": rc.commit.author,
|
|
|
+ "subject": rc.commit.message.split("\n", 1)[0]
|
|
|
+ if rc.commit.message
|
|
|
+ else "no subject",
|
|
|
+ "key": rc.commit.key,
|
|
|
+ }
|
|
|
+ for rc in release_commits
|
|
|
+ ]
|
|
|
+
|
|
|
+ def release_url(self, release: Release) -> str:
|
|
|
+ return str(
|
|
|
+ absolute_uri(
|
|
|
+ f"/organizations/{release.organization.slug}/releases/{release.version}/?project={release.project_id}"
|
|
|
+ )
|
|
|
+ )
|