From 410e923a16f21bbc94cda45f1f5b3002226a1c90 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Wed, 8 Sep 2021 16:41:33 -0700 Subject: [PATCH 01/10] Add function for making a POST to Slack, providing the CDO slack_token in the Auth header. --- lib/cdo/slack.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/cdo/slack.rb b/lib/cdo/slack.rb index bb53f2408ea34..0267d21d7e270 100644 --- a/lib/cdo/slack.rb +++ b/lib/cdo/slack.rb @@ -1,6 +1,7 @@ +require 'uri' require 'net/http' -require 'open-uri' require 'retryable' +require 'json' class Slack COLOR_MAP = { @@ -226,4 +227,20 @@ def self.join_room(name) gsub(/<\/a>/, '>'). gsub(//, "\n") end + + private_class_method def self.post_to_slack(url, payload = nil) + headers = { + "Content-type" => "application/json; charset=utf-8", + "Authorization" => "Bearer #{SLACK_TOKEN}" + } + + uri = URI(url) + https = Net::HTTP.new(uri.host, uri.port) + https.use_ssl = true + req = Net::HTTP::Post.new(url, headers) + req.body = payload.to_json if payload + + res = https.request(req) + JSON.parse(res.body) + end end From 2fcf8591dc035f79ff3b332d2bc4ca9085ae1d1f Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Wed, 8 Sep 2021 16:48:44 -0700 Subject: [PATCH 02/10] Fix most functions to use post_to_slack --- lib/cdo/slack.rb | 94 ++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/lib/cdo/slack.rb b/lib/cdo/slack.rb index 0267d21d7e270..43fa2ddddb3d5 100644 --- a/lib/cdo/slack.rb +++ b/lib/cdo/slack.rb @@ -18,6 +18,18 @@ class Slack 'production' => 'infra-production' }.freeze + # Common channel name to ID mappings + CHANNEL_IDS = { + 'developers' => 'C0T0PNTM3', + 'deploy-status' => 'C7GS8NE8L', + 'infra-staging' => 'C03CK8E51', + 'infra-test' => 'C03CM903Y', + 'infra-production' => 'C03CK8FGX', + 'infra-honeybadger' => 'C55JZ1BPZ', + 'levelbuilder' => 'C0T10H2HY', + 'server-operations' => 'C0CCSS3PX' + }.freeze + SLACK_TOKEN = CDO.slack_token.freeze # Returns the user (mention) name of the user. @@ -26,9 +38,7 @@ class Slack # @raise [ArgumentError] If the email does not correspond to a Slack user. # @return [nil | String] The user (mention) name for the Slack user. def self.user_name(email) - users_list = open("https://slack.com/api/users.list?token=#{SLACK_TOKEN}"). - read - members = JSON.parse(users_list)['members'] + members = post_to_slack("https://slack.com/api/users.list")['members'] user = members.find {|member| email == member['profile']['email']} raise "Slack email #{email} not found" unless user user['name'] @@ -44,25 +54,10 @@ def self.get_topic(channel_name, use_channel_map = false) channel_id = get_channel_id(channel_name) return nil unless channel_id - response = Retryable.retryable(on: [Errno::ETIMEDOUT, OpenURI::HTTPError], tries: 2) do - open( - 'https://slack.com/api/conversations.info'\ - "?token=#{SLACK_TOKEN}"\ - "&channel=#{channel_id}"\ - ) - end + response = post_to_slack("https://slack.com/api/conversations.info?channel=#{channel_id}") - begin - parsed_response = JSON.parse(response.read) - rescue JSON::ParserError - return nil - end - - unless parsed_response['ok'] - return nil - end - - replace_user_links(parsed_response['channel']['topic']['value']) + return nil unless response['ok'] + replace_user_links(response['channel']['topic']['value']) end # @param channel_name [String] The channel to update the topic. @@ -78,12 +73,10 @@ def self.update_topic(channel_name, new_topic, use_channel_map = false) channel_id = get_channel_id(channel_name) return false unless channel_id - response = open('https://slack.com/api/conversations.setTopic'\ - "?token=#{SLACK_TOKEN}"\ - "&channel=#{channel_id}"\ - "&topic=#{new_topic}" - ) - result = JSON.parse(response.read) + url = "https://slack.com/api/conversations.setTopic" + payload = {"channel" => channel_id, "topic" => new_topic} + result = post_to_slack(url, payload) + raise "Failed to update_topic, with error: #{result['error']}" if result['error'] result['ok'] end @@ -92,16 +85,14 @@ def self.replace_user_links(message) message.gsub(/<@(.*?)>/) {'@' + get_display_name($1)} end + # @param user_id [String] The user whose name you are looking for. + # @return [String] Slack 'display_name' if one is set, otherwise Slack 'real_name'. + # Returns provided user_id if not found. def self.get_display_name(user_id) - response = open( - 'https://slack.com/api/users.info'\ - "?token=#{SLACK_TOKEN}"\ - "&user=#{user_id}"\ - ).read - return user_id unless response - parsed_response = JSON.parse(response) - return user_id unless parsed_response['ok'] - parsed_response['user']['profile']['display_name'] + response = post_to_slack("https://slack.com/api/users.info?user=#{user_id}") + return user_id unless response['ok'] + return response['user']['profile']['display_name'] unless response['user']['profile']['display_name'] == "" + response['user']['real_name'] end # For more information about the Slack API, see @@ -114,6 +105,7 @@ def self.get_display_name(user_id) # color (optional): The color the post should be. # @return [Boolean] Whether the text was posted to Slack successfully. # WARNING: This function mutates params. + # NOTE: This function utilizes an incoming webhook, not the Slack token def self.message(text, params={}) return false unless CDO.slack_endpoint params[:channel] = "\##{Slack::CHANNEL_MAP[params[:channel]] || params[:channel]}" @@ -169,24 +161,19 @@ def self.command(channel_name, command, message="") result['ok'] end + # @param room [String] Channel name or id to post the snippet. + # @param text [String] Snippet text. def self.snippet(room, text) # omit leading '#' when passing channel names to this API channel = CHANNEL_MAP[room] || room - open('https://slack.com/api/files.upload'\ - "?token=#{SLACK_TOKEN}"\ - "&content=#{URI.escape(text)}"\ - "&channels=#{channel}" - ) + result = post_to_slack("https://slack.com/api/files.upload?channels=#{channel}&content=#{URI.escape(text)}") + result['ok'] end + # @param name [String] Name of the Slack channel to join. def self.join_room(name) - response = open( - 'https://slack.com/api/conversations.join'\ - "?token=#{SLACK_TOKEN}"\ - "&channel=#{get_channel_id(name)}" - ) + result = post_to_slack("https://slack.com/api/conversations.join", {"channel" => get_channel_id(name)}) - result = JSON.parse(response.read) raise "Failed to join_room, with error: #{result['error']}" if result['error'] result['ok'] end @@ -196,16 +183,13 @@ def self.join_room(name) # @return [nil | String] The Slack channel ID for the channel, nil if not # found. private_class_method def self.get_channel_id(channel_name) + return CHANNEL_IDS[channel_name] if CHANNEL_IDS[channel_name] + raise "CDO.slack_token undefined" if SLACK_TOKEN.nil? # Documentation at https://api.slack.com/methods/channels.list. - slack_api_url = "https://slack.com/api/conversations.list"\ - "?token=#{SLACK_TOKEN}&limit=1000&types=public_channel&exclude_archived=true" - channels = open(slack_api_url).read - begin - parsed_channels = JSON.parse(channels) - rescue JSON::ParserError - return nil - end + url = "https://slack.com/api/conversations.list?limit=1000&types=public_channel&exclude_archived=true" + parsed_channels = post_to_slack(url) + return nil unless parsed_channels['channels'] parsed_channels['channels'].each do |parsed_channel| return parsed_channel['id'] if parsed_channel['name'] == channel_name From ed8749b3999a3e20641635d1f1306006f1668a11 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Wed, 8 Sep 2021 16:53:51 -0700 Subject: [PATCH 03/10] Stop using the old chat.command API (which we were only using to schedule a reminder for the DOTD to check Zendesk in 2 hours) and utilize chat.shceduleMessage instead. --- aws/ci_build | 8 +++----- lib/cdo/chat_client.rb | 8 -------- lib/cdo/slack.rb | 32 ++++++++++++++------------------ 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/aws/ci_build b/aws/ci_build index 466f758acab55..f24d53a8de721 100755 --- a/aws/ci_build +++ b/aws/ci_build @@ -162,11 +162,9 @@ def main ChatClient.message 'server operations', commit_url, color: 'gray', message_format: 'text' DevelopersTopic.set_dtp 'yes' InfraProductionTopic.set_dtp_commit GitHub.sha('production') - ChatClient.set_reminder( - 'developers', - "@#{DevelopersTopic.dotd}", - "to check Zendesk in 2 hours" - ) + + # Schedule a reminder for the dotd to check Zendesk in 2 hours + Slack.remind(Slack.user_id(DevelopersTopic.dotd), Time.now.to_i + 7200, 'check Zendesk') # Check hoc_mode and hoc_launch only on successful DTPs, so that we get about 1 reminder per # day to bring staging, test and production to the same hoc_mode and hoc_launch after a diff --git a/lib/cdo/chat_client.rb b/lib/cdo/chat_client.rb index e91aa2710b792..d2a01eca9bad6 100644 --- a/lib/cdo/chat_client.rb +++ b/lib/cdo/chat_client.rb @@ -44,14 +44,6 @@ def self.message(room, message, options={}) ) end - # @param room [String] Name of the Slack channel to post /remind to. - # @param recipient [String] Slack user to remind, include @ in the argument - # @param reminder [String] Message for the /remind commmand - def self.set_reminder(room, recipient, reminder) - message = recipient + " " + reminder - Slack.command(room, "remind", message) - end - def self.snippet(message) Slack.snippet(CDO.slack_log_room, message) end diff --git a/lib/cdo/slack.rb b/lib/cdo/slack.rb index 43fa2ddddb3d5..fb93b6431bb5d 100644 --- a/lib/cdo/slack.rb +++ b/lib/cdo/slack.rb @@ -44,6 +44,13 @@ def self.user_name(email) user['name'] end + def self.user_id(name) + members = post_to_slack("https://slack.com/api/users.list")['members'] + user = members.find {|member| name == member['name']} + raise "Slack user #{name} not found" unless user + user['id'] + end + # @param channel_name [String] The channel to fetch the topic. # @return [String | nil] The existing topic, nil if not found. def self.get_topic(channel_name, use_channel_map = false) @@ -141,24 +148,13 @@ def self.message(text, params={}) end end - # For more information see - # https://github.com/ErikKalkoken/slackApiDoc/blob/master/chat.command.md. NOTE This API is 'undocumented' and not part of the official Slack APIs. - # @param channel_name [String] Name of the Slack channel to post the command to. - # @param command [String] Command to execute, excluding the /. - # @param message [String] Optional text passed to the command. - # @return [Boolean] Whether the command was posted to Slack successfully. - def self.command(channel_name, command, message="") - channel_id = get_channel_id(channel_name) - response = open( - "https://slack.com/api/chat.command?channel=#{channel_id}"\ - "&command=/#{command}"\ - "&text=#{message}"\ - "&token=#{SLACK_TOKEN}" - ) - - result = JSON.parse(response.read) - raise "Failed to post command with: #{result['error']}" if result['error'] - result['ok'] + # Bot tokens are unable to post to reminders.add or chat.command, so we will mimic the functionality of a slack reminder + # by scheduling a DM to the user at a specific time. + # @param recipient_id [String] Slack ID of user to message. + # @param time [String] Unix timestamp of the time the message should be sent. + # @param message [String] Text to be sent in the scheduled message. + def self.remind(recipient_id, time, message) + post_to_slack("https://slack.com/api/chat.scheduleMessage", {"channel" => recipient_id, "post_at" => time, "text" => message}) end # @param room [String] Channel name or id to post the snippet. From 1a9a60b1bdd218f7ad318b6579a61e7853950310 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Wed, 8 Sep 2021 17:25:27 -0700 Subject: [PATCH 04/10] Now that we are using a shared token instead of personal tokens, we don't need to try to add the user to these channels anymore --- bin/dotd | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/bin/dotd b/bin/dotd index 123a27aa0d114..d88e962ee33fa 100755 --- a/bin/dotd +++ b/bin/dotd @@ -476,16 +476,6 @@ end def main check_for_cdo_keys - # auto-join Slack rooms where the DOTD might be @mentioned - # or need to affect the room topic. - Slack.join_room('developers') - Slack.join_room('deploy-status') - Slack.join_room('infra-staging') - Slack.join_room('infra-test') - Slack.join_room('infra-production') - Slack.join_room('infra-honeybadger') - Slack.join_room('levelbuilder') - dotd_name = ENV['CDODEV_DOTD_NAME'] || ENV['USER'] @logger.info("#{Time.new.strftime('%A, %B %d %Y')}: #{dotd_name} is DOTD") From e036430f8ed0b59dd3089074e185d24c180d5f27 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Wed, 8 Sep 2021 17:36:44 -0700 Subject: [PATCH 05/10] Update DOTD script instructions to specify where to find the new slack_token --- bin/dotd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/dotd b/bin/dotd index d88e962ee33fa..da4d567502c0c 100755 --- a/bin/dotd +++ b/bin/dotd @@ -38,9 +38,10 @@ def check_for_cdo_keys Create your API tokens from these pages: https://github.com/settings/tokens ('public_repo' permission) - https://api.slack.com/custom-integrations/legacy-tokens https://app.honeybadger.io/users/edit#authentication + The slack_token can be found in the Shared-Engineering folder in LastPass, under DOTD Slack Token. + Please add them to your locals.yml and rerun the script. CDO.devinternal_db_writer should be pulled automatically from AWS Secrets Manager. From 7ffb0ca23c6a5e8f07a7edb93fb9b6c16a9458d8 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Tue, 28 Sep 2021 16:38:34 -0700 Subject: [PATCH 06/10] Change 'check zendesk' reminder to include a link to the list of unassigned tickets --- aws/ci_build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/ci_build b/aws/ci_build index f24d53a8de721..c1bd1fc224168 100755 --- a/aws/ci_build +++ b/aws/ci_build @@ -164,7 +164,7 @@ def main InfraProductionTopic.set_dtp_commit GitHub.sha('production') # Schedule a reminder for the dotd to check Zendesk in 2 hours - Slack.remind(Slack.user_id(DevelopersTopic.dotd), Time.now.to_i + 7200, 'check Zendesk') + Slack.remind(Slack.user_id(DevelopersTopic.dotd), Time.now.to_i + 7200, 'check ') # Check hoc_mode and hoc_launch only on successful DTPs, so that we get about 1 reminder per # day to bring staging, test and production to the same hoc_mode and hoc_launch after a From c213cf0a6f56456ce5e9acf55a01f178ae468837 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Thu, 7 Oct 2021 16:05:44 -0700 Subject: [PATCH 07/10] Add slack_bot_token as a new secret in locals.yml, separate from the legacy slack_token. The Slack integration will prefer the slack_bot_token if available, but can fall back to the slack_token and send a warning to Honeybadger that a legacy token is still being used somewhere. Also add Honeybadger logging if the calls to Slack fail for any reason. --- config.yml.erb | 1 + lib/cdo/slack.rb | 80 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/config.yml.erb b/config.yml.erb index dbd5d19dcee9d..ae8a42b4e3de8 100644 --- a/config.yml.erb +++ b/config.yml.erb @@ -197,6 +197,7 @@ slack_set_last_dtt_green_token: slack_start_build_token: slack_endpoint: !Secret slack_token: !Secret +slack_bot_token: !Secret slack_log_room: <%=env%> hip_chat_logging: false # Logging endpoint used by broken link checker. diff --git a/lib/cdo/slack.rb b/lib/cdo/slack.rb index fb93b6431bb5d..4dcb4f73716b6 100644 --- a/lib/cdo/slack.rb +++ b/lib/cdo/slack.rb @@ -2,6 +2,7 @@ require 'net/http' require 'retryable' require 'json' +require 'cdo/honeybadger' class Slack COLOR_MAP = { @@ -30,7 +31,8 @@ class Slack 'server-operations' => 'C0CCSS3PX' }.freeze - SLACK_TOKEN = CDO.slack_token.freeze + SLACK_TOKEN = CDO.methods.include?(:slack_token) ? CDO.slack_token.freeze : nil + SLACK_BOT_TOKEN = CDO.methods.include?(:slack_bot_token) ? CDO.slack_bot_token.freeze : nil # Returns the user (mention) name of the user. # WARNING: Does not include the mention character '@'. @@ -39,6 +41,7 @@ class Slack # @return [nil | String] The user (mention) name for the Slack user. def self.user_name(email) members = post_to_slack("https://slack.com/api/users.list")['members'] + raise "Failed to query users.list" unless members user = members.find {|member| email == member['profile']['email']} raise "Slack email #{email} not found" unless user user['name'] @@ -46,6 +49,7 @@ def self.user_name(email) def self.user_id(name) members = post_to_slack("https://slack.com/api/users.list")['members'] + raise "Failed to query users.list" unless members user = members.find {|member| name == member['name']} raise "Slack user #{name} not found" unless user user['id'] @@ -62,8 +66,7 @@ def self.get_topic(channel_name, use_channel_map = false) return nil unless channel_id response = post_to_slack("https://slack.com/api/conversations.info?channel=#{channel_id}") - - return nil unless response['ok'] + return nil unless response replace_user_links(response['channel']['topic']['value']) end @@ -84,8 +87,8 @@ def self.update_topic(channel_name, new_topic, use_channel_map = false) payload = {"channel" => channel_id, "topic" => new_topic} result = post_to_slack(url, payload) - raise "Failed to update_topic, with error: #{result['error']}" if result['error'] - result['ok'] + raise "Failed to update topic in #{channel_name}" unless result + return true end def self.replace_user_links(message) @@ -93,13 +96,15 @@ def self.replace_user_links(message) end # @param user_id [String] The user whose name you are looking for. - # @return [String] Slack 'display_name' if one is set, otherwise Slack 'real_name'. + # @return [String] Slack 'display_name' if one is set, otherwise Slack 'name'. # Returns provided user_id if not found. def self.get_display_name(user_id) response = post_to_slack("https://slack.com/api/users.info?user=#{user_id}") - return user_id unless response['ok'] - return response['user']['profile']['display_name'] unless response['user']['profile']['display_name'] == "" - response['user']['real_name'] + + return user_id unless response + profile = response['user']['profile'] + return profile['display_name'] unless profile['display_name'] == "" + response['user']['name'] end # For more information about the Slack API, see @@ -154,7 +159,8 @@ def self.message(text, params={}) # @param time [String] Unix timestamp of the time the message should be sent. # @param message [String] Text to be sent in the scheduled message. def self.remind(recipient_id, time, message) - post_to_slack("https://slack.com/api/chat.scheduleMessage", {"channel" => recipient_id, "post_at" => time, "text" => message}) + result = post_to_slack("https://slack.com/api/chat.scheduleMessage", {"channel" => recipient_id, "post_at" => time, "text" => message}) + return !!result end # @param room [String] Channel name or id to post the snippet. @@ -163,15 +169,15 @@ def self.snippet(room, text) # omit leading '#' when passing channel names to this API channel = CHANNEL_MAP[room] || room result = post_to_slack("https://slack.com/api/files.upload?channels=#{channel}&content=#{URI.escape(text)}") - result['ok'] + return !!result end # @param name [String] Name of the Slack channel to join. def self.join_room(name) - result = post_to_slack("https://slack.com/api/conversations.join", {"channel" => get_channel_id(name)}) - - raise "Failed to join_room, with error: #{result['error']}" if result['error'] - result['ok'] + channel = get_channel_id(name) + return false unless channel + result = post_to_slack("https://slack.com/api/conversations.join", {"channel" => channel}) + return !!result end # Returns the channel ID for the channel with the requested channel_name. @@ -185,8 +191,8 @@ def self.join_room(name) # Documentation at https://api.slack.com/methods/channels.list. url = "https://slack.com/api/conversations.list?limit=1000&types=public_channel&exclude_archived=true" parsed_channels = post_to_slack(url) + return nil unless parsed_channels && parsed_channels['channels'] - return nil unless parsed_channels['channels'] parsed_channels['channels'].each do |parsed_channel| return parsed_channel['id'] if parsed_channel['name'] == channel_name end @@ -209,9 +215,23 @@ def self.join_room(name) end private_class_method def self.post_to_slack(url, payload = nil) + if SLACK_BOT_TOKEN && SLACK_BOT_TOKEN != '' + token = SLACK_BOT_TOKEN + else + # TODO: Remove after deprecating legacy SLACK_TOKEN + opts = { + error_class: "Slack integration [warn]", + error_message: "Using legacy token", + context: {url: url, payload: payload} + } + Honeybadger.notify_cronjob_error opts + + token = SLACK_TOKEN + end + headers = { "Content-type" => "application/json; charset=utf-8", - "Authorization" => "Bearer #{SLACK_TOKEN}" + "Authorization" => "Bearer #{token}" } uri = URI(url) @@ -220,7 +240,29 @@ def self.join_room(name) req = Net::HTTP::Post.new(url, headers) req.body = payload.to_json if payload - res = https.request(req) - JSON.parse(res.body) + begin + res = https.request(req) + parsed_res = JSON.parse(res.body) + response = parsed_res + + unless response['ok'] + opts = { + error_class: "Slack integration [error]", + error_message: parsed_res['error'], + context: {url: url, payload: payload, response: parsed_res} + } + Honeybadger.notify_cronjob_error opts + response = false + end + rescue Exception => error + opts = { + error_class: "Slack integration [error]", + error_message: error, + context: {url: url, payload: payload} + } + Honeybadger.notify_cronjob_error opts + response = false + end + response end end From aa18c4705207cf9a2d0de69a8fbb2d77aabea9a2 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Thu, 7 Oct 2021 16:07:26 -0700 Subject: [PATCH 08/10] Slightly change wording in the scheduled Zendesk reminder after a deploy. Change Zendesk link to point to the 'All Open Tickets' filter. --- aws/ci_build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/ci_build b/aws/ci_build index c1bd1fc224168..8cb1e7d50aac1 100755 --- a/aws/ci_build +++ b/aws/ci_build @@ -164,7 +164,7 @@ def main InfraProductionTopic.set_dtp_commit GitHub.sha('production') # Schedule a reminder for the dotd to check Zendesk in 2 hours - Slack.remind(Slack.user_id(DevelopersTopic.dotd), Time.now.to_i + 7200, 'check ') + Slack.remind(Slack.user_id(DevelopersTopic.dotd), Time.now.to_i + 7200, 'Reminder: check ') # Check hoc_mode and hoc_launch only on successful DTPs, so that we get about 1 reminder per # day to bring staging, test and production to the same hoc_mode and hoc_launch after a From 79a7f0270e8a6556130b470dfa108c6f3ecbc70c Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Fri, 8 Oct 2021 10:19:33 -0700 Subject: [PATCH 09/10] Update dotd setup instructions with new slack_bot_token name --- bin/dotd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/dotd b/bin/dotd index da4d567502c0c..082c7df9abec6 100755 --- a/bin/dotd +++ b/bin/dotd @@ -33,14 +33,14 @@ def check_for_cdo_keys puts <<-EOS.unindent - This script requires CDO.github_access_token, CDO.slack_token, and CDO.honeybadger_api_token and CDO.devinternal_db_writer. + This script requires CDO.github_access_token, CDO.slack_bot_token, and CDO.honeybadger_api_token and CDO.devinternal_db_writer. Create your API tokens from these pages: https://github.com/settings/tokens ('public_repo' permission) https://app.honeybadger.io/users/edit#authentication - The slack_token can be found in the Shared-Engineering folder in LastPass, under DOTD Slack Token. + The slack_bot_token can be found in the Shared-Engineering folder in LastPass, under DOTD Slack Bot Token. Please add them to your locals.yml and rerun the script. CDO.devinternal_db_writer should be pulled automatically from AWS Secrets Manager. From 179d87d990755c0ec7732067185b418acdd60744 Mon Sep 17 00:00:00 2001 From: Katie Shipley Date: Mon, 11 Oct 2021 17:33:04 -0700 Subject: [PATCH 10/10] Fix slack tests to work with new post_to_slack method --- lib/cdo/slack.rb | 4 +--- lib/test/cdo/test_slack.rb | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/cdo/slack.rb b/lib/cdo/slack.rb index 4dcb4f73716b6..40ebf162a5636 100644 --- a/lib/cdo/slack.rb +++ b/lib/cdo/slack.rb @@ -86,9 +86,7 @@ def self.update_topic(channel_name, new_topic, use_channel_map = false) url = "https://slack.com/api/conversations.setTopic" payload = {"channel" => channel_id, "topic" => new_topic} result = post_to_slack(url, payload) - - raise "Failed to update topic in #{channel_name}" unless result - return true + return !!result end def self.replace_user_links(message) diff --git a/lib/test/cdo/test_slack.rb b/lib/test/cdo/test_slack.rb index 67a03c7ce6d7b..732de88b16804 100644 --- a/lib/test/cdo/test_slack.rb +++ b/lib/test/cdo/test_slack.rb @@ -14,39 +14,37 @@ def setup end def test_get_topic - Slack.expects(:open).returns( - stub( - read: { - 'ok' => true, - 'channel' => { - 'topic' => { - 'value' => FAKE_TOPIC - } + Slack.expects(:post_to_slack).returns( + { + 'ok' => true, + 'channel' => { + 'topic' => { + 'value' => FAKE_TOPIC } - }.to_json - ) + } + } ) actual_topic = Slack.get_topic FAKE_CHANNEL assert_equal FAKE_TOPIC, actual_topic end def test_get_topic_with_error_response - Slack.expects(:open).returns(stub(read: {'ok' => false}.to_json)) + Slack.stubs(:post_to_slack).returns(false) assert_nil Slack.get_topic FAKE_CHANNEL end def test_update_topic - Slack.expects(:open).returns(stub(read: {'ok' => true}.to_json)) + Slack.stubs(:post_to_slack).returns({'ok' => true}) assert Slack.update_topic(FAKE_CHANNEL, FAKE_TOPIC) end def test_join_room - Slack.expects(:open).returns(stub(read: {'ok' => true}.to_json)) + Slack.stubs(:post_to_slack).returns({'ok' => true}) assert Slack.join_room(FAKE_CHANNEL) end def test_update_topic_with_error_response - Slack.expects(:open).returns(stub(read: {'ok' => false}.to_json)) + Slack.stubs(:post_to_slack).returns(false) refute Slack.update_topic(FAKE_CHANNEL, FAKE_TOPIC) end