statistrano 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/changelog.md +161 -0
  3. data/doc/config/file-permissions.md +33 -0
  4. data/doc/config/log-files.md +32 -0
  5. data/doc/config/task-definitions.md +88 -0
  6. data/doc/getting-started.md +96 -0
  7. data/doc/strategies/base.md +38 -0
  8. data/doc/strategies/branches.md +82 -0
  9. data/doc/strategies/releases.md +110 -0
  10. data/doc/strategies.md +17 -0
  11. data/lib/statistrano/config/configurable.rb +53 -0
  12. data/lib/statistrano/config/rake_task_with_context_creation.rb +43 -0
  13. data/lib/statistrano/config.rb +52 -0
  14. data/lib/statistrano/deployment/log_file.rb +44 -0
  15. data/lib/statistrano/deployment/manifest.rb +88 -0
  16. data/lib/statistrano/deployment/rake_tasks.rb +74 -0
  17. data/lib/statistrano/deployment/registerable.rb +11 -0
  18. data/lib/statistrano/deployment/releaser/revisions.rb +163 -0
  19. data/lib/statistrano/deployment/releaser/single.rb +48 -0
  20. data/lib/statistrano/deployment/releaser.rb +2 -0
  21. data/lib/statistrano/deployment/strategy/base.rb +132 -0
  22. data/lib/statistrano/deployment/strategy/branches/index/template.html.erb +78 -0
  23. data/lib/statistrano/deployment/strategy/branches/index.rb +40 -0
  24. data/lib/statistrano/deployment/strategy/branches/release.rb +73 -0
  25. data/lib/statistrano/deployment/strategy/branches.rb +198 -0
  26. data/lib/statistrano/deployment/strategy/check_git.rb +43 -0
  27. data/lib/statistrano/deployment/strategy/invoke_tasks.rb +58 -0
  28. data/lib/statistrano/deployment/strategy/releases.rb +76 -0
  29. data/lib/statistrano/deployment/strategy.rb +37 -0
  30. data/lib/statistrano/deployment.rb +10 -0
  31. data/lib/statistrano/log/default_logger.rb +105 -0
  32. data/lib/statistrano/log.rb +33 -0
  33. data/lib/statistrano/remote/file.rb +79 -0
  34. data/lib/statistrano/remote.rb +111 -0
  35. data/lib/statistrano/shell.rb +17 -0
  36. data/lib/statistrano/util/file_permissions.rb +34 -0
  37. data/lib/statistrano/util.rb +27 -0
  38. data/lib/statistrano/version.rb +3 -0
  39. data/lib/statistrano.rb +55 -0
  40. data/readme.md +247 -0
  41. data/spec/integration_tests/base_integration_spec.rb +103 -0
  42. data/spec/integration_tests/branches_integration_spec.rb +189 -0
  43. data/spec/integration_tests/releases/deploy_integration_spec.rb +116 -0
  44. data/spec/integration_tests/releases/list_releases_integration_spec.rb +38 -0
  45. data/spec/integration_tests/releases/prune_releases_integration_spec.rb +86 -0
  46. data/spec/integration_tests/releases/rollback_release_integration_spec.rb +46 -0
  47. data/spec/lib/statistrano/config/configurable_spec.rb +88 -0
  48. data/spec/lib/statistrano/config/rake_task_with_context_creation_spec.rb +73 -0
  49. data/spec/lib/statistrano/config_spec.rb +34 -0
  50. data/spec/lib/statistrano/deployment/log_file_spec.rb +75 -0
  51. data/spec/lib/statistrano/deployment/manifest_spec.rb +171 -0
  52. data/spec/lib/statistrano/deployment/rake_tasks_spec.rb +107 -0
  53. data/spec/lib/statistrano/deployment/registerable_spec.rb +19 -0
  54. data/spec/lib/statistrano/deployment/releaser/revisions_spec.rb +486 -0
  55. data/spec/lib/statistrano/deployment/releaser/single_spec.rb +59 -0
  56. data/spec/lib/statistrano/deployment/strategy/base_spec.rb +158 -0
  57. data/spec/lib/statistrano/deployment/strategy/branches_spec.rb +19 -0
  58. data/spec/lib/statistrano/deployment/strategy/check_git_spec.rb +39 -0
  59. data/spec/lib/statistrano/deployment/strategy/invoke_tasks_spec.rb +66 -0
  60. data/spec/lib/statistrano/deployment/strategy/releases_spec.rb +257 -0
  61. data/spec/lib/statistrano/deployment/strategy_spec.rb +76 -0
  62. data/spec/lib/statistrano/deployment_spec.rb +4 -0
  63. data/spec/lib/statistrano/log/default_logger_spec.rb +172 -0
  64. data/spec/lib/statistrano/log_spec.rb +36 -0
  65. data/spec/lib/statistrano/remote/file_spec.rb +166 -0
  66. data/spec/lib/statistrano/remote_spec.rb +226 -0
  67. data/spec/lib/statistrano/util/file_permissions_spec.rb +25 -0
  68. data/spec/lib/statistrano/util_spec.rb +23 -0
  69. data/spec/lib/statistrano_spec.rb +52 -0
  70. data/spec/spec_helper.rb +86 -0
  71. data/spec/support/given.rb +39 -0
  72. metadata +223 -0
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Log::DefaultLogger do
4
+
5
+ before :each do
6
+ formatter_double = instance_double "Statistrano::Log::DefaultLogger::Formatter",
7
+ output: "stubbed"
8
+ Formatter = Statistrano::Log::DefaultLogger::Formatter unless defined?(Formatter)
9
+ allow( Formatter ).to receive(:new)
10
+ .and_return( formatter_double )
11
+ end
12
+
13
+ describe "#info [& debug]" do
14
+ it "outputs to stdout" do
15
+ expect( $stdout ).to receive(:puts)
16
+ subject.info 'foo'
17
+ end
18
+
19
+ it "defaults to a blank status" do
20
+ expect( Formatter ).to receive(:new)
21
+ .with( '', :bright, 'msg' )
22
+
23
+ subject.info 'msg'
24
+ end
25
+
26
+ it "uses a status if given one" do
27
+ expect( Formatter ).to receive(:new)
28
+ .with( :status, :bright, 'msg' )
29
+
30
+ subject.info :status, 'msg'
31
+ end
32
+
33
+ it "colorizes green if given :success as status" do
34
+ expect( Formatter ).to receive(:new)
35
+ .with( :success, :green, 'msg' )
36
+
37
+ subject.info :success, 'msg'
38
+ end
39
+
40
+ it "takes multiple lines of messages" do
41
+ expect( Formatter ).to receive(:new)
42
+ .with( '', :bright, 'msg', 'msg2' )
43
+
44
+ subject.info 'msg', 'msg2'
45
+ end
46
+ end
47
+
48
+ describe "#warn" do
49
+ it "outputs to stdout" do
50
+ expect( $stdout ).to receive(:puts)
51
+ subject.warn 'foo'
52
+ end
53
+
54
+ it "defaults to 'warning' status" do
55
+ expect( Formatter ).to receive(:new)
56
+ .with( 'warning', :yellow, 'msg' )
57
+
58
+ subject.warn 'msg'
59
+ end
60
+
61
+ it "allows status to be overriden" do
62
+ expect( Formatter ).to receive(:new)
63
+ .with( :omg, :yellow, 'msg' )
64
+
65
+ subject.warn :omg, 'msg'
66
+ end
67
+
68
+ it "colorizes yellow" do
69
+ expect( Formatter ).to receive(:new)
70
+ .with( 'warning', :yellow, 'msg' )
71
+
72
+ subject.warn 'msg'
73
+ end
74
+
75
+ it "takes multiple lines of messages" do
76
+ expect( Formatter ).to receive(:new)
77
+ .with( 'warning', :yellow, 'msg', 'msg2' )
78
+
79
+ subject.warn 'msg', 'msg2'
80
+ end
81
+ end
82
+
83
+ describe "#error [& fatal]" do
84
+ it "outputs to stderr" do
85
+ expect( $stderr ).to receive(:puts)
86
+ subject.error 'foo'
87
+ end
88
+
89
+ it "defaults to 'error' status" do
90
+ expect( Formatter ).to receive(:new)
91
+ .with( 'error', :red, 'msg' )
92
+
93
+ subject.error 'msg'
94
+ end
95
+
96
+ it "colorizes red" do
97
+ expect( Formatter ).to receive(:new)
98
+ .with( 'error', :red, 'msg' )
99
+
100
+ subject.error 'msg'
101
+ end
102
+
103
+ it "takes multiple lines of messages" do
104
+ expect( Formatter ).to receive(:new)
105
+ .with( 'error', :red, 'msg', 'msg2' )
106
+
107
+ subject.error 'msg', 'msg2'
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ describe Statistrano::Log::DefaultLogger::Formatter do
114
+
115
+ describe "#initialize" do
116
+ it "sets status as a string" do
117
+ expect( described_class.new( :status, '', '' ).status ).to eq 'status'
118
+ end
119
+
120
+ it "sets the given color" do
121
+ expect( described_class.new( '', 'color', '' ).color ).to eq 'color'
122
+ end
123
+
124
+ it "sets msgs" do
125
+ expect( described_class.new( '', '', 'msg', 'msg2' ).msgs ).to match_array ['msg','msg2']
126
+ end
127
+ end
128
+
129
+ describe "#output" do
130
+ it "pads messages" do
131
+ subject = described_class.new( '', :green, 'msg' )
132
+ expect( subject.output ).to match /->\s{15}msg/
133
+ end
134
+
135
+ it "pads multiple lined messages" do
136
+ subject = described_class.new( '', :green, 'msg', 'msg2' )
137
+ lines = subject.output.split("\n")
138
+
139
+ expect( lines.first ).to match /->\s{15}msg/
140
+ expect( lines.last ).to match /\s{16}msg2/
141
+ end
142
+
143
+ it "handles 'too long' status by padding message on second line to match first line" do
144
+ subject = described_class.new( 'onetwothreefourfive', :green, 'msg', 'msg2' )
145
+ lines = subject.output.split("\n")
146
+
147
+ expect( lines.first ).to match /->\sonetwothreefourfive\smsg/
148
+ expect( lines.last ).to match /\s{23}msg2/
149
+ end
150
+
151
+ it "colorizes status with given color" do
152
+ Rainbow.enabled = true
153
+
154
+ rainbow_double = double
155
+ subject = described_class.new( 'status', :green, 'msg' )
156
+ allow( Rainbow::Presenter ).to receive(:new)
157
+ .and_call_original
158
+ allow( Rainbow::Presenter ).to receive(:new)
159
+ .with('status')
160
+ .and_return(rainbow_double)
161
+
162
+ expect( rainbow_double ).to receive(:green)
163
+ .and_return('green')
164
+ subject.output
165
+
166
+ unless ENV['RAINBOW']
167
+ Rainbow.enabled = false
168
+ end
169
+ end
170
+ end
171
+
172
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Log do
4
+
5
+ def clean_logger_cache
6
+ if described_class.instance_variable_get(:@_logger)
7
+ described_class.send(:remove_instance_variable, :@_logger)
8
+ end
9
+ end
10
+
11
+ before :each do
12
+ clean_logger_cache
13
+ end
14
+
15
+ after :each do
16
+ clean_logger_cache
17
+ end
18
+
19
+ describe "::set_logger" do
20
+ it "sets the logger" do
21
+ Statistrano::Log.set_logger 'foo'
22
+ expect( Statistrano::Log.instance_variable_get(:@_logger) ).to eq 'foo'
23
+ end
24
+ end
25
+
26
+ describe "::logger_instance" do
27
+ it "returns the cached logger" do
28
+ Statistrano::Log.instance_variable_set(:@_logger, 'foo')
29
+ expect( Statistrano::Log.logger_instance ).to eq 'foo'
30
+ end
31
+ it "initializes a new DefaultLogger if no logger is set" do
32
+ expect( Statistrano::Log::DefaultLogger ).to receive(:new)
33
+ Statistrano::Log.logger_instance
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Remote::File do
4
+
5
+ def stub_remote_file_to_exist
6
+ expect( @remote ).to receive(:run) # the file doesn't exist
7
+ .with("[ -f /path ] && echo \"exists\"")
8
+ .and_return( HereOrThere::Response.new("exists\n",'',true) )
9
+ end
10
+
11
+ def stub_remote_file_to_not_exist
12
+ expect( @remote ).to receive(:run) # the file doesn't exist
13
+ .with("[ -f /path ] && echo \"exists\"")
14
+ .and_return( HereOrThere::Response.new('','',true) )
15
+ end
16
+
17
+ describe "#initialize" do
18
+ it "sets the given path" do
19
+ subject = described_class.new "/path", :remote
20
+ expect( subject.path ).to eq "/path"
21
+ end
22
+ it "sets the given remote" do
23
+ subject = described_class.new "/path", :remote
24
+ expect( subject.remote ).to eq :remote
25
+ end
26
+ it "sets the given permissions" do
27
+ subject = described_class.new "/path", :remote, 660
28
+ expect( subject.permissions ).to eq 660
29
+ end
30
+ it "defaults to 644 permissions if not set" do
31
+ subject = described_class.new "/path", :remote
32
+ expect( subject.permissions ).to eq 644
33
+ end
34
+ end
35
+
36
+ describe "#content" do
37
+ it "returns string of file content" do
38
+ remote_double = instance_double("Statistrano::Remote")
39
+ subject = described_class.new "/path", remote_double
40
+
41
+ expect(remote_double).to receive(:run)
42
+ .with("cat /path")
43
+ .and_return(HereOrThere::Response.new("content","",true))
44
+ expect( subject.content ).to eq "content"
45
+ end
46
+
47
+ it "returns an empty string if errors on remote" do
48
+ remote_double = instance_double("Statistrano::Remote")
49
+ subject = described_class.new "/path", remote_double
50
+
51
+ expect(remote_double).to receive(:run)
52
+ .with("cat /path")
53
+ .and_return(HereOrThere::Response.new("content","error",false))
54
+ expect( subject.content ).to eq ""
55
+ end
56
+ end
57
+
58
+ describe "#update_content!" do
59
+ before :each do
60
+ @config = double("Statistrano::Config", hostname: 'web01')
61
+ @remote = instance_double("Statistrano::Remote", config: @config )
62
+ allow( @remote ).to receive(:run)
63
+ .and_return( HereOrThere::Response.new("",'',true) )
64
+ @subject = described_class.new '/path', @remote
65
+ end
66
+
67
+ it "tests if file exists" do
68
+ expect( @remote ).to receive(:run)
69
+ .with("[ -f /path ] && echo \"exists\"")
70
+ .and_return( HereOrThere::Response.new("exists\n",'',true) )
71
+ @subject.update_content! "foooo"
72
+ end
73
+
74
+ context "when remote file doesn't exist" do
75
+ before :each do
76
+ stub_remote_file_to_not_exist
77
+ end
78
+
79
+ it "creates the file" do
80
+ expect( @remote ).to receive(:run)
81
+ .with("touch /path " +
82
+ "&& chmod 644 /path")
83
+ .and_return( HereOrThere::Response.new("",'',true) )
84
+
85
+ @subject.update_content! "content"
86
+ end
87
+
88
+ it "sets the content to the given content" do
89
+ expect( @remote ).to receive(:run)
90
+ .with( "echo 'content' > /path" )
91
+ .and_return( HereOrThere::Response.new('','',true) )
92
+
93
+ @subject.update_content! "content"
94
+ end
95
+ end
96
+
97
+ context "when remote file already existed" do
98
+ before :each do
99
+ stub_remote_file_to_exist
100
+ end
101
+ it "sets the content to the given content" do
102
+ expect( @remote ).to receive(:run)
103
+ .with( "echo 'content' > /path" )
104
+ .and_return( HereOrThere::Response.new('','',true) )
105
+
106
+ @subject.update_content! "content"
107
+ end
108
+ end
109
+ end
110
+
111
+
112
+ describe "#append_content!" do
113
+
114
+ before :each do
115
+ @config = double("Statistrano::Config", hostname: 'web01')
116
+ @remote = instance_double("Statistrano::Remote", config: @config )
117
+ allow( @remote ).to receive(:run)
118
+ .and_return( HereOrThere::Response.new("",'',true) )
119
+ @subject = described_class.new '/path', @remote
120
+ end
121
+
122
+ context "when remote file doesn't exist" do
123
+
124
+ before :each do
125
+ stub_remote_file_to_not_exist
126
+ end
127
+
128
+ it "creates the file before trying to append" do
129
+ expect( @remote ).to receive(:run)
130
+ .with("touch /path " +
131
+ "&& chmod 644 /path")
132
+
133
+ @subject.append_content! "the content"
134
+ end
135
+ end
136
+
137
+ context "when remote file already exists" do
138
+
139
+ before :each do
140
+ stub_remote_file_to_exist
141
+ end
142
+
143
+ it "appends new content to file" do
144
+ expect( @remote ).to receive(:run)
145
+ .with("echo 'the content' >> /path")
146
+
147
+ @subject.append_content! "the content"
148
+ end
149
+ end
150
+ end
151
+
152
+
153
+ describe "#destroy!" do
154
+ it "removes the file" do
155
+ config = double("Statistrano::Config", hostname: 'web01')
156
+ remote = instance_double("Statistrano::Remote", config: config )
157
+ allow( remote ).to receive(:run)
158
+ .and_return( HereOrThere::Response.new("",'',true) )
159
+ subject = described_class.new '/path', remote
160
+
161
+ expect(remote).to receive(:run).with("rm /path")
162
+ subject.destroy!
163
+ end
164
+ end
165
+
166
+ end
@@ -0,0 +1,226 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe Statistrano::Remote do
5
+
6
+ let(:default_options) do
7
+ {
8
+ hostname: 'web01',
9
+ verbose: false,
10
+ user: nil,
11
+ passowrd: nil,
12
+ dir_permissions: 755,
13
+ file_permissions: 644,
14
+ rsync_flags: '-aqz --delete-after'
15
+ }
16
+ end
17
+
18
+ let(:default_config) do
19
+ config default_options
20
+ end
21
+
22
+ def create_ssh_double
23
+ ssh_double = instance_double("HereOrThere::Remote::SSH")
24
+ allow( HereOrThere::Remote ).to receive(:session).and_return(ssh_double)
25
+ return ssh_double
26
+ end
27
+
28
+ def config options
29
+ OpenStruct.new( options )
30
+ end
31
+
32
+ describe "#initialize" do
33
+ it "assigns given config to config" do
34
+ subject = described_class.new default_config
35
+ expect( subject.config ).to eq default_config
36
+ end
37
+
38
+ it "raises an error if no hostname is given" do
39
+ expect{
40
+ described_class.new( Struct.new(:hostname).new )
41
+ }.to raise_error ArgumentError, 'a hostname is required'
42
+ end
43
+ end
44
+
45
+ describe "#run" do
46
+ it "passes command to ssh_session#run" do
47
+ ssh_double = create_ssh_double
48
+ subject = described_class.new default_config
49
+
50
+ expect( ssh_double ).to receive(:run).with('ls')
51
+ subject.run 'ls'
52
+ end
53
+
54
+ it "logs the command if verbose is true" do
55
+ ssh_double = create_ssh_double
56
+ subject = described_class.new config default_options.merge verbose: true
57
+
58
+
59
+ allow( ssh_double ).to receive(:run).with('ls')
60
+ expect( Statistrano::Log ).to receive(:info)
61
+ .with( :web01, "running cmd: ls")
62
+ subject.run 'ls'
63
+ end
64
+ end
65
+
66
+ describe "#done" do
67
+ it "passes close_session command to ssh_session" do
68
+ ssh_double = create_ssh_double
69
+ subject = described_class.new default_config
70
+
71
+ expect( ssh_double ).to receive(:close_session)
72
+ subject.done
73
+ end
74
+ end
75
+
76
+ describe "#test_connection" do
77
+ it "runs whoami on remote" do
78
+ ssh_double = create_ssh_double
79
+ allow(ssh_double).to receive(:close_session)
80
+ subject = described_class.new default_config
81
+
82
+ expect( ssh_double ).to receive(:run).with('whoami')
83
+ .and_return( HereOrThere::Response.new("statistrano","",true))
84
+ subject.test_connection
85
+ end
86
+ it "returns true if successful" do
87
+ ssh_double = create_ssh_double
88
+ allow(ssh_double).to receive(:close_session)
89
+ subject = described_class.new default_config
90
+
91
+ expect( ssh_double ).to receive(:run).with('whoami')
92
+ .and_return( HereOrThere::Response.new("statistrano","",true))
93
+ expect( subject.test_connection ).to be_truthy
94
+ end
95
+ it "returns false if fails" do
96
+ ssh_double = create_ssh_double
97
+ allow(ssh_double).to receive(:close_session)
98
+ subject = described_class.new default_config
99
+
100
+ expect( ssh_double ).to receive(:run).with('whoami')
101
+ .and_return( HereOrThere::Response.new("","error",false))
102
+ expect( subject.test_connection ).to be_falsy
103
+ end
104
+ end
105
+
106
+ describe "#create_remote_dir" do
107
+ it "runs mkdir command on remote" do
108
+ ssh_double = create_ssh_double
109
+ subject = described_class.new default_config
110
+
111
+ expect( ssh_double ).to receive(:run)
112
+ .with("mkdir -p -m 755 /var/www/proj")
113
+ .and_return( HereOrThere::Response.new("","",true) )
114
+ subject.create_remote_dir "/var/www/proj"
115
+ end
116
+
117
+ it "requires an absolute path" do
118
+ ssh_double = create_ssh_double
119
+ subject = described_class.new default_config
120
+
121
+ expect {
122
+ subject.create_remote_dir "var/www/proj"
123
+ }.to raise_error ArgumentError, "path must be absolute"
124
+ end
125
+
126
+ it "uses the set dir_permissions" do
127
+ ssh_double = create_ssh_double
128
+ subject = described_class.new config default_options.merge dir_permissions: 644
129
+
130
+ expect( ssh_double ).to receive(:run)
131
+ .with("mkdir -p -m 644 /var/www/proj")
132
+ .and_return( HereOrThere::Response.new("","",true) )
133
+ subject.create_remote_dir "/var/www/proj"
134
+ end
135
+
136
+ context "when remote dir creation fails" do
137
+ it "logs error & exits" do
138
+ ssh_double = create_ssh_double
139
+ subject = described_class.new default_config
140
+ allow( ssh_double ).to receive(:run)
141
+ .with("mkdir -p -m 755 /var/www/proj")
142
+ .and_return( HereOrThere::Response.new("","oh noes",false) )
143
+
144
+ expect( Statistrano::Log ).to receive(:error)
145
+ .with( "Unable to create directory '/var/www/proj' on web01",
146
+ "oh noes")
147
+ expect{
148
+ subject.create_remote_dir "/var/www/proj"
149
+ }.to raise_error SystemExit
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "#rsync_to_remote" do
155
+ it "runs command to rsync local to remote" do
156
+ subject = described_class.new default_config
157
+
158
+ expect( Statistrano::Shell ).to receive(:run_local)
159
+ .with("rsync -aqz --delete-after " +
160
+ "--chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r " +
161
+ "-e ssh local_path/ " +
162
+ "web01:remote_path/")
163
+ .and_return( HereOrThere::Response.new("","",true) )
164
+
165
+ subject.rsync_to_remote 'local_path', 'remote_path'
166
+ end
167
+
168
+ it "corrects for adding a trailing slash to local_path or remote_path" do
169
+ subject = described_class.new default_config
170
+
171
+ expect( Statistrano::Shell ).to receive(:run_local)
172
+ .with("rsync -aqz --delete-after " +
173
+ "--chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r " +
174
+ "-e ssh local_path/ " +
175
+ "web01:remote_path/")
176
+ .and_return( HereOrThere::Response.new("","",true) )
177
+
178
+ subject.rsync_to_remote 'local_path/', 'remote_path/'
179
+ end
180
+
181
+ it "uses the set dir_permissions & file_permissions" do
182
+ subject = described_class.new config default_options.merge dir_permissions: 644, file_permissions: 755
183
+
184
+ expect( Statistrano::Shell ).to receive(:run_local)
185
+ .with("rsync -aqz --delete-after " +
186
+ "--chmod=Du=rw,Dg=r,Do=r,Fu=rwx,Fg=rx,Fo=rx " +
187
+ "-e ssh local_path/ " +
188
+ "web01:remote_path/")
189
+ .and_return( HereOrThere::Response.new("","",true) )
190
+
191
+ subject.rsync_to_remote 'local_path/', 'remote_path/'
192
+ end
193
+
194
+ it "uses the set rsync_flags" do
195
+ subject = described_class.new config default_options.merge rsync_flags: "-aqz"
196
+
197
+ expect( Statistrano::Shell ).to receive(:run_local)
198
+ .with("rsync -aqz " +
199
+ "--chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r " +
200
+ "-e ssh local_path/ " +
201
+ "web01:remote_path/")
202
+ .and_return( HereOrThere::Response.new("","",true) )
203
+
204
+ subject.rsync_to_remote 'local_path/', 'remote_path/'
205
+ end
206
+
207
+ it "logs error if rsync command fails" do
208
+ subject = described_class.new default_config
209
+ expect( Statistrano::Shell ).to receive(:run_local)
210
+ .and_return( HereOrThere::Response.new("","",false) )
211
+
212
+ expect( Statistrano::Log ).to receive(:error)
213
+ subject.rsync_to_remote 'local_path', 'remote_path'
214
+ end
215
+
216
+ it "returns the response" do
217
+ subject = described_class.new default_config
218
+ response = HereOrThere::Response.new("woo","",true)
219
+ expect( Statistrano::Shell ).to receive(:run_local)
220
+ .and_return( response )
221
+
222
+ expect( subject.rsync_to_remote('local_path','remote_path') ).to eq response
223
+ end
224
+ end
225
+
226
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Util::FilePermissions do
4
+
5
+ describe "#initialize" do
6
+ it "sets user, group, and others based on given perm integer" do
7
+ subject = described_class.new 644
8
+
9
+ expect( subject.user ).to eq "6"
10
+ expect( subject.group ).to eq "4"
11
+ expect( subject.others ).to eq "4"
12
+ end
13
+ end
14
+
15
+ describe "#to_chmod" do
16
+ it "returns an object with the correct user, group, and others" do
17
+ subject = described_class.new( 644 ).to_chmod
18
+
19
+ expect( subject.user ).to eq "rw"
20
+ expect( subject.group ).to eq "r"
21
+ expect( subject.others ).to eq "r"
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Statistrano::Util do
4
+
5
+ describe "::symbolize_hash_keys" do
6
+ it "symbolizes keys of hash" do
7
+ expect(
8
+ Statistrano::Util.symbolize_hash_keys( { 'foo' => 'bar' })
9
+ ).to eq foo: 'bar'
10
+ end
11
+ it "symbolizes keys of nested hashes" do
12
+ expect(
13
+ Statistrano::Util.symbolize_hash_keys( { 'foo' => { 'bar' => 'baz' }})
14
+ ).to eq foo: { bar: 'baz' }
15
+ end
16
+ it "symbolizes keys of hashes nested in arrays" do
17
+ expect(
18
+ Statistrano::Util.symbolize_hash_keys( { 'foo' => [{'bar'=>'baz'},{'wu'=>'tang'}]})
19
+ ).to eq foo: [{bar:'baz'},{wu:'tang'}]
20
+ end
21
+ end
22
+
23
+ end