-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f83e222
commit 0412f48
Showing
3 changed files
with
104 additions
and
88 deletions.
There are no files selected for viewing
This file contains 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
This file was deleted.
Oops, something went wrong.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'base64' | ||
require 'digest' | ||
require 'openssl' | ||
require 'shellwords' | ||
|
||
URL = 'https://s3.amazonaws.com/ActiveAdmin' | ||
PREFIX = "ruby_#{RUBY_VERSION}-rails_#{ENV.fetch 'RAILS'}-" | ||
ID = ENV.fetch 'AWS_S3_ID' | ||
SECRET = ENV.fetch 'AWS_S3_SECRET' | ||
|
||
def download_bundle | ||
s3 :save, file: 'bundle.sha2', as: 'remote_bundle.sha2' | ||
s3 :save, file: 'bundle.tgz', as: 'remote_bundle.tgz', untar: true | ||
end | ||
|
||
# Don't use an existing archive if the Gemfile.lock changed | ||
def download_app | ||
s3 :save, file: 'app.sha2', as: 'remote_app.sha2' | ||
if !digest_changed?('Gemfile.lock', 'remote_bundle.sha2', 'bundle.sha2') && | ||
!digest_changed?('spec/support', 'remote_app.sha2', 'app.sha2') | ||
s3 :save, file: 'app.tgz', as: 'remote_app.tgz', untar: 'spec' | ||
end | ||
end | ||
|
||
def upload | ||
[ ['Gemfile.lock', 'bundle', 'bundle'], | ||
['spec/support', 'app', 'spec/rails'] | ||
].each do |to_check, name, to_save| | ||
puts "=> Checking #{to_check} for changes" | ||
if digest_changed? to_check, "remote_#{name}.sha2", "#{name}.sha2" | ||
puts " => Changes found" | ||
|
||
puts " => Creating an archive" | ||
`tar -cjf #{to_save} #{name}.tgz` | ||
|
||
puts " => Uploading a new archive" | ||
s3 :upload, file: "#{name}.tgz" | ||
s3 :upload, file: "#{name}.sha2" | ||
else | ||
puts " => There were no changes, doing nothing" | ||
end | ||
end | ||
end | ||
|
||
def digest_changed?(to_check, old_digest_file, new_digest_file) | ||
if File.exists? new_digest_file | ||
digest = File.read new_digest_file | ||
else | ||
# Supports a single file, as well as a folder | ||
files = Dir[to_check, "#{to_check}/**/*"].reject{ |f| File.directory? f } | ||
content = files.map{ |f| File.read f }.join | ||
digest = Digest::SHA2.hexdigest content | ||
File.write new_digest_file, digest | ||
end | ||
|
||
old_digest = File.read old_digest_file if File.exists? old_digest_file | ||
|
||
digest != old_digest | ||
end | ||
|
||
def sign(secret, to_sign, digest = 'sha1') | ||
Base64.strict_encode64 OpenSSL::HMAC.digest OpenSSL::Digest.new(digest), secret, to_sign | ||
end | ||
|
||
# s3 :list | ||
# s3 :upload, file: 'foo' | ||
# s3 :find, file: 'foo' | ||
# s3 :save, file: 'foo', as: 'bar' | ||
# s3 :save, file: 'foo', untar: true | ||
# s3 :save, file: 'foo', untar: 'another_directory' | ||
def s3(action, options = {}) | ||
verb = {list: :get, upload: :put, find: :get, save: :get}.fetch action | ||
file = PREFIX + options.fetch(:file) unless action == :list | ||
extra_arg = { | ||
upload: ->{ %[-T "#{file}"] }, | ||
save: ->{ %[-o "#{options[:as]}"] if options[:as] } | ||
}[action].call | ||
if options[:untar] | ||
do_after = "&& tar -xf #{options[:as] || file}" | ||
do_after << " -C #{options[:untar]}" if options[:untar].is_a? String | ||
end | ||
|
||
now = Time.now.strftime "%a, %d %b %Y %H:%M:%S %z" | ||
signature = sign SECRET, "#{verb.upcase}\n\n\n#{now}\n/ActiveAdmin/#{file}" | ||
headers = ["Authorization: AWS #{ID}:#{signature}", "Date: #{now}"].map do |h| | ||
"-H #{Shellwords.escape h}" | ||
end.join ' ' | ||
|
||
output = `curl -f #{headers} #{extra_arg} #{URL}/#{file} #{do_after}` | ||
[$?.success?, output] | ||
end | ||
|
||
if %w[download_bundle download_app upload].include? ARGV[0] | ||
send ARGV[0] | ||
else | ||
raise "unexpected argument(s): #{ARGV}" | ||
end |