diff --git a/engine/apps/slack/scenarios/paging.py b/engine/apps/slack/scenarios/paging.py index 4cbd1d32..a7948e2b 100644 --- a/engine/apps/slack/scenarios/paging.py +++ b/engine/apps/slack/scenarios/paging.py @@ -125,7 +125,7 @@ class StartDirectPaging(scenario_step.ScenarioStep): # Check if command is /escalate. It's a legacy command we keep for smooth transition. is_legacy_command = slash_command.command == settings.SLACK_DIRECT_PAGING_SLASH_COMMAND # Check if command is /grafana escalate. It's a new command from unified app. - is_unified_app_command = slash_command.is_grafana_command and slash_command.subcommand == "escalate" + is_unified_app_command = slash_command.is_root_command and slash_command.subcommand == "escalate" return is_legacy_command or is_unified_app_command def process_scenario( @@ -163,13 +163,17 @@ class StartDirectPaging(scenario_step.ScenarioStep): # catch all exceptions to prevent the slash command from failing logger.warning("StartDirectPaging: failed to send ephemeral message to user", exc_info=True) else: - self._slack_client.chat_postEphemeral( - channel=channel_id, - user=slack_user_identity.slack_id, - text="The new Slack IRM integration is now available. Please use /grafana-irm escalate to " - "complete the action", - ) - return + # hack, parsing command again to determine if it's a legacy command + cmd = SlashCommand.parse(payload) + is_legacy_command = cmd.command == settings.SLACK_DIRECT_PAGING_SLASH_COMMAND + if is_legacy_command: + self._slack_client.chat_postEphemeral( + channel=channel_id, + user=slack_user_identity.slack_id, + text=f"The new Slack IRM integration is now available. " + f"Please use `/{settings.SLACK_IRM_ROOT_COMMAND}` escalate to complete the action", + ) + return private_metadata = { "channel_id": channel_id, diff --git a/engine/apps/slack/slash_command.py b/engine/apps/slack/slash_command.py index 779e16ec..4bd5c3f8 100644 --- a/engine/apps/slack/slash_command.py +++ b/engine/apps/slack/slash_command.py @@ -1,3 +1,5 @@ +from django.conf import settings + from apps.slack.types.interaction_payloads import SlashCommandPayload @@ -37,5 +39,5 @@ class SlashCommand: return SlashCommand(command, args) @property - def is_grafana_command(self): - return self.command in ["grafana-irm", "grafana-irm-dev", "grafana-irm-ops", "grafana-irm-prod"] + def is_root_command(self): + return self.command == settings.SLACK_IRM_ROOT_COMMAND diff --git a/engine/apps/slack/tests/test_interactive_api_endpoint.py b/engine/apps/slack/tests/test_interactive_api_endpoint.py index a49d1553..a8be48c3 100644 --- a/engine/apps/slack/tests/test_interactive_api_endpoint.py +++ b/engine/apps/slack/tests/test_interactive_api_endpoint.py @@ -306,7 +306,7 @@ def test_grafana_escalate( "channel_name": "test", "user_id": slack_user_identity.slack_id, "user_name": "Steve", - "command": "/grafana-irm", + "command": "/grafana", "text": "escalate", "response_url": "https://hooks.slack.com/commands/1234/5678", "trigger_id": "13345224609.738474920.8088930838d88f008e0", @@ -349,7 +349,7 @@ def test_grafana_escalate_with_org_from_chatops_proxy_defines_org( "channel_name": "test", "user_id": slack_user_identity.slack_id, "user_name": "Steve", - "command": "/grafana-irm", + "command": "/grafana", "text": "escalate", "response_url": "https://hooks.slack.com/commands/1234/5678", "trigger_id": "13345224609.738474920.8088930838d88f008e0", diff --git a/engine/apps/slack/tests/test_slash_command.py b/engine/apps/slack/tests/test_slash_command.py index 9827f9f1..6074ff91 100644 --- a/engine/apps/slack/tests/test_slash_command.py +++ b/engine/apps/slack/tests/test_slash_command.py @@ -1,9 +1,11 @@ +from django.test import override_settings + from apps.slack.slash_command import SlashCommand def test_parse(): payload = { - "command": "/grafana-irm", + "command": "/grafana", "text": "escalate", "trigger_id": "trigger_id", "user_id": "user_id", @@ -11,10 +13,27 @@ def test_parse(): "api_app_id": "api_app_id", } slash_command = SlashCommand.parse(payload) - assert slash_command.command == "grafana-irm" + assert slash_command.command == "grafana" assert slash_command.args == ["escalate"] assert slash_command.subcommand == "escalate" - assert slash_command.is_grafana_command + assert slash_command.is_root_command + + +@override_settings(SLACK_IRM_ROOT_COMMAND="gops") +def test_parse_non_default_root_command(): + payload = { + "command": "/gops", + "text": "escalate", + "trigger_id": "trigger_id", + "user_id": "user_id", + "user_name": "user_name", + "api_app_id": "api_app_id", + } + slash_command = SlashCommand.parse(payload) + assert slash_command.command == "gops" + assert slash_command.args == ["escalate"] + assert slash_command.subcommand == "escalate" + assert slash_command.is_root_command def test_parse_command_without_subcommand(): diff --git a/engine/settings/base.py b/engine/settings/base.py index 0112f002..14dce731 100644 --- a/engine/settings/base.py +++ b/engine/settings/base.py @@ -710,6 +710,8 @@ SLACK_SIGNING_SECRET_LIVE = os.environ.get("SLACK_SIGNING_SECRET_LIVE", "") SLACK_CLIENT_OAUTH_ID = os.environ.get("SLACK_CLIENT_OAUTH_ID") SLACK_CLIENT_OAUTH_SECRET = os.environ.get("SLACK_CLIENT_OAUTH_SECRET") SLACK_DIRECT_PAGING_SLASH_COMMAND = os.environ.get("SLACK_DIRECT_PAGING_SLASH_COMMAND", "/escalate").lstrip("/") +# it's a root command for unified slack - '/ incident new', '/ escalate' +SLACK_IRM_ROOT_COMMAND = os.environ.get("SLACK_IRM_ROOT_COMMAND", "/grafana").lstrip("/") # Controls if slack integration can be installed/uninstalled. SLACK_INTEGRATION_MAINTENANCE_ENABLED = os.environ.get("SLACK_INTEGRATION_MAINTENANCE_ENABLED", False) diff --git a/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx b/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx index 947eac23..defdcd52 100644 --- a/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx +++ b/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; import { css } from '@emotion/css'; import { GrafanaTheme2, PluginConfigPageProps, PluginMeta } from '@grafana/data'; import { Alert, Field, HorizontalGroup, Input, LoadingPlaceholder, useStyles2, VerticalGroup } from '@grafana/ui'; -import { observer } from 'mobx-react-lite'; +import { observer } from 'mobx-react'; import { Controller, useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom-v5-compat'; import { OnCallPluginMetaJSONData } from 'types';