asset_sync 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -16,6 +16,10 @@ Add the gem to your Gemfile
16
16
  Generate the rake task and config files
17
17
 
18
18
  rails g asset_sync:install
19
+
20
+ If you would like to use a YAML file for configuration instead of the default (Rails Initializer) then
21
+
22
+ rails g asset_sync:install --use-yml
19
23
 
20
24
  ## Configuration
21
25
 
@@ -27,31 +31,56 @@ S3 as the asset host and ensure precompiling is enabled.
27
31
  request.ssl? ? 'https://my_bucket.s3.amazonaws.com' : 'http://my_bucket.s3.amazonaws.com'
28
32
  end
29
33
 
30
- ### asset_sync.yml
34
+ We support two methods of configuration.
35
+
36
+ * Rails Initializer
37
+ * A YAML config file
38
+
39
+ Using an **Initializer** is the default method and is best used with **environment** variables. It's the recommended approach for deployments on Heroku.
40
+
41
+ Using a **YAML** config file is a traditional strategy for Capistrano deployments. If you are using [Moonshine](https://github.com/railsmachine/moonshine) (which we would recommend) then it is best used with [shared configuration files](https://github.com/railsmachine/moonshine/wiki/Shared-Configuration-Files).
42
+
43
+ The recommend way to configure **asset_sync** is by using environment variables however it's up to you, it will work fine if you hard code them too. The main reason is that then your access keys are not checked into version control.
44
+
45
+ ### Initializer (config/initializers/asset_sync.rb)
46
+
47
+ The generator will create a Rails initializer at `config/initializers/asset_sync.rb`.
48
+
49
+ AssetSync.configure do |config|
50
+ config.aws_access_key = ENV['AWS_ACCESS_KEY']
51
+ config.aws_access_secret = ENV['AWS_ACCESS_SECRET']
52
+ config.aws_bucket = ENV['AWS_BUCKET']
53
+ # config.aws_region = 'eu-west-1'
54
+ config.existing_remote_files = "keep"
55
+ end
56
+
57
+
58
+ ### YAML (config/asset_sync.yml)
31
59
 
32
- The recommend way to configure your **asset_sync.yml** is by adding an environment variable. That way your access keys are not checked into version control.
60
+ If you used the `--use-yml` flag, the generator will create a YAML file at `config/initializers/asset_sync.rb`.
33
61
 
34
62
  defaults: &defaults
35
- access_key_id: "<%= ENV['AWS_ACCESS_KEY'] %>"
36
- secret_access_key: "<%= ENV['AWS_ACCESS_SECRET'] %>"
63
+ aws_access_key: "<%= ENV['AWS_ACCESS_KEY'] %>"
64
+ aws_access_secret: "<%= ENV['AWS_ACCESS_SECRET'] %>"
37
65
  # You may need to specify what region your S3 bucket is in
38
- # region: "eu-west-1"
66
+ # aws_region: "eu-west-1"
39
67
 
40
68
  development:
41
69
  <<: *defaults
42
- bucket: "backoffice_development"
70
+ aws_bucket: "rails_app_development"
43
71
  existing_remote_files: keep # Existing pre-compiled assets on S3 will be kept
44
72
 
45
73
  test:
46
74
  <<: *defaults
47
- bucket: "backoffice_test"
75
+ aws_bucket: "rails_app_test"
48
76
  existing_remote_files: keep
49
77
 
50
78
  production:
51
79
  <<: *defaults
52
- bucket: "backoffice_production"
80
+ aws_bucket: "rails_app_production"
53
81
  existing_remote_files: delete # Existing pre-compiled assets on S3 will be deleted
54
82
 
83
+ ### Environment Variables
55
84
 
56
85
  Add your Amazon S3 configuration details to **heroku**
57
86
 
@@ -63,13 +92,6 @@ Or add to a traditional unix system
63
92
  export AWS_ACCESS_KEY=xxxx
64
93
  export AWS_ACCESS_SECRET=xxxx
65
94
 
66
- If you are using anything other than the US buckets with S3 then you'll want to set the **region**. For example with an EU bucket you could set the following
67
-
68
- production:
69
- access_key_id: 'MY_ACCESS_KEY'
70
- secret_access_key: 'MY_ACCESS_SECRET'
71
- region: 'eu-west-1'
72
-
73
95
  ### Available Configuration Options
74
96
 
75
97
  * **access\_key\_id**: your Amazon S3 access key
@@ -77,6 +99,22 @@ If you are using anything other than the US buckets with S3 then you'll want to
77
99
  * **region**: the region your S3 bucket is in e.g. *eu-west-1*
78
100
  * **existing_remote_files**: what to do with previously precompiled files, options are **keep** or **delete**
79
101
 
102
+ ## Amazon S3 Multiple Region Support
103
+
104
+ If you are using anything other than the US buckets with S3 then you'll want to set the **region**. For example with an EU bucket you could set the following with YAML.
105
+
106
+ production:
107
+ # ...
108
+ region: 'eu-west-1'
109
+
110
+ Or via the initializer
111
+
112
+ AssetSync.configure do |config|
113
+ # ...
114
+ config.aws_region = 'eu-west-1'
115
+ end
116
+
117
+
80
118
  ## Rake Task
81
119
 
82
120
  A rake task is installed with the generator to enhance the rails
@@ -84,14 +122,14 @@ precompile task by automatically running after it:
84
122
 
85
123
  # lib/tasks/asset_sync.rake
86
124
  Rake::Task["assets:precompile"].enhance do
87
- AssetSync::Assets.sync
125
+ AssetSync.sync
88
126
  end
89
127
 
90
128
  ## Todo
91
129
 
92
- 1. Write some specs
93
- 2. Add some before and after filters for deleting and uploading
94
- 3. Provide more configuration options
130
+ 1. Add some before and after filters for deleting and uploading
131
+ 2. Support more cloud storage providers
132
+ 3. Better test coverage
95
133
 
96
134
  ## Credits
97
135
 
@@ -6,7 +6,7 @@ require "asset_sync/version"
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "asset_sync"
8
8
  s.version = AssetSync::VERSION
9
- s.date = "2011-08-06"
9
+ s.date = "2011-08-22"
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = ["Simon Hamilton", "David Rice"]
12
12
  s.email = ["shamilton@rumblelabs.com", "me@davidjrice.co.uk"]
@@ -17,8 +17,10 @@ Gem::Specification.new do |s|
17
17
  s.rubyforge_project = "asset_sync"
18
18
 
19
19
  s.add_dependency('fog')
20
-
20
+
21
21
  s.add_development_dependency "rspec"
22
+ s.add_development_dependency "bundler"
23
+ s.add_development_dependency "jeweler"
22
24
 
23
25
  s.files = `git ls-files`.split("\n")
24
26
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,2 +1,5 @@
1
1
  require 'fog'
2
+ require 'erb'
2
3
  require "asset_sync/asset_sync"
4
+ require 'asset_sync/config'
5
+ require 'asset_sync/storage'
@@ -1,83 +1,30 @@
1
1
  module AssetSync
2
- class Assets
3
2
 
4
- def self.s3_config
5
- @config ||= YAML.load(ERB.new(IO.read(File.join(Rails.root, "config/asset_sync.yml"))).result)[Rails.env] rescue nil || {}
6
- end
7
-
8
- def self.connection
9
- storage = {
10
- :provider => 'AWS',
11
- :aws_access_key_id => s3_config["access_key_id"],
12
- :aws_secret_access_key => s3_config["secret_access_key"]
13
- }
14
- storage.merge!({:region => s3_config["region"]}) if s3_config.has_key?("region")
15
-
16
- Fog::Storage.new(storage)
17
- end
18
-
19
- def self.bucket
20
- @bucket ||= connection.directories.get(s3_config["bucket"])
21
- end
22
-
23
- def self.keep_existing_remote_files
24
- (s3_config["existing_remote_files"]) ? (s3_config["existing_remote_files"] == "keep") : true
25
- end
26
-
27
- def self.path
28
- "#{Rails.root.to_s}/public"
29
- end
30
-
31
- def self.local_files
32
- Dir["#{path}/assets/**/**"].map { |f| f[path.length+1,f.length-path.length] }
33
- end
3
+ class << self
34
4
 
35
- def self.get_remote_files
36
- return bucket.files.map { |f| f.key }
5
+ def config=(data)
6
+ @config = data
37
7
  end
38
8
 
39
- def self.delete_file(f, remote_files_to_delete)
40
- if remote_files_to_delete.include?(f.key)
41
- STDERR.puts "Deleting: #{f.key}"
42
- f.destroy
43
- end
9
+ def config
10
+ @config ||= Config.new
11
+ raise Config::Invalid("Your configuration in (config/asset_sync.yml or config/initializers/asset_sync.rb) is missing or invalid, please refer to the documention and emend") unless @config && @config.valid?
12
+ @config
44
13
  end
45
14
 
46
- def self.delete_extra_remote_files
47
- remote_files = get_remote_files
48
- from_remote_files_to_delete = (local_files | remote_files) - (local_files & remote_files)
49
-
50
- # Delete unneeded remote files
51
- bucket.files.each do |f|
52
- delete_file(f, from_remote_files_to_delete)
53
- end
15
+ def configure(&proc)
16
+ @config ||= Config.new
17
+ yield @config
54
18
  end
55
19
 
56
- def self.upload_file(f)
57
- STDERR.puts "Uploading: #{f}"
58
- file = bucket.files.create(
59
- :key => "#{f}",
60
- :body => File.open("#{path}/#{f}"),
61
- :public => true
62
- )
20
+ def storage
21
+ @storage ||= Storage.new(self.config)
63
22
  end
64
23
 
65
- def self.upload_files
66
- # get a fresh list of remote files
67
- remote_files = get_remote_files
68
- local_files_to_upload = (remote_files | local_files) - (remote_files & local_files)
69
-
70
- # Upload new files
71
- local_files_to_upload.each do |f|
72
- next unless File.file? "#{path}/#{f}" # Only files.
73
- upload_file f
74
- end
24
+ def sync
25
+ self.storage.sync
75
26
  end
76
27
 
77
- def self.sync
78
- delete_extra_remote_files unless keep_existing_remote_files
79
- upload_files
80
- STDERR.puts "Done."
81
- end
82
28
  end
29
+
83
30
  end
@@ -0,0 +1,64 @@
1
+ module AssetSync
2
+ class Config
3
+
4
+ class Invalid < StandardError; end
5
+
6
+ attr_accessor :provider
7
+ attr_accessor :aws_access_key, :aws_access_secret
8
+ attr_accessor :aws_bucket
9
+ attr_accessor :aws_region
10
+ attr_accessor :existing_remote_files
11
+
12
+ def initialize
13
+ self.provider = 'AWS'
14
+ self.aws_region = nil
15
+ self.existing_remote_files = 'keep'
16
+ load_yml! if yml_exists?
17
+ end
18
+
19
+ def existing_remote_files?
20
+ (self.existing_remote_files) ? (self.existing_remote_files == "keep") : true
21
+ end
22
+
23
+
24
+ def yml_exists?
25
+ File.exists?(self.yml_path)
26
+ end
27
+
28
+ def yml
29
+ y ||= YAML.load(ERB.new(IO.read(yml_path)).result)[Rails.env] rescue nil || {}
30
+ end
31
+
32
+ def yml_path
33
+ File.join(Rails.root, "config/asset_sync.yml")
34
+ end
35
+
36
+ def load_yml!
37
+ self.aws_access_key = yml["aws_access_key"]
38
+ self.aws_access_secret = yml["aws_access_secret"]
39
+ self.aws_bucket = yml["aws_bucket"]
40
+ self.aws_region = yml["aws_region"]
41
+
42
+ # TODO deprecate old style config settings
43
+ self.aws_access_key = yml["access_key_id"] if yml.has_key?("access_key_id")
44
+ self.aws_access_secret = yml["secret_access_key"] if yml.has_key?("secret_access_key")
45
+ self.aws_bucket = yml["bucket"] if yml.has_key?("bucket")
46
+ self.aws_region = yml["region"] if yml.has_key?("region")
47
+ end
48
+
49
+ def fog_options
50
+ options = {
51
+ :provider => provider,
52
+ :aws_access_key_id => aws_access_key,
53
+ :aws_secret_access_key => aws_access_secret
54
+ }
55
+ options.merge!({:region => aws_region}) if aws_region
56
+ return options
57
+ end
58
+
59
+ def valid?
60
+ true
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,80 @@
1
+ module AssetSync
2
+ class Storage
3
+
4
+ attr_accessor :config
5
+
6
+ def initialize(cfg)
7
+ @config = cfg
8
+ end
9
+
10
+ def connection
11
+ @connection ||= Fog::Storage.new(self.config.fog_options)
12
+ end
13
+
14
+ def bucket
15
+ @bucket ||= connection.directories.get(self.config.aws_bucket)
16
+ end
17
+
18
+ def keep_existing_remote_files
19
+ self.config.existing_remote_files?
20
+ end
21
+
22
+ def path
23
+ "#{Rails.root.to_s}/public"
24
+ end
25
+
26
+ def local_files
27
+ Dir["#{path}/assets/**/**"].map { |f| f[path.length+1,f.length-path.length] }
28
+ end
29
+
30
+ def get_remote_files
31
+ return bucket.files.map { |f| f.key }
32
+ end
33
+
34
+ def delete_file(f, remote_files_to_delete)
35
+ if remote_files_to_delete.include?(f.key)
36
+ STDERR.puts "Deleting: #{f.key}"
37
+ f.destroy
38
+ end
39
+ end
40
+
41
+ def delete_extra_remote_files
42
+ remote_files = get_remote_files
43
+ from_remote_files_to_delete = (local_files | remote_files) - (local_files & remote_files)
44
+
45
+ # Delete unneeded remote files
46
+ bucket.files.each do |f|
47
+ delete_file(f, from_remote_files_to_delete)
48
+ end
49
+ end
50
+
51
+ def upload_file(f)
52
+ STDERR.puts "Uploading: #{f}"
53
+ file = bucket.files.create(
54
+ :key => "#{f}",
55
+ :body => File.open("#{path}/#{f}"),
56
+ :public => true,
57
+ 'Cache-Control' => 'max-age=29030400, public'
58
+ )
59
+ end
60
+
61
+ def upload_files
62
+ # get a fresh list of remote files
63
+ remote_files = get_remote_files
64
+ local_files_to_upload = (remote_files | local_files) - (remote_files & local_files)
65
+
66
+ # Upload new files
67
+ local_files_to_upload.each do |f|
68
+ next unless File.file? "#{path}/#{f}" # Only files.
69
+ upload_file f
70
+ end
71
+ end
72
+
73
+ def sync
74
+ delete_extra_remote_files unless keep_existing_remote_files
75
+ upload_files
76
+ STDERR.puts "Done."
77
+ end
78
+
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module AssetSync
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -4,10 +4,7 @@ module AssetSync
4
4
  desc "Install a config/asset_sync.yml and the asset:precompile rake task enhancer"
5
5
 
6
6
  # Commandline options can be defined here using Thor-like options:
7
- class_option :my_opt, :type => :boolean, :default => false, :desc => "My Option"
8
-
9
- # I can later access that option using:
10
- # options[:my_opt]
7
+ class_option :use_yml, :type => :boolean, :default => false, :desc => "Use YML file instead of Rails Initializer"
11
8
 
12
9
  def self.source_root
13
10
  @source_root ||= File.join(File.dirname(__FILE__), 'templates')
@@ -26,9 +23,17 @@ module AssetSync
26
23
  end
27
24
 
28
25
  def generate_config
29
- template "asset_sync.yml", "config/asset_sync.yml"
26
+ if options[:use_yml]
27
+ template "asset_sync.yml", "config/asset_sync.yml"
28
+ end
29
+ end
30
+
31
+ def generate_initializer
32
+ unless options[:use_yml]
33
+ template "asset_sync.rb", "config/initializers/asset_sync.rb"
34
+ end
30
35
  end
31
-
36
+
32
37
  def generate_rake_task
33
38
  template "asset_sync.rake", "lib/tasks/asset_sync.rake"
34
39
  end
@@ -1,3 +1,3 @@
1
1
  Rake::Task["assets:precompile"].enhance do
2
- AssetSync::Assets.sync
2
+ AssetSync.sync
3
3
  end
@@ -0,0 +1,7 @@
1
+ AssetSync.configure do |config|
2
+ config.aws_access_key = ENV['AWS_ACCESS_KEY']
3
+ config.aws_access_secret = ENV['AWS_ACCESS_SECRET']
4
+ config.aws_bucket = ENV['AWS_BUCKET']
5
+ # config.aws_region = "eu-west-1"
6
+ config.existing_remote_files = "keep"
7
+ end
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+
4
+ describe AssetSync, 'with initializer' do
5
+
6
+ before(:all) do
7
+ AssetSync.configure do |config|
8
+ config.aws_access_key = 'aaaa'
9
+ config.aws_access_secret = 'bbbb'
10
+ config.aws_bucket = 'mybucket'
11
+ config.aws_region = 'eu-west-1'
12
+ config.existing_remote_files = "keep"
13
+ end
14
+ end
15
+
16
+ it "should should keep existing remote files" do
17
+ AssetSync.config.keep_existing_remote_files?.should == true
18
+ end
19
+
20
+ it "should configure aws_access_key" do
21
+ AssetSync.config.aws_access_key.should == "aaaa"
22
+ end
23
+
24
+ it "should configure aws_access_key" do
25
+ AssetSync.config.aws_access_secret.should == "bbbb"
26
+ end
27
+
28
+ it "should configure aws_access_key" do
29
+ AssetSync.config.aws_bucket.should == "mybucket"
30
+ end
31
+
32
+ it "should configure aws_access_key" do
33
+ AssetSync.config.aws_region.should == "eu-west-1"
34
+ end
35
+
36
+ it "should configure aws_access_key" do
37
+ AssetSync.config.existing_remote_files.should == "keep"
38
+ end
39
+
40
+ end
41
+
42
+
43
+ describe AssetSync, 'from yml' do
44
+
45
+ before(:all) do
46
+ AssetSync.config = AssetSync::Config.new
47
+ end
48
+
49
+ it "should configure aws_access_key" do
50
+ AssetSync.config.aws_access_key.should == "xxxx"
51
+ end
52
+
53
+ it "should configure aws_access_key" do
54
+ AssetSync.config.aws_access_secret.should == "zzzz"
55
+ end
56
+
57
+ it "should configure aws_access_key" do
58
+ AssetSync.config.aws_bucket.should == "rails_app_test"
59
+ end
60
+
61
+ it "should configure aws_access_key" do
62
+ AssetSync.config.aws_region.should == "eu-west-1"
63
+ end
64
+
65
+ it "should configure aws_access_key" do
66
+ AssetSync.config.existing_remote_files.should == "keep"
67
+ end
68
+
69
+ end
@@ -0,0 +1,20 @@
1
+ defaults: &defaults
2
+ access_key_id: "xxxx"
3
+ secret_access_key: "zzzz"
4
+ region: "eu-west-1"
5
+
6
+ development:
7
+ <<: *defaults
8
+ bucket: "rails_app_development"
9
+ existing_remote_files: keep
10
+
11
+ test:
12
+ <<: *defaults
13
+ bucket: "rails_app_test"
14
+ existing_remote_files: keep
15
+
16
+ production:
17
+ <<: *defaults
18
+ bucket: "rails_app_production"
19
+ existing_remote_files: delete
20
+
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ require 'asset_sync'
14
+
15
+ class Rails
16
+
17
+ def self.env
18
+ "test"
19
+ end
20
+
21
+ def self.root
22
+ File.expand_path(File.join('spec', 'rails_app'))
23
+ end
24
+
25
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: asset_sync
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.6
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Simon Hamilton
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-08-06 00:00:00 Z
14
+ date: 2011-08-22 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: fog
@@ -35,6 +35,28 @@ dependencies:
35
35
  version: "0"
36
36
  type: :development
37
37
  version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: bundler
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: jeweler
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :development
59
+ version_requirements: *id004
38
60
  description: After you run assets:precompile your assets will be synchronised with your S3 bucket, deleting unused files and only uploading the files it needs to.
39
61
  email:
40
62
  - shamilton@rumblelabs.com
@@ -53,10 +75,16 @@ files:
53
75
  - asset_sync.gemspec
54
76
  - lib/asset_sync.rb
55
77
  - lib/asset_sync/asset_sync.rb
78
+ - lib/asset_sync/config.rb
79
+ - lib/asset_sync/storage.rb
56
80
  - lib/asset_sync/version.rb
57
81
  - lib/generators/asset_sync/install_generator.rb
58
82
  - lib/generators/asset_sync/templates/asset_sync.rake
83
+ - lib/generators/asset_sync/templates/asset_sync.rb
59
84
  - lib/generators/asset_sync/templates/asset_sync.yml
85
+ - spec/asset_sync_spec.rb
86
+ - spec/rails_app/config/asset_sync.yml
87
+ - spec/spec_helper.rb
60
88
  homepage: https://github.com/rumblelabs/asset_sync
61
89
  licenses: []
62
90
 
@@ -80,9 +108,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
108
  requirements: []
81
109
 
82
110
  rubyforge_project: asset_sync
83
- rubygems_version: 1.7.2
111
+ rubygems_version: 1.8.7
84
112
  signing_key:
85
113
  specification_version: 3
86
114
  summary: Synchronises Assets between Rails and S3
87
- test_files: []
88
-
115
+ test_files:
116
+ - spec/asset_sync_spec.rb
117
+ - spec/rails_app/config/asset_sync.yml
118
+ - spec/spec_helper.rb