Instantly share code, notes, and snippets.

Embed
What would you like to do?
Code for the blog article about Reporting console commands in Rails
is_staging_or_prod = Rails.env.production? || Rails.env.staging?
dyno_in_run_mode = ENV.fetch('DYNO', 'nope').starts_with?('run')
dev_name = ENV.fetch('DEV_NAME', '')
if is_staging_or_prod && dyno_in_run_mode
raise Drivy::Errors::DevNameNotSetError if dev_name.blank?
# Override how printing to sdtout works by sending
# the output of stdout to a Slack webhook also.
# When writing commands in irb, irb prints to stdout
class << STDOUT
include Drivy::Console::ReportCommand
alias :usual_write :write
def write(string)
usual_write(string)
send_command_to_slack(dev_name, string)
end
end
end
module Drivy::Console::ReportCommand
def send_command_to_slack(developer_name, command_output)
return unless has_command? && has_output?(command_output)
# Documentation is at https://api.slack.com/docs/message-attachments
fields = [
{
title: "Command",
value: wrap_command(read_command),
short: true,
},
{
title: "Output",
value: wrap_command(parse_output(command_output)),
short: false,
},
{
title: "Developer",
value: developer_name,
short: true,
}
]
env_color, env_title = env_params
params = {
attachments: [
{
fields: fields,
color: env_color,
footer: "Console #{env_title} spy",
footer_icon: "https://drivy-prod-static.s3.amazonaws.com/slack/spy-small.png",
ts: Time.zone.now.to_i,
mrkdwn_in: ["fields"],
}
]
}
response = slack_client.post('', params)
raise "Failed to notify Slack of console command, status: #{response.status}" unless response.success?
end
private
def env_params
if Rails.env.production?
return ["#e74c3c", "production"] # red
elsif Rails.env.staging?
return ["#f1c40f", "staging"] # orange
else
return ["#2ecc71", "development"] # yellow
end
end
def wrap_command(value)
"```#{value}```"
end
def parse_output(command_output)
command_output.gsub('=>', '').strip
end
def has_command?
Readline::HISTORY.length >= 1
end
def has_output?(command_output)
return false unless command_output.instance_of? String
command_output.strip.start_with? "=>"
end
def read_command
Readline::HISTORY[Readline::HISTORY.length-1]
end
def slack_client
endpoint = ENV.fetch('SLACK_WEBHOOK_CONSOLE', '')
raise "SLACK_WEBHOOK_CONSOLE is not defined" if endpoint.blank?
Faraday.new(url: endpoint) do |c|
c.request :json
c.adapter Faraday.default_adapter
end
end
end
@rahul

This comment has been minimized.

rahul commented May 20, 2018

Hey, thank you for this creative way of reporting commands in Rails to slack.

I'm facing an issue that's preventing me from deploying this.

Heroku's build process seems to kick off a one-off dyno' in order to deploy the application, which satisfies the dyno_in_run_mode` check in the code.

But at the time of deployment, ENV['DEV_NAME'] isn't expected to be set. We're expecting the dev pass along a temporary environment variable whenever they start the rails console (eg: heroku run EXEC_USER_NAME=rahul rails console).

So, due to the missing DEV_NAME, the deployment fails because dyno_in_run_mode is true during deployment.

Is this an issue that you've come across?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment