Permalink
Browse files

Auto deploy assets to CDN.

  • Loading branch information...
huacnlee committed May 10, 2012
1 parent 310615c commit d050f7f8b7441fbd88671e0008205f4ccffca8b5
Showing with 215 additions and 2 deletions.
  1. +1 −1 config/deploy.rb
  2. +1 −1 config/environments/production.rb
  3. +205 −0 lib/ftp_sync.rb
  4. +8 −0 lib/tasks/assets/cdn.rake
View
@@ -56,7 +56,7 @@
end
task :compile_assets, :roles => :web do
run "cd #{deploy_to}/current/; bundle exec rake assets:precompile"
run "cd #{deploy_to}/current/; bundle exec rake assets:precompile && bundle exec rake assets:cdn"
end
task :mongoid_migrate_database, :roles => :web do
@@ -32,7 +32,7 @@
config.serve_static_assets = true
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
config.action_controller.asset_host = "http://y.ruby-china.org"
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
View
@@ -0,0 +1,205 @@
#!/usr/bin/ruby
require 'net/ftp'
require 'date'
require 'fileutils'
# usage:
# ftp = FtpSync.new('ftp.site.com', 'user', 'password')
# ftp.sync('/Users/james/Desktop/test_ftp', '/home/james/Sites')
# ftp.copy_folder('/home/james/Sites/folder1', '/home/james/Sites/folder3')
# simple class to sync local directory to a remote ftp directory, or copy directories on remote server
class FtpSync
def initialize(host, user, password, passive=FALSE)
@host = host
@user = user
@password = password
@passive = passive
end
# sync a local directory to a remote directory
def sync(local_dir, remote_dir)
ftp = Net::FTP.new(@host)
begin
ftp.login(@user, @password)
ftp.passive = @passive
puts "logged in, start syncing..."
sync_folder(local_dir, remote_dir, ftp)
puts "sync finished"
rescue Net::FTPPermError => e
puts "Failed: #{e.message}"
return false
end
end
# copy a remote directory to another location
# dir_dest should not contain the final dir name, but its parent dir, .eg:
# copy_folder('/home/james/test/folder', '/home/james/') will eventually create /home/james/folder
def copy_folder(dir_source, dir_dest)
ftp = Net::FTP.new(@host)
begin
ftp.login(@user, @password)
ftp.passive = @passive
puts "logged in, start copying #{dir_source} to #{dir_dest}..."
#create a tmp folder locally
tmp_folder = "tmp/ftp_sync"
if not File.exist?(tmp_folder)
FileUtils.mkdir tmp_folder
end
Dir.chdir tmp_folder
#download whole folder
ftp.chdir File.dirname(dir_source)
target = File.basename(dir_source)
download_folder(target, ftp)
#upload to dest
ftp.chdir dir_dest
upload_folder(target, ftp)
#todo delete local tmp folder
Dir.chdir ".."
FileUtils.rm_rf tmp_folder
puts "copy finished"
end
end
private
def put_title(title)
puts "#{title}"
end
def download_folder(remote_dir, ftp)
ftp.chdir remote_dir
FileUtils.mkdir remote_dir
Dir.chdir remote_dir
dirs, files = get_remote_dir_and_file_names(ftp)
dirs.each do |dir|
download_folder(dir, ftp)
end
files.each do |file|
ftp.get(file)
end
parent = ([".."] * (1 + remote_dir.count("/"))).join("/")
Dir.chdir(parent)
ftp.chdir(parent)
end
def full_file_path(file)
File.join(Dir.pwd, file)
end
def upload_file(file, ftp)
put_title "upload file: #{full_file_path(file)}"
ftp.put(file)
end
def upload_folder(dir, ftp)
put_title "upload folder: #{full_file_path(dir)}"
Dir.chdir dir
ftp.mkdir dir
ftp.chdir dir
local_dirs, local_files = get_local_dir_and_file_names
local_dirs.each do |subdir|
upload_folder(subdir, ftp)
end
local_files.each do |file|
upload_file(file, ftp)
end
parent = ([".."] * (1 + dir.count("/"))).join("/")
Dir.chdir(parent)
ftp.chdir(parent)
end
def sync_folder(local_dir, remote_dir, ftp)
Dir.chdir local_dir
begin
ftp.chdir remote_dir
rescue
# if the remote dir doesn't exist, we create it
ftp.mkdir remote_dir
ftp.chdir remote_dir
end
put_title "process folder: #{Dir.pwd}"
local_dirs, local_files = get_local_dir_and_file_names
remote_dirs, remote_files = get_remote_dir_and_file_names(ftp)
new_dirs = local_dirs - remote_dirs
new_files = local_files - remote_files
existing_dirs = local_dirs - new_dirs
existing_files = local_files - new_files
# put_title "new dirs"
# puts new_dirs
# put_title "new files"
# puts new_files
# put_title "existing dirs"
# puts existing_dirs
# put_title "existing files"
# puts existing_files
new_files.each do |file|
upload_file(file, ftp)
end
existing_files.each do |file|
upload_file(file, ftp)
end
new_dirs.each do |dir|
upload_folder(dir, ftp)
end
existing_dirs.each do |dir|
sync_folder(dir, dir, ftp)
end
Dir.chdir(([".."] * (1 + local_dir.count("/"))).join("/"))
ftp.chdir(([".."] * (1 + remote_dir.count("/"))).join("/"))
end
def get_local_dir_and_file_names
dirs = []
files = []
Dir.glob("*").each do |file|
if File.file?(file)
files << file
else
dirs << file
end
end
return [dirs, files]
end
def get_remote_dir_and_file_names(ftp)
dirs = []
files = []
ftp.ls do |file|
#-rw-r--r-- 1 james staff 6 Jan 07 03:54 hello.txt
fname = file.gsub(/\S+\s+\d+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+/, '')
case file[0, 1]
when "-"
files << fname
when "d"
dirs << fname
end
end
return [dirs, files]
end
end
@@ -0,0 +1,8 @@
require 'ftp_sync'
namespace :assets do
desc 'sync assets to cdns'
task :cdn => :environment do
ftp = FtpSync.new("v1.ftp.upyun.com", [Setting.upyun_username,Setting.upyun_bucket].join("/"), Setting.upyun_password,true)
ftp.sync("#{Rails.root}/public/assets/", "/assets")
end
end

1 comment on commit d050f7f

@kesin

This comment has been minimized.

Show comment
Hide comment
@kesin

kesin Apr 23, 2014

haha,that's greate

kesin commented on d050f7f Apr 23, 2014

haha,that's greate

Please sign in to comment.