branchable_cdn_assets 0.5.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 +7 -0
- data/lib/branchable_cdn_assets.rb +19 -0
- data/lib/branchable_cdn_assets/check_before.rb +49 -0
- data/lib/branchable_cdn_assets/cloudfront.rb +28 -0
- data/lib/branchable_cdn_assets/config.rb +80 -0
- data/lib/branchable_cdn_assets/config/environment_attribute_reader.rb +17 -0
- data/lib/branchable_cdn_assets/file_manager.rb +222 -0
- data/lib/branchable_cdn_assets/file_manager/checks.rb +41 -0
- data/lib/branchable_cdn_assets/manifest.rb +63 -0
- data/lib/branchable_cdn_assets/rake_tasks.rb +69 -0
- data/lib/branchable_cdn_assets/shell.rb +17 -0
- data/lib/branchable_cdn_assets/version.rb +3 -0
- data/spec/lib/branchable_cdn_assets/check_before_spec.rb +61 -0
- data/spec/lib/branchable_cdn_assets/config_spec.rb +152 -0
- data/spec/lib/branchable_cdn_assets/file_manager/find_spec.rb +61 -0
- data/spec/lib/branchable_cdn_assets/file_manager_spec.rb +256 -0
- data/spec/lib/branchable_cdn_assets/manifest_spec.rb +138 -0
- data/spec/lib/branchable_cdn_assets/rake_tasks_spec.rb +64 -0
- data/spec/lib/branchable_cdn_assets_spec.rb +9 -0
- data/spec/lib/cloudfront_spec.rb +67 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/given.rb +28 -0
- data/spec/support/hash.rb +8 -0
- metadata +146 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module BranchableCDNAssets
|
4
|
+
class Manifest
|
5
|
+
|
6
|
+
attr_reader :source_file, :file_set
|
7
|
+
|
8
|
+
def initialize source_file
|
9
|
+
@source_file = source_file
|
10
|
+
@file_set = File.exists?(source_file) ? read_source_file : Set.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# list files set as an Array
|
14
|
+
# @return [Array]
|
15
|
+
def files
|
16
|
+
file_set.to_a
|
17
|
+
end
|
18
|
+
|
19
|
+
# add new files to the manifest set
|
20
|
+
# @param new_files [Array]
|
21
|
+
# @return [Set]
|
22
|
+
def merge_files new_files
|
23
|
+
file_set.merge Array(new_files)
|
24
|
+
end
|
25
|
+
|
26
|
+
# remove a set of files from the manifest
|
27
|
+
# @param files_to_remove [Array]
|
28
|
+
# @return [Set]
|
29
|
+
def remove_files files_to_remove
|
30
|
+
file_set.subtract Array(files_to_remove)
|
31
|
+
end
|
32
|
+
|
33
|
+
# updates the manifest file with the
|
34
|
+
# most recent set of files
|
35
|
+
# @return [Void]
|
36
|
+
def update_source_file!
|
37
|
+
destroy! && return if file_set.empty?
|
38
|
+
|
39
|
+
File.open( source_file, 'w' ) do |file|
|
40
|
+
file.write manifest_content
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# read the manifest source_file
|
47
|
+
def read_source_file
|
48
|
+
IO.read(source_file).split("\n").to_set
|
49
|
+
end
|
50
|
+
|
51
|
+
# render/serialize the manifest set
|
52
|
+
def manifest_content
|
53
|
+
file_set.to_a.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
# remove the manifest source_file
|
57
|
+
def destroy!
|
58
|
+
File.delete(source_file)
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'branchable_cdn_assets'
|
3
|
+
|
4
|
+
module BranchableCDNAssets
|
5
|
+
|
6
|
+
class RakeTasks
|
7
|
+
include ::Rake::DSL
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def register namespace, data={}
|
11
|
+
RakeTasks.new( namespace, Config.new(data) ).register_tasks
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :file_manager, :rake_namespace
|
16
|
+
|
17
|
+
def initialize namespace, config
|
18
|
+
@file_manager = FileManager.new config
|
19
|
+
@rake_namespace = namespace
|
20
|
+
end
|
21
|
+
|
22
|
+
def tasks
|
23
|
+
{
|
24
|
+
list: 'list of local files',
|
25
|
+
pull!: 'move the current branch\'s remote files to local',
|
26
|
+
push!: 'move local files to the current branch\'s remote',
|
27
|
+
prune!: 'remove local files with the same name as remote files',
|
28
|
+
move_to_production: 'move named branch files to production cdn'
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def register_tasks
|
33
|
+
tasks.each do |name, desc|
|
34
|
+
if self.respond_to?(:"register_#{name}")
|
35
|
+
self.send(:"register_#{name}", desc)
|
36
|
+
else
|
37
|
+
register_task name, desc
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def register_move_to_production task_desc
|
43
|
+
in_namespace do
|
44
|
+
desc task_desc
|
45
|
+
task :move_to_production, :branch do |t,args|
|
46
|
+
puts file_manager.with_check(:move_to_production, args[:branch])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def in_namespace &block
|
54
|
+
namespace rake_namespace do
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def register_task task_name, task_desc
|
60
|
+
in_namespace do
|
61
|
+
desc task_desc
|
62
|
+
task task_name.to_s.sub('!','') do
|
63
|
+
puts file_manager.public_send( :with_check, task_name )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BranchableCDNAssets::CheckBefore do
|
4
|
+
|
5
|
+
class Stub
|
6
|
+
extend BranchableCDNAssets::CheckBefore
|
7
|
+
|
8
|
+
def hello; 'world'; end
|
9
|
+
def filter; true; end
|
10
|
+
end
|
11
|
+
|
12
|
+
after :each do
|
13
|
+
Stub.remove_instance_variable :@_before_checks
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "::before_checks" do
|
17
|
+
it "returns an array if @_before_checks not set" do
|
18
|
+
expect( Stub.before_checks.is_a?(Array) ).to be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returs @_before_checks if set" do
|
22
|
+
Stub.instance_variable_set :@_before_checks, ['hello']
|
23
|
+
expect( Stub.before_checks ).to match_array ['hello']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "::check_before" do
|
28
|
+
it "adds hash with params to before_checks" do
|
29
|
+
Stub.check_before :check, {hello: 'world'}
|
30
|
+
expect( Stub.before_checks.first ).to eq check: :check, hello: 'world'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#with_check" do
|
35
|
+
|
36
|
+
it "sends the the called method" do
|
37
|
+
stub = Stub.new
|
38
|
+
expect( stub ).to receive(:hello)
|
39
|
+
stub.with_check( :hello )
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with check defined on method" do
|
43
|
+
before :each do
|
44
|
+
Stub.instance_eval do; check_before :filter, methods: [:hello]; end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "runs included checks" do
|
48
|
+
stub = Stub.new
|
49
|
+
expect( stub ).to receive(:filter)
|
50
|
+
stub.with_check(:hello)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "runs the called method" do
|
54
|
+
stub = Stub.new
|
55
|
+
expect( stub ).to receive(:hello)
|
56
|
+
stub.with_check(:hello)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BranchableCDNAssets::Config do
|
4
|
+
|
5
|
+
let(:data) do
|
6
|
+
{
|
7
|
+
production_branch: 'production',
|
8
|
+
default_env: 'default',
|
9
|
+
dir: 'cdn_dir',
|
10
|
+
environments: {
|
11
|
+
production: {
|
12
|
+
host: 'production',
|
13
|
+
url: 'http://production.com',
|
14
|
+
root: '/var/www/production'
|
15
|
+
},
|
16
|
+
test: {
|
17
|
+
host: 'test',
|
18
|
+
url: 'http://test.com',
|
19
|
+
root: '/var/www/test'
|
20
|
+
},
|
21
|
+
staging: {
|
22
|
+
host: 'staging',
|
23
|
+
url: 'http://staging.com',
|
24
|
+
root: '/var/www/staging'
|
25
|
+
},
|
26
|
+
default: {
|
27
|
+
host: 'default',
|
28
|
+
url: 'http://default.com',
|
29
|
+
root: '/var/www/default'
|
30
|
+
}
|
31
|
+
},
|
32
|
+
cloudfront: {
|
33
|
+
access_key: 'FooBar',
|
34
|
+
secret_key: 'SecretBaz',
|
35
|
+
distribution: 'Distro',
|
36
|
+
path_prefix: '/'
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:yaml) do
|
42
|
+
"foo: bar\n" +
|
43
|
+
"baz: wu\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#raw_data" do
|
47
|
+
context "when given a hash" do
|
48
|
+
it "uses hash data as is" do
|
49
|
+
expect( described_class.new( data ).raw_data ).to eq data
|
50
|
+
end
|
51
|
+
it "symbolizes data's keys if they are strings" do
|
52
|
+
expect( described_class.new( {'foo'=>'foo', 'bar' => { 'baz' => 'baz' }} ).raw_data ).to eq foo: 'foo', bar: { baz: 'baz' }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
context "when given a path" do
|
56
|
+
it "reads yaml data in config" do
|
57
|
+
allow(File).to receive(:exists?).with('yaml').and_return(true)
|
58
|
+
allow(IO).to receive(:read).with('yaml').and_return(yaml)
|
59
|
+
|
60
|
+
expect( described_class.new('yaml').raw_data ).to eq foo: 'bar', baz: 'wu'
|
61
|
+
end
|
62
|
+
it "raises exception if file not found" do
|
63
|
+
allow(File).to receive(:exists?).with('yaml').and_return(false)
|
64
|
+
|
65
|
+
expect{
|
66
|
+
described_class.new('yaml')
|
67
|
+
}.to raise_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#branch" do
|
73
|
+
it "defaults to the Asgit.current_branch" do
|
74
|
+
allow( Asgit ).to receive(:current_branch).and_return('foo_bar')
|
75
|
+
expect( described_class.new( data ).branch ).to eq 'foo_bar'
|
76
|
+
end
|
77
|
+
it "can be overriden by passing in a branch" do
|
78
|
+
expect( described_class.new( data, 'baz' ).branch ).to eq 'baz'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#production_branch" do
|
83
|
+
it "defaults to 'master' if none is passed" do
|
84
|
+
expect( described_class.new( data.without_key(:production_branch) ).production_branch ).to eq 'master'
|
85
|
+
end
|
86
|
+
it "can be set with data" do
|
87
|
+
expect( described_class.new( data ).production_branch ).to eq 'production'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#cloudfront" do
|
92
|
+
it "is set to the passed value" do
|
93
|
+
expect( described_class.new( data ).cloudfront ).to eq data[:cloudfront]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#cdn_dir" do
|
98
|
+
it "is set to the passed value" do
|
99
|
+
expect( described_class.new( data ).cdn_dir ).to eq 'cdn_dir'
|
100
|
+
end
|
101
|
+
|
102
|
+
it "falls back to 'cdn' if no value is passed" do
|
103
|
+
expect( described_class.new( data.without_key(:dir) ).cdn_dir ).to eq 'cdn'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#env" do
|
108
|
+
context "when the current branch matches production_branch" do
|
109
|
+
before :each do
|
110
|
+
allow( Asgit ).to receive(:current_branch).and_return('production')
|
111
|
+
end
|
112
|
+
it "is :production" do
|
113
|
+
expect( described_class.new( data ).env ).to eq :production
|
114
|
+
end
|
115
|
+
end
|
116
|
+
context "when on a branch with a matching environment key" do
|
117
|
+
before :each do
|
118
|
+
allow( Asgit ).to receive(:current_branch).and_return('test')
|
119
|
+
end
|
120
|
+
it "matchs the current_branch" do
|
121
|
+
expect( described_class.new( data ).env ).to eq :test
|
122
|
+
end
|
123
|
+
end
|
124
|
+
context "when on a branch that doesn't match an env key" do
|
125
|
+
before :each do
|
126
|
+
allow( Asgit ).to receive(:current_branch).and_return('random')
|
127
|
+
end
|
128
|
+
it "sets env to the set default_env" do
|
129
|
+
expect( described_class.new( data ).env ).to eq :default
|
130
|
+
end
|
131
|
+
it "falls back to 'staging' if no default env given" do
|
132
|
+
expect( described_class.new( data.without_key(:default_env) ).env ).to eq :staging
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#environments" do
|
138
|
+
it "returns data namespaced with branch" do
|
139
|
+
production = described_class.new( data, 'production' )
|
140
|
+
default = described_class.new( data, 'foo_bar' )
|
141
|
+
|
142
|
+
expect( production.root ).to eq '/var/www/production'
|
143
|
+
expect( production.host ).to eq 'production'
|
144
|
+
expect( production.url ).to eq 'http://production.com'
|
145
|
+
|
146
|
+
expect( default.root ).to eq '/var/www/default/foo_bar/'
|
147
|
+
expect( default.host ).to eq 'default'
|
148
|
+
expect( default.url ).to eq 'http://default.com/foo_bar'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BranchableCDNAssets::FileManager do
|
4
|
+
|
5
|
+
describe "#find" do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
Given.fixture 'base'
|
9
|
+
Given.file 'cdn/master.manifest', "image_one\nimage_remote_one\n"
|
10
|
+
Given.file 'cdn/staging.manifest', "image_one\nimage_remote_two\n"
|
11
|
+
Given.file 'cdn/image_one', ''
|
12
|
+
Given.file 'cdn/image_two', ''
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when on production branch" do
|
16
|
+
before :each do
|
17
|
+
allow( Asgit ).to receive(:current_branch)
|
18
|
+
.and_return('master')
|
19
|
+
@manager = described_class.new BranchableCDNAssets::Config.new('config/cdn_assets.yaml')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns :local if asset is local" do
|
23
|
+
expect( @manager.find('image_one') ).to eq :local
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns the production url of the asset" do
|
27
|
+
expect( @manager.find('image_remote_one') ).to eq 'http://production.com/image_remote_one'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns nil if asset is missing" do
|
31
|
+
expect( @manager.find('missing') ).to be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when on staging branch" do
|
36
|
+
before :each do
|
37
|
+
allow( Asgit ).to receive(:current_branch)
|
38
|
+
.and_return('staging')
|
39
|
+
@manager = described_class.new BranchableCDNAssets::Config.new('config/cdn_assets.yaml')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns :local if asset is local" do
|
43
|
+
expect( @manager.find('image_one') ).to eq :local
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns namespaced staging url if listed in staging manifest" do
|
47
|
+
expect( @manager.find('image_remote_two') ).to eq 'http://staging.com/staging/image_remote_two'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns production url if listed only in production manifest" do
|
51
|
+
expect( @manager.find('image_remote_one') ).to eq 'http://production.com/image_remote_one'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns nil if asset is missing" do
|
55
|
+
expect( @manager.find('missing') ).to be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BranchableCDNAssets::FileManager do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@config_data = {
|
7
|
+
env: 'default',
|
8
|
+
branch: 'branch',
|
9
|
+
cdn_dir: 'cdn',
|
10
|
+
host: 'host',
|
11
|
+
root: 'root',
|
12
|
+
cloudfront: {
|
13
|
+
path_prefix: '/prefix'
|
14
|
+
}
|
15
|
+
}
|
16
|
+
@config = instance_double( "BranchableCDNAssets::Config", @config_data )
|
17
|
+
allow( BranchableCDNAssets::Config ).to receive(:new).and_return( @config )
|
18
|
+
|
19
|
+
@file_list = [
|
20
|
+
'filename_one',
|
21
|
+
'filename_two',
|
22
|
+
'directory/dir_file'
|
23
|
+
]
|
24
|
+
|
25
|
+
allow( Dir).to receive(:[]).with(anything()).and_call_original
|
26
|
+
allow( Dir).to receive(:[]).with( "#{Dir.pwd}/cdn/**/*" ).and_return( @file_list.map { |f| File.join( Dir.pwd, 'cdn', f ) } )
|
27
|
+
|
28
|
+
@manifest = instance_double("BranchableCDNAssets::Manifest", files: @file_list )
|
29
|
+
allow( BranchableCDNAssets::Manifest ).to receive(:new).and_return( @manifest )
|
30
|
+
|
31
|
+
@cloudfront = instance_double("BranchableCDNAssets::Cloudfront")
|
32
|
+
allow( BranchableCDNAssets::Cloudfront ).to receive(:new).and_return( @cloudfront )
|
33
|
+
|
34
|
+
@tempfile = instance_double( "Tempfile",
|
35
|
+
unlink: nil,
|
36
|
+
path: 'tempfile_path',
|
37
|
+
write: nil,
|
38
|
+
close: nil
|
39
|
+
)
|
40
|
+
allow( Tempfile ).to receive(:new).and_return( @tempfile )
|
41
|
+
|
42
|
+
@success_response = instance_double("HereOrThere::Response",
|
43
|
+
success?: true,
|
44
|
+
stderr: "",
|
45
|
+
stdout: ">f+++++++++ filename_one\n" +
|
46
|
+
">f+++++++++ filename_two\n" +
|
47
|
+
">d+++++++++ directory/\n" +
|
48
|
+
">f+++++++++ directory/dir_file\n"
|
49
|
+
)
|
50
|
+
|
51
|
+
@error_response = instance_double("HereOrThere::Response",
|
52
|
+
success?: false,
|
53
|
+
stderr: "stderr",
|
54
|
+
stdout: ""
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#config' do
|
59
|
+
it "returns the provided config" do
|
60
|
+
files = described_class.new( @config )
|
61
|
+
expect( files.config ).to eq @config
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#root' do
|
66
|
+
it "returns the provided root from config" do
|
67
|
+
files = described_class.new( @config )
|
68
|
+
expect( files.root ).to eq 'cdn'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#manifest' do
|
73
|
+
it "returns a manifest with the environment manifest path" do
|
74
|
+
expect( BranchableCDNAssets::Manifest ).to receive(:new).with( "cdn/#{@config.branch}.manifest" )
|
75
|
+
files = described_class.new( @config )
|
76
|
+
expect( files.manifest ).to eq @manifest
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#branch" do
|
81
|
+
it "is defaults to the config.branch" do
|
82
|
+
expect( described_class.new(@config).branch ).to eq @config.branch
|
83
|
+
end
|
84
|
+
it "can be overriden by passed arg" do
|
85
|
+
expect( described_class.new(@config, 'foo').branch ).to eq 'foo'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#list' do
|
90
|
+
|
91
|
+
let(:remote_files) { ['filename_one', 'remote_one', 'remote_two'] }
|
92
|
+
let(:local_files) { @file_list }
|
93
|
+
|
94
|
+
before :each do
|
95
|
+
allow( @manifest ).to receive(:files).and_return(remote_files)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns remote files when arg is :remote" do
|
99
|
+
expect( described_class.new(@config).list(:remote) ).to match_array remote_files
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns local files when arg is :local" do
|
103
|
+
expect( described_class.new(@config).list(:local) ).to match_array local_files
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns both local and remote files when :all" do
|
107
|
+
expect( described_class.new(@config).list() ).to match_array remote_files + local_files
|
108
|
+
end
|
109
|
+
|
110
|
+
it "returns intersecting files whe :both" do
|
111
|
+
expect( described_class.new(@config).list(:both) ).to match_array ['filename_one']
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#pull!" do
|
117
|
+
|
118
|
+
context "when pull is successful" do
|
119
|
+
before :each do
|
120
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_local).and_return( @success_response )
|
121
|
+
allow( @manifest ).to receive(:remove_files)
|
122
|
+
allow( @manifest ).to receive(:update_source_file!)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "returns list of pulled files" do
|
126
|
+
expect( described_class.new(@config).pull! ).to match_array @file_list
|
127
|
+
end
|
128
|
+
|
129
|
+
it "removes files & updates manifest" do
|
130
|
+
expect( @manifest ).to receive(:remove_files).with(@file_list)
|
131
|
+
expect( @manifest ).to receive(:update_source_file!)
|
132
|
+
described_class.new(@config).pull!
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "when pull returns error" do
|
137
|
+
it "raises an error" do
|
138
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_local).and_return( @error_response )
|
139
|
+
|
140
|
+
expect{
|
141
|
+
described_class.new(@config).pull!
|
142
|
+
}.to raise_error
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#push!" do
|
148
|
+
|
149
|
+
before :each do
|
150
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_remote)
|
151
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_local).and_return( @success_response )
|
152
|
+
allow( @manifest ).to receive(:merge_files)
|
153
|
+
allow( @manifest ).to receive(:update_source_file!)
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when setup_remote is successful" do
|
157
|
+
before :each do
|
158
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_remote).with('mkdir -p root', hostname: 'host').and_return(@success_response)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "sets up remote" do
|
162
|
+
expect( BranchableCDNAssets::Shell ).to receive(:run_remote).with('mkdir -p root', hostname: 'host').and_return(@success_response)
|
163
|
+
described_class.new(@config).push!
|
164
|
+
end
|
165
|
+
|
166
|
+
it "returns an array of pushed files" do
|
167
|
+
expect( described_class.new(@config).push! ).to match_array @file_list
|
168
|
+
end
|
169
|
+
|
170
|
+
it "adds files and updates the manifest" do
|
171
|
+
expect( @manifest ).to receive(:merge_files).with(@file_list)
|
172
|
+
expect( @manifest ).to receive(:update_source_file!)
|
173
|
+
|
174
|
+
described_class.new(@config).push!
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when env is production" do
|
178
|
+
|
179
|
+
before :each do
|
180
|
+
allow( @config ).to receive(:env).and_return(:production)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "invalidates intersecting files" do
|
184
|
+
expect( @cloudfront ).to receive(:invalidate_files).with( @file_list.map { |f| "/prefix/#{f}"} )
|
185
|
+
described_class.new(@config).push!
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context "when setup_remote fails" do
|
191
|
+
it "aborts and prints error" do
|
192
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_remote).and_return( @error_response )
|
193
|
+
expect {
|
194
|
+
described_class.new(@config).push!
|
195
|
+
}.to raise_error
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#prune!" do
|
201
|
+
|
202
|
+
let(:remote_files) { ['filename_one', 'remote_one', 'remote_two'] }
|
203
|
+
let(:local_files) { @file_list }
|
204
|
+
|
205
|
+
before :each do
|
206
|
+
allow( @manifest ).to receive(:files).and_return(remote_files)
|
207
|
+
end
|
208
|
+
|
209
|
+
context "when confirm removal" do
|
210
|
+
it "removes files that are local and on remote" do
|
211
|
+
expect( BranchableCDNAssets::Shell ).to receive(:run_local).with("rm cdn/filename_one")
|
212
|
+
release_stdin 'y' do
|
213
|
+
described_class.new(@config).prune!
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
it "removes empty directories" do
|
218
|
+
files = described_class.new(@config)
|
219
|
+
expect( files ).to receive(:remove_empty_directories)
|
220
|
+
release_stdin 'y' do
|
221
|
+
files.prune!
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context "when removal aborted" do
|
227
|
+
it "does not remove files and exits" do
|
228
|
+
expect( BranchableCDNAssets::Shell ).not_to receive(:run_local).with(/rm\s[\w\/\.]+$/)
|
229
|
+
|
230
|
+
expect{
|
231
|
+
release_stdin 'n' do
|
232
|
+
described_class.new(@config).prune!
|
233
|
+
end
|
234
|
+
}.to raise_error SystemExit
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "#move_to_production" do
|
240
|
+
before :each do
|
241
|
+
@orig_cdn = described_class.new(@config)
|
242
|
+
@branch_cdn = instance_double("BranchableCDNAssets::FileManager", manifest: @manifest )
|
243
|
+
allow( BranchableCDNAssets::Shell ).to receive(:run_local).and_return(@success_response)
|
244
|
+
allow( described_class ).to receive(:new).and_call_original
|
245
|
+
allow( @config ).to receive(:raw_data)
|
246
|
+
allow( described_class ).to receive(:new).with( @config ).and_return( @branch_cdn )
|
247
|
+
end
|
248
|
+
|
249
|
+
it "pulls from remote branch & pushes on current branch" do
|
250
|
+
expect( @branch_cdn ).to receive(:pull!).and_return([])
|
251
|
+
expect( @orig_cdn ).to receive(:push!).and_return([])
|
252
|
+
@orig_cdn.move_to_production('test')
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|