Browse Source

feat(notifications): Parsed Versions (#28971)

Marcos Gaeta 3 years ago
parent
commit
36f0714733

+ 13 - 7
src/sentry/notifications/notifications/activity/release.py

@@ -1,5 +1,7 @@
 from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Set, Union
 
+from sentry_relay import parse_release
+
 from sentry.models import Activity, CommitFileChange, Project, Team, User
 from sentry.notifications.utils import (
     get_commits_for_release,
@@ -37,6 +39,7 @@ class ReleaseActivityNotification(ActivityNotification):
             self.repos: Iterable[Mapping[str, Any]] = set()
             self.projects: Set[Project] = set()
             self.version = "unknown"
+            self.version_parsed = self.version
             return
 
         self.projects = set(self.release.projects.all())
@@ -47,7 +50,9 @@ class ReleaseActivityNotification(ActivityNotification):
         self.repos = get_repos(self.commit_list, users, self.organization)
         self.environment = get_environment_for_deploy(self.deploy)
         self.group_counts_by_project = get_group_counts_by_project(self.release, self.projects)
+
         self.version = self.release.version
+        self.version_parsed = parse_release(self.version)["description"]
 
     def should_email(self) -> bool:
         return bool(self.release and self.deploy)
@@ -65,15 +70,16 @@ class ReleaseActivityNotification(ActivityNotification):
     def get_context(self) -> MutableMapping[str, Any]:
         return {
             **self.get_base_context(),
-            "commit_count": len(self.commit_list),
             "author_count": len(self.email_list),
-            "file_count": CommitFileChange.objects.get_count_for_commits(self.commit_list),
-            "repos": self.repos,
-            "release": self.release,
+            "commit_count": len(self.commit_list),
             "deploy": self.deploy,
             "environment": self.environment,
+            "file_count": CommitFileChange.objects.get_count_for_commits(self.commit_list),
+            "release": self.release,
+            "repos": self.repos,
             "setup_repo_link": absolute_uri(f"/organizations/{self.organization.slug}/repos/"),
-            "text_description": f"Version {self.version} was deployed to {self.environment}",
+            "text_description": f"Version {self.version_parsed} was deployed to {self.environment}",
+            "version_parsed": self.version_parsed,
         }
 
     def get_projects(self, recipient: Union["Team", "User"]) -> Set[Project]:
@@ -104,7 +110,7 @@ class ReleaseActivityNotification(ActivityNotification):
         }
 
     def get_subject(self, context: Optional[Mapping[str, Any]] = None) -> str:
-        return f"Deployed version {self.version} to {self.environment}"
+        return f"Deployed version {self.version_parsed} to {self.environment}"
 
     def get_title(self) -> str:
         return self.get_subject()
@@ -115,7 +121,7 @@ class ReleaseActivityNotification(ActivityNotification):
             projects_text = " for this project"
         elif len(self.projects) > 1:
             projects_text = " for these projects"
-        return f"Release {self.version} was deployed to {self.environment}{projects_text}"
+        return f"Release {self.version_parsed} was deployed to {self.environment}{projects_text}"
 
     def get_filename(self) -> str:
         return "activity/release"

+ 1 - 1
src/sentry/templates/sentry/emails/activity/release.html

@@ -8,7 +8,7 @@
 
 {% block activity %}
     <h2 style="margin-bottom: 10px">
-        Version {{ release.version }} was deployed to {{ environment }}
+        Version {{ version_parsed }} was deployed to {{ environment }}
     </h2>
     <p class="muted"><small><strong style="color: #72697d;">{{ deploy.date_finished }}</strong> <span class="divider">&nbsp;</span>  {{ commit_count }} commit{{ commit_count|pluralize }}, {{ author_count }} author{{ author_count|pluralize }}, and {{ file_count }} file{{ file_count|pluralize }} changed across {{ project_count }} project{{ project_count|pluralize }}</small></p>
 

+ 1 - 1
src/sentry/templates/sentry/emails/activity/release.txt

@@ -1,4 +1,4 @@
-Version {{ release.version }} was deployed to {{ environment }} on {{ deploy.date_finished }}
+Version {{ version_parsed }} was deployed to {{ environment }} on {{ deploy.date_finished }}
 
 {% for project, release_link, resolved_issue_count in projects %}
     {{ release_link }}

+ 13 - 9
src/sentry/web/frontend/debug/debug_new_release_email.py

@@ -2,6 +2,7 @@ import datetime
 
 import pytz
 from django.views.generic import View
+from sentry_relay import parse_release
 
 from sentry.models import Commit, CommitAuthor, Deploy, Organization, Project, Release, User
 from sentry.notifications.types import GroupSubscriptionReason
@@ -19,9 +20,11 @@ class DebugNewReleaseEmailView(View):
             Project(id=2, organization=org, slug="another-project", name="Another Project"),
             Project(id=3, organization=org, slug="yet-another-project", name="Yet Another Project"),
         ]
+        version = "6c998f755f304593a4713abd123eaf8833a2de5e"
+        version_parsed = parse_release(version)["description"]
         release = Release(
             organization_id=org.id,
-            version="6c998f755f304593a4713abd123eaf8833a2de5e",
+            version=version,
             date_added=datetime.datetime(2016, 10, 12, 15, 39, tzinfo=pytz.utc),
         )
 
@@ -95,16 +98,17 @@ class DebugNewReleaseEmailView(View):
             html_template="sentry/emails/activity/release.html",
             text_template="sentry/emails/activity/release.txt",
             context={
-                "release": release,
-                "projects": zip(projects, release_links, [6, 1, 0]),
-                "repos": repos,
-                "reason": GroupSubscriptionReason.descriptions[GroupSubscriptionReason.committed],
-                "project_count": len(projects),
-                "commit_count": 4,
                 "author_count": 1,
-                "file_count": 5,
-                "environment": "production",
+                "commit_count": 4,
                 "deploy": deploy,
+                "environment": "production",
+                "file_count": 5,
+                "project_count": len(projects),
+                "projects": zip(projects, release_links, [6, 1, 0]),
+                "reason": GroupSubscriptionReason.descriptions[GroupSubscriptionReason.committed],
+                "release": release,
+                "repos": repos,
                 "setup_repo_link": absolute_uri(f"/organizations/{org.slug}/repos/"),
+                "version_parsed": version_parsed,
             },
         ).render(request)

+ 8 - 8
tests/acceptance/test_emails.py

@@ -38,30 +38,30 @@ def read_txt_email_fixture(name: str) -> str:
     filename = name.replace(" ", "_") + ".txt"
     path = join(dirname(__file__), os.pardir, "fixtures", "emails", filename)
 
-    fixture = None
     with open(path) as f:
-        fixture = f.read()
-    return fixture
+        return f.read()
+
+
+def build_url(path: str, format: str = "html") -> str:
+    return f"{path}?{urlencode({'format': format, 'seed': b'123'})}"
 
 
 class EmailTestCase(AcceptanceTestCase):
     def setUp(self):
         super().setUp()
+        # This email address is required to match FIXTURES.
         self.user = self.create_user("foo@example.com")
         self.login_as(self.user)
 
-    def build_url(self, path: str, format: str = "html") -> str:
-        return "{}?{}".format(path, urlencode({"format": format, "seed": b"123"}))
-
     def test_emails(self):
         for url, name in EMAILS:
             # HTML output is captured as a snapshot
-            self.browser.get(self.build_url(url, "html"))
+            self.browser.get(build_url(url, "html"))
             self.browser.wait_until("#preview")
             self.browser.snapshot(f"{name} email html")
 
             # Text output is asserted against static fixture files
-            self.browser.get(self.build_url(url, "txt"))
+            self.browser.get(build_url(url, "txt"))
             self.browser.wait_until("#preview")
             elem = self.browser.find_element_by_css_selector("#preview pre")
             text_src = elem.get_attribute("innerHTML")

+ 1 - 1
tests/fixtures/emails/release.txt

@@ -1,4 +1,4 @@
-Version 6c998f755f304593a4713abd123eaf8833a2de5e was deployed to production on Oct. 12, 2016, 3:39 p.m.
+Version 6c998f755f30 was deployed to production on Oct. 12, 2016, 3:39 p.m.
 
 
     http://testserver/organizations/organization/releases/6c998f755f304593a4713abd123eaf8833a2de5e/?project=1

+ 5 - 3
tests/sentry/notifications/test_notifications.py

@@ -6,6 +6,7 @@ from urllib.parse import parse_qs
 import responses
 from django.core import mail
 from django.utils import timezone
+from sentry_relay import parse_release
 
 from sentry.event_manager import EventManager
 from sentry.models import (
@@ -219,6 +220,7 @@ class ActivityNotificationTest(APITestCase):
         """
 
         release = self.create_release()
+        version_parsed = self.version_parsed = parse_release(release.version)["description"]
         url = f"/api/0/organizations/{self.organization.slug}/releases/{release.version}/deploys/"
         with self.tasks():
             response = self.client.post(
@@ -228,10 +230,10 @@ class ActivityNotificationTest(APITestCase):
 
         msg = mail.outbox[0]
         # check the txt version
-        assert f"Version {release.version} was deployed to {self.environment.name} on" in msg.body
+        assert f"Version {version_parsed} was deployed to {self.environment.name} on" in msg.body
         # check the html version
         assert (
-            f"Version {release.version} was deployed to {self.environment.name}\n    </h2>\n"
+            f"Version {version_parsed} was deployed to {self.environment.name}\n    </h2>\n"
             in msg.alternatives[0][0]
         )
 
@@ -239,7 +241,7 @@ class ActivityNotificationTest(APITestCase):
 
         assert (
             text
-            == f"Release {release.version} was deployed to {self.environment.name} for this project"
+            == f"Release {version_parsed} was deployed to {self.environment.name} for this project"
         )
         assert (
             attachment["actions"][0]["url"]