statistrano 1.2.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.
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