Skip to content

Commit 43f8754

Browse files
authored
ref(slack): Remove unused Slack channel lookup code (#54244)
The new Slack channel lookup has been GA'd for about a month now, it's safe to remove the old code and the feature flags. Closes #54004
1 parent e72ed3b commit 43f8754

File tree

11 files changed

+154
-421
lines changed

11 files changed

+154
-421
lines changed

src/sentry/conf/server.py

-2
Original file line numberDiff line numberDiff line change
@@ -1689,8 +1689,6 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
16891689
"organizations:org-auth-tokens": False,
16901690
# Enable detecting SDK crashes during event processing
16911691
"organizations:sdk-crash-detection": False,
1692-
# Enables slack channel lookup via schedule message
1693-
"organizations:slack-use-new-lookup": False,
16941692
# Enable functionality for recap server polling.
16951693
"organizations:recap-server": False,
16961694
# Adds additional filters and a new section to issue alert rules.

src/sentry/features/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@
262262
default_manager.add("organizations:ds-sliding-window", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)
263263
default_manager.add("organizations:ds-sliding-window-org", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)
264264
default_manager.add("organizations:ds-org-recalibration", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)
265-
default_manager.add("organizations:slack-use-new-lookup", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
266265
default_manager.add("organizations:slack-disable-on-broken", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
267266
default_manager.add("organizations:sourcemaps-bundle-flat-file-indexing", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
268267
default_manager.add("organizations:recap-server", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)

src/sentry/integrations/slack/utils/channel.py

+2-88
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from django.core.exceptions import ValidationError
77

8-
from sentry import features
98
from sentry.integrations.slack.client import SlackClient
109
from sentry.models import Integration, Organization
1110
from sentry.services.hybrid_cloud.integration import RpcIntegration
@@ -61,14 +60,12 @@ def get_channel_id(
6160
else:
6261
timeout = SLACK_DEFAULT_TIMEOUT
6362

64-
# XXX(meredith): For large accounts that have many, many channels it's
65-
# possible for us to timeout while attempting to paginate through to find the channel id
63+
# XXX(meredith): For large accounts that have many, many users it's
64+
# possible for us to timeout while attempting to paginate through to find the user id
6665
# This means some users are unable to create/update alert rules. To avoid this, we attempt
6766
# to find the channel id asynchronously if it takes longer than a certain amount of time,
6867
# which I have set as the SLACK_DEFAULT_TIMEOUT - arbitrarily - to 10 seconds.
6968

70-
if features.has("organizations:slack-use-new-lookup", organization):
71-
return get_channel_id_with_timeout_new(integration, channel_name, timeout)
7269
return get_channel_id_with_timeout(integration, channel_name, timeout)
7370

7471

@@ -106,89 +103,6 @@ def get_channel_id_with_timeout(
106103
integration: Integration | RpcIntegration,
107104
name: Optional[str],
108105
timeout: int,
109-
) -> Tuple[str, Optional[str], bool]:
110-
"""
111-
Fetches the internal slack id of a channel.
112-
:param integration: The slack integration
113-
:param name: The name of the channel
114-
:param timeout: Our self-imposed time limit.
115-
:return: a tuple of three values
116-
1. prefix: string (`"#"` or `"@"`)
117-
2. channel_id: string or `None`
118-
3. timed_out: boolean (whether we hit our self-imposed time limit)
119-
"""
120-
121-
payload = {
122-
"exclude_archived": False,
123-
"exclude_members": True,
124-
"types": "public_channel,private_channel",
125-
}
126-
127-
list_types = LIST_TYPES
128-
129-
time_to_quit = time.time() + timeout
130-
131-
client = SlackClient(integration_id=integration.id)
132-
id_data: Optional[Tuple[str, Optional[str], bool]] = None
133-
found_duplicate = False
134-
prefix = ""
135-
for list_type, result_name, prefix in list_types:
136-
cursor = ""
137-
while True:
138-
endpoint = f"/{list_type}.list"
139-
try:
140-
# Slack limits the response of `<list_type>.list` to 1000 channels
141-
items = client.get(endpoint, params=dict(payload, cursor=cursor, limit=1000))
142-
except ApiRateLimitedError as e:
143-
logger.info(
144-
f"rule.slack.{list_type}_list_rate_limited",
145-
extra={"error": str(e), "integration_id": integration.id},
146-
)
147-
raise e
148-
except ApiError as e:
149-
logger.info(
150-
f"rule.slack.{list_type}_list_other_error",
151-
extra={"error": str(e), "integration_id": integration.id},
152-
)
153-
return prefix, None, False
154-
155-
if not isinstance(items, dict):
156-
continue
157-
158-
for c in items[result_name]:
159-
# The "name" field is unique (this is the username for users)
160-
# so we return immediately if we find a match.
161-
# convert to lower case since all names in Slack are lowercase
162-
if name and c["name"].lower() == name.lower():
163-
return prefix, c["id"], False
164-
# If we don't get a match on a unique identifier, we look through
165-
# the users' display names, and error if there is a repeat.
166-
if list_type == "users":
167-
profile = c.get("profile")
168-
if profile and profile.get("display_name") == name:
169-
if id_data:
170-
found_duplicate = True
171-
else:
172-
id_data = (prefix, c["id"], False)
173-
174-
cursor = items.get("response_metadata", {}).get("next_cursor", None)
175-
if time.time() > time_to_quit:
176-
return prefix, None, True
177-
178-
if not cursor:
179-
break
180-
if found_duplicate:
181-
raise DuplicateDisplayNameError(name)
182-
elif id_data:
183-
return id_data
184-
185-
return prefix, None, False
186-
187-
188-
def get_channel_id_with_timeout_new(
189-
integration: Integration | RpcIntegration,
190-
name: Optional[str],
191-
timeout: int,
192106
) -> Tuple[str, Optional[str], bool]:
193107
"""
194108
Fetches the internal slack id of a channel using scheduled message.

tests/sentry/api/endpoints/notifications/test_notification_actions_details.py

+13-15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sentry.testutils.cases import APITestCase
1919
from sentry.testutils.helpers.slack import install_slack
2020
from sentry.testutils.silo import assume_test_silo_mode, region_silo_test
21+
from sentry.utils import json
2122

2223

2324
@region_silo_test(stable=True)
@@ -233,26 +234,23 @@ class MockActionRegistration(ActionRegistration):
233234

234235
self.mock_register(data)(MockActionRegistration)
235236

236-
# Can't find slack channel
237237
responses.add(
238-
method=responses.GET,
239-
url="https://slack.com/api/conversations.list",
240-
status=500,
241-
)
242-
self.get_error_response(
243-
self.organization.slug,
244-
self.notif_action.id,
245-
status_code=status.HTTP_400_BAD_REQUEST,
246-
method="PUT",
247-
**data,
238+
method=responses.POST,
239+
url="https://slack.com/api/chat.scheduleMessage",
240+
status=200,
241+
content_type="application/json",
242+
body=json.dumps(
243+
{"ok": "true", "channel": channel_id, "scheduled_message_id": "Q1298393284"}
244+
),
248245
)
249-
# Successful search for channel
250246
responses.add(
251-
method=responses.GET,
252-
url="https://slack.com/api/conversations.list",
247+
method=responses.POST,
248+
url="https://slack.com/api/chat.deleteScheduledMessage",
253249
status=200,
254-
json={"ok": True, "channels": [{"name": channel_name, "id": channel_id}]},
250+
content_type="application/json",
251+
body=json.dumps({"ok": True}),
255252
)
253+
256254
response = self.get_success_response(
257255
self.organization.slug,
258256
self.notif_action.id,

tests/sentry/api/endpoints/notifications/test_notification_actions_index.py

+12-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sentry.testutils.cases import APITestCase
1919
from sentry.testutils.helpers.slack import install_slack
2020
from sentry.testutils.silo import assume_test_silo_mode, region_silo_test
21+
from sentry.utils import json
2122

2223

2324
@region_silo_test(stable=True)
@@ -281,24 +282,21 @@ class MockActionRegistration(ActionRegistration):
281282

282283
self.mock_register(data)(MockActionRegistration)
283284

284-
# Can't find slack channel
285285
responses.add(
286-
method=responses.GET,
287-
url="https://slack.com/api/conversations.list",
288-
status=500,
289-
)
290-
self.get_error_response(
291-
self.organization.slug,
292-
status_code=status.HTTP_400_BAD_REQUEST,
293-
method="POST",
294-
**data,
286+
method=responses.POST,
287+
url="https://slack.com/api/chat.scheduleMessage",
288+
status=200,
289+
content_type="application/json",
290+
body=json.dumps(
291+
{"ok": "true", "channel": channel_id, "scheduled_message_id": "Q1298393284"}
292+
),
295293
)
296-
# Successful search for channel
297294
responses.add(
298-
method=responses.GET,
299-
url="https://slack.com/api/conversations.list",
295+
method=responses.POST,
296+
url="https://slack.com/api/chat.deleteScheduledMessage",
300297
status=200,
301-
json={"ok": True, "channels": [{"name": channel_name, "id": channel_id}]},
298+
content_type="application/json",
299+
body=json.dumps({"ok": True}),
302300
)
303301
response = self.get_success_response(
304302
self.organization.slug,

tests/sentry/incidents/action_handlers/test_slack.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,21 @@ def setUp(self):
2828
self.channel_id = "some_id"
2929
self.channel_name = "#hello"
3030
responses.add(
31-
method=responses.GET,
32-
url="https://slack.com/api/conversations.list",
31+
method=responses.POST,
32+
url="https://slack.com/api/chat.scheduleMessage",
3333
status=200,
3434
content_type="application/json",
3535
body=json.dumps(
36-
{"ok": "true", "channels": [{"name": self.channel_name[1:], "id": self.channel_id}]}
36+
{"ok": "true", "channel": self.channel_id, "scheduled_message_id": "Q1298393284"}
3737
),
3838
)
39+
responses.add(
40+
method=responses.POST,
41+
url="https://slack.com/api/chat.deleteScheduledMessage",
42+
status=200,
43+
content_type="application/json",
44+
body=json.dumps({"ok": True}),
45+
)
3946
self.action = self.create_alert_rule_trigger_action(
4047
target_identifier=self.channel_name,
4148
type=AlertRuleTriggerAction.Type.SLACK,

0 commit comments

Comments
 (0)