asset_sync 2.4.0 → 2.14.0
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/.github/workflows/tests.yaml +64 -0
- data/.travis.yml +25 -26
- data/Appraisals +6 -10
- data/CHANGELOG.md +158 -2
- data/README.md +120 -9
- data/asset_sync.gemspec +4 -3
- data/gemfiles/{rails_4_1.gemfile → rails_5_2.gemfile} +1 -1
- data/gemfiles/{rails_4_2.gemfile → rails_6_0.gemfile} +1 -1
- data/gemfiles/{rails_5_0.gemfile → rails_6_1.gemfile} +1 -1
- data/lib/asset_sync/config.rb +150 -12
- data/lib/asset_sync/engine.rb +8 -0
- data/lib/asset_sync/multi_mime.rb +7 -2
- data/lib/asset_sync/storage.rb +81 -20
- data/lib/asset_sync/version.rb +1 -1
- data/lib/generators/asset_sync/install_generator.rb +21 -1
- data/lib/generators/asset_sync/templates/asset_sync.rb +21 -0
- data/lib/generators/asset_sync/templates/asset_sync.yml +20 -1
- data/lib/tasks/asset_sync.rake +3 -1
- data/spec/fixtures/backblaze_with_yml/config/asset_sync.yml +20 -0
- data/spec/fixtures/google_with_service_account_yml/config/asset_sync.yml +19 -0
- data/spec/integration/backblaze_intergration_spec.rb +74 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/asset_sync_spec.rb +35 -3
- data/spec/unit/backblaze_spec.rb +150 -0
- data/spec/unit/google_spec.rb +124 -29
- data/spec/unit/multi_mime_spec.rb +47 -0
- data/spec/unit/railsless_spec.rb +4 -3
- data/spec/unit/storage_spec.rb +150 -7
- metadata +49 -14
- data/gemfiles/rails_5_1.gemfile +0 -10
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,141 @@ 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
|
52
|
+
|
53
|
+
it "should configure google_storage_secret_access_key" do
|
54
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq("bbbb")
|
55
|
+
end
|
56
|
+
|
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
|
61
69
|
|
62
|
-
|
63
|
-
|
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
|
64
77
|
end
|
65
78
|
|
66
|
-
|
67
|
-
|
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
|
68
100
|
end
|
69
101
|
|
70
|
-
|
71
|
-
|
102
|
+
describe "when using service account with JSON key string" do
|
103
|
+
before(:each) do
|
104
|
+
AssetSync.configure do |config|
|
105
|
+
config.google_json_key_string = 'a-google-json-key-string'
|
106
|
+
config.google_project = 'a-google-project-name'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should configure google_json_key_string" do
|
111
|
+
expect(AssetSync.config.google_json_key_string).to eq("a-google-json-key-string")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should return the correct fog_options" do
|
115
|
+
expected_fog_options = { google_json_key_string: "a-google-json-key-string",
|
116
|
+
google_project: 'a-google-project-name',
|
117
|
+
provider: "Google"}
|
118
|
+
expect(AssetSync.config.fog_options).to eq(expected_fog_options)
|
119
|
+
end
|
120
|
+
it "should not require that google_storage_secret_access_key or access_key_id be set" do
|
121
|
+
expect(AssetSync.config.valid?).to eq(true)
|
122
|
+
end
|
72
123
|
end
|
124
|
+
end
|
73
125
|
|
74
|
-
|
75
|
-
|
126
|
+
describe 'from yml' do
|
127
|
+
describe 'when using S3 interop API' do
|
128
|
+
before(:each) do
|
129
|
+
set_rails_root('google_with_yml')
|
130
|
+
AssetSync.config = AssetSync::Config.new
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should configure google_storage_access_key_id" do
|
134
|
+
expect(AssetSync.config.google_storage_access_key_id).to eq("xxxx")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should configure google_storage_secret_access_key" do
|
138
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq("zzzz")
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should not configure google_json_key_location" do
|
142
|
+
expect(AssetSync.config.google_json_key_location).to eq(nil)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should configure fog_directory" do
|
146
|
+
expect(AssetSync.config.fog_directory).to eq("rails_app_test")
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should configure existing_remote_files" do
|
150
|
+
expect(AssetSync.config.existing_remote_files).to eq("keep")
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should default gzip_compression to false" do
|
154
|
+
expect(AssetSync.config.gzip_compression).to be_falsey
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should default manifest to false" do
|
158
|
+
expect(AssetSync.config.manifest).to be_falsey
|
159
|
+
end
|
76
160
|
end
|
77
161
|
|
78
|
-
|
79
|
-
|
162
|
+
describe 'when using service account API' do
|
163
|
+
before(:each) do
|
164
|
+
set_rails_root('google_with_service_account_yml')
|
165
|
+
AssetSync.config = AssetSync::Config.new
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should configure google_json_key_location" do
|
169
|
+
expect(AssetSync.config.google_json_key_location).to eq("gcs.json")
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should not configure google_storage_secret_access_key" do
|
173
|
+
expect(AssetSync.config.google_storage_secret_access_key).to eq(nil)
|
174
|
+
end
|
80
175
|
end
|
81
176
|
end
|
82
177
|
|
@@ -36,6 +36,8 @@ describe AssetSync::MultiMime do
|
|
36
36
|
$".grep(/mime\//).each do |file_path|
|
37
37
|
$".delete(file_path)
|
38
38
|
end
|
39
|
+
|
40
|
+
AssetSync.config = AssetSync::Config.new
|
39
41
|
end
|
40
42
|
|
41
43
|
after(:all) do
|
@@ -69,4 +71,49 @@ describe AssetSync::MultiMime do
|
|
69
71
|
|
70
72
|
end
|
71
73
|
|
74
|
+
describe "use of option file_ext_to_mime_type_overrides" do
|
75
|
+
before(:each) do
|
76
|
+
require 'mime/types'
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with default value" do
|
80
|
+
it "should return default value set by gem" do
|
81
|
+
expect(
|
82
|
+
AssetSync::MultiMime.lookup("js").to_s,
|
83
|
+
).to eq("application/javascript")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
context "with empty value" do
|
87
|
+
before(:each) do
|
88
|
+
AssetSync.config = AssetSync::Config.new
|
89
|
+
AssetSync.configure do |config|
|
90
|
+
config.file_ext_to_mime_type_overrides.clear
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should return value from mime-types gem" do
|
95
|
+
expect(
|
96
|
+
AssetSync::MultiMime.lookup("js").to_s,
|
97
|
+
).to eq(::MIME::Types.type_for("js").first.to_s)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
context "with custom value" do
|
101
|
+
before(:each) do
|
102
|
+
AssetSync.config = AssetSync::Config.new
|
103
|
+
AssetSync.configure do |config|
|
104
|
+
config.file_ext_to_mime_type_overrides.add(
|
105
|
+
:js,
|
106
|
+
:"application/x-javascript",
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return custom value" do
|
112
|
+
expect(
|
113
|
+
AssetSync::MultiMime.lookup("js").to_s,
|
114
|
+
).to eq("application/x-javascript")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
72
119
|
end
|
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,19 +54,105 @@ 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
|
-
'public/image.png',
|
60
|
-
'public/image-82389298328.png',
|
61
|
-
'public/image-a8389f9h324.png',
|
140
|
+
'public/great-image.png',
|
141
|
+
'public/great-image-82389298328.png',
|
142
|
+
'public/great-image-a8389f9h324.png',
|
143
|
+
"public/new\nline.js",
|
144
|
+
"public/new\nline-aaaaaaaaaaa.js",
|
145
|
+
"public/new\nline-bbbbbbbbbbb.js",
|
62
146
|
'public/application.js',
|
63
147
|
'public/application-b3389d983k1.js',
|
64
148
|
'public/application-ac387d53f31.js',
|
65
149
|
'public',
|
66
150
|
]
|
67
151
|
@remote_files = [
|
68
|
-
'public/image.png',
|
69
|
-
'public/image-a8389f9h324.png',
|
152
|
+
'public/great-image.png',
|
153
|
+
'public/great-image-a8389f9h324.png',
|
154
|
+
"public/new\nline.js",
|
155
|
+
"public/new\nline-aaaaaaaaaaa.js",
|
70
156
|
'public/application.js',
|
71
157
|
'public/application-b3389d983k1.js',
|
72
158
|
]
|
@@ -77,7 +163,8 @@ describe AssetSync::Storage do
|
|
77
163
|
allow(File).to receive(:file?).and_return(true) # Pretend they all exist
|
78
164
|
|
79
165
|
updated_nonfingerprinted_files = [
|
80
|
-
'public/image.png',
|
166
|
+
'public/great-image.png',
|
167
|
+
"public/new\nline.js",
|
81
168
|
'public/application.js',
|
82
169
|
]
|
83
170
|
(@local_files - @remote_files + updated_nonfingerprinted_files).each do |file|
|
@@ -125,7 +212,7 @@ describe AssetSync::Storage do
|
|
125
212
|
end
|
126
213
|
end
|
127
214
|
|
128
|
-
it 'should upload additonal
|
215
|
+
it 'should upload additonal files' do
|
129
216
|
@local_files = [
|
130
217
|
'public/image.png',
|
131
218
|
'public/image-82389298328.png',
|
@@ -307,4 +394,60 @@ describe AssetSync::Storage do
|
|
307
394
|
storage.upload_file('assets/some_longer_path/local_image2.jpg')
|
308
395
|
end
|
309
396
|
end
|
397
|
+
|
398
|
+
describe '#delete_extra_remote_files' do
|
399
|
+
it 'should delete the files in bulk' do
|
400
|
+
remote_files = ['public/image.png']
|
401
|
+
connection = double
|
402
|
+
config = double
|
403
|
+
|
404
|
+
storage = AssetSync::Storage.new(@config)
|
405
|
+
|
406
|
+
[:local_files, :ignored_files, :always_upload_files].each do |method|
|
407
|
+
expect(storage).to receive(method).and_return([])
|
408
|
+
end
|
409
|
+
|
410
|
+
allow(storage).to receive(:get_remote_files).and_return(remote_files)
|
411
|
+
allow(storage).to receive(:connection).and_return(connection).twice
|
412
|
+
allow(storage).to receive(:config).and_return(config).twice
|
413
|
+
allow(config).to receive(:aws?).and_return(true)
|
414
|
+
allow(config).to receive(:fog_directory).and_return('foo')
|
415
|
+
expect(connection).to receive(:delete_multiple_objects).with('foo', remote_files)
|
416
|
+
|
417
|
+
storage.delete_extra_remote_files
|
418
|
+
end
|
419
|
+
|
420
|
+
context 'when not aws' do
|
421
|
+
it 'deletes files sequentially' do
|
422
|
+
remote_files = ['public/image.png']
|
423
|
+
connection = double
|
424
|
+
config = double
|
425
|
+
directories = double
|
426
|
+
directory = double
|
427
|
+
file = double
|
428
|
+
|
429
|
+
storage = AssetSync::Storage.new(@config)
|
430
|
+
|
431
|
+
[:local_files, :ignored_files, :always_upload_files].each do |method|
|
432
|
+
expect(storage).to receive(method).and_return([])
|
433
|
+
end
|
434
|
+
|
435
|
+
allow(storage).to receive(:get_remote_files).and_return(remote_files)
|
436
|
+
allow(storage).to receive(:connection).and_return(connection).twice
|
437
|
+
allow(storage).to receive(:config).and_return(config)
|
438
|
+
allow(config).to receive(:aws?).and_return(false)
|
439
|
+
allow(config).to receive(:fog_directory).and_return('foo')
|
440
|
+
allow(config).to receive(:assets_prefix).and_return('foo')
|
441
|
+
allow(directories).to receive(:get).and_return(directory)
|
442
|
+
allow(directory).to receive(:files).and_return([file])
|
443
|
+
allow(file).to receive(:key).and_return('public/image.png')
|
444
|
+
allow(connection).to receive(:directories).and_return(directories)
|
445
|
+
allow(config).to receive(:backblaze?).and_return(false)
|
446
|
+
expect(connection).not_to receive(:delete_multiple_objects)
|
447
|
+
expect(file).to receive(:destroy)
|
448
|
+
|
449
|
+
storage.delete_extra_remote_files
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
310
453
|
end
|