harrison 0.1.0 → 0.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.
- data/CHANGELOG +4 -0
- data/IDEAS +1 -1
- data/README.md +7 -3
- data/harrison.gemspec +1 -1
- data/lib/harrison/deploy.rb +47 -0
- data/lib/harrison/version.rb +1 -1
- data/spec/unit/harrison/deploy_spec.rb +111 -0
- metadata +4 -4
data/CHANGELOG
CHANGED
data/IDEAS
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
Ideas:
|
2
2
|
------
|
3
|
+
[ ] Split deploy into distinct stages (e.g. pre-deploy, deploy, post-deploy) and ensure stage succeeds on each host before attempting next stage.
|
3
4
|
[ ] Allow more elaborate hosts config, e.g.: h.hosts = [ { host: '10.16.18.207', tags: %w(util migrate) } ]
|
4
5
|
[ ] Some kind of --dry-run option.
|
5
6
|
[ ] Allow deploy_via to include alternate user/connection options.
|
@@ -9,4 +10,3 @@ Ideas:
|
|
9
10
|
[ ] Something like a "status" command that shows what commit is live for env (on each host?)
|
10
11
|
[ ] Move artifacts out of pkg/ (and into like pkg/deployed) once they have been deployed? (Some sort of flag for the significant env?)
|
11
12
|
[ ] Include branch name in artifact file name.
|
12
|
-
[ ] Make --purge the default behavior for the package step.
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Simple artifact-based deployment for web applications.
|
4
4
|
|
5
|
-
[](https://travis-ci.org/puppetlabs/harrison)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -26,7 +26,7 @@ First, create a Harrisonfile in the root of your project. Here's an example:
|
|
26
26
|
# Project-wide Config
|
27
27
|
Harrison.config do |h|
|
28
28
|
h.project = 'harrison'
|
29
|
-
h.git_src = "git@github.com:
|
29
|
+
h.git_src = "git@github.com:puppetlabs/harrison.git"
|
30
30
|
end
|
31
31
|
|
32
32
|
Harrison.package do |h|
|
@@ -157,12 +157,16 @@ else
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
You can use the `--keep` option (or set it in the deploy section of your Harrisonfile) to specify the total number of
|
161
|
+
deploys you want to retain on each server after a successful deployment. The default is to keep all previous deploys
|
162
|
+
around indefinitely.
|
163
|
+
|
160
164
|
There are some additional options available, run `harrison deploy --help` to see everything available.
|
161
165
|
|
162
166
|
|
163
167
|
## Contributing
|
164
168
|
|
165
|
-
1. Fork it ( https://github.com/
|
169
|
+
1. Fork it ( https://github.com/puppetlabs/harrison/fork )
|
166
170
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
167
171
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
168
172
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/harrison.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Jesse Scott"]
|
10
10
|
spec.email = ["jesse@puppetlabs.com"]
|
11
11
|
spec.summary = %q{Simple artifact-based deployment for web applications.}
|
12
|
-
spec.homepage = "https://github.com/
|
12
|
+
spec.homepage = "https://github.com/puppetlabs/harrison"
|
13
13
|
spec.license = "Apache 2.0"
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
data/lib/harrison/deploy.rb
CHANGED
@@ -11,11 +11,13 @@ module Harrison
|
|
11
11
|
self.class.option_helper(:env)
|
12
12
|
self.class.option_helper(:base_dir)
|
13
13
|
self.class.option_helper(:deploy_via)
|
14
|
+
self.class.option_helper(:keep)
|
14
15
|
|
15
16
|
# Command line opts for this action. Will be merged with common opts.
|
16
17
|
arg_opts = [
|
17
18
|
[ :hosts, "List of remote hosts to deploy to. Can also be specified in Harrisonfile.", :type => :strings ],
|
18
19
|
[ :env, "Environment to deploy to. This can be examined in your Harrisonfile to calculate target hosts.", :type => :string ],
|
20
|
+
[ :keep, "Number of recent deploys to keep after a successful deploy. (Including the most recent deploy.) Defaults to keeping all deploys forever.", :type => :integer ],
|
19
21
|
]
|
20
22
|
|
21
23
|
super(arg_opts, opts)
|
@@ -88,12 +90,42 @@ module Harrison
|
|
88
90
|
# Run user supplied deploy code to restart server or whatever.
|
89
91
|
super
|
90
92
|
|
93
|
+
# Cleanup old releases if a keep value is set.
|
94
|
+
if (self.keep)
|
95
|
+
cleanup_deploys(self.keep)
|
96
|
+
cleanup_releases
|
97
|
+
end
|
98
|
+
|
91
99
|
close(self.host)
|
92
100
|
end
|
93
101
|
|
94
102
|
puts "Sucessfully deployed #{artifact} to #{hosts.join(', ')}."
|
95
103
|
end
|
96
104
|
|
105
|
+
def cleanup_deploys(limit)
|
106
|
+
# Grab a list of deploys to be removed.
|
107
|
+
purge_deploys = self.deploys.sort.reverse.slice(limit..-1) || []
|
108
|
+
|
109
|
+
if purge_deploys.size > 0
|
110
|
+
puts "Purging #{purge_deploys.size} old deploys on #{self.host}, keeping #{limit}..."
|
111
|
+
|
112
|
+
purge_deploys.each do |stale_deploy|
|
113
|
+
remote_exec("cd deploys && rm -f #{stale_deploy}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def cleanup_releases
|
119
|
+
# Figure out which releases need to be kept.
|
120
|
+
keep_releases = self.active_releases
|
121
|
+
|
122
|
+
self.releases.each do |release|
|
123
|
+
unless keep_releases.include?(release)
|
124
|
+
remote_exec("cd releases && rm -rf #{release}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
97
129
|
def close(host=nil)
|
98
130
|
if host
|
99
131
|
@_conns[host].close if @_conns && @_conns[host]
|
@@ -114,5 +146,20 @@ module Harrison
|
|
114
146
|
def remote_project_dir
|
115
147
|
"#{base_dir}/#{project}"
|
116
148
|
end
|
149
|
+
|
150
|
+
# Return a sorted list of deploys, unsorted.
|
151
|
+
def deploys
|
152
|
+
remote_exec("cd deploys && ls -1").split("\n")
|
153
|
+
end
|
154
|
+
|
155
|
+
# Return a list of all releases, unsorted.
|
156
|
+
def releases
|
157
|
+
remote_exec("cd releases && ls -1").split("\n")
|
158
|
+
end
|
159
|
+
|
160
|
+
# Return a list of releases with at least 1 deploy pointing to them, unsorted.
|
161
|
+
def active_releases
|
162
|
+
self.deploys.collect { |deploy| remote_exec("cd deploys && basename `readlink #{deploy}`") }.uniq
|
163
|
+
end
|
117
164
|
end
|
118
165
|
end
|
data/lib/harrison/version.rb
CHANGED
@@ -121,6 +121,17 @@ describe Harrison::Deploy do
|
|
121
121
|
expect(output).to include('host1', 'host2', 'host3')
|
122
122
|
end
|
123
123
|
|
124
|
+
it 'should clean up old releases if passed a --keep option' do
|
125
|
+
instance.keep = 3
|
126
|
+
|
127
|
+
expect(instance).to receive(:cleanup_deploys).with(3)
|
128
|
+
expect(instance).to receive(:cleanup_releases)
|
129
|
+
|
130
|
+
output = capture(:stdout) do
|
131
|
+
instance.run
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
124
135
|
context 'when deploying from a remote artifact source' do
|
125
136
|
before(:each) do
|
126
137
|
instance.artifact = 'test_user@test_host1:/tmp/test_artifact.tar.gz'
|
@@ -150,6 +161,39 @@ describe Harrison::Deploy do
|
|
150
161
|
end
|
151
162
|
end
|
152
163
|
|
164
|
+
describe '#cleanup_deploys' do
|
165
|
+
before(:each) do
|
166
|
+
allow(instance).to receive(:deploys).and_return([ 'deploy_1', 'deploy_2', 'deploy_3', 'deploy_4', 'deploy_5' ])
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should remove deploys beyond the passed in limit' do
|
170
|
+
expect(instance).to receive(:remote_exec).with(/rm -f deploy_2/).and_return('')
|
171
|
+
expect(instance).to receive(:remote_exec).with(/rm -f deploy_1/).and_return('')
|
172
|
+
|
173
|
+
output = capture(:stdout) do
|
174
|
+
instance.cleanup_deploys(3)
|
175
|
+
end
|
176
|
+
|
177
|
+
expect(output).to include('purging', 'deploys', 'keeping 3')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#cleanup_releases' do
|
182
|
+
before(:each) do
|
183
|
+
allow(instance).to receive(:releases).and_return([ 'release_1', 'release_2', 'release_3', 'release_4', 'release_5' ])
|
184
|
+
allow(instance).to receive(:active_releases).and_return([ 'release_3', 'release_4', 'release_5' ])
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should remove inactive releases' do
|
188
|
+
expect(instance).to receive(:remote_exec).with(/rm -rf release_1/).and_return('')
|
189
|
+
expect(instance).to receive(:remote_exec).with(/rm -rf release_2/).and_return('')
|
190
|
+
|
191
|
+
capture(:stdout) do
|
192
|
+
instance.cleanup_releases
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
153
197
|
describe '#close' do
|
154
198
|
before(:each) do
|
155
199
|
@test_host1_ssh = double(:ssh, 'closed?' => false)
|
@@ -204,5 +248,72 @@ describe Harrison::Deploy do
|
|
204
248
|
expect(instance.send(:remote_project_dir)).to include('/test_base_dir', 'test_project')
|
205
249
|
end
|
206
250
|
end
|
251
|
+
|
252
|
+
describe '#deploys' do
|
253
|
+
it 'should invoke ls in the correct directory on the remote server' do
|
254
|
+
expect(instance).to receive(:remote_exec).with(/deploys.*ls -1/).and_return('')
|
255
|
+
|
256
|
+
instance.send(:deploys)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should return an array of deploys' do
|
260
|
+
expect(instance).to receive(:remote_exec).and_return("deploy_1\ndeploy_2\ndeploy_3\n")
|
261
|
+
|
262
|
+
deploys = instance.send(:deploys)
|
263
|
+
|
264
|
+
expect(deploys).to respond_to(:size)
|
265
|
+
expect(deploys.size).to be 3
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#releases' do
|
270
|
+
it 'should invoke ls in the correct directory on the remote server' do
|
271
|
+
expect(instance).to receive(:remote_exec).with(/releases.*ls -1/).and_return('')
|
272
|
+
|
273
|
+
instance.send(:releases)
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'should return an array of releases' do
|
277
|
+
expect(instance).to receive(:remote_exec).and_return("release_1\nrelease_2\nrelease_3\n")
|
278
|
+
|
279
|
+
releases = instance.send(:releases)
|
280
|
+
|
281
|
+
expect(releases).to respond_to(:size)
|
282
|
+
expect(releases.size).to be 3
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe '#active_releases' do
|
287
|
+
before(:each) do
|
288
|
+
allow(instance).to receive(:remote_exec).with(/readlink/) do |cmd|
|
289
|
+
"release_" + /`readlink deploy_([0-9]+)`/.match(cmd).captures[0]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'should return an array of releases' do
|
294
|
+
expect(instance).to receive(:deploys).and_return([ 'deploy_3', 'deploy_4', 'deploy_5' ])
|
295
|
+
|
296
|
+
active_releases = instance.send(:active_releases)
|
297
|
+
|
298
|
+
expect(active_releases).to respond_to(:size)
|
299
|
+
expect(active_releases.size).to be 3
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'should only return distinct releases' do
|
303
|
+
expect(instance).to receive(:deploys).and_return([ 'deploy_3', 'deploy_4', 'deploy_5', 'deploy_3' ])
|
304
|
+
|
305
|
+
active_releases = instance.send(:active_releases)
|
306
|
+
|
307
|
+
expect(active_releases.size).to be 3
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should return releases corresponding to given deploys' do
|
311
|
+
expect(instance).to receive(:deploys).and_return([ 'deploy_3' ])
|
312
|
+
|
313
|
+
active_releases = instance.send(:active_releases)
|
314
|
+
|
315
|
+
expect(active_releases).to include('release_3')
|
316
|
+
end
|
317
|
+
end
|
207
318
|
end
|
208
319
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: harrison
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-09-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: trollop
|
@@ -174,7 +174,7 @@ files:
|
|
174
174
|
- spec/unit/harrison/package_spec.rb
|
175
175
|
- spec/unit/harrison/ssh_spec.rb
|
176
176
|
- spec/unit/harrison_spec.rb
|
177
|
-
homepage: https://github.com/
|
177
|
+
homepage: https://github.com/puppetlabs/harrison
|
178
178
|
licenses:
|
179
179
|
- Apache 2.0
|
180
180
|
post_install_message:
|
@@ -195,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
195
195
|
version: '0'
|
196
196
|
segments:
|
197
197
|
- 0
|
198
|
-
hash:
|
198
|
+
hash: 1433589896306598119
|
199
199
|
requirements: []
|
200
200
|
rubyforge_project:
|
201
201
|
rubygems_version: 1.8.29
|