Last active
August 29, 2015 14:13
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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