Skip to content

Instantly share code, notes, and snippets.

@monteirobrena
Created April 9, 2016 19:57
Show Gist options
  • Save monteirobrena/02c9d48b9e901cfe9a19c4bc77385df1 to your computer and use it in GitHub Desktop.
Save monteirobrena/02c9d48b9e901cfe9a19c4bc77385df1 to your computer and use it in GitHub Desktop.
Rails assets on MS Azure CDN
require 'azure_blob_service'
namespace :azure do
desc 'Uploads application assets to Azure'
task upload_assets: :environment do
service = AzureBlobService.new(
Rails.application.secrets.azure['account_name'],
Rails.application.secrets.azure['access_key'])
service.ensure_container_exists('assets')
Dir.glob("#{Rails.root}/public/assets/**/*").each do |file|
if File.file?(file)
filename = file.gsub("#{Rails.root}/public/assets/", '')
unless service.blob_exists?('assets', filename)
Rails.logger.info("Uploading to Azure: #{filename}")
service.upload_blob('assets', file, filename)
end
end
end
end
end
require 'azure'
class AzureBlobService
def initialize(account_name, access_key)
Azure.configure do |config|
config.storage_account_name = account_name
config.storage_access_key = access_key
end
@service = Azure::BlobService.new
setup_cors
end
def upload_blob(container, file, filename)
content = File.open(file, 'rb') { |file| file.read }
content_type = MIME::Types.of(file).try(:first).try(:content_type)
hash = Digest::MD5.base64digest(content)
@service.create_block_blob(container, filename, content,
content_type: content_type,
content_md5: hash,
cache_control: 'public, max-age=604800')
end
def ensure_container_exists(name)
unless @service.list_containers.any? { |c| c.name == name }
@service.create_container(name, public_access_level: 'blob')
end
end
def blob_exists?(container, name)
begin
@service.get_blob_properties(container, name)
return true
rescue Azure::Core::Http::HTTPError => err
if err.status_code == 404
return false
else
raise err
end
end
end
def setup_cors
props = @service.get_service_properties
return unless props.cors.cors_rules.empty?
rule = Azure::Service::CorsRule.new
rule.allowed_origins = cors_origins_for(Rails.application.secrets.domain_name, %w(app staging www))
rule.allowed_headers = rule.exposed_headers = ['*']
rule.max_age_in_seconds = 3600
rule.allowed_methods = %w(GET HEAD)
props.cors.cors_rules << rule
@service.set_service_properties(props)
end
private
def cors_origins_for(domain, subdomains, protocols = %w(http https))
protocols.map do |proto|
["#{proto}://#{domain}"] + subdomains.map { |subdomain| "#{proto}://#{subdomain}.#{domain}" }
end.flatten
end
end
namespace :deploy do
task :upload_assets do
on roles(fetch(:assets_roles)).first do
within release_path do
execute :rake, 'azure:upload_assets'
end
end
end
after 'deploy:assets:precompile', :upload_assets
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment