-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Cloud Slack to always respond in a thread #1372
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -550,7 +550,7 @@ func (b *CloudSlack) send(ctx context.Context, event slackMessage, resp interact | |
var file *slack.File | ||
var err error | ||
if len(markdown) >= slackMaxMessageSize { | ||
file, err = uploadFileToSlack(ctx, event.Channel, resp, b.client, event.ThreadTimeStamp) | ||
file, err = b.uploadFileToSlack(ctx, event, resp) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -578,10 +578,6 @@ func (b *CloudSlack) send(ctx context.Context, event slackMessage, resp interact | |
b.renderer.RenderInteractiveMessage(resp), | ||
} | ||
|
||
if ts := b.getThreadOptionIfNeeded(event, file); ts != nil { | ||
options = append(options, ts) | ||
} | ||
|
||
if resp.ReplaceOriginal && event.ResponseURL != "" { | ||
options = append(options, slack.MsgOptionReplaceOriginal(event.ResponseURL)) | ||
} | ||
|
@@ -591,6 +587,10 @@ func (b *CloudSlack) send(ctx context.Context, event slackMessage, resp interact | |
return fmt.Errorf("while posting Slack message visible only to user: %w", err) | ||
} | ||
} else { | ||
if ts := b.getThreadOptionIfNeeded(event, file); ts != nil { | ||
options = append(options, ts) | ||
} | ||
|
||
if _, _, err := b.client.PostMessageContext(ctx, event.Channel, options...); err != nil { | ||
return fmt.Errorf("while posting Slack message: %w", err) | ||
} | ||
|
@@ -600,6 +600,24 @@ func (b *CloudSlack) send(ctx context.Context, event slackMessage, resp interact | |
return nil | ||
} | ||
|
||
func (b *CloudSlack) uploadFileToSlack(ctx context.Context, event slackMessage, resp interactive.CoreMessage) (*slack.File, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't we use the BTW it's in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this function is using new |
||
params := slack.FileUploadParameters{ | ||
Filename: "Response.txt", | ||
Title: "Response.txt", | ||
InitialComment: resp.Description, | ||
Content: interactive.MessageToPlaintext(resp, interactive.NewlineFormatter), | ||
Channels: []string{event.Channel}, | ||
ThreadTimestamp: event.GetTimestamp(), | ||
} | ||
|
||
file, err := b.client.UploadFileContext(ctx, params) | ||
if err != nil { | ||
return nil, fmt.Errorf("while uploading file: %w", err) | ||
} | ||
|
||
return file, nil | ||
} | ||
|
||
func (b *CloudSlack) findAndTrimBotMention(msg string) (string, bool) { | ||
if !b.botMentionRegex.MatchString(msg) { | ||
return "", false | ||
|
@@ -619,20 +637,17 @@ func (b *CloudSlack) BotName() string { | |
} | ||
|
||
func (b *CloudSlack) getThreadOptionIfNeeded(event slackMessage, file *slack.File) slack.MsgOption { | ||
//if the message is from thread then add an option to return the response to the thread | ||
if event.ThreadTimeStamp != "" { | ||
return slack.MsgOptionTS(event.ThreadTimeStamp) | ||
} | ||
|
||
if file == nil { | ||
return nil | ||
if file != nil { | ||
// If the message was already as a file attachment, reply it a given thread | ||
for _, share := range file.Shares.Public { | ||
if len(share) >= 1 && share[0].Ts != "" { | ||
return slack.MsgOptionTS(share[0].Ts) | ||
} | ||
} | ||
} | ||
|
||
// If the message was already as a file attachment, reply it a given thread | ||
for _, share := range file.Shares.Public { | ||
if len(share) >= 1 && share[0].Ts != "" { | ||
return slack.MsgOptionTS(share[0].Ts) | ||
} | ||
if ts := event.GetTimestamp(); ts != "" { | ||
return slack.MsgOptionTS(ts) | ||
} | ||
|
||
return nil | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -374,34 +374,46 @@ func TestCloudSlackE2E(t *testing.T) { | |
t.Log("Testing ping with --cluster-name") | ||
command := fmt.Sprintf("ping --cluster-name %s", deployment.Name) | ||
expectedMessage := fmt.Sprintf("`%s` on `%s`\n```\npong", command, deployment.Name) | ||
tester.PostMessageToBot(t, channel.ID(), command) | ||
tester.PostMessageToBot(t, channel.Identifier(), command) | ||
err = tester.WaitForLastMessageContains(tester.BotUserID(), channel.ID(), expectedMessage) | ||
require.NoError(t, err) | ||
|
||
t.Log("Testing ping for not connected deployment #2") | ||
command = "ping" | ||
expectedBlockMessage := notConnectedMessage(deployment2.Name, deployment2.ID) | ||
tester.PostMessageToBot(t, channel.ID(), fmt.Sprintf("%s --cluster-name %s", command, deployment2.Name)) | ||
tester.PostMessageToBot(t, channel.Identifier(), fmt.Sprintf("%s --cluster-name %s", command, deployment2.Name)) | ||
|
||
renderedMsg := interactive.RenderMessage(tester.MDFormatter(), expectedBlockMessage) | ||
renderedMsg = strings.Replace(renderedMsg, "\n", " ", -1) | ||
renderedMsg = strings.TrimSuffix(renderedMsg, " ") | ||
err = tester.WaitForLastInteractiveMessagePostedEqualWithCustomRender(tester.BotUserID(), channel.ID(), renderedMsg) | ||
if err != nil { // the new cloud backend not release yet | ||
t.Logf("Fallback to the old behavior with message sent at the channel level...") | ||
err = tester.OnChannel().WaitForLastInteractiveMessagePostedEqualWithCustomRender(tester.BotUserID(), channel.ID(), renderedMsg) | ||
} | ||
require.NoError(t, err) | ||
|
||
t.Log("Testing ping for not existing deployment") | ||
command = "ping" | ||
deployName := "non-existing-deployment" | ||
expectedMessage = fmt.Sprintf("*Instance not found* The cluster %q does not exist.", deployName) | ||
tester.PostMessageToBot(t, channel.ID(), fmt.Sprintf("%s --cluster-name %s", command, deployName)) | ||
tester.PostMessageToBot(t, channel.Identifier(), fmt.Sprintf("%s --cluster-name %s", command, deployName)) | ||
err = tester.WaitForLastMessageContains(tester.BotUserID(), channel.ID(), expectedMessage) | ||
if err != nil { // the new cloud backend not release yet | ||
t.Logf("Fallback to the old behavior with message sent at the channel level...") | ||
err = tester.OnChannel().WaitForLastMessageContains(tester.BotUserID(), channel.ID(), expectedMessage) | ||
} | ||
require.NoError(t, err) | ||
|
||
t.Log("Setting cluster as default") | ||
tester.PostMessageToBot(t, channel.ID(), fmt.Sprintf("cloud set default-instance %s", deployment.ID)) | ||
tester.PostMessageToBot(t, channel.Identifier(), fmt.Sprintf("cloud set default-instance %s", deployment.ID)) | ||
t.Log("Waiting for confirmation message...") | ||
expectedClusterDefaultMsg := fmt.Sprintf(":white_check_mark: Instance %s was successfully selected as the default cluster for this channel.", deployment.Name) | ||
err = tester.WaitForLastMessageEqual(tester.BotUserID(), channel.ID(), expectedClusterDefaultMsg) | ||
if err != nil { // the new cloud backend not release yet | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can remove the fallback later after release 🤔 Can you make a reminder for it? Thanks! |
||
t.Logf("Fallback to the old behavior with message sent at the channel level...") | ||
err = tester.OnChannel().WaitForLastMessageEqual(tester.BotUserID(), channel.ID(), expectedClusterDefaultMsg) | ||
} | ||
require.NoError(t, err) | ||
|
||
t.Log("Testing getting all deployments") | ||
|
@@ -411,7 +423,7 @@ func TestCloudSlackE2E(t *testing.T) { | |
strings.Contains(msg, "coredns") && | ||
strings.Contains(msg, "botkube"), 0, "" | ||
} | ||
tester.PostMessageToBot(t, channel.ID(), command) | ||
tester.PostMessageToBot(t, channel.Identifier(), command) | ||
err = tester.WaitForMessagePosted(tester.BotUserID(), channel.ID(), 1, assertionFn) | ||
require.NoError(t, err) | ||
}) | ||
|
@@ -458,22 +470,23 @@ func TestCloudSlackE2E(t *testing.T) { | |
} | ||
return result, 0, "" | ||
} | ||
err = tester.WaitForMessagePosted(tester.BotUserID(), channel.ID(), 1, assertionFn) | ||
err = tester.OnChannel().WaitForMessagePosted(tester.BotUserID(), channel.ID(), 1, assertionFn) | ||
require.NoError(t, err) | ||
}) | ||
|
||
t.Run("Botkube Deployment -> Cloud sync", func(t *testing.T) { | ||
t.Log("Disabling notification...") | ||
tester.PostMessageToBot(t, channel.ID(), "disable notifications") | ||
tester.PostMessageToBot(t, channel.Identifier(), "disable notifications") | ||
t.Log("Waiting for config reload message...") | ||
expectedReloadMsg := fmt.Sprintf(":arrows_counterclockwise: Configuration reload requested for cluster '%s'. Hold on a sec...", deployment.Name) | ||
err = tester.WaitForMessagePostedRecentlyEqual(tester.BotUserID(), channel.ID(), expectedReloadMsg) | ||
|
||
err = tester.OnChannel().WaitForMessagePostedRecentlyEqual(tester.BotUserID(), channel.ID(), expectedReloadMsg) | ||
require.NoError(t, err) | ||
|
||
t.Log("Waiting for watch begin message...") | ||
expectedWatchBeginMsg := fmt.Sprintf("My watch begins for cluster '%s'! :crossed_swords:", deployment.Name) | ||
recentMessages := 2 // take into the account the optional "upgrade checker message" | ||
err = tester.WaitForMessagePosted(tester.BotUserID(), channel.ID(), recentMessages, func(msg string) (bool, int, string) { | ||
err = tester.OnChannel().WaitForMessagePosted(tester.BotUserID(), channel.ID(), recentMessages, func(msg string) (bool, int, string) { | ||
if !strings.EqualFold(expectedWatchBeginMsg, msg) { | ||
count := diff.CountMatchBlock(expectedWatchBeginMsg, msg) | ||
msgDiff := diff.Diff(expectedWatchBeginMsg, msg) | ||
|
@@ -490,7 +503,7 @@ func TestCloudSlackE2E(t *testing.T) { | |
command := "status notifications" | ||
expectedBody := formatx.CodeBlock(fmt.Sprintf("Notifications from cluster '%s' are disabled here.", deployment.Name)) | ||
expectedMessage := fmt.Sprintf("%s\n%s", cmdHeader(command), expectedBody) | ||
tester.PostMessageToBot(t, channel.ID(), "status notifications") | ||
tester.PostMessageToBot(t, channel.Identifier(), "status notifications") | ||
err = tester.WaitForLastMessageEqual(tester.BotUserID(), channel.ID(), expectedMessage) | ||
require.NoError(t, err) | ||
}) | ||
|
@@ -502,13 +515,13 @@ func TestCloudSlackE2E(t *testing.T) { | |
|
||
t.Log("Waiting for config reload message...") | ||
expectedReloadMsg := fmt.Sprintf(":arrows_counterclockwise: Configuration reload requested for cluster '%s'. Hold on a sec...", deployment.Name) | ||
err = tester.WaitForMessagePostedRecentlyEqual(tester.BotUserID(), channel.ID(), expectedReloadMsg) | ||
err = tester.OnChannel().WaitForMessagePostedRecentlyEqual(tester.BotUserID(), channel.ID(), expectedReloadMsg) | ||
require.NoError(t, err) | ||
|
||
t.Log("Waiting for watch begin message...") | ||
expectedWatchBeginMsg := fmt.Sprintf("My watch begins for cluster '%s'! :crossed_swords:", deployment.Name) | ||
recentMessages := 2 // take into the account the optional "upgrade checker message" | ||
err = tester.WaitForMessagePosted(tester.BotUserID(), channel.ID(), recentMessages, func(msg string) (bool, int, string) { | ||
err = tester.OnChannel().WaitForMessagePosted(tester.BotUserID(), channel.ID(), recentMessages, func(msg string) (bool, int, string) { | ||
if !strings.EqualFold(expectedWatchBeginMsg, msg) { | ||
count := diff.CountMatchBlock(expectedWatchBeginMsg, msg) | ||
msgDiff := diff.Diff(expectedWatchBeginMsg, msg) | ||
|
@@ -517,13 +530,13 @@ func TestCloudSlackE2E(t *testing.T) { | |
return true, 0, "" | ||
}) | ||
require.NoError(t, err) | ||
tester.PostMessageToBot(t, channel.ID(), "list sources") | ||
tester.PostMessageToBot(t, channel.Identifier(), "list sources") | ||
|
||
t.Log("Waiting for empty source list...") | ||
expectedSourceListMsg := fmt.Sprintf("%s\n```\nSOURCE ENABLED RESTARTS STATUS LAST_RESTART\n```", cmdHeader("list sources")) | ||
err = tester.WaitForLastMessageEqual(tester.BotUserID(), channel.ID(), expectedSourceListMsg) | ||
require.NoError(t, err) | ||
tester.PostMessageToBot(t, channel.ID(), "list actions") | ||
tester.PostMessageToBot(t, channel.Identifier(), "list actions") | ||
t.Log("Waiting for actions list...") | ||
expectedActionsListMsg := fmt.Sprintf("%s\n```\nACTION ENABLED DISPLAY NAME\naction_xxx22 true Action Name\n```", cmdHeader("list actions")) | ||
err = tester.WaitForLastMessageEqual(tester.BotUserID(), channel.ID(), expectedActionsListMsg) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do in the next PR globally to all our actions to not trigger the CI once again on this PR 👍