Skip to content

Instantly share code, notes, and snippets.

@marten
Created November 13, 2014 10:26
Show Gist options
  • Save marten/f1048a6d98b52808d870 to your computer and use it in GitHub Desktop.
Save marten/f1048a6d98b52808d870 to your computer and use it in GitHub Desktop.
Capistrano Flowdock integration
set :format, :capture
# rest of your deploy.rb goes here
after 'deploy:started', 'notify:flowdock:started' do
$flowdock_deploy_thread = Deployer::Flowdock::Deployment.new(application: fetch(:application),
environment: fetch(:rails_env) || fetch(:rack_env),
repo_name: fetch(:repo_url).gsub(/\Agit@github.com:(.*).git/, "\\1"),
previous_ref: fetch(:previous_revision),
logs: env.backend.config.output.buffer
)
$flowdock_deploy_thread.start
end
after 'deploy:set_current_revision', 'notifiy:flowdock:set_revision' do
$flowdock_deploy_thread.deploying_ref = fetch(:current_revision)
end
after 'database:backup', 'notifiy:flowdock:backups' do
$flowdock_deploy_thread.update('Database backups made')
end if Rake.application.lookup('database:backup')
after 'deploy:updated', 'notify:flowdock:updated' do
$flowdock_deploy_thread.update('Code updated')
end
after 'deploy:migrate', 'notify:flowdock:migrated' do
$flowdock_deploy_thread.update('Migrations run')
end
after 'deploy:assets:precompile', 'notify:flowdock:assets' do
$flowdock_deploy_thread.update('Assets fetched')
end
after 'deploy:published', 'notify:flowdock:published' do
$flowdock_deploy_thread.update('Restarting app')
end
after 'deploy:finished', 'notify:flowdock:finished' do
$flowdock_deploy_thread.finish
end
require 'flowdock'
require 'faraday'
require 'faraday_middleware'
module Deployer
module Flowdock
class Deployment
attr_accessor :flow_token, :application, :environment, :repo_name, :deploying_ref, :previous_ref, :logs
def initialize(application:, environment:, repo_name:, deploying_ref: nil, previous_ref: nil, logs:)
@flow_token = ENV["FLOWDOCK_FLOW_TOKEN"]
@application = application
@environment = environment
@repo_name = repo_name
@deploying_ref = deploying_ref
@previous_ref = previous_ref
@logs = logs
@status = nil
@deployment_id = Time.now.to_i
end
def start
@status = :starting
post("Starting deployment")
end
def update(message)
@status = :underway
post(message)
end
def finish
@status = :finished
post("Finished")
end
private
def post(message)
thread_client.post '/messages', {
flow_token: flow_token,
event: 'activity',
title: message,
external_thread_id: flowdock_thread_id,
thread: thread_data,
author: activity_author,
tags: tags
}
end
def thread_data
{
title: "Deployment of #{application} to #{environment}",
body: "<pre><code>" + logs.string.gsub("\n", "<br>") + "</code></pre>",
status: thread_status,
fields: thread_fields
}
end
def thread_status
case @status
when :starting
{value: 'Starting', color: 'yellow'}
when :underway
{value: 'Busy', color: 'yellow'}
when :finished
{value: 'Done', color: 'green'}
when :failed
{value: 'Failed', color: 'red'}
else
{value: 'Unknown', color: 'purple'}
end
end
def thread_fields
fields = []
fields << {label: 'Application', value: application}
fields << {label: 'Environment', value: environment}
if deploying_ref
repo_link = "<a href='#{github_url('/tree/' + deploying_ref)}'>#{application}</a>"
commit_link = "<a href='#{github_url('/commit/' + deploying_ref)}'>#{deploying_ref}</a>"
fields << {label: 'Deployed ref', value: "#{repo_link} @ #{commit_link}"}
end
if deploying_ref and previous_ref
repo_link = "<a href='#{github_url("/tree/#{previous_ref}")}'>#{previous_ref}</a>"
diff_link = "<a href='#{github_url("/compare/#{deploying_ref}...#{previous_ref}")}'>diff</a>"
fields << {label: 'Previous ref', value: "#{repo_link} | (#{diff_link})"}
end
fields << {label: 'Initiated from', value: `hostname`.strip}
fields << {label: 'Initiated by', value: `whoami`.strip}
fields
end
def github_url(path)
"https://github.com/#{repo_name}/#{path}"
end
def activity_author
{
name: "Capistrano",
avatar: "https://d2ph5hv9wbwvla.cloudfront.net/heaven/build_ok.png",
email: "build@flowdock.com"
}
end
def tags
["deploy", application, environment].compact
end
def flowdock_thread_id
"deployer:#{application}:#{environment}:#{deployment_number}"
end
def deployment_number
@deployment_id
end
def thread_client
@thread_client ||= Faraday.new(::Flowdock::FLOWDOCK_API_URL) do |connection|
connection.request :json
connection.response :json, :content_type => /\bjson$/
connection.use Faraday::Response::RaiseError
connection.adapter Faraday.default_adapter
end
end
end
end
end
require 'sshkit'
module SSHKit
module Formatter
class Capture < Abstract
def buffer
@buffer ||= StringIO.new
end
def write(obj)
output = StringIO.new
simple_formatter = SSHKit::Formatter::SimpleText.new(output)
simple_formatter.write(obj)
buffer << output.string
pretty_formatter = SSHKit::Formatter::Pretty.new(original_output)
pretty_formatter.write(obj)
end
alias :<< :write
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment