require 'net/http' require 'json' require 'forwardable' load File.expand_path("../tasks/slack.rake", __FILE__) module Slackistrano class Capistrano extend Forwardable def_delegators :env, :fetch, :run_locally # # # def initialize(env) @env = env end # # # def run(action) should_run = fetch("slack_run".to_sym) should_run &&= fetch("slack_run_#{action}".to_sym) return unless should_run _self = self run_locally { _self.post(action, self) } end # # # def post(action, backend) team = fetch(:slack_team) token = fetch(:slack_token) webhook = fetch(:slack_webhook) via_slackbot = fetch(:slack_via_slackbot) channels = fetch(:slack_channel) channel_action = "slack_channel_#{action}".to_sym channels = fetch(channel_action) if fetch(channel_action) channels = Array(channels) if via_slackbot == false && channels.empty? channels = [nil] # default webhook channel end payload = { username: fetch(:slack_username), icon_url: fetch(:slack_icon_url), icon_emoji: fetch(:slack_icon_emoji), } payload[:attachments] = case action when :updated make_attachments(action, color: 'good') when :reverted make_attachments(action, color: '#4CBDEC') when :failed make_attachments(action, color: 'danger') else make_attachments(action) end channels.each do |channel| payload[:channel] = channel dry_run = if ::Capistrano::Configuration.respond_to?(:dry_run?) ::Capistrano::Configuration.dry_run? else ::Capistrano::Configuration.env.send(:config)[:sshkit_backend] == SSHKit::Backend::Printer end if dry_run backend.info("[slackistrano] Slackistrano Dry Run:") backend.info("[slackistrano] Team: #{team}") backend.info("[slackistrano] Webhook: #{webhook}") backend.info("[slackistrano] Via Slackbot: #{via_slackbot}") backend.info("[slackistrano] Payload: #{payload.to_json}") # Post to the channel. else begin response = post_to_slack(team: team, token: token, webhook: webhook, via_slackbot: via_slackbot, payload: payload) rescue => e backend.warn("[slackistrano] Error notifying Slack!") backend.warn("[slackistrano] Error: #{e.inspect}") end if response.code !~ /^2/ warn("[slackistrano] Slack API Failure!") warn("[slackistrano] URI: #{response.uri}") warn("[slackistrano] Code: #{response.code}") warn("[slackistrano] Message: #{response.message}") warn("[slackistrano] Body: #{response.body}") if response.message != response.body && response.body !~ / payload.to_json} if webhook.nil? webhook = "https://#{team}.slack.com/services/hooks/incoming-webhook" params.merge!('token' => token) end uri = URI(webhook) Net::HTTP.post_form(uri, params) end private :post_as_webhook end end