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