asset_sync 2.6.0 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +11 -4
- data/Appraisals +4 -4
- data/CHANGELOG.md +102 -2
- data/README.md +42 -4
- data/asset_sync.gemspec +0 -2
- data/gemfiles/{rails_4_2.gemfile → rails_6_0.gemfile} +1 -1
- data/lib/asset_sync/config.rb +57 -12
- data/lib/asset_sync/engine.rb +4 -0
- data/lib/asset_sync/multi_mime.rb +2 -2
- data/lib/asset_sync/storage.rb +64 -16
- data/lib/asset_sync/version.rb +1 -1
- data/lib/generators/asset_sync/install_generator.rb +4 -0
- data/lib/generators/asset_sync/templates/asset_sync.rb +10 -0
- data/lib/generators/asset_sync/templates/asset_sync.yml +3 -0
- data/spec/fixtures/google_with_service_account_yml/config/asset_sync.yml +19 -0
- data/spec/unit/asset_sync_spec.rb +35 -3
- data/spec/unit/google_spec.rb +103 -30
- data/spec/unit/railsless_spec.rb +4 -3
- data/spec/unit/storage_spec.rb +137 -1
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fbb82cb5023ce3d6e1f088aa62fa32718f8e743977c31b773e3f2a324a0a397
|
4
|
+
data.tar.gz: 504e104e3dfe839bb19b0794a7af8f4bb932fd7f7500347374c14b8862e5ae43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2945ac417bfcc350068b1c9ce3c59781f0cd7bb50bd606919803e55602a81b06d6d6fed24de0c7e62ca695a83901481d296a9ae20031b5ab1e9edfc61a69823a
|
7
|
+
data.tar.gz: b96f8274e66d1d7ec2ab182fdcb3833edd7c24b9dc9d9fd9d038a3db8608dc1102a23b2998ec5c9749e89fe6d12212488dc9733ec927328fcc0f388bf84df357
|
data/.travis.yml
CHANGED
@@ -5,21 +5,24 @@ language: ruby
|
|
5
5
|
cache:
|
6
6
|
bundler: true
|
7
7
|
rvm:
|
8
|
-
- 2.2
|
9
8
|
- 2.3
|
10
9
|
- 2.4
|
11
10
|
- 2.5
|
12
11
|
- 2.6
|
12
|
+
- 2.7
|
13
13
|
- ruby-head
|
14
14
|
- jruby
|
15
15
|
- jruby-head
|
16
16
|
gemfile:
|
17
|
-
- gemfiles/rails_4_2.gemfile
|
18
17
|
- gemfiles/rails_5_0.gemfile
|
19
18
|
- gemfiles/rails_5_1.gemfile
|
20
19
|
- gemfiles/rails_5_2.gemfile
|
20
|
+
- gemfiles/rails_6_0.gemfile
|
21
21
|
before_install:
|
22
|
-
|
22
|
+
# Cannot use bundler 2.x due to dependency (mainly rails 4.2)
|
23
|
+
# Solution from https://github.com/rails/rails/blob/4-2-stable/.travis.yml
|
24
|
+
- "travis_retry gem update --system --no-doc || travis_retry gem update --system --no-rdoc --no-ri"
|
25
|
+
- "travis_retry gem install bundler -v '<2'"
|
23
26
|
env:
|
24
27
|
global:
|
25
28
|
- FOG_DIRECTORY=asset-sync-travis
|
@@ -29,9 +32,13 @@ env:
|
|
29
32
|
matrix:
|
30
33
|
fast_finish: true
|
31
34
|
allow_failures:
|
32
|
-
- rvm: 2.6
|
33
35
|
- rvm: ruby-head
|
34
36
|
- rvm: jruby-head
|
37
|
+
exclude:
|
38
|
+
- rvm: 2.3
|
39
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
40
|
+
- rvm: 2.4
|
41
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
35
42
|
notifications:
|
36
43
|
webhooks:
|
37
44
|
urls:
|
data/Appraisals
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
|
2
|
-
appraise "rails_4_2" do
|
3
|
-
gem "rails", "~> 4.2.0"
|
4
|
-
end
|
5
|
-
|
6
2
|
appraise "rails_5_0" do
|
7
3
|
gem "rails", "~> 5.0.0"
|
8
4
|
end
|
@@ -14,3 +10,7 @@ end
|
|
14
10
|
appraise "rails_5_2" do
|
15
11
|
gem "rails", "~> 5.2.0"
|
16
12
|
end
|
13
|
+
|
14
|
+
appraise "rails_6_0" do
|
15
|
+
gem "rails", "~> 6.0.0"
|
16
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -18,6 +18,96 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
18
|
- Nothing
|
19
19
|
|
20
20
|
|
21
|
+
## [2.12.1] - 2020-06-17
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
|
25
|
+
- Fix initializer template in generator
|
26
|
+
(https://github.com/AssetSync/asset_sync/pull/404)
|
27
|
+
|
28
|
+
|
29
|
+
## [2.12.0] - 2020-06-11
|
30
|
+
|
31
|
+
### Added
|
32
|
+
|
33
|
+
- Add option `aws_session_token` to support AWS Temporary Security Credentials
|
34
|
+
(https://github.com/AssetSync/asset_sync/pull/403)
|
35
|
+
|
36
|
+
|
37
|
+
## [2.11.0] - 2020-03-13
|
38
|
+
|
39
|
+
### Added
|
40
|
+
|
41
|
+
- Add option `remote_file_list_cache_file_path` to skip scanning remote
|
42
|
+
(https://github.com/AssetSync/asset_sync/pull/400)
|
43
|
+
|
44
|
+
|
45
|
+
## [2.10.0] - 2020-02-26
|
46
|
+
|
47
|
+
### Added
|
48
|
+
|
49
|
+
- Add option `concurrent_uploads_max_threads` to limit number of threads for uploading files
|
50
|
+
(https://github.com/AssetSync/asset_sync/pull/398)
|
51
|
+
|
52
|
+
|
53
|
+
## [2.9.1] - 2020-02-20
|
54
|
+
|
55
|
+
### Fixed
|
56
|
+
|
57
|
+
- Fix uploading of sprockets manifest file
|
58
|
+
(https://github.com/AssetSync/asset_sync/pull/397)
|
59
|
+
|
60
|
+
|
61
|
+
## [2.9.0] - 2020-01-15
|
62
|
+
|
63
|
+
### Added
|
64
|
+
|
65
|
+
- Add option `concurrent_uploads` to improve speed of uploading
|
66
|
+
(https://github.com/AssetSync/asset_sync/pull/393)
|
67
|
+
|
68
|
+
|
69
|
+
## [2.8.2] - 2019-12-27
|
70
|
+
|
71
|
+
### Changed
|
72
|
+
|
73
|
+
- Use `delete_multiple_objects` when storage is `aws`
|
74
|
+
(https://github.com/AssetSync/asset_sync/pull/392)
|
75
|
+
|
76
|
+
|
77
|
+
## [2.8.1] - 2019-07-25
|
78
|
+
|
79
|
+
### Changed
|
80
|
+
|
81
|
+
- Removed `rubyforge_project` from gemspec
|
82
|
+
(https://github.com/AssetSync/asset_sync/pull/386)
|
83
|
+
|
84
|
+
### Fixed
|
85
|
+
|
86
|
+
- Fixed when `fog_public` set to `false`, file were still set to be public
|
87
|
+
(https://github.com/AssetSync/asset_sync/pull/387)
|
88
|
+
|
89
|
+
|
90
|
+
## [2.8.0] - 2019-06-17
|
91
|
+
|
92
|
+
### Added
|
93
|
+
|
94
|
+
- Add option `fog_port`
|
95
|
+
(https://github.com/AssetSync/asset_sync/pull/385)
|
96
|
+
|
97
|
+
|
98
|
+
## [2.7.0] - 2019-03-15
|
99
|
+
|
100
|
+
### Added
|
101
|
+
|
102
|
+
- Adds JSON API support when using Google Storage
|
103
|
+
(https://github.com/AssetSync/asset_sync/pull/381)
|
104
|
+
|
105
|
+
### Changed
|
106
|
+
|
107
|
+
- Update `AssetSync::MultiMime.lookup` to always return strings (kind of internal change)
|
108
|
+
(https://github.com/AssetSync/asset_sync/pull/380)
|
109
|
+
|
110
|
+
|
21
111
|
## [2.6.0] - 2018-12-07
|
22
112
|
|
23
113
|
### Added
|
@@ -105,7 +195,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
105
195
|
|
106
196
|
- Only support mime-type >= 2.99,
|
107
197
|
which is released at the end of 2015
|
108
|
-
- Only support
|
198
|
+
- Only support activemodel >= 4.1,
|
109
199
|
which is released in 2014
|
110
200
|
|
111
201
|
|
@@ -888,7 +978,17 @@ Changes:
|
|
888
978
|
* Merge branch 'sinatra'
|
889
979
|
|
890
980
|
|
891
|
-
[Unreleased]: https://github.com/AssetSync/asset_sync/compare/v2.
|
981
|
+
[Unreleased]: https://github.com/AssetSync/asset_sync/compare/v2.12.1...HEAD
|
982
|
+
[2.12.1]: https://github.com/AssetSync/asset_sync/compare/v2.12.0...v2.12.1
|
983
|
+
[2.12.0]: https://github.com/AssetSync/asset_sync/compare/v2.11.0...v2.12.0
|
984
|
+
[2.11.0]: https://github.com/AssetSync/asset_sync/compare/v2.10.0...v2.11.0
|
985
|
+
[2.10.0]: https://github.com/AssetSync/asset_sync/compare/v2.9.1...v2.10.0
|
986
|
+
[2.9.1]: https://github.com/AssetSync/asset_sync/compare/v2.9.0...v2.9.1
|
987
|
+
[2.9.0]: https://github.com/AssetSync/asset_sync/compare/v2.8.2...v2.9.0
|
988
|
+
[2.8.2]: https://github.com/AssetSync/asset_sync/compare/v2.8.1...v2.8.2
|
989
|
+
[2.8.1]: https://github.com/AssetSync/asset_sync/compare/v2.8.0...v2.8.1
|
990
|
+
[2.8.0]: https://github.com/AssetSync/asset_sync/compare/v2.7.0...v2.8.0
|
991
|
+
[2.7.0]: https://github.com/AssetSync/asset_sync/compare/v2.6.0...v2.7.0
|
892
992
|
[2.6.0]: https://github.com/AssetSync/asset_sync/compare/v2.5.0...v2.6.0
|
893
993
|
[2.5.0]: https://github.com/AssetSync/asset_sync/compare/v2.4.0...v2.5.0
|
894
994
|
[2.4.0]: https://github.com/AssetSync/asset_sync/compare/v2.3.0...v2.4.0
|
data/README.md
CHANGED
@@ -103,10 +103,10 @@ On **non default S3 bucket region**: If your bucket is set to a region that is n
|
|
103
103
|
|
104
104
|
If you wish to have your assets sync to a sub-folder of your bucket instead of into the root add the following to your ``production.rb`` file
|
105
105
|
|
106
|
-
```ruby
|
106
|
+
``` ruby
|
107
107
|
# store assets in a 'folder' instead of bucket root
|
108
108
|
config.assets.prefix = "/production/assets"
|
109
|
-
|
109
|
+
```
|
110
110
|
|
111
111
|
Also, ensure the following are defined (in production.rb or application.rb)
|
112
112
|
|
@@ -170,7 +170,17 @@ heroku config:add FOG_DIRECTORY=xxxx
|
|
170
170
|
heroku config:add FOG_PROVIDER=Rackspace
|
171
171
|
```
|
172
172
|
|
173
|
-
Google Storage Cloud configuration is supported as well
|
173
|
+
Google Storage Cloud configuration is supported as well. The preferred option is using the [GCS JSON API](https://github.com/fog/fog-google#storage) which requires that you create an appropriate service account, generate the signatures and make them accessible to asset sync at the prescribed location
|
174
|
+
|
175
|
+
```bash
|
176
|
+
heroku config:add FOG_PROVIDER=Google
|
177
|
+
heroku config:add GOOGLE_PROJECT=xxxx
|
178
|
+
heroku config:add GOOGLE_JSON_KEY_LOCATION=xxxx
|
179
|
+
heroku config:add FOG_DIRECTORY=xxxx
|
180
|
+
```
|
181
|
+
|
182
|
+
If using the S3 API the following config is required
|
183
|
+
|
174
184
|
``` bash
|
175
185
|
heroku config:add FOG_PROVIDER=Google
|
176
186
|
heroku config:add GOOGLE_STORAGE_ACCESS_KEY_ID=xxxx
|
@@ -198,6 +208,7 @@ AssetSync.configure do |config|
|
|
198
208
|
config.fog_directory = ENV['FOG_DIRECTORY']
|
199
209
|
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
200
210
|
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
211
|
+
config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
|
201
212
|
|
202
213
|
# Don't delete files from the store
|
203
214
|
# config.existing_remote_files = 'keep'
|
@@ -216,6 +227,9 @@ AssetSync.configure do |config|
|
|
216
227
|
# Change host option in fog (only if you need to)
|
217
228
|
# config.fog_host = 's3.amazonaws.com'
|
218
229
|
#
|
230
|
+
# Change port option in fog (only if you need to)
|
231
|
+
# config.fog_port = "9000"
|
232
|
+
#
|
219
233
|
# Use http instead of https.
|
220
234
|
# config.fog_scheme = 'http'
|
221
235
|
#
|
@@ -229,6 +243,15 @@ AssetSync.configure do |config|
|
|
229
243
|
# Upload the manifest file also.
|
230
244
|
# config.include_manifest = false
|
231
245
|
#
|
246
|
+
# Upload files concurrently
|
247
|
+
# config.concurrent_uploads = false
|
248
|
+
#
|
249
|
+
# Number of threads when concurrent_uploads is enabled
|
250
|
+
# config.concurrent_uploads_max_threads = 10
|
251
|
+
#
|
252
|
+
# Path to cache file to skip scanning remote
|
253
|
+
# config.remote_file_list_cache_file_path = './.asset_sync_remote_file_list_cache.json'
|
254
|
+
#
|
232
255
|
# Fail silently. Useful for environments such as Heroku
|
233
256
|
# config.fail_silently = true
|
234
257
|
#
|
@@ -325,6 +348,9 @@ AssetSync.config.gzip_compression == ENV['ASSET_SYNC_GZIP_COMPRESSION']
|
|
325
348
|
* **gzip\_compression**: (`true, false`) when enabled, will automatically replace files that have a gzip compressed equivalent with the compressed version. **default:** `'false'`
|
326
349
|
* **manifest**: (`true, false`) when enabled, will use the `manifest.yml` generated by Rails to get the list of local files to upload. **experimental**. **default:** `'false'`
|
327
350
|
* **include_manifest**: (`true, false`) when enabled, will upload the `manifest.yml` generated by Rails. **default:** `'false'`
|
351
|
+
* **concurrent_uploads**: (`true, false`) when enabled, will upload the files in different Threads, this greatly improves the upload speed. **default:** `'false'`
|
352
|
+
* **concurrent_uploads_max_threads**: when concurrent_uploads is enabled, this determines the number of threads that will be created. **default:** `10`
|
353
|
+
* **remote_file_list_cache_file_path**: if present, use this path to cache remote file list to skip scanning remote **default:** `nil`
|
328
354
|
* **enabled**: (`true, false`) when false, will disable asset sync. **default:** `'true'` (enabled)
|
329
355
|
* **ignored\_files**: an array of files to ignore e.g. `['ignore_me.js', %r(ignore_some/\d{32}\.css)]` Useful if there are some files that are created dynamically on the server and you don't want to upload on deploy **default**: `[]`
|
330
356
|
* **cache\_asset\_regexps**: an array of files to add cache headers e.g. `['cache_me.js', %r(cache_some\.\d{8}\.css)]` Useful if there are some files that are added to sprockets assets list and need to be set as 'Cacheable' on uploaded server. Only rails compiled regexp is matched internally **default**: `[]`
|
@@ -385,6 +411,14 @@ The blocks are run when local files are being scanned and uploaded
|
|
385
411
|
* **rackspace\_api\_key**: your Rackspace API Key.
|
386
412
|
|
387
413
|
#### Google Storage
|
414
|
+
|
415
|
+
When using the JSON API
|
416
|
+
|
417
|
+
- **google\_project**: your Google Cloud Project name where the Google Cloud Storage bucket resides
|
418
|
+
- **google\_json\_key\_location**: path to the location of the service account key. The service account key must be a JSON type key
|
419
|
+
|
420
|
+
When using the S3 API
|
421
|
+
|
388
422
|
* **google\_storage\_access\_key\_id**: your Google Storage access key
|
389
423
|
* **google\_storage\_secret\_access\_key**: your Google Storage access secret
|
390
424
|
|
@@ -515,6 +549,10 @@ AssetSync.configure do |config|
|
|
515
549
|
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
516
550
|
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
517
551
|
config.prefix = 'assets'
|
552
|
+
# Can be a `Pathname` or `String`
|
553
|
+
# Will be converted into an `Pathname`
|
554
|
+
# If relative, will be converted into an absolute path
|
555
|
+
# via `::Rails.root` or `::Dir.pwd`
|
518
556
|
config.public_path = Pathname('./public')
|
519
557
|
end
|
520
558
|
```
|
@@ -584,7 +622,7 @@ Make sure you have a .env file with these details:-
|
|
584
622
|
AWS_SECRET_ACCESS_KEY=<yoursecretkey>
|
585
623
|
FOG_DIRECTORY=<yourbucket>
|
586
624
|
FOG_REGION=<youbucketregion>
|
587
|
-
|
625
|
+
|
588
626
|
# for AzureRM provider
|
589
627
|
AZURE_STORAGE_ACCOUNT_NAME=<youraccountname>
|
590
628
|
AZURE_STORAGE_ACCESS_KEY=<youraccesskey>
|
data/asset_sync.gemspec
CHANGED
@@ -5,6 +5,6 @@ source "https://rubygems.org"
|
|
5
5
|
gem "rcov", platforms: :mri_18, group: [:development, :test]
|
6
6
|
gem "simplecov", platforms: [:jruby, :mri_19, :ruby_19, :mri_20, :rbx], group: [:development, :test], require: false
|
7
7
|
gem "jruby-openssl", platform: :jruby
|
8
|
-
gem "rails", "~>
|
8
|
+
gem "rails", "~> 6.0.0"
|
9
9
|
|
10
10
|
gemspec path: "../"
|
data/lib/asset_sync/config.rb
CHANGED
@@ -26,7 +26,9 @@ module AssetSync
|
|
26
26
|
attr_accessor :cdn_distribution_id
|
27
27
|
attr_accessor :cache_asset_regexps
|
28
28
|
attr_accessor :include_manifest
|
29
|
-
|
29
|
+
attr_accessor :concurrent_uploads
|
30
|
+
attr_accessor :concurrent_uploads_max_threads
|
31
|
+
attr_accessor :remote_file_list_cache_file_path
|
30
32
|
|
31
33
|
# FOG configuration
|
32
34
|
attr_accessor :fog_provider # Currently Supported ['AWS', 'Rackspace']
|
@@ -35,8 +37,9 @@ module AssetSync
|
|
35
37
|
attr_reader :fog_public # e.g. true, false, "default"
|
36
38
|
|
37
39
|
# Amazon AWS
|
38
|
-
attr_accessor :aws_access_key_id, :aws_secret_access_key, :aws_reduced_redundancy, :aws_iam_roles, :aws_signature_version
|
40
|
+
attr_accessor :aws_access_key_id, :aws_secret_access_key, :aws_session_token, :aws_reduced_redundancy, :aws_iam_roles, :aws_signature_version
|
39
41
|
attr_accessor :fog_host # e.g. 's3.amazonaws.com'
|
42
|
+
attr_accessor :fog_port # e.g. '9000'
|
40
43
|
attr_accessor :fog_path_style # e.g. true
|
41
44
|
attr_accessor :fog_scheme # e.g. 'http'
|
42
45
|
|
@@ -44,7 +47,9 @@ module AssetSync
|
|
44
47
|
attr_accessor :rackspace_username, :rackspace_api_key, :rackspace_auth_url
|
45
48
|
|
46
49
|
# Google Storage
|
47
|
-
attr_accessor :google_storage_secret_access_key, :google_storage_access_key_id
|
50
|
+
attr_accessor :google_storage_secret_access_key, :google_storage_access_key_id # when using S3 interop
|
51
|
+
attr_accessor :google_json_key_location # when using service accounts
|
52
|
+
attr_accessor :google_project # when using service accounts
|
48
53
|
|
49
54
|
# Azure Blob with Fog::AzureRM
|
50
55
|
attr_accessor :azure_storage_account_name
|
@@ -59,8 +64,11 @@ module AssetSync
|
|
59
64
|
validates :aws_secret_access_key, :presence => true, :if => proc {aws? && !aws_iam?}
|
60
65
|
validates :rackspace_username, :presence => true, :if => :rackspace?
|
61
66
|
validates :rackspace_api_key, :presence => true, :if => :rackspace?
|
62
|
-
validates :google_storage_secret_access_key, :presence => true, :if => :
|
63
|
-
validates :google_storage_access_key_id, :presence => true, :if => :
|
67
|
+
validates :google_storage_secret_access_key, :presence => true, :if => :google_interop?
|
68
|
+
validates :google_storage_access_key_id, :presence => true, :if => :google_interop?
|
69
|
+
validates :google_json_key_location, :presence => true, :if => :google_service_account?
|
70
|
+
validates :google_project, :presence => true, :if => :google_service_account?
|
71
|
+
validates :concurrent_uploads, :inclusion => { :in => [true, false] }
|
64
72
|
|
65
73
|
def initialize
|
66
74
|
self.fog_region = nil
|
@@ -79,6 +87,9 @@ module AssetSync
|
|
79
87
|
self.invalidate = []
|
80
88
|
self.cache_asset_regexps = []
|
81
89
|
self.include_manifest = false
|
90
|
+
self.concurrent_uploads = false
|
91
|
+
self.concurrent_uploads_max_threads = 10
|
92
|
+
self.remote_file_list_cache_file_path = nil
|
82
93
|
@additional_local_file_paths_procs = []
|
83
94
|
|
84
95
|
load_yml! if defined?(::Rails) && yml_exists?
|
@@ -130,6 +141,14 @@ module AssetSync
|
|
130
141
|
fog_provider =~ /google/i
|
131
142
|
end
|
132
143
|
|
144
|
+
def google_interop?
|
145
|
+
google? && google_json_key_location.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
def google_service_account?
|
149
|
+
google? && google_json_key_location
|
150
|
+
end
|
151
|
+
|
133
152
|
def azure_rm?
|
134
153
|
fog_provider =~ /azurerm/i
|
135
154
|
end
|
@@ -159,10 +178,24 @@ module AssetSync
|
|
159
178
|
@public_path || ::Rails.public_path
|
160
179
|
end
|
161
180
|
|
181
|
+
def public_path=(path)
|
182
|
+
# Generate absolute path even when relative path passed in
|
183
|
+
# Required for generating relative sprockets manifest path
|
184
|
+
pathname = Pathname(path)
|
185
|
+
@public_path = if pathname.absolute?
|
186
|
+
pathname
|
187
|
+
elsif defined?(::Rails.root)
|
188
|
+
::Rails.root.join(pathname)
|
189
|
+
else
|
190
|
+
Pathname(::Dir.pwd).join(pathname)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
162
194
|
def load_yml!
|
163
195
|
self.enabled = yml["enabled"] if yml.has_key?('enabled')
|
164
196
|
self.fog_provider = yml["fog_provider"]
|
165
197
|
self.fog_host = yml["fog_host"]
|
198
|
+
self.fog_port = yml["fog_port"]
|
166
199
|
self.fog_directory = yml["fog_directory"]
|
167
200
|
self.fog_region = yml["fog_region"]
|
168
201
|
self.fog_public = yml["fog_public"] if yml.has_key?("fog_public")
|
@@ -170,14 +203,17 @@ module AssetSync
|
|
170
203
|
self.fog_scheme = yml["fog_scheme"]
|
171
204
|
self.aws_access_key_id = yml["aws_access_key_id"]
|
172
205
|
self.aws_secret_access_key = yml["aws_secret_access_key"]
|
206
|
+
self.aws_session_token = yml["aws_session_token"] if yml.has_key?("aws_session_token")
|
173
207
|
self.aws_reduced_redundancy = yml["aws_reduced_redundancy"]
|
174
208
|
self.aws_iam_roles = yml["aws_iam_roles"]
|
175
209
|
self.aws_signature_version = yml["aws_signature_version"]
|
176
210
|
self.rackspace_username = yml["rackspace_username"]
|
177
211
|
self.rackspace_auth_url = yml["rackspace_auth_url"] if yml.has_key?("rackspace_auth_url")
|
178
212
|
self.rackspace_api_key = yml["rackspace_api_key"]
|
179
|
-
self.
|
180
|
-
self.
|
213
|
+
self.google_json_key_location = yml["google_json_key_location"] if yml.has_key?("google_json_key_location")
|
214
|
+
self.google_project = yml["google_project"] if yml.has_key?("google_project")
|
215
|
+
self.google_storage_secret_access_key = yml["google_storage_secret_access_key"] if yml.has_key?("google_storage_secret_access_key")
|
216
|
+
self.google_storage_access_key_id = yml["google_storage_access_key_id"] if yml.has_key?("google_storage_access_key_id")
|
181
217
|
self.existing_remote_files = yml["existing_remote_files"] if yml.has_key?("existing_remote_files")
|
182
218
|
self.gzip_compression = yml["gzip_compression"] if yml.has_key?("gzip_compression")
|
183
219
|
self.manifest = yml["manifest"] if yml.has_key?("manifest")
|
@@ -190,6 +226,9 @@ module AssetSync
|
|
190
226
|
self.cdn_distribution_id = yml['cdn_distribution_id'] if yml.has_key?("cdn_distribution_id")
|
191
227
|
self.cache_asset_regexps = yml['cache_asset_regexps'] if yml.has_key?("cache_asset_regexps")
|
192
228
|
self.include_manifest = yml['include_manifest'] if yml.has_key?("include_manifest")
|
229
|
+
self.concurrent_uploads = yml['concurrent_uploads'] if yml.has_key?('concurrent_uploads')
|
230
|
+
self.concurrent_uploads_max_threads = yml['concurrent_uploads_max_threads'] if yml.has_key?('concurrent_uploads_max_threads')
|
231
|
+
self.remote_file_list_cache_file_path = yml['remote_file_list_cache_file_path'] if yml.has_key?('remote_file_list_cache_file_path')
|
193
232
|
|
194
233
|
self.azure_storage_account_name = yml['azure_storage_account_name'] if yml.has_key?("azure_storage_account_name")
|
195
234
|
self.azure_storage_access_key = yml['azure_storage_access_key'] if yml.has_key?("azure_storage_access_key")
|
@@ -222,8 +261,10 @@ module AssetSync
|
|
222
261
|
:aws_access_key_id => aws_access_key_id,
|
223
262
|
:aws_secret_access_key => aws_secret_access_key
|
224
263
|
})
|
264
|
+
options.merge!({:aws_session_token => aws_session_token}) if aws_session_token
|
225
265
|
end
|
226
266
|
options.merge!({:host => fog_host}) if fog_host
|
267
|
+
options.merge!({:port => fog_port}) if fog_port
|
227
268
|
options.merge!({:scheme => fog_scheme}) if fog_scheme
|
228
269
|
options.merge!({:aws_signature_version => aws_signature_version}) if aws_signature_version
|
229
270
|
options.merge!({:path_style => fog_path_style}) if fog_path_style
|
@@ -236,10 +277,14 @@ module AssetSync
|
|
236
277
|
options.merge!({ :rackspace_region => fog_region }) if fog_region
|
237
278
|
options.merge!({ :rackspace_auth_url => rackspace_auth_url }) if rackspace_auth_url
|
238
279
|
elsif google?
|
239
|
-
|
240
|
-
:
|
241
|
-
|
242
|
-
|
280
|
+
if google_json_key_location
|
281
|
+
options.merge!({:google_json_key_location => google_json_key_location, :google_project => google_project})
|
282
|
+
else
|
283
|
+
options.merge!({
|
284
|
+
:google_storage_secret_access_key => google_storage_secret_access_key,
|
285
|
+
:google_storage_access_key_id => google_storage_access_key_id
|
286
|
+
})
|
287
|
+
end
|
243
288
|
options.merge!({:region => fog_region}) if fog_region
|
244
289
|
elsif azure_rm?
|
245
290
|
require 'fog/azurerm'
|
@@ -340,7 +385,7 @@ module AssetSync
|
|
340
385
|
end
|
341
386
|
|
342
387
|
def to_bool
|
343
|
-
|
388
|
+
!!@value
|
344
389
|
end
|
345
390
|
end
|
346
391
|
end
|
data/lib/asset_sync/engine.rb
CHANGED
@@ -17,11 +17,13 @@ module AssetSync
|
|
17
17
|
config.fog_directory = ENV['FOG_DIRECTORY'] if ENV.has_key?('FOG_DIRECTORY')
|
18
18
|
config.fog_region = ENV['FOG_REGION'] if ENV.has_key?('FOG_REGION')
|
19
19
|
config.fog_host = ENV['FOG_HOST'] if ENV.has_key?('FOG_HOST')
|
20
|
+
config.fog_port = ENV['FOG_PORT'] if ENV.has_key?('FOG_PORT')
|
20
21
|
config.fog_scheme = ENV['FOG_SCHEMA'] if ENV.has_key?('FOG_SCHEMA')
|
21
22
|
config.fog_path_style = ENV['FOG_PATH_STYLE'] if ENV.has_key?('FOG_PATH_STYLE')
|
22
23
|
|
23
24
|
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID'] if ENV.has_key?('AWS_ACCESS_KEY_ID')
|
24
25
|
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] if ENV.has_key?('AWS_SECRET_ACCESS_KEY')
|
26
|
+
config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.has_key?('AWS_SESSION_TOKEN')
|
25
27
|
config.aws_signature_version = ENV['AWS_SIGNATURE_VERSION'] if ENV.has_key?('AWS_SIGNATURE_VERSION')
|
26
28
|
config.aws_reduced_redundancy = ENV['AWS_REDUCED_REDUNDANCY'] == true if ENV.has_key?('AWS_REDUCED_REDUNDANCY')
|
27
29
|
|
@@ -41,6 +43,8 @@ module AssetSync
|
|
41
43
|
config.gzip_compression = (ENV['ASSET_SYNC_GZIP_COMPRESSION'] == 'true') if ENV.has_key?('ASSET_SYNC_GZIP_COMPRESSION')
|
42
44
|
config.manifest = (ENV['ASSET_SYNC_MANIFEST'] == 'true') if ENV.has_key?('ASSET_SYNC_MANIFEST')
|
43
45
|
config.include_manifest = (ENV['ASSET_SYNC_INCLUDE_MANIFEST'] == 'true') if ENV.has_key?('ASSET_SYNC_INCLUDE_MANIFEST')
|
46
|
+
config.concurrent_uploads = (ENV['ASSET_SYNC_CONCURRENT_UPLOADS'] == 'true') if ENV.has_key?('ASSET_SYNC_CONCURRENT_UPLOADS')
|
47
|
+
config.remote_file_list_cache_file_path = ENV['ASSET_SYNC_REMOTE_FILE_LIST_CACHE_FILE_PATH'] if ENV.has_key?('ASSET_SYNC_REMOTE_FILE_LIST_CACHE_FILE_PATH')
|
44
48
|
end
|
45
49
|
|
46
50
|
config.prefix = ENV['ASSET_SYNC_PREFIX'] if ENV.has_key?('ASSET_SYNC_PREFIX')
|
@@ -11,9 +11,9 @@ module AssetSync
|
|
11
11
|
end
|
12
12
|
|
13
13
|
if defined?(::MIME::Types)
|
14
|
-
::MIME::Types.type_for(ext).first
|
14
|
+
::MIME::Types.type_for(ext).first.to_s
|
15
15
|
elsif defined?(::Mime::Type)
|
16
|
-
::Mime::Type.lookup_by_extension(ext)
|
16
|
+
::Mime::Type.lookup_by_extension(ext).to_s
|
17
17
|
elsif defined?(::Rack::Mime)
|
18
18
|
ext_with_dot = ".#{ext}"
|
19
19
|
::Rack::Mime.mime_type(ext_with_dot)
|
data/lib/asset_sync/storage.rb
CHANGED
@@ -37,6 +37,10 @@ module AssetSync
|
|
37
37
|
self.config.public_path
|
38
38
|
end
|
39
39
|
|
40
|
+
def remote_file_list_cache_file_path
|
41
|
+
self.config.remote_file_list_cache_file_path
|
42
|
+
end
|
43
|
+
|
40
44
|
def ignored_files
|
41
45
|
expand_file_names(self.config.ignored_files)
|
42
46
|
end
|
@@ -58,6 +62,32 @@ module AssetSync
|
|
58
62
|
(get_local_files + config.additional_local_file_paths).uniq
|
59
63
|
end
|
60
64
|
|
65
|
+
def remote_files
|
66
|
+
return [] if ignore_existing_remote_files?
|
67
|
+
return @remote_files if @remote_files
|
68
|
+
|
69
|
+
if remote_file_list_cache_file_path && File.file?(remote_file_list_cache_file_path)
|
70
|
+
begin
|
71
|
+
content = File.read(remote_file_list_cache_file_path)
|
72
|
+
return @remote_files = JSON.parse(content)
|
73
|
+
rescue JSON::ParserError
|
74
|
+
warn "Failed to parse #{remote_file_list_cache_file_path} as json"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
@remote_files = get_remote_files
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_remote_file_list_cache(local_files_to_upload)
|
82
|
+
return unless remote_file_list_cache_file_path
|
83
|
+
return if ignore_existing_remote_files?
|
84
|
+
|
85
|
+
File.open(self.remote_file_list_cache_file_path, 'w') do |file|
|
86
|
+
uploaded = local_files_to_upload + remote_files
|
87
|
+
file.write(uploaded.to_json)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
61
91
|
def always_upload_files
|
62
92
|
expand_file_names(self.config.always_upload) + get_manifest_path
|
63
93
|
end
|
@@ -132,9 +162,15 @@ module AssetSync
|
|
132
162
|
from_remote_files_to_delete = remote_files - local_files - ignored_files - always_upload_files
|
133
163
|
|
134
164
|
log "Flagging #{from_remote_files_to_delete.size} file(s) for deletion"
|
135
|
-
# Delete unneeded remote files
|
136
|
-
|
137
|
-
|
165
|
+
# Delete unneeded remote files, if we are on aws delete in bulk else use sequential delete
|
166
|
+
if self.config.aws? && connection.respond_to?(:delete_multiple_objects)
|
167
|
+
from_remote_files_to_delete.each_slice(500) do |slice|
|
168
|
+
connection.delete_multiple_objects(config.fog_directory, slice)
|
169
|
+
end
|
170
|
+
else
|
171
|
+
bucket.files.each do |f|
|
172
|
+
delete_file(f, from_remote_files_to_delete)
|
173
|
+
end
|
138
174
|
end
|
139
175
|
end
|
140
176
|
|
@@ -231,28 +267,38 @@ module AssetSync
|
|
231
267
|
})
|
232
268
|
end
|
233
269
|
|
234
|
-
if config.azure_rm?
|
235
|
-
# converts content_type from MIME::Type to String.
|
236
|
-
# because Azure::Storage (called from Fog::AzureRM) expects content_type as a String like "application/json; charset=utf-8"
|
237
|
-
file[:content_type] = file[:content_type].content_type if file[:content_type].is_a?(::MIME::Type)
|
238
|
-
end
|
239
|
-
|
240
270
|
bucket.files.create( file ) unless ignore
|
241
271
|
file_handle.close
|
242
272
|
gzip_file_handle.close if gzip_file_handle
|
243
273
|
end
|
244
274
|
|
245
275
|
def upload_files
|
246
|
-
# get a fresh list of remote files
|
247
|
-
remote_files = ignore_existing_remote_files? ? [] : get_remote_files
|
248
276
|
# fixes: https://github.com/rumblelabs/asset_sync/issues/19
|
249
277
|
local_files_to_upload = local_files - ignored_files - remote_files + always_upload_files
|
250
278
|
local_files_to_upload = (local_files_to_upload + get_non_fingerprinted(local_files_to_upload)).uniq
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
279
|
+
# Only files.
|
280
|
+
local_files_to_upload = local_files_to_upload.select { |f| File.file? "#{path}/#{f}" }
|
281
|
+
|
282
|
+
if self.config.concurrent_uploads
|
283
|
+
jobs = Queue.new
|
284
|
+
local_files_to_upload.each { |f| jobs.push(f) }
|
285
|
+
jobs.close
|
286
|
+
|
287
|
+
num_threads = [self.config.concurrent_uploads_max_threads, local_files_to_upload.length].min
|
288
|
+
# Upload new files
|
289
|
+
workers = Array.new(num_threads) do
|
290
|
+
Thread.new do
|
291
|
+
while f = jobs.pop
|
292
|
+
upload_file(f)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
workers.map(&:join)
|
297
|
+
else
|
298
|
+
# Upload new files
|
299
|
+
local_files_to_upload.each do |f|
|
300
|
+
upload_file f
|
301
|
+
end
|
256
302
|
end
|
257
303
|
|
258
304
|
if self.config.cdn_distribution_id && files_to_invalidate.any?
|
@@ -261,6 +307,8 @@ module AssetSync
|
|
261
307
|
data = cdn.post_invalidation(self.config.cdn_distribution_id, files_to_invalidate)
|
262
308
|
log "Invalidation id: #{data.body["Id"]}"
|
263
309
|
end
|
310
|
+
|
311
|
+
update_remote_file_list_cache(local_files_to_upload)
|
264
312
|
end
|
265
313
|
|
266
314
|
def sync
|
data/lib/asset_sync/version.rb
CHANGED
@@ -4,6 +4,7 @@ if defined?(AssetSync)
|
|
4
4
|
config.fog_provider = 'AWS'
|
5
5
|
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
6
6
|
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
7
|
+
config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
|
7
8
|
# To use AWS reduced redundancy storage.
|
8
9
|
# config.aws_reduced_redundancy = true
|
9
10
|
#
|
@@ -13,6 +14,9 @@ if defined?(AssetSync)
|
|
13
14
|
# Change host option in fog (only if you need to)
|
14
15
|
# config.fog_host = "s3.amazonaws.com"
|
15
16
|
#
|
17
|
+
# Change port option in fog (only if you need to)
|
18
|
+
# config.fog_port = "9000"
|
19
|
+
#
|
16
20
|
# Use http instead of https. Default should be "https" (at least for fog-aws)
|
17
21
|
# config.fog_scheme = "http"
|
18
22
|
<%- elsif google? -%>
|
@@ -60,6 +64,12 @@ if defined?(AssetSync)
|
|
60
64
|
# Upload the manifest file also.
|
61
65
|
# config.include_manifest = false
|
62
66
|
#
|
67
|
+
# Upload files concurrently
|
68
|
+
# config.concurrent_uploads = false
|
69
|
+
#
|
70
|
+
# Path to cache file to skip scanning remote
|
71
|
+
# config.remote_file_list_cache_file_path = './.asset_sync_remote_file_list_cache.json'
|
72
|
+
#
|
63
73
|
# Fail silently. Useful for environments such as Heroku
|
64
74
|
# config.fail_silently = true
|
65
75
|
#
|
@@ -13,6 +13,9 @@ defaults: &defaults
|
|
13
13
|
# Change host option in fog (only if you need to)
|
14
14
|
# fog_host: "s3.amazonaws.com"
|
15
15
|
#
|
16
|
+
# Change port option in fog (only if you need to)
|
17
|
+
# config.fog_port = "9000"
|
18
|
+
#
|
16
19
|
# Use http instead of https. Default should be "https" (at least for fog-aws)
|
17
20
|
# fog_scheme: "http"
|
18
21
|
<%- elsif google? -%>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
fog_provider: "Google"
|
3
|
+
google_json_key_location: 'gcs.json'
|
4
|
+
google_project: 'some-project'
|
5
|
+
|
6
|
+
development:
|
7
|
+
<<: *defaults
|
8
|
+
fog_directory: "rails_app_development"
|
9
|
+
existing_remote_files: keep
|
10
|
+
|
11
|
+
test:
|
12
|
+
<<: *defaults
|
13
|
+
fog_directory: "rails_app_test"
|
14
|
+
existing_remote_files: keep
|
15
|
+
|
16
|
+
production:
|
17
|
+
<<: *defaults
|
18
|
+
fog_directory: "rails_app_production"
|
19
|
+
existing_remote_files: delete
|
@@ -145,7 +145,7 @@ describe AssetSync do
|
|
145
145
|
|
146
146
|
it "should default asset_regexps to match regexps" do
|
147
147
|
expect(AssetSync.config.cache_asset_regexps).to eq(['cache_me.js', /cache_some\.\d{8}\.css/])
|
148
|
-
end
|
148
|
+
end
|
149
149
|
end
|
150
150
|
|
151
151
|
describe 'from yml, exporting to a mobile hybrid development directory' do
|
@@ -255,12 +255,12 @@ describe AssetSync do
|
|
255
255
|
expect(AssetSync.config.manifest_path).to match(/public\/custom_assets\/manifest.yml/)
|
256
256
|
end
|
257
257
|
end
|
258
|
-
|
258
|
+
|
259
259
|
describe 'with cache_asset_regexps' do
|
260
260
|
before(:each) do
|
261
261
|
AssetSync.config = AssetSync::Config.new
|
262
262
|
end
|
263
|
-
|
263
|
+
|
264
264
|
it "config.cache_asset_regexp should set cache_asset_regexps" do
|
265
265
|
AssetSync.config.cache_asset_regexp = /\.[a-f0-9]{8}/i
|
266
266
|
expect(AssetSync.config.cache_asset_regexps.size).to eq(1)
|
@@ -283,4 +283,36 @@ describe AssetSync do
|
|
283
283
|
expect{ AssetSync::Config.new }.to raise_error(Psych::SyntaxError)
|
284
284
|
end
|
285
285
|
end
|
286
|
+
|
287
|
+
describe 'FogPublicValue' do
|
288
|
+
describe "#to_bool" do
|
289
|
+
it "true should be converted to true" do
|
290
|
+
expect(AssetSync::Config::FogPublicValue.new(true).to_bool).to be_truthy
|
291
|
+
end
|
292
|
+
it "false should be converted to false" do
|
293
|
+
expect(AssetSync::Config::FogPublicValue.new(false).to_bool).to be_falsey
|
294
|
+
end
|
295
|
+
it "nil should be converted to false" do
|
296
|
+
expect(AssetSync::Config::FogPublicValue.new(nil).to_bool).to be_falsey
|
297
|
+
end
|
298
|
+
it "'default' should be converted to false" do
|
299
|
+
expect(AssetSync::Config::FogPublicValue.new("default").to_bool).to be_truthy
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe "#use_explicit_value?" do
|
304
|
+
it "true should be converted to true" do
|
305
|
+
expect(AssetSync::Config::FogPublicValue.new(true).use_explicit_value?).to be_truthy
|
306
|
+
end
|
307
|
+
it "false should be converted to true" do
|
308
|
+
expect(AssetSync::Config::FogPublicValue.new(false).use_explicit_value?).to be_truthy
|
309
|
+
end
|
310
|
+
it "nil should be converted to true" do
|
311
|
+
expect(AssetSync::Config::FogPublicValue.new(nil).use_explicit_value?).to be_truthy
|
312
|
+
end
|
313
|
+
it "'default' should be converted to false" do
|
314
|
+
expect(AssetSync::Config::FogPublicValue.new("default").use_explicit_value?).to be_falsey
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
286
318
|
end
|
data/spec/unit/google_spec.rb
CHANGED
@@ -8,8 +8,6 @@ describe AssetSync do
|
|
8
8
|
AssetSync.config = AssetSync::Config.new
|
9
9
|
AssetSync.configure do |config|
|
10
10
|
config.fog_provider = 'Google'
|
11
|
-
config.google_storage_access_key_id = 'aaaa'
|
12
|
-
config.google_storage_secret_access_key = 'bbbb'
|
13
11
|
config.fog_directory = 'mybucket'
|
14
12
|
config.existing_remote_files = "keep"
|
15
13
|
end
|
@@ -24,14 +22,6 @@ describe AssetSync do
|
|
24
22
|
expect(AssetSync.config.existing_remote_files?).to eq(true)
|
25
23
|
end
|
26
24
|
|
27
|
-
it "should configure google_storage_access_key_id" do
|
28
|
-
expect(AssetSync.config.google_storage_access_key_id).to eq("aaaa")
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should configure google_storage_secret_access_key" do
|
32
|
-
expect(AssetSync.config.google_storage_secret_access_key).to eq("bbbb")
|
33
|
-
end
|
34
|
-
|
35
25
|
it "should configure fog_directory" do
|
36
26
|
expect(AssetSync.config.fog_directory).to eq("mybucket")
|
37
27
|
end
|
@@ -47,36 +37,119 @@ describe AssetSync do
|
|
47
37
|
it "should default manifest to false" do
|
48
38
|
expect(AssetSync.config.manifest).to be_falsey
|
49
39
|
end
|
50
|
-
end
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
41
|
+
describe "when using S3 interop API" do
|
42
|
+
before(:each) do
|
43
|
+
AssetSync.configure do |config|
|
44
|
+
config.google_storage_access_key_id = 'aaaa'
|
45
|
+
config.google_storage_secret_access_key = 'bbbb'
|
46
|
+
end
|
47
|
+
end
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
|
49
|
+
it "should configure google_storage_access_key_id" do
|
50
|
+
expect(AssetSync.config.google_storage_access_key_id).to eq("aaaa")
|
51
|
+
end
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
53
|
+
it "should configure google_storage_secret_access_key" do
|
54
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq("bbbb")
|
55
|
+
end
|
65
56
|
|
66
|
-
|
67
|
-
|
57
|
+
it "should return the correct fog_options" do
|
58
|
+
expected_fog_options = { google_storage_access_key_id: "aaaa",
|
59
|
+
google_storage_secret_access_key: "bbbb",
|
60
|
+
provider: "Google"}
|
61
|
+
expect(AssetSync.config.fog_options).to eq(expected_fog_options)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not require that google_json_key_location be set" do
|
65
|
+
expect(AssetSync.config.valid?).to eq(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should require that google_storage_secret_access_key or access_key_id be set" do
|
69
|
+
|
70
|
+
AssetSync.configure do |config|
|
71
|
+
config.google_storage_access_key_id = nil
|
72
|
+
config.google_storage_secret_access_key = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
expect(AssetSync.config.valid?).to eq(false)
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
70
|
-
|
71
|
-
|
79
|
+
describe "when using service account" do
|
80
|
+
before(:each) do
|
81
|
+
AssetSync.configure do |config|
|
82
|
+
config.google_json_key_location = '/path/to.json'
|
83
|
+
config.google_project = 'a-google-project-name'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should configure google_json_key_location" do
|
88
|
+
expect(AssetSync.config.google_json_key_location).to eq("/path/to.json")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return the correct fog_options" do
|
92
|
+
expected_fog_options = { google_json_key_location: "/path/to.json",
|
93
|
+
google_project: 'a-google-project-name',
|
94
|
+
provider: "Google"}
|
95
|
+
expect(AssetSync.config.fog_options).to eq(expected_fog_options)
|
96
|
+
end
|
97
|
+
it "should not require that google_storage_secret_access_key or access_key_id be set" do
|
98
|
+
expect(AssetSync.config.valid?).to eq(true)
|
99
|
+
end
|
72
100
|
end
|
73
101
|
|
74
|
-
|
75
|
-
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'from yml' do
|
105
|
+
describe 'when using S3 interop API' do
|
106
|
+
before(:each) do
|
107
|
+
set_rails_root('google_with_yml')
|
108
|
+
AssetSync.config = AssetSync::Config.new
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should configure google_storage_access_key_id" do
|
112
|
+
expect(AssetSync.config.google_storage_access_key_id).to eq("xxxx")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should configure google_storage_secret_access_key" do
|
116
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq("zzzz")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should not configure google_json_key_location" do
|
120
|
+
expect(AssetSync.config.google_json_key_location).to eq(nil)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should configure fog_directory" do
|
124
|
+
expect(AssetSync.config.fog_directory).to eq("rails_app_test")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should configure existing_remote_files" do
|
128
|
+
expect(AssetSync.config.existing_remote_files).to eq("keep")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should default gzip_compression to false" do
|
132
|
+
expect(AssetSync.config.gzip_compression).to be_falsey
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should default manifest to false" do
|
136
|
+
expect(AssetSync.config.manifest).to be_falsey
|
137
|
+
end
|
76
138
|
end
|
77
139
|
|
78
|
-
|
79
|
-
|
140
|
+
describe 'when using service account API' do
|
141
|
+
before(:each) do
|
142
|
+
set_rails_root('google_with_service_account_yml')
|
143
|
+
AssetSync.config = AssetSync::Config.new
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should configure google_json_key_location" do
|
147
|
+
expect(AssetSync.config.google_json_key_location).to eq("gcs.json")
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not configure google_storage_secret_access_key" do
|
151
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq(nil)
|
152
|
+
end
|
80
153
|
end
|
81
154
|
end
|
82
155
|
|
data/spec/unit/railsless_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe AssetSync do
|
|
14
14
|
config.fog_region = 'eu-west-1'
|
15
15
|
config.existing_remote_files = "keep"
|
16
16
|
config.prefix = "assets"
|
17
|
-
config.public_path =
|
17
|
+
config.public_path = "./public"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -22,8 +22,9 @@ describe AssetSync do
|
|
22
22
|
expect(AssetSync.config.prefix).to eq("assets")
|
23
23
|
end
|
24
24
|
|
25
|
-
it "should have
|
26
|
-
expect(AssetSync.config.public_path.to_s).to
|
25
|
+
it "should have public_path" do
|
26
|
+
expect(AssetSync.config.public_path.to_s).to be_end_with("/public")
|
27
|
+
expect(AssetSync.config.public_path).to be_absolute
|
27
28
|
end
|
28
29
|
|
29
30
|
it "should default AssetSync to enabled" do
|
data/spec/unit/storage_spec.rb
CHANGED
@@ -54,6 +54,87 @@ describe AssetSync::Storage do
|
|
54
54
|
storage.upload_files
|
55
55
|
end
|
56
56
|
|
57
|
+
it 'should upload files concurrently if enabled' do
|
58
|
+
@config.concurrent_uploads = true
|
59
|
+
storage = AssetSync::Storage.new(@config)
|
60
|
+
|
61
|
+
allow(storage).to receive(:get_local_files).and_return(@local_files)
|
62
|
+
allow(storage).to receive(:get_remote_files).and_return(@remote_files)
|
63
|
+
allow(File).to receive(:file?).and_return(true) # Pretend they all exist
|
64
|
+
|
65
|
+
expect(Thread).to receive(:new).exactly(3).times.and_call_original
|
66
|
+
(@local_files - @remote_files + storage.always_upload_files).each do |file|
|
67
|
+
expect(storage).to receive(:upload_file).with(file)
|
68
|
+
end
|
69
|
+
|
70
|
+
storage.upload_files
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should allow custom number of threads' do
|
74
|
+
@config.concurrent_uploads = true
|
75
|
+
@config.concurrent_uploads_max_threads = 2
|
76
|
+
storage = AssetSync::Storage.new(@config)
|
77
|
+
|
78
|
+
allow(storage).to receive(:get_local_files).and_return(@local_files)
|
79
|
+
allow(storage).to receive(:get_remote_files).and_return(@remote_files)
|
80
|
+
allow(File).to receive(:file?).and_return(true) # Pretend they all exist
|
81
|
+
|
82
|
+
expect(Thread).to receive(:new).exactly(2).times.and_call_original
|
83
|
+
(@local_files - @remote_files + storage.always_upload_files).each do |file|
|
84
|
+
expect(storage).to receive(:upload_file).with(file)
|
85
|
+
end
|
86
|
+
|
87
|
+
storage.upload_files
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should allow remote_file_list_cache_file_path configuration' do
|
91
|
+
file_path = './foo.json'
|
92
|
+
@config.remote_file_list_cache_file_path = file_path
|
93
|
+
storage = AssetSync::Storage.new(@config)
|
94
|
+
|
95
|
+
allow(storage).to receive(:get_local_files).and_return(@local_files)
|
96
|
+
File.write(file_path, @remote_files.to_json)
|
97
|
+
expect(storage).not_to receive(:get_remote_files)
|
98
|
+
allow(File).to receive(:file?).and_return(true) # Pretend they all exist
|
99
|
+
|
100
|
+
(@local_files - @remote_files + storage.always_upload_files).each do |file|
|
101
|
+
expect(storage).to receive(:upload_file).with(file)
|
102
|
+
end
|
103
|
+
|
104
|
+
expect(storage).not_to receive(:warn)
|
105
|
+
storage.upload_files
|
106
|
+
|
107
|
+
# update remote_file_list_cache corretly
|
108
|
+
updated = JSON.parse(File.read(file_path))
|
109
|
+
expect(updated.sort.uniq).to eq (@remote_files + @local_files + storage.always_upload_files).sort.uniq
|
110
|
+
|
111
|
+
File.delete(file_path)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should work with broken cache' do
|
115
|
+
file_path = './foo.json'
|
116
|
+
@config.remote_file_list_cache_file_path = file_path
|
117
|
+
|
118
|
+
storage = AssetSync::Storage.new(@config)
|
119
|
+
|
120
|
+
File.write(file_path, 'some non-json text file content')
|
121
|
+
|
122
|
+
allow(storage).to receive(:get_local_files).and_return(@local_files)
|
123
|
+
allow(storage).to receive(:get_remote_files).and_return(@remote_files)
|
124
|
+
allow(File).to receive(:file?).and_return(true) # Pretend they all exist
|
125
|
+
|
126
|
+
(@local_files - @remote_files + storage.always_upload_files).each do |file|
|
127
|
+
expect(storage).to receive(:upload_file).with(file)
|
128
|
+
end
|
129
|
+
|
130
|
+
# when broken, warning message should be prompted
|
131
|
+
expect(storage).to receive(:warn)
|
132
|
+
|
133
|
+
storage.upload_files
|
134
|
+
|
135
|
+
File.delete(file_path)
|
136
|
+
end
|
137
|
+
|
57
138
|
it 'should upload updated non-fingerprinted files' do
|
58
139
|
@local_files = [
|
59
140
|
'public/image.png',
|
@@ -125,7 +206,7 @@ describe AssetSync::Storage do
|
|
125
206
|
end
|
126
207
|
end
|
127
208
|
|
128
|
-
it 'should upload additonal
|
209
|
+
it 'should upload additonal files' do
|
129
210
|
@local_files = [
|
130
211
|
'public/image.png',
|
131
212
|
'public/image-82389298328.png',
|
@@ -307,4 +388,59 @@ describe AssetSync::Storage do
|
|
307
388
|
storage.upload_file('assets/some_longer_path/local_image2.jpg')
|
308
389
|
end
|
309
390
|
end
|
391
|
+
|
392
|
+
describe '#delete_extra_remote_files' do
|
393
|
+
it 'should delete the files in bulk' do
|
394
|
+
remote_files = ['public/image.png']
|
395
|
+
connection = double
|
396
|
+
config = double
|
397
|
+
|
398
|
+
storage = AssetSync::Storage.new(@config)
|
399
|
+
|
400
|
+
[:local_files, :ignored_files, :always_upload_files].each do |method|
|
401
|
+
expect(storage).to receive(method).and_return([])
|
402
|
+
end
|
403
|
+
|
404
|
+
allow(storage).to receive(:get_remote_files).and_return(remote_files)
|
405
|
+
allow(storage).to receive(:connection).and_return(connection).twice
|
406
|
+
allow(storage).to receive(:config).and_return(config).twice
|
407
|
+
allow(config).to receive(:aws?).and_return(true)
|
408
|
+
allow(config).to receive(:fog_directory).and_return('foo')
|
409
|
+
expect(connection).to receive(:delete_multiple_objects).with('foo', remote_files)
|
410
|
+
|
411
|
+
storage.delete_extra_remote_files
|
412
|
+
end
|
413
|
+
|
414
|
+
context 'when not aws' do
|
415
|
+
it 'deletes files sequentially' do
|
416
|
+
remote_files = ['public/image.png']
|
417
|
+
connection = double
|
418
|
+
config = double
|
419
|
+
directories = double
|
420
|
+
directory = double
|
421
|
+
file = double
|
422
|
+
|
423
|
+
storage = AssetSync::Storage.new(@config)
|
424
|
+
|
425
|
+
[:local_files, :ignored_files, :always_upload_files].each do |method|
|
426
|
+
expect(storage).to receive(method).and_return([])
|
427
|
+
end
|
428
|
+
|
429
|
+
allow(storage).to receive(:get_remote_files).and_return(remote_files)
|
430
|
+
allow(storage).to receive(:connection).and_return(connection).twice
|
431
|
+
allow(storage).to receive(:config).and_return(config)
|
432
|
+
allow(config).to receive(:aws?).and_return(false)
|
433
|
+
allow(config).to receive(:fog_directory).and_return('foo')
|
434
|
+
allow(config).to receive(:assets_prefix).and_return('foo')
|
435
|
+
allow(directories).to receive(:get).and_return(directory)
|
436
|
+
allow(directory).to receive(:files).and_return([file])
|
437
|
+
allow(file).to receive(:key).and_return('public/image.png')
|
438
|
+
allow(connection).to receive(:directories).and_return(directories)
|
439
|
+
expect(connection).not_to receive(:delete_multiple_objects)
|
440
|
+
expect(file).to receive(:destroy)
|
441
|
+
|
442
|
+
storage.delete_extra_remote_files
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
310
446
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asset_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Hamilton
|
8
8
|
- David Rice
|
9
9
|
- Phil McClure
|
10
10
|
- Toby Osbourn
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2020-06-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: fog-core
|
@@ -203,10 +203,10 @@ files:
|
|
203
203
|
- UPGRADING.md
|
204
204
|
- asset_sync.gemspec
|
205
205
|
- docs/heroku.md
|
206
|
-
- gemfiles/rails_4_2.gemfile
|
207
206
|
- gemfiles/rails_5_0.gemfile
|
208
207
|
- gemfiles/rails_5_1.gemfile
|
209
208
|
- gemfiles/rails_5_2.gemfile
|
209
|
+
- gemfiles/rails_6_0.gemfile
|
210
210
|
- lib/asset_sync.rb
|
211
211
|
- lib/asset_sync/asset_sync.rb
|
212
212
|
- lib/asset_sync/config.rb
|
@@ -223,6 +223,7 @@ files:
|
|
223
223
|
- spec/dummy_app/app/assets/javascripts/application.js
|
224
224
|
- spec/fixtures/aws_with_yml/config/asset_sync.yml
|
225
225
|
- spec/fixtures/azure_rm_with_yml/config/asset_sync.yml
|
226
|
+
- spec/fixtures/google_with_service_account_yml/config/asset_sync.yml
|
226
227
|
- spec/fixtures/google_with_yml/config/asset_sync.yml
|
227
228
|
- spec/fixtures/rackspace_with_yml/config/asset_sync.yml
|
228
229
|
- spec/fixtures/with_invalid_yml/config/asset_sync.yml
|
@@ -240,7 +241,7 @@ homepage: https://github.com/rumblelabs/asset_sync
|
|
240
241
|
licenses:
|
241
242
|
- MIT
|
242
243
|
metadata: {}
|
243
|
-
post_install_message:
|
244
|
+
post_install_message:
|
244
245
|
rdoc_options: []
|
245
246
|
require_paths:
|
246
247
|
- lib
|
@@ -255,9 +256,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
255
256
|
- !ruby/object:Gem::Version
|
256
257
|
version: '0'
|
257
258
|
requirements: []
|
258
|
-
|
259
|
-
|
260
|
-
signing_key:
|
259
|
+
rubygems_version: 3.1.4
|
260
|
+
signing_key:
|
261
261
|
specification_version: 4
|
262
262
|
summary: Synchronises Assets in a Rails 3 application and Amazon S3/Cloudfront and
|
263
263
|
Rackspace Cloudfiles
|
@@ -266,6 +266,7 @@ test_files:
|
|
266
266
|
- spec/dummy_app/app/assets/javascripts/application.js
|
267
267
|
- spec/fixtures/aws_with_yml/config/asset_sync.yml
|
268
268
|
- spec/fixtures/azure_rm_with_yml/config/asset_sync.yml
|
269
|
+
- spec/fixtures/google_with_service_account_yml/config/asset_sync.yml
|
269
270
|
- spec/fixtures/google_with_yml/config/asset_sync.yml
|
270
271
|
- spec/fixtures/rackspace_with_yml/config/asset_sync.yml
|
271
272
|
- spec/fixtures/with_invalid_yml/config/asset_sync.yml
|