class Capistrano::Releases::Manager

Class for pushing/pulling Capistrano releases.

Attributes

defaults[RW]
params[R]

Public Class Methods

new(parameters = {}) click to toggle source
# File lib/capistrano/releases/manager.rb, line 15
def initialize(parameters = {})
  @params = parameters

  params[:bucket] ||=
    defaults[:bucket] || raise('bucket_name is a required parameter')

  params[:deploy_to] ||=
    defaults[:deploy_to] || raise('deploy_to is a required parameter')

  params[:keep_releases] ||=
    (defaults[:keep_releases] || 5)
end

Public Instance Methods

pull() click to toggle source
# File lib/capistrano/releases/manager.rb, line 48
def pull
  make_dirs

  locals = Set.new(local_releases)
  puts "Local releases: #{locals.to_a.inspect}"

  to_download_releases = remote_releases.last(params[:keep_releases])
                                        .reject { |r| locals.include?(r) }
  to_download_releases.each do |r|
    puts "Downloading release: #{r}"
    download_release(r)
  end

  self.local_current = remote_current

  puts "Setting local current to: #{local_current}"
  Dir.chdir(File.join(params[:deploy_to], 'current'))

  download_bundle

  to_download_releases
end
push() click to toggle source
# File lib/capistrano/releases/manager.rb, line 28
def push
  make_dirs

  remotes = Set.new(remote_releases)
  puts "Remote releases: #{remotes.to_a.inspect}"

  to_upload_releases = local_releases.reject { |r| remotes.include?(r) }
  to_upload_releases.each do |r|
    puts "Uploading release: #{r}"
    upload_release(r)
  end

  puts "Setting remote current to: #{remote_current}"
  self.remote_current = local_current

  upload_bundle

  to_upload_releases
end

Private Instance Methods

bucket() click to toggle source
# File lib/capistrano/releases/manager.rb, line 207
def bucket
  @bucket ||= Aws::S3::Bucket.new(params[:bucket])
end
defaults() click to toggle source
# File lib/capistrano/releases/manager.rb, line 97
def defaults
  self.class.defaults || {}
end
download_bundle() click to toggle source
# File lib/capistrano/releases/manager.rb, line 190
def download_bundle
  return if Dir.exist?(File.join(local_shared_path, 'bundle'))

  puts 'Downloading bundle'

  tmp = Tempfile.new(['capistrano-releases_download-bundle', '.tar.gz'],
                     Dir.tmpdir, encoding: 'BINARY')

  begin
    bucket.object('bundle.tar.gz').get(response_target: tmp)
    system!(['tar', 'Cxfz', local_shared_path, tmp.path])
  ensure
    tmp.close
    tmp.unlink
  end
end
download_release(release) click to toggle source
# File lib/capistrano/releases/manager.rb, line 160
def download_release(release)
  tmp = Tempfile.new(["capistrano-releases_download-release-#{release}", '.tar.gz'],
                     Dir.tmpdir, encoding: 'BINARY')

  begin
    bucket.object("#{release}.tar.gz").get(response_target: tmp)
    system!(['tar', 'Cxfz', local_releases_path, tmp.path])
  ensure
    tmp.close
    tmp.unlink
  end
end
local_current() click to toggle source
# File lib/capistrano/releases/manager.rb, line 123
def local_current
  File.readlink(File.join(params[:deploy_to], 'current')).split('/').last
end
local_current=(release) click to toggle source
# File lib/capistrano/releases/manager.rb, line 131
def local_current=(release)
  cur_path = File.join(params[:deploy_to], 'current')
  rel_path = File.join(local_releases_path, release)

  File.unlink(cur_path) if File.symlink?(cur_path)
  File.symlink(rel_path, cur_path)

  nil
end
local_releases() click to toggle source
# File lib/capistrano/releases/manager.rb, line 109
def local_releases
  Dir.glob("#{local_releases_path}/*")
     .sort
     .map { |r| r.split('/').last }.sort
end
local_releases_path() click to toggle source
# File lib/capistrano/releases/manager.rb, line 101
def local_releases_path
  File.join(params[:deploy_to], 'releases')
end
local_shared_path() click to toggle source
# File lib/capistrano/releases/manager.rb, line 105
def local_shared_path
  File.join(params[:deploy_to], 'shared')
end
make_dirs() click to toggle source
# File lib/capistrano/releases/manager.rb, line 73
def make_dirs
  dirs = %w[
    shared
    shared/public
    shared/public/assets
    shared/public/system
    shared/log
    shared/tmp
    shared/tmp/cache
    shared/tmp/pids
    shared/tmp/sockets
    shared/vendor
    releases
  ]

  dirs.each do |dir|
    full_dir = File.join(params[:deploy_to], dir)
    unless Dir.exist?(full_dir)
      Dir.mkdir(full_dir)
      puts "Creating directory: #{full_dir}"
    end
  end
end
remote_current() click to toggle source
# File lib/capistrano/releases/manager.rb, line 127
def remote_current
  bucket.object('current.txt').get.body.read
end
remote_current=(release) click to toggle source
# File lib/capistrano/releases/manager.rb, line 141
def remote_current=(release)
  bucket.object('current.txt').put(body: release)

  nil
end
remote_releases() click to toggle source
# File lib/capistrano/releases/manager.rb, line 115
def remote_releases
  bucket.objects
        .map(&:key)
        .select { |k| k =~ /\A\d+.*\.tar\.gz\z/ }
        .map { |k| k.gsub(/\.tar\.gz\z/, '') }
        .sort
end
system!(cmd_array) click to toggle source
# File lib/capistrano/releases/manager.rb, line 211
def system!(cmd_array)
  raise 'Must be an array' unless cmd_array.is_a?(Array)
  cmd = cmd_array.map { |c| Shellwords.shellescape(c) }.join(' ')
  raise "command failed: #{cmd}" unless system(cmd)
end
upload_bundle() click to toggle source
# File lib/capistrano/releases/manager.rb, line 173
def upload_bundle
  return unless Dir.exist?(File.join(local_shared_path, 'bundle'))

  puts 'Uploading bundle'

  tmp = Tempfile.new(['capistrano-releases_upload-bundle', '.tar.gz'],
                     Dir.tmpdir, encoding: 'BINARY')

  begin
    system!(['tar', 'Ccfz', local_shared_path, tmp.path, 'bundle'])
    bucket.object('bundle.tar.gz').put(body: tmp)
  ensure
    tmp.close
    tmp.unlink
  end
end
upload_release(release) click to toggle source
# File lib/capistrano/releases/manager.rb, line 147
def upload_release(release)
  tmp = Tempfile.new(["capistrano-releases_upload-release-#{release}", '.tar.gz'],
                     Dir.tmpdir, encoding: 'BINARY')

  begin
    system!(['tar', 'Ccfz', local_releases_path, tmp.path, release])
    bucket.object("#{release}.tar.gz").put(body: tmp)
  ensure
    tmp.close
    tmp.unlink
  end
end