statistrano 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/changelog.md +161 -0
- data/doc/config/file-permissions.md +33 -0
- data/doc/config/log-files.md +32 -0
- data/doc/config/task-definitions.md +88 -0
- data/doc/getting-started.md +96 -0
- data/doc/strategies/base.md +38 -0
- data/doc/strategies/branches.md +82 -0
- data/doc/strategies/releases.md +110 -0
- data/doc/strategies.md +17 -0
- data/lib/statistrano/config/configurable.rb +53 -0
- data/lib/statistrano/config/rake_task_with_context_creation.rb +43 -0
- data/lib/statistrano/config.rb +52 -0
- data/lib/statistrano/deployment/log_file.rb +44 -0
- data/lib/statistrano/deployment/manifest.rb +88 -0
- data/lib/statistrano/deployment/rake_tasks.rb +74 -0
- data/lib/statistrano/deployment/registerable.rb +11 -0
- data/lib/statistrano/deployment/releaser/revisions.rb +163 -0
- data/lib/statistrano/deployment/releaser/single.rb +48 -0
- data/lib/statistrano/deployment/releaser.rb +2 -0
- data/lib/statistrano/deployment/strategy/base.rb +132 -0
- data/lib/statistrano/deployment/strategy/branches/index/template.html.erb +78 -0
- data/lib/statistrano/deployment/strategy/branches/index.rb +40 -0
- data/lib/statistrano/deployment/strategy/branches/release.rb +73 -0
- data/lib/statistrano/deployment/strategy/branches.rb +198 -0
- data/lib/statistrano/deployment/strategy/check_git.rb +43 -0
- data/lib/statistrano/deployment/strategy/invoke_tasks.rb +58 -0
- data/lib/statistrano/deployment/strategy/releases.rb +76 -0
- data/lib/statistrano/deployment/strategy.rb +37 -0
- data/lib/statistrano/deployment.rb +10 -0
- data/lib/statistrano/log/default_logger.rb +105 -0
- data/lib/statistrano/log.rb +33 -0
- data/lib/statistrano/remote/file.rb +79 -0
- data/lib/statistrano/remote.rb +111 -0
- data/lib/statistrano/shell.rb +17 -0
- data/lib/statistrano/util/file_permissions.rb +34 -0
- data/lib/statistrano/util.rb +27 -0
- data/lib/statistrano/version.rb +3 -0
- data/lib/statistrano.rb +55 -0
- data/readme.md +247 -0
- data/spec/integration_tests/base_integration_spec.rb +103 -0
- data/spec/integration_tests/branches_integration_spec.rb +189 -0
- data/spec/integration_tests/releases/deploy_integration_spec.rb +116 -0
- data/spec/integration_tests/releases/list_releases_integration_spec.rb +38 -0
- data/spec/integration_tests/releases/prune_releases_integration_spec.rb +86 -0
- data/spec/integration_tests/releases/rollback_release_integration_spec.rb +46 -0
- data/spec/lib/statistrano/config/configurable_spec.rb +88 -0
- data/spec/lib/statistrano/config/rake_task_with_context_creation_spec.rb +73 -0
- data/spec/lib/statistrano/config_spec.rb +34 -0
- data/spec/lib/statistrano/deployment/log_file_spec.rb +75 -0
- data/spec/lib/statistrano/deployment/manifest_spec.rb +171 -0
- data/spec/lib/statistrano/deployment/rake_tasks_spec.rb +107 -0
- data/spec/lib/statistrano/deployment/registerable_spec.rb +19 -0
- data/spec/lib/statistrano/deployment/releaser/revisions_spec.rb +486 -0
- data/spec/lib/statistrano/deployment/releaser/single_spec.rb +59 -0
- data/spec/lib/statistrano/deployment/strategy/base_spec.rb +158 -0
- data/spec/lib/statistrano/deployment/strategy/branches_spec.rb +19 -0
- data/spec/lib/statistrano/deployment/strategy/check_git_spec.rb +39 -0
- data/spec/lib/statistrano/deployment/strategy/invoke_tasks_spec.rb +66 -0
- data/spec/lib/statistrano/deployment/strategy/releases_spec.rb +257 -0
- data/spec/lib/statistrano/deployment/strategy_spec.rb +76 -0
- data/spec/lib/statistrano/deployment_spec.rb +4 -0
- data/spec/lib/statistrano/log/default_logger_spec.rb +172 -0
- data/spec/lib/statistrano/log_spec.rb +36 -0
- data/spec/lib/statistrano/remote/file_spec.rb +166 -0
- data/spec/lib/statistrano/remote_spec.rb +226 -0
- data/spec/lib/statistrano/util/file_permissions_spec.rb +25 -0
- data/spec/lib/statistrano/util_spec.rb +23 -0
- data/spec/lib/statistrano_spec.rb +52 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/support/given.rb +39 -0
- 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
|