Skip to content

Instantly share code, notes, and snippets.

@ahawkins
Created March 29, 2012 13:59
Show Gist options
  • Select an option

  • Save ahawkins/2237714 to your computer and use it in GitHub Desktop.

Select an option

Save ahawkins/2237714 to your computer and use it in GitHub Desktop.

Revisions

  1. Adam Hawkins revised this gist Mar 29, 2012. 1 changed file with 8 additions and 1 deletion.
    9 changes: 8 additions & 1 deletion deploy.rb
    Original file line number Diff line number Diff line change
    @@ -19,6 +19,13 @@
    #
    # The whole process is logged to deploy.log
    #
    # Use:
    # $ curl -s "https://raw.github.com/gist/2237714/c5b4c117014c0dfa026c7d8e8c193429b0c30a45/deploy.rb" -o script/deploy
    # $ chmod +x script/deploy
    # $ git add script/deploy
    # $ git commit -m 'Add simple deploy script'
    # $ ./script/deploy
    #
    # Enjoy!

    require "rubygems" # ruby1.9 doesn't "require" it though
    @@ -207,4 +214,4 @@ def run_deploy
    default_task :run_deploy
    end

    Deploy.start
    Deploy.start
  2. Adam Hawkins revised this gist Mar 29, 2012. 1 changed file with 22 additions and 0 deletions.
    22 changes: 22 additions & 0 deletions deploy.rb
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,26 @@
    #!/usr/bin/env ruby

    # This is a basic deploy script for Heroku apps.
    # It provides a structure you can use to expand on
    # and add your own prereqs and deploy tasks.
    #
    # It basically ensures that:
    # 1. There are no uncommited files
    # 2. You can ssh to github
    # 3. You can connect to heroku
    # 4. This commit is a fast forward commit to master
    # 5. This HEAD hasn't been deployed to Heroku
    #
    # Then given all that it:
    # 1. Records this commit & time in a deploys file
    # 2. Commits the deploy file
    # 3. Pushes to Github
    # 4. Pushes to Heroku
    #
    # The whole process is logged to deploy.log
    #
    # Enjoy!

    require "rubygems" # ruby1.9 doesn't "require" it though
    require "thor"

  3. Adam Hawkins created this gist Mar 29, 2012.
    188 changes: 188 additions & 0 deletions deploy.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,188 @@
    #!/usr/bin/env ruby
    require "rubygems" # ruby1.9 doesn't "require" it though
    require "thor"

    RAILS_ROOT = File.expand_path "../../", __FILE__

    LOG_FILE = "#{RAILS_ROOT}/deploy.log"
    DEPLOY_FILE = "#{RAILS_ROOT}/deploys.md"

    class Deploy < Thor
    include Thor::Actions

    class CommandFailed < StandardError ; end

    no_tasks do
    def run(command, options = {})
    `echo "#{command}" > #{LOG_FILE}`

    command = "#{command} > #{LOG_FILE} 2>&1" unless options[:capture]

    options[:verbose] ||= false

    super command, options
    end

    def run_with_status(command, options = {})
    run command, options
    $?
    end

    def success?(command, options = {})
    run_with_status(command, options).success?
    end

    def run!(command, options = {})
    raise CommandFailed, "Expected #{command} to return successfully, but didn't" unless success?(command, options)
    end

    def pass(message)
    say_status "OK", message, :green
    true
    end

    def abort_deploy(message)
    say_status "ABORT", message, :red
    say "Deploy Failed! Check log file #{LOG_FILE}"
    end

    def failure(message)
    say_status "FAIL", message, :red
    false
    end
    end

    desc "ensure_github_connection", "Tests this user can ssh to github"
    def ensure_github_connection
    if run_with_status("ssh -T git@github.com ").exitstatus == 1
    pass "Github conencted"
    else
    failure "SSH keys missing for Github"
    end
    end

    desc "ensure_heroku_connection", "Tests this user can access heroku"
    def ensure_heroku_connection
    if success? "heroku config"
    pass "Heroku connected"
    else
    failure "SSH key missing or user is not a collabator"
    end
    end

    desc "ensure_clean", "Test to see if the repo is clean"
    def ensure_clean
    if success? "git diff --exit-code"
    pass "No uncommited files"
    else
    failure "There are uncommited files"
    end
    end

    desc "ensure_heroku_outdated", "Test to see if this code has been deployed or not"
    def ensure_heroku_outdated
    if !success? "git diff head heroku/master --exit-code"
    pass "Code not deployed"
    else
    failure "Code already deployed"
    end
    end

    desc "ensure_fast_forward", "Tests if this is a fast forward commit"
    def ensure_fast_forward
    inside RAILS_ROOT do
    if success? "git pull origin master"
    return pass "Fast forwarded"
    else
    failure "Could not fast forward. Human required"
    run "git reset --hard HEAD"
    return false
    end
    end
    end

    desc "record", "Records this deploy in deploys.md"
    def record
    inside RAILS_ROOT do
    commit_info = run('git show --format="format:%h - %an: %s"', :capture => true, :verbose => false).split("\n")[0]

    format = "* [%s] %s\n"

    run "touch #{DEPLOY_FILE}"

    existing_contents = File.read DEPLOY_FILE

    File.open DEPLOY_FILE, 'w' do |f|
    f.puts format % [Time.now.strftime("%Y-%m-%d %H:%M %z"), commit_info]
    f.puts existing_contents.chomp
    end

    say_status "Deploy Log", commit_info
    end

    true
    end

    desc "commit", "Commits files neede to deploy"
    def commit
    inside RAILS_ROOT do
    run! "git add #{DEPLOY_FILE}"
    run! "git commit -m '[Deploy]'"
    @new_commit = true # so we can catch the failure and blow away the last commit
    end

    say_status "Deploy Files", "Commited"
    end

    desc "run_deploy", "Tests prereqs and runs a deploy"
    method_option :environment, :default => "production"
    def run_deploy
    say "Checking prereqs..."

    prereqs = invoke(:ensure_clean) &&
    invoke(:ensure_github_connection) &&
    invoke(:ensure_heroku_connection) &&
    invoke(:ensure_heroku_outdated) &&
    invoke(:ensure_fast_forward)

    if !prereqs
    abort_deploy "Failed prereqs"
    return false
    end

    say "Running predeploy tasks..."

    begin
    invoke :record
    invoke :commit
    rescue CommandFailed => ex
    abort_deploy "A deploy step failed to run: #{ex}"

    if @new_commit
    run "git reset HEAD~1"
    else
    run "git reset --hard HEAD"
    end

    return false
    end

    say "Deploying..."

    begin
    inside RAILS_ROOT do
    run! "git push origin master"
    say_status "Github", "Pushed"

    run! "git push heroku master"
    say_status "Heorku", "Deployed"
    end
    rescue CommandFailed => ex
    abort_deploy "Push failed. Please check logs."
    end
    end

    default_task :run_deploy
    end

    Deploy.start