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
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