himynameisjonas/heroku-deployer

View on GitHub
lib/heroku_deployer.rb

Summary

Maintainability
A
35 mins
Test Coverage
require 'git-ssh-wrapper'
require 'git'
require 'zlib'
require 'ostruct'
require 'logger'

class HerokuDeployer
  attr_reader :app, :logger

  def self.exists?(app)
    !!(ENV["#{app}_HEROKU_REPO"] && ENV["#{app}_GIT_REPO"] && ENV["#{app}_SSH_KEY"])
  end

  def initialize(app_name, logger = Logger.new(STDOUT))
    @app = app_name
    @logger = logger
  end

  def deploy
    tries = 0
    begin
      update_local_repository
      push
      post_deploy_command
    rescue
      tries += 1
      if tries <= 1
        `rm -r #{local_folder}` rescue nil
        retry
      end
    end
    logger.info 'done'
  end

  private

  def config
    @config ||= OpenStruct.new({
      heroku_repo: ENV["#{app}_HEROKU_REPO"],
      git_repo: ENV["#{app}_GIT_REPO"],
      ssh_key: ENV["#{app}_SSH_KEY"],
      post_deploy_command: ENV["#{app}_POST_DEPLOY_COMMAND"],
      github_branch: ENV["#{app}_BRANCH"] || 'master'
    })
  end

  def local_folder
    @local_folder ||= "repos/#{Zlib.crc32(config.git_repo + config.github_branch)}"
  end

  def repo_exists?
    Dir.exists?(File.join(local_folder, '.git'))
  end

  def update_local_repository
    GitSSHWrapper.with_wrapper(:private_key => config.ssh_key) do |wrapper|
      wrapper.set_env
      clone unless repo_exists?
      logger.info "fetching #{config.github_branch}"
      logger.debug `cd #{local_folder} && git fetch && git reset --hard origin/#{config.github_branch}`
    end
  end

  def clone
    logger.info "cloning"
    logger.debug `git clone #{config.git_repo} #{local_folder}`
    logger.info "switching to branch #{config.github_branch}"
    logger.debug `cd #{local_folder} && git fetch && git checkout #{config.github_branch} && git pull`
    logger.debug `cd #{local_folder} && git remote add heroku #{config.heroku_repo}`

  end

  def push
    GitSSHWrapper.with_wrapper(:private_key => ENV['DEPLOY_SSH_KEY']) do |wrapper|
      wrapper.set_env
      logger.info "pushing"
      logger.debug `cd #{local_folder}; git push -f heroku #{config.github_branch}:master`
    end
  end

  def post_deploy_command
    if config.post_deploy_command
      logger.info "calling post deploy command"
      logger.debug `#{config.post_deploy_command}`
    end
  end
end