Skip to content

Instantly share code, notes, and snippets.

@mattgibson
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mattgibson/c9fbe8d4b29d98c4a0ca to your computer and use it in GitHub Desktop.
Save mattgibson/c9fbe8d4b29d98c4a0ca to your computer and use it in GitHub Desktop.
Post deploy hook to push a Rails app from Solano Labs (Tddium) to AWS OpsWorks if the CI build is successful
# To set up:
#
# Add this file to /lib/tasks/tddium.rake
#
# Create an IAM user on AWS with no special policies, then add the access
# key and secret key to your Tddium suite config like this:
#
# cd /your/local/app/directory
# tddium config:add suite AWS_ACCESS_KEY yourkeyhere
# tddium config:add suite AWS_SECRET_KEY yoursecrethere
#
# Then, give the user deploy permissions in the stack settings:
# OpsWorks --> your stack --> Users (top right)
# Import IAM Users
# Then Edit the user and choose 'deploy' for the permissions and press save
#
# Now get the stack id and app id from their respective settings pages in AWS
# and add them too. They are both labelled 'OpsWorks ID'.
#
# tddium config:add suite OPSWORKS_STACK_ID yourstackidhere
# tddium config:add suite OPSWORKS_APP_ID yourappidhere
require 'timeout'
require 'aws-sdk-v1'
ENV['CI_DEPLOYMENT_BRANCH'] ||= 'master'
def current_branch
`git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3-`.strip
end
class OpsWorksDeployer
attr_accessor :deployment_id
def deploy
set_aws_credentials
send_deployment_api_call_to_aws
wait_to_see_what_happened
end
protected
def start_time
@start_time ||= Time.now
end
def timeout_seconds
600
end
def time_elapsed
Time.now - start_time
end
def current_deploy_status
result = opsworks.client.describe_deployments deployment_ids: [deployment_id]
result[:deployments].first[:status]
end
def time_between_status_checks
5 # seconds
end
def wait_to_see_what_happened
while true do
status = current_deploy_status
case status
when 'running'
sleep time_between_status_checks
when 'failed'
raise "Deployment #{deployment_id} failed. Check the OpsWorks logs for details."
when 'successful'
return
else # Some weird outcome?
if time_elapsed < timeout_seconds
sleep time_between_status_checks
else
raise "Deployment #{deployment_id} timed out after #{timeout_seconds} seconds. Status: #{status}"
end
end
end
end
def set_aws_credentials
# Do not include the region here. It makes it hang on the connection.
AWS.config(access_key_id: aws_access_key, secret_access_key: aws_secret_key)
end
def send_deployment_api_call_to_aws
result = opsworks.client.create_deployment stack_id: stack_id,
app_id: app_id,
command: {"name" => "deploy",
"args" => {"migrate" => ["true"]}}
@deployment_id = result[:deployment_id]
end
def opsworks
@opsworks ||= AWS::OpsWorks.new
end
def aws_access_key
ENV.fetch('AWS_ACCESS_KEY')
end
def aws_secret_key
ENV.fetch('AWS_SECRET_KEY')
end
def stack_id
ENV.fetch 'OPSWORKS_STACK_ID'
end
def app_id
ENV.fetch 'OPSWORKS_APP_ID'
end
end
namespace :tddium do
desc "Run post-build script"
task :post_build_hook do
# Print out status information
puts "Solano CI? " + ENV.member?('TDDIUM').to_s
puts "status " + ENV['TDDIUM_BUILD_STATUS']
puts "on_tracked_branch? " + on_tracked_branch?.inspect
puts "deploy? " + deploy?.inspect
if deploy?
Rake::Task["deploy:production"].execute
end
end
private
def deploy?
result = ENV.member?('TDDIUM')
result &&= ENV['TDDIUM_BUILD_STATUS'] == 'passed'
result && on_tracked_branch?
end
def on_tracked_branch?
current_branch == ENV['CI_DEPLOYMENT_BRANCH']
end
end
namespace :deploy do
desc "Deploy master branch to production server"
task :production do
Timeout::timeout(600) do
deploy
end
end
private
def deploy
allow_connections_without_webmock_interfering
OpsWorksDeployer.new.deploy
end
def allow_connections_without_webmock_interfering
if WebMock
WebMock.allow_net_connect!
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment