public
Created

Upload assets to S3, preserve two most recent versions.

  • Download Gist
assets.rake
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
namespace :assets do
 
# uploads assets to s3 under assets/githash, deletes stale assets
task :uploadToS3, [ :to ] => :environment do |t, args|
from = File.join(Rails.root, 'public/assets')
to = args[:to]
hash = (`git rev-parse --short HEAD` || "").chomp
logger.info("[#{Time.now}] fetching keys from #{to}")
existing_objects_hash = {}
existing_assets_hash = {}
s3i.incrementally_list_bucket(to, prefix: "assets/") do |response|
response[:contents].each do |existing_object|
existing_objects_hash[existing_object[:key]] = existing_object
previous_asset_hash = existing_object[:key].split('/')[1]
existing_assets_hash[previous_asset_hash] ||= DateTime.parse(existing_object[:last_modified])
end
end
 
logger.info("[#{Time.now}] #{existing_assets_hash.count} existing asset(s)")
previous_hash = nil
existing_assets_hash.each_pair do |asset_hash, last_modified|
logger.info(" #{asset_hash} => #{last_modified}")
previous_hash = asset_hash unless (previous_hash and existing_assets_hash[previous_hash] > last_modified)
end
logger.info("[#{Time.now}] keeping #{previous_hash}") if previous_hash
logger.info("[#{Time.now}] copying from #{from} to s3:#{to} @ #{hash}")
Dir.glob(from + "/**/*").each do |entry|
next if File::directory?(entry)
File.open(entry) do |entry_file|
content_options = {}
content_type = MIME::Types.type_for(entry)[0]
content_options['x-amz-acl'] = 'public-read'
if entry.ends_with?('.gz')
uncompressed_entry = entry[0..-4]
entry = "#{uncompressed_entry}.cgz"
content_type = MIME::Types.type_for(uncompressed_entry)[0]
content_options['content-encoding'] = 'gzip'
end
content_options['content-type'] = content_type.to_s
key = 'assets/'
key += (hash + '/') if hash
key += entry.slice(from.length + 1, entry.length - from.length - 1)
existing_objects_hash.delete(key)
logger.info("[#{Time.now}] uploading #{key} (#{content_type})")
s3i.put(to, key, entry_file, content_options)
end
end
existing_objects_hash.keys.each do |key|
next if previous_hash and key.start_with?("assets/#{previous_hash}/")
puts "deleting #{key}"
s3i.delete(to, key)
end
end
namespace :push do
task :to_staging => [ :environment, :assets ] do
Rake::Task["assets:uploadToS3"].execute({ to: 'staging-bucket' })
end
task :to_production => [ :environment, :assets ] do
Rake::Task["assets:uploadToS3"].execute({ to: 'production-bucket' })
end
task :to_heroku => [ :environment, :assets ] do
s3_bucket = Heroku::Config['S3_BUCKET']
raise "missing S3_BUCKET in heroku config" if (s3_bucket.nil?)
Rake::Task["assets:uploadToS3"].execute({ to: s3_bucket })
end
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.