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
data/readme.md ADDED
@@ -0,0 +1,247 @@
1
+ Description
2
+ ===========
3
+
4
+ A gem to simplify the deployment of static sites, and staging of feature branches.
5
+
6
+
7
+
8
+ Installation
9
+ ============
10
+
11
+ With Bundler
12
+ ```ruby
13
+ gem "statistrano", git: "git@github.com:mailchimp/statistrano.git",
14
+ tag: "X.X.X"
15
+ ```
16
+
17
+
18
+ Examples
19
+ ========
20
+
21
+ ### Base deployment
22
+
23
+ The base setup simply copies a local directory to a remote directory
24
+
25
+ ```ruby
26
+ # deploy.rake
27
+ require 'statistrano'
28
+
29
+ deployment = define_deployment "basic" do
30
+
31
+ hostname 'remote_name'
32
+ user 'freddie' # optional if remote is setup in .ssh/config
33
+ password 'something long and stuff' # optional if remote is setup in .ssh/config
34
+
35
+ remote_dir '/var/www/mailchimp.com'
36
+ local_dir 'build'
37
+ build_task 'middleman:build' # optional if nothing needs to be built
38
+ post_deploy_task 'base:post_deploy' # optional if no task should be run after deploy
39
+
40
+ dir_permissions 755 # optional, the perms set on rsync & setup for directories
41
+ file_permissions 644 # optional, the perms set on rsync & setup for files
42
+ rsync_flags '-aqz --delete-after' # optional, flags for rsync
43
+
44
+ check_git true # optional, set to false if git shouldn't be checked
45
+ git_branch 'master' # which branch to check against
46
+
47
+ # optional, you can define multiple remotes to deploy to
48
+ # any config option can be overriden in the remote's data hash
49
+ remotes [
50
+ { hostname: 'remote01', remote_dir: '/var/www/mailchimp01' },
51
+ { hostname: 'remote02', remote_dir: '/var/www/mailchimp02' }
52
+ ]
53
+
54
+ end
55
+ ```
56
+
57
+ **Rake Tasks**
58
+
59
+ Once a deployment is defined, you can register it's tasks -- or call the methods directly.
60
+
61
+ ```ruby
62
+ # deploy.rake
63
+ deployment.register_tasks
64
+ # => rake tasks are registered
65
+ ```
66
+
67
+ `rake basic:deploy`
68
+ deploys the local_dir to the remote_dir. optionally call `deployment.deploy`
69
+
70
+
71
+ ### Releases deployment
72
+
73
+ Out of the box Statistrano allows you to pick from a release based deployment, or branch based. Releases act as a series of snapshots of your project with the most recent linked to the `public_dir`. You can quickly rollback in case of errors.
74
+
75
+ ```ruby
76
+ # deploy.rake
77
+ require 'statistrano'
78
+
79
+ deployment = define_deployment "production", :releases do
80
+
81
+ # in addition to the "base" config options, there
82
+ # are some (all defaulted) options specific for releases
83
+ release_count 5
84
+ release_dir "releases"
85
+ public_dir "current"
86
+
87
+ end
88
+ ```
89
+
90
+ **Rake Tasks**
91
+
92
+ Once a deployment is defined, you can register it's tasks -- or call the methods directly.
93
+
94
+ ```ruby
95
+ # deploy.rake
96
+ deployment.register_tasks
97
+ # => rake tasks are registered
98
+ ```
99
+
100
+ `rake production:deploy`
101
+ deploys local_dir to the remote, and symlinks remote_dir/current to the release.
102
+
103
+ `rake production:rollback`
104
+ rolls back to the previous release.
105
+
106
+ `rake production:prune`
107
+ manually removes old releases beyond the release count
108
+
109
+ `rake production:list`
110
+ lists all the currently deployed releases
111
+
112
+
113
+ ### Branch deployment
114
+
115
+ The branch deployment type adds some nice defaults to use the current branch as your release name. So with the correct nginx/apache config you can have your branches mounted as subdomains (eg: `http://my_awesome_branch.example.com`). Aditionally it is set up to create an `index` release that shows a list of your currently deployed branches.
116
+
117
+
118
+ ```ruby
119
+ deployment = define_deployment "branches", :branches do
120
+
121
+ # in addition to the "base" options
122
+ base_domain "mailchimp.com" # used to generate the subdomain links in the index file
123
+ public_dir "current_branch" # defaults to a slugged version of the current branch
124
+ post_deploy_task "name:generate_index" # defaults to create the index file
125
+
126
+ end
127
+ ```
128
+
129
+ **Rake Tasks**
130
+
131
+ Once a deployment is defined, you can register it's tasks -- or call the methods directly.
132
+
133
+ ```ruby
134
+ # deploy.rake
135
+ deployment.register_tasks
136
+ # => rake tasks are registered
137
+ ```
138
+
139
+ `rake branches:deploy`
140
+ deploys local_dir to the remote named for the current git branch, and generates an index page
141
+
142
+ `rake branches:list`
143
+ lists all the currently deployed branches
144
+
145
+ `rake branches:open`
146
+ If you have set a base_domain, opens the branch in your default browser
147
+
148
+ `rake branches:prune`
149
+ shows list of currently deployed branches to pick from and remove
150
+
151
+ `rake branches:generate_index`
152
+ manually kicks of index generation, typically you shouldn't need to do this
153
+
154
+
155
+ ## Build & Post Deploy Tasks
156
+
157
+ Of note, the `build_task` & `post_deploy_task` can be defined as a block. Some release types (like "releases") will use a hash if it is returned by the block.
158
+
159
+ ```ruby
160
+ deployment = define_deployment 'multi', :releases do
161
+ build_task do
162
+ Rake::Task['build'].invoke
163
+ { commit: Asgit.current_commit }
164
+ end
165
+ end
166
+
167
+ deployment.deploy
168
+ # => remote/manifest.manifest will end up with [{release: 'timestamp', commit: 'commit_sha'}]
169
+ ```
170
+
171
+ You can also access the current deployment info by giving the block arity.
172
+
173
+ ```ruby
174
+ deployment = define_deployment 'multi', :releases do
175
+ build_task do |dep|
176
+ puts dep.name
177
+ end
178
+ end
179
+
180
+ deployment.invoke_build_task
181
+ # => will output the deployment name 'multi'
182
+ ```
183
+
184
+ ### Config Syntax
185
+
186
+ In addition to the "DSL" way of configuring, the `define_deployment` block will yield the config if an argument is passed. You can use this if you need to do any specific manipulation to config (is also the "old" syntax).
187
+
188
+ ```ruby
189
+ define_deployment "basic" do |config|
190
+
191
+ config.remote = 'remote_name'
192
+ config.remote_dir = '/var/www/mailchimp.com'
193
+ config.local_dir = 'build'
194
+
195
+ end
196
+ ```
197
+
198
+
199
+ Testing
200
+ =======
201
+
202
+ Tests are written in rspec, and can be run with `rspec`. To run an individual test, run `rspec path/to/spec.rb`.
203
+
204
+ Integraton tests run through `localhost`, this requires that you setup ssh through localhost to run the tests. Look at [setup](#setup) for help with that.
205
+
206
+
207
+ ### Setup
208
+
209
+ On Mac OS X 10.8, you should enable remote login.
210
+
211
+ ```
212
+ System Preferences -> Sharing -> Turn on Remote Login
213
+ ```
214
+
215
+ And setup your `.ssh/config`
216
+
217
+ ```
218
+ Host localhost
219
+ HostName localhost
220
+ User {{your_username}}
221
+ ```
222
+
223
+ Then add your pub key to `.ssh/authorized_keys`.
224
+
225
+ Depending on how you've setup your `.bashrc` is setup, you may need to move any PATH manipulation to the front of the file to prevent commands from failing.
226
+
227
+
228
+ ### Test accross multiple rubies
229
+
230
+ To run specs accross the supported rubies, run `bin/multi_ruby_rspec`
231
+
232
+
233
+ Contributing
234
+ ============
235
+
236
+ If there is any thing you'd like to contribute or fix, please:
237
+
238
+ - Fork the repo
239
+ - Add tests for any new functionality
240
+ - Make your changes
241
+ - Verify all existing tests work properly
242
+ - Make a pull request
243
+
244
+
245
+ License
246
+ =======
247
+ The statistrano gem is distributed under the MIT License.
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Base integration", :integration do
4
+
5
+ after :each do
6
+ reenable_rake_tasks
7
+ Given.cleanup!
8
+ end
9
+
10
+ context "with a single remote" do
11
+ it "deploys the contents of source to the 'deploy' folder" do
12
+ Given.fixture "base"
13
+ base = define_deployment "base" do |c|
14
+ c.build_task = 'remote:copy'
15
+ c.hostname = 'localhost'
16
+ c.local_dir = 'build'
17
+ c.remote_dir = File.join( Dir.pwd, 'deployment' )
18
+ end
19
+
20
+ base.deploy
21
+ result_a = Statistrano::Shell.run_local("ls source")
22
+ result_b = Statistrano::Shell.run_local("ls deployment")
23
+
24
+ expect( result_a ).to be_success
25
+ expect( result_b ).to be_success
26
+ expect( result_a.stdout ).to eq result_b.stdout
27
+ end
28
+
29
+ it "doesn't create a deployment on the remote & should return false if there is a build error" do
30
+ Given.fixture "error_on_build"
31
+ expect( Statistrano::Shell.run_local("rake error:deploy") ).not_to be_success #confirming the error
32
+
33
+ expect( Dir.exists?("deployment") ).to be_falsy
34
+ end
35
+
36
+ it "appends to a log file with each deploy" do
37
+ Given.fixture "base"
38
+ deploys = 0
39
+ base = define_deployment "base" do
40
+ build_task 'remote:copy'
41
+ hostname 'localhost'
42
+ local_dir 'build'
43
+ remote_dir File.join( Dir.pwd, 'deployment' )
44
+
45
+ log_file_path File.join( Dir.pwd, 'deploy.log' )
46
+ log_file_entry do |d, r, b_d, p_d_d|
47
+ { deployment: (deploys += 1) }
48
+ end
49
+ end
50
+
51
+ base.deploy
52
+ base.deploy
53
+
54
+ expect( Statistrano::Shell.run_local("cat deploy.log").stdout ).to eq "{\"deployment\":1}\n{\"deployment\":2}\n"
55
+ end
56
+ end
57
+
58
+ context "with multiple remotes" do
59
+ it "deploys the contents of source to each remote" do
60
+ Given.fixture "base"
61
+ base = define_deployment "base" do
62
+ build_task "remote:copy"
63
+ hostname "localhost"
64
+ local_dir "build"
65
+ remote_dir File.join( Dir.pwd, 'deployment' )
66
+
67
+ remotes [
68
+ { remote_dir: File.join( Dir.pwd, "deployment", "target01" ) },
69
+ { remote_dir: File.join( Dir.pwd, "deployment", "target02" ) }
70
+ ]
71
+ end
72
+
73
+ base.deploy
74
+
75
+ expect( deployment_folder_contents ).to match_array [ "target01", "target02" ]
76
+ end
77
+ end
78
+
79
+ context "with specific file permissions" do
80
+ it "deploys with those permissions" do
81
+ Given.fixture "base"
82
+ base = define_deployment "base" do
83
+ build_task "remote:copy"
84
+ hostname "localhost"
85
+ local_dir "build"
86
+ remote_dir File.join( Dir.pwd, 'deployment' )
87
+
88
+ # these are really bad perms on purpose
89
+ dir_permissions 777
90
+ file_permissions 666
91
+ end
92
+
93
+ base.deploy
94
+
95
+ deployment_dir_perms = sprintf( "%o", File.stat("deployment").mode ).chars.to_a.last(3).join
96
+ deployment_file_perms = sprintf( "%o", File.stat("deployment/index.html").mode ).chars.to_a.last(3).join
97
+
98
+ expect( deployment_dir_perms ).to eq "777"
99
+ expect( deployment_file_perms ).to eq "666"
100
+ end
101
+ end
102
+
103
+ end
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Branches integration", :integration do
4
+
5
+ context "with a single remote" do
6
+ before :all do
7
+ Given.fixture "base"
8
+
9
+ RSpec::Mocks.with_temporary_scope do
10
+ @deployment = define_deployment "branches", :branches do |c|
11
+ c.build_task = 'remote:copy'
12
+ c.hostname = 'localhost'
13
+ c.local_dir = 'build'
14
+ c.remote_dir = File.join( Dir.pwd, 'deployment' )
15
+ c.base_domain = "example.com"
16
+ end
17
+
18
+ allow( Asgit ).to receive(:current_branch)
19
+ .and_return('first_branch')
20
+ allow( Time ).to receive(:now)
21
+ .and_return(1372020000)
22
+ @deployment.deploy
23
+
24
+ allow( Asgit ).to receive(:current_branch)
25
+ .and_return('second_branch')
26
+ allow( Time ).to receive(:now)
27
+ .and_return(1372030000)
28
+ @deployment.deploy
29
+ end
30
+ end
31
+
32
+ after :each do
33
+ reenable_rake_tasks
34
+ end
35
+
36
+ after :all do
37
+ Given.cleanup!
38
+ end
39
+
40
+ it "generates a release at the specified branches" do
41
+ ["first_branch", "index", "second_branch"].each do |dir|
42
+ expect( deployment_folder_contents ).to include dir
43
+ end
44
+ end
45
+
46
+ it "lists the deployed branches" do
47
+ output = catch_stdout {
48
+ @deployment.list_releases
49
+ }
50
+ expect( output ).to include "first_branch"
51
+ expect( output ).to include "second_branch"
52
+ end
53
+
54
+ it "generates an index page with the correct order of branches" do
55
+ index_html = IO.read("deployment/index/index.html")
56
+ expect( index_html ).to include <<-eof
57
+ <li>
58
+ <a href="http://second_branch.example.com">second_branch</a>
59
+ <small>updated: Sunday Jun 23, 2013 at 7:26 pm</small>
60
+ </li>
61
+
62
+ <li>
63
+ <a href="http://first_branch.example.com">first_branch</a>
64
+ <small>updated: Sunday Jun 23, 2013 at 4:40 pm</small>
65
+ </li>
66
+ eof
67
+ end
68
+
69
+ it "removes the selected branch to prune" do
70
+ release_stdin 1 do
71
+ @deployment.prune_releases
72
+ expect( Dir[ "deployment/**" ] ).not_to include "deployment/first_branch"
73
+ end
74
+ end
75
+ end
76
+
77
+ context "with multiple remotes" do
78
+ before :all do
79
+ Given.fixture "base"
80
+
81
+ RSpec::Mocks.with_temporary_scope do
82
+ @deployment = define_deployment "branches", :branches do
83
+ build_task 'remote:copy'
84
+ hostname 'localhost'
85
+ local_dir 'build'
86
+ base_domain "example.com"
87
+ remote_dir File.join( Dir.pwd, 'deployment' )
88
+
89
+ remotes [
90
+ { remote_dir: File.join( Dir.pwd, 'deployment', 'remote01' ) },
91
+ { remote_dir: File.join( Dir.pwd, 'deployment', 'remote02' ) }
92
+ ]
93
+ end
94
+
95
+ allow( Asgit ).to receive(:current_branch)
96
+ .and_return('first_branch')
97
+ allow( Time ).to receive(:now)
98
+ .and_return(1372020000)
99
+ @deployment.deploy
100
+
101
+ allow( Asgit ).to receive(:current_branch)
102
+ .and_return('second_branch')
103
+ allow( Time ).to receive(:now)
104
+ .and_return(1372030000)
105
+ @deployment.deploy
106
+ end
107
+ end
108
+
109
+ after :each do
110
+ reenable_rake_tasks
111
+ end
112
+
113
+ after :all do
114
+ Given.cleanup!
115
+ end
116
+
117
+ def deployment_dir_contents
118
+ Dir[ "deployment/**/*" ].map do |e|
119
+ e.sub /^deployment\/?/, ''
120
+ end
121
+ end
122
+
123
+ it "creates a release on each remote" do
124
+ expect( deployment_dir_contents ).to match_array [
125
+ "remote01",
126
+ "remote01/index",
127
+ "remote01/index/index.html",
128
+ "remote01/first_branch",
129
+ "remote01/first_branch/index.html",
130
+ "remote01/second_branch",
131
+ "remote01/second_branch/index.html",
132
+ "remote01/manifest.json",
133
+
134
+ "remote02",
135
+ "remote02/index",
136
+ "remote02/index/index.html",
137
+ "remote02/first_branch",
138
+ "remote02/first_branch/index.html",
139
+ "remote02/second_branch",
140
+ "remote02/second_branch/index.html",
141
+ "remote02/manifest.json"
142
+ ]
143
+ end
144
+
145
+ it "lists the deployed branches" do
146
+ @deployment.list_releases
147
+ output = catch_stdout {
148
+ @deployment.list_releases
149
+ }
150
+ expect( output ).to include "first_branch"
151
+ expect( output ).to include "second_branch"
152
+ end
153
+
154
+ it "generates an index page with the correct order of branches" do
155
+ expected_html = <<-eof
156
+ <li>
157
+ <a href="http://second_branch.example.com">second_branch</a>
158
+ <small>updated: Sunday Jun 23, 2013 at 7:26 pm</small>
159
+ </li>
160
+
161
+ <li>
162
+ <a href="http://first_branch.example.com">first_branch</a>
163
+ <small>updated: Sunday Jun 23, 2013 at 4:40 pm</small>
164
+ </li>
165
+ eof
166
+
167
+ expect( IO.read("deployment/remote01/index/index.html") ).to include expected_html
168
+ expect( IO.read("deployment/remote02/index/index.html") ).to include expected_html
169
+ end
170
+
171
+ it "removes the selected branch to prune" do
172
+ # verify deployments are there to begin with
173
+ expect( deployment_dir_contents ).to include "remote01/first_branch"
174
+ expect( deployment_dir_contents ).to include "remote02/first_branch"
175
+
176
+ release_stdin 1 do
177
+ @deployment.prune_releases
178
+ end
179
+
180
+ expect( deployment_dir_contents ).not_to include "remote01/first_branch"
181
+ expect( deployment_dir_contents ).not_to include "remote02/first_branch"
182
+
183
+ # verify the one we didn't remove is still there
184
+ expect( deployment_dir_contents ).to include "remote01/second_branch"
185
+ expect( deployment_dir_contents ).to include "remote02/second_branch"
186
+ end
187
+ end
188
+
189
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Strategy::Releases#deploy integration", :integration do
4
+
5
+ context "with a single target" do
6
+ before :each do
7
+ reenable_rake_tasks
8
+ Given.fixture "base"
9
+ @subject = define_deployment "single_target", :releases do
10
+ build_task "remote:copy"
11
+ local_dir "build"
12
+ remote_dir File.join( Dir.pwd, "deployment" )
13
+
14
+ release_count 2
15
+ remotes [{ hostname: 'localhost', verbose: true }]
16
+ end
17
+
18
+ allow( Time ).to receive(:now).and_return(1372020000)
19
+ @subject.deploy
20
+
21
+ allow( Time ).to receive(:now).and_return(1372030000)
22
+ @subject.deploy
23
+
24
+ allow( Time ).to receive(:now).and_return(1372040000)
25
+ @subject.deploy
26
+ end
27
+
28
+ after :each do
29
+ Given.cleanup!
30
+ end
31
+
32
+ it "generates a release with the correct time stamp,\n" +
33
+ "restricts the release count to the defined number,\n" +
34
+ "& symlinks the pub_dir to the most recent release" do
35
+ expect( release_folder_contents ).to match_array ["1372030000", "1372040000"]
36
+ expect( release_folder_contents.length ).to eq 2
37
+ resp = Statistrano::Shell.run_local("ls -l deployment")
38
+ expect( resp.stdout ).to match /current\s->(.+)\/deployment\/releases\/1372040000/
39
+ end
40
+
41
+ context "when pre_symlink_task fails" do
42
+ it "leaves the release inplace, but unlinked" do
43
+ @subject = define_deployment "single_target", :releases do
44
+ build_task "remote:copy"
45
+ local_dir "build"
46
+ remote_dir File.join( Dir.pwd, "deployment" )
47
+
48
+ release_count 2
49
+ remotes [{ hostname: 'localhost', verbose: true }]
50
+ pre_symlink_task do
51
+ false
52
+ end
53
+ end
54
+
55
+ allow( Time ).to receive(:now).and_return(1372050000)
56
+
57
+ expect {
58
+ @subject.deploy
59
+ }.to raise_error SystemExit
60
+
61
+ expect( release_folder_contents ).to match_array ["1372030000", "1372040000", "1372050000"]
62
+ resp = Statistrano::Shell.run_local("ls -l deployment")
63
+ expect( resp.stdout ).to match /current\s->(.+)\/deployment\/releases\/1372040000/
64
+ end
65
+ end
66
+ end
67
+
68
+ context "with multiple remotes" do
69
+
70
+ before :each do
71
+ reenable_rake_tasks
72
+ Given.fixture "base"
73
+ subject = define_deployment "multi_target", :releases do
74
+ build_task "remote:copy"
75
+ local_dir "build"
76
+ hostname "localhost"
77
+ remote_dir File.join( Dir.pwd, "deployment" )
78
+
79
+ release_count 2
80
+ remotes [
81
+ { remote_dir: File.join( Dir.pwd, "deployment", "target01" ) },
82
+ { remote_dir: File.join( Dir.pwd, "deployment", "target02" ) },
83
+ { remote_dir: File.join( Dir.pwd, "deployment", "target03" ) }
84
+ ]
85
+ end
86
+
87
+ allow( Time ).to receive(:now).and_return(1372020000)
88
+ subject.deploy
89
+
90
+ allow( Time ).to receive(:now).and_return(1372030000)
91
+ subject.deploy
92
+
93
+ allow( Time ).to receive(:now).and_return(1372040000)
94
+ subject.deploy
95
+ end
96
+
97
+ after :each do
98
+ Given.cleanup!
99
+ end
100
+
101
+ it "generates a release with the correct time stamp,\n" +
102
+ "restricts the release count to the defined number,\n" +
103
+ "& symlinks the pub_dir to the most recent release" do
104
+ expect( multi_release_folder_contents )
105
+ .to match_array [ "target01/releases/1372030000", "target01/releases/1372040000",
106
+ "target02/releases/1372030000", "target02/releases/1372040000",
107
+ "target03/releases/1372030000", "target03/releases/1372040000" ]
108
+
109
+ ["target01","target02","target03"].each do |target|
110
+ resp = Statistrano::Shell.run_local("ls -l deployment/#{target}")
111
+ expect( resp.stdout ).to match /current\s->(.+)\/deployment\/#{target}\/releases\/1372040000/
112
+ end
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Statistrano::Deployment::Strategy::Releases#list_releases integration", :integration do
4
+
5
+ context "with multiple_targets target" do
6
+
7
+ before :each do
8
+ Given.fixture "releases-deployed"
9
+ @subject = define_deployment "releases", :releases do
10
+ build_task "remote:copy"
11
+ local_dir "build"
12
+ hostname "localhost"
13
+ remote_dir File.join( Dir.pwd, "deployment" )
14
+
15
+ release_count 2
16
+ remotes [
17
+ { remote_dir: File.join( Dir.pwd, "deployment", "target01" ) },
18
+ { remote_dir: File.join( Dir.pwd, "deployment", "target02" ) },
19
+ { remote_dir: File.join( Dir.pwd, "deployment", "target03" ) }
20
+ ]
21
+ end
22
+ end
23
+
24
+ after :each do
25
+ Given.cleanup!
26
+ end
27
+
28
+ it "lists currently deployed releases" do
29
+ output = catch_stdout do
30
+ @subject.list_releases
31
+ end
32
+
33
+ expect( output ).to match /->(.+?)localhost(.+?)\[\"1372040000\", \"1372030000\"\]/
34
+ end
35
+
36
+ end
37
+
38
+ end