fezzik 0.8.0.beta2 → 0.8.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/README.md +156 -64
- data/bin/fez +134 -94
- data/example/Gemfile +1 -1
- data/example/Rakefile +12 -11
- data/example/run_app.sh +4 -0
- data/lib/fezzik.rb +0 -1
- data/lib/fezzik/base.rb +6 -4
- data/lib/fezzik/role.rb +1 -0
- data/lib/fezzik/util.rb +4 -14
- data/lib/fezzik/version.rb +1 -1
- data/tasks/command.rake +3 -1
- data/tasks/deploy.rake +48 -29
- data/tasks/rollback.rake +12 -10
- metadata +6 -6
- data/lib/fezzik/colors.rb +0 -7
- data/tasks/environment.rake +0 -45
- data/weave_todo.md +0 -21
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
gemspec
|
data/README.md
CHANGED
@@ -5,9 +5,13 @@ This is useful for many tasks, including deployment.
|
|
5
5
|
|
6
6
|
It wraps a rake-based rsync workflow and tries to keep things simple.
|
7
7
|
|
8
|
+
If upgrading to 0.8 from an earlier version of Fezzik, see [Upgrading](#upgrading).
|
9
|
+
|
8
10
|
## Install
|
9
11
|
|
10
|
-
|
12
|
+
```
|
13
|
+
gem install fezzik
|
14
|
+
```
|
11
15
|
|
12
16
|
## Basic setup
|
13
17
|
|
@@ -17,27 +21,60 @@ Require Fezzik in your project Rakefile and define a destination:
|
|
17
21
|
require "fezzik"
|
18
22
|
|
19
23
|
Fezzik.destination :prod do
|
20
|
-
set :user, "root"
|
21
|
-
set :domain, "myapp.com"
|
24
|
+
Fezzik.set :user, "root"
|
25
|
+
Fezzik.set :domain, "myapp.com"
|
22
26
|
end
|
23
27
|
```
|
24
28
|
|
25
|
-
|
29
|
+
A host task is similar to a normal Rake task, but will run once for every host defined by `:domain`. The body
|
30
|
+
of a host task exposes two methods:
|
31
|
+
|
32
|
+
```
|
33
|
+
run <command> Run a shell command on the remote host
|
34
|
+
host The domain that the currently running host task is targeting
|
35
|
+
```
|
36
|
+
|
37
|
+
Write some host tasks that will execute on the specified destination:
|
26
38
|
|
27
39
|
```ruby
|
28
40
|
namespace :fezzik do
|
29
|
-
|
30
|
-
run "
|
41
|
+
Fezzik.host_task :echo do
|
42
|
+
run "echo 'Running on #{host}'"
|
31
43
|
end
|
32
44
|
end
|
33
45
|
```
|
34
46
|
|
35
|
-
Run your
|
47
|
+
Run your host tasks with fezzik by passing a destination and list of tasks to run:
|
36
48
|
|
37
49
|
```
|
38
|
-
$ fez prod
|
50
|
+
$ fez prod echo
|
39
51
|
```
|
40
52
|
|
53
|
+
### host_task
|
54
|
+
|
55
|
+
The `host_task` method is similar to Rake's `task` in functionality, but has a slightly different API due to
|
56
|
+
its additional options. A host task is defined with a name and three (optional) options: `:args`, `:deps`,
|
57
|
+
and `:roles`. `:args` and `:deps` correspond to Rake's task arguments and task dependencies, and `:roles` is a
|
58
|
+
Fezzik-specific option explained later.
|
59
|
+
|
60
|
+
A Rake task that looks like this:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
task :echo, [:arg1, :arg2] => [:dep1, :dep2] do |t, args|
|
64
|
+
...
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
would look like this as a host task:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
Fezzik.host_task :echo, :args => [:arg1, :arg2],
|
72
|
+
:deps => [:dep1, :dep2] do |t, args|
|
73
|
+
...
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
|
41
78
|
## Deployments
|
42
79
|
|
43
80
|
One of the more useful things you can use Fezzik for is handling deployments.
|
@@ -48,25 +85,24 @@ require "fezzik"
|
|
48
85
|
# Fezzik will automatically load any .rake files it finds in this directory.
|
49
86
|
Fezzik.init(:tasks => "config/tasks")
|
50
87
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
|
54
|
-
set :
|
55
|
-
set :deploy_to, "/opt/#{app}"
|
56
|
-
set :release_path, "#{deploy_to}/releases/#{Time.now.strftime("%Y%m%d%H%M")}"
|
57
|
-
set :
|
58
|
-
set :user, "root"
|
88
|
+
# The only special settings are `:domain` and `:user`. The rest are purely convention. All settings can be
|
89
|
+
# retrieved in your tasks with `get` (e.g., `Fezzik.get :current_path`).
|
90
|
+
Fezzik.set :app, "myapp"
|
91
|
+
Fezzik.set :user, "root"
|
92
|
+
Fezzik.set :deploy_to, "/opt/#{app}"
|
93
|
+
Fezzik.set :release_path, "#{deploy_to}/releases/#{Time.now.strftime("%Y%m%d%H%M")}"
|
94
|
+
Fezzik.set :current_path, "#{deploy_to}/current"
|
59
95
|
|
60
96
|
Fezzik.destination :staging do
|
61
|
-
set :domain, "myapp-staging.com"
|
97
|
+
Fezzik.set :domain, "myapp-staging.com"
|
62
98
|
end
|
63
99
|
|
64
100
|
Fezzik.destination :prod do
|
65
|
-
set :domain, "myapp.com"
|
101
|
+
Fezzik.set :domain, "myapp.com"
|
66
102
|
end
|
67
103
|
```
|
68
104
|
|
69
|
-
Fezzik comes bundled with some useful
|
105
|
+
Fezzik comes bundled with some useful tasks for common things like deployment.
|
70
106
|
You can download the ones you need:
|
71
107
|
|
72
108
|
```
|
@@ -82,13 +118,13 @@ project.
|
|
82
118
|
namespace :fezzik do
|
83
119
|
...
|
84
120
|
desc "runs the executable in project/bin"
|
85
|
-
|
86
|
-
puts "starting from #{
|
87
|
-
run "cd #{current_path} && ./bin/run_app.sh"
|
121
|
+
host_task :start do
|
122
|
+
puts "starting from #{(run "readlink #{Fezzik.get :current_path}", :output => capture)[:stdout] }}"
|
123
|
+
run "cd #{Fezzik.get :current_path} && ./bin/run_app.sh"
|
88
124
|
end
|
89
125
|
|
90
126
|
desc "kills the application by searching for the specified process name"
|
91
|
-
|
127
|
+
host_task :stop do
|
92
128
|
puts "stopping app"
|
93
129
|
run "(kill `ps aux | grep 'myapp' | grep -v grep | awk '{print $2}'` || true)"
|
94
130
|
end
|
@@ -101,7 +137,7 @@ Deploy win!
|
|
101
137
|
```
|
102
138
|
$ fez prod deploy
|
103
139
|
...
|
104
|
-
myapp deployed!
|
140
|
+
[out|myapp.com] myapp deployed!
|
105
141
|
[success]
|
106
142
|
```
|
107
143
|
|
@@ -111,13 +147,13 @@ Configuration often changes when you deploy your project. Fezzik lets you set en
|
|
111
147
|
|
112
148
|
```
|
113
149
|
$ cd config/tasks
|
114
|
-
$ fez get
|
115
|
-
[new]
|
150
|
+
$ fez get deploy
|
151
|
+
[new] deploy.rake
|
116
152
|
```
|
117
153
|
|
118
154
|
```ruby
|
119
155
|
Fezzik.destination :prod do
|
120
|
-
set :domain, "myapp.com"
|
156
|
+
Fezzik.set :domain, "myapp.com"
|
121
157
|
Fezzik.env :rack_env, "production"
|
122
158
|
end
|
123
159
|
```
|
@@ -128,17 +164,16 @@ project directly.
|
|
128
164
|
|
129
165
|
```ruby
|
130
166
|
desc "runs the executable in project/bin"
|
131
|
-
|
132
|
-
|
133
|
-
run "cd #{current_path} && (source environment.sh || true) && ./bin/run_app.sh"
|
167
|
+
Fezzik.host_task :start do
|
168
|
+
run "cd #{Fezzik.get :current_path} && (source environment.sh || true) && ./bin/run_app.sh"
|
134
169
|
end
|
135
170
|
```
|
136
171
|
|
137
|
-
You can assign different environments to
|
172
|
+
You can assign different environments to subsets of hosts:
|
138
173
|
|
139
174
|
```ruby
|
140
175
|
Fezzik.destination :prod do
|
141
|
-
set :domain, ["myapp1.com", "myapp2.com"]
|
176
|
+
Fezzik.set :domain, ["myapp1.com", "myapp2.com"]
|
142
177
|
Fezzik.env :rack_env, "production"
|
143
178
|
Fezzik.env :is_canary, "true", :hosts => ["myapp1.com"]
|
144
179
|
end
|
@@ -149,37 +184,45 @@ This can be useful if you have common environment variables shared across destin
|
|
149
184
|
|
150
185
|
```ruby
|
151
186
|
Fezzik.destination :staging, :prod do
|
152
|
-
env :unicorn_workers, 4
|
187
|
+
Fezzik.env :unicorn_workers, 4
|
153
188
|
end
|
154
189
|
```
|
155
190
|
|
156
191
|
You can access the environment settings in your tasks, if you like. It's a hash.
|
157
192
|
|
158
193
|
```ruby
|
159
|
-
task :
|
194
|
+
task :inspect_all_environments do
|
160
195
|
puts Fezzik.environments.inspect
|
161
196
|
end
|
162
197
|
```
|
163
198
|
|
199
|
+
To access the environment for the currently targeted host:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
Fezzik.host_task :inspect_environment do
|
203
|
+
puts Fezzik.environemnts[host].inspect
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
164
207
|
|
165
208
|
## Roles
|
166
209
|
|
167
|
-
Fezzik supports role deployments. Roles allow you to assign
|
210
|
+
Fezzik supports role deployments. Roles allow you to assign host tasks different configurations according
|
168
211
|
to their purpose. For example, you might want to perform your initial package installations as root, but run
|
169
212
|
your app as an unprivileged user.
|
170
213
|
|
171
214
|
```ruby
|
172
215
|
Fezzik.destination :prod do
|
173
|
-
set :domain, "myapp.com"
|
216
|
+
Fezzik.set :domain, "myapp.com"
|
174
217
|
Fezzik.role :root_user, :user => "root"
|
175
218
|
Fezzik.role :run_user, :user => "app"
|
176
219
|
end
|
177
220
|
|
178
|
-
|
221
|
+
Fezzik.host_task :install, :roles => :root_user
|
179
222
|
# Install all the things.
|
180
223
|
end
|
181
224
|
|
182
|
-
|
225
|
+
Fezzik.host_task :run, :roles => :run_user
|
183
226
|
# Run all the things.
|
184
227
|
end
|
185
228
|
```
|
@@ -188,7 +231,7 @@ Or, you might have different domains for database deployment and app deployment.
|
|
188
231
|
|
189
232
|
```ruby
|
190
233
|
Fezzik.destination :prod do
|
191
|
-
set :user, "root"
|
234
|
+
Fezzik.set :user, "root"
|
192
235
|
Fezzik.role :db, :domain => "db.myapp.com"
|
193
236
|
Fezzik.role :app, :domain => "myapp.com"
|
194
237
|
end
|
@@ -205,13 +248,13 @@ end
|
|
205
248
|
```
|
206
249
|
|
207
250
|
The `Fezzik.role` method accepts a role name and a hash of values that you want assigned with the
|
208
|
-
`set :var, value` syntax. These will override the global or destination settings when
|
251
|
+
`set :var, value` syntax. These will override the global or destination settings when a host task is
|
209
252
|
run.
|
210
253
|
|
211
254
|
|
212
255
|
## Utilities
|
213
256
|
|
214
|
-
Fezzik exposes some functions that can be useful when running
|
257
|
+
Fezzik exposes some functions that can be useful when running host tasks.
|
215
258
|
|
216
259
|
### Override hosts from command line
|
217
260
|
|
@@ -222,33 +265,30 @@ $ domain="example1.com,example2.com" fez prod deploy
|
|
222
265
|
Set the "domain" environment variable to override the domains set in your destination block. Useful for running
|
223
266
|
one-off tasks against a subset of your hosts.
|
224
267
|
|
225
|
-
### Capture or
|
268
|
+
### Capture or modify output
|
226
269
|
|
227
|
-
|
228
|
-
Fezzik::Util.capture_output(&block)
|
229
|
-
```
|
270
|
+
The output of `run` can be captured or modified instead of printing directly with the host prefix.
|
230
271
|
|
231
|
-
|
272
|
+
It can return a hash of `:stdout, :stderr`, or it can stream the raw output without prefixing each host.
|
232
273
|
|
233
274
|
```ruby
|
234
|
-
|
235
|
-
|
236
|
-
server_output = Fezzik::Util.capture_output { run "echo 'hello'"}
|
275
|
+
# prints "[out|myapp.com] hi"
|
276
|
+
run "echo 'hi'"
|
237
277
|
|
238
|
-
|
239
|
-
|
240
|
-
|
278
|
+
# prints "hi"
|
279
|
+
run "echo 'hi'", :output => :raw
|
280
|
+
|
281
|
+
# output == { :stdout => "hi" :stderr => "" }
|
282
|
+
output = run "echo 'hi'", :output => :capture
|
241
283
|
```
|
242
284
|
|
243
|
-
###
|
285
|
+
### A note on `puts`
|
244
286
|
|
245
|
-
|
287
|
+
Ruby's `puts` is not thread-safe. In particular, running multiple `puts` in parallel can result in the
|
288
|
+
newlines being separated from the rest of the string.
|
246
289
|
|
247
|
-
|
248
|
-
|
249
|
-
puts Fezzik.target_destination
|
250
|
-
end
|
251
|
-
```
|
290
|
+
As a helper, any `puts` used from within a host task will call an overridden thread-safe version of `puts`. If
|
291
|
+
`$stdout.puts` or `$stderr.puts` is used instead, the normal thread-unsafe method will be called.
|
252
292
|
|
253
293
|
|
254
294
|
## DSL
|
@@ -258,6 +298,9 @@ the following functions:
|
|
258
298
|
|
259
299
|
```
|
260
300
|
destination
|
301
|
+
host_task
|
302
|
+
set
|
303
|
+
get
|
261
304
|
env
|
262
305
|
role
|
263
306
|
capture_output
|
@@ -269,19 +312,24 @@ This lets you write your configuration more tersely:
|
|
269
312
|
include Fezzik::DSL
|
270
313
|
|
271
314
|
destination :prod do
|
315
|
+
set :domain "myapp.com"
|
272
316
|
env :rack_env, "production"
|
273
317
|
role :root_user, :user => "root"
|
274
318
|
end
|
319
|
+
|
320
|
+
host_task :echo do
|
321
|
+
run "echo 'Running on #{host}'"
|
322
|
+
end
|
275
323
|
```
|
276
324
|
|
277
325
|
|
278
|
-
## Tasks
|
326
|
+
## Included Tasks
|
279
327
|
|
280
|
-
Fezzik has a number of useful tasks other than
|
328
|
+
Fezzik has a number of useful tasks other than those defined in deploy.rake. These can also be downloaded
|
281
329
|
with `$ fez get <task>` and placed in the directory you specify with `Fezzik.init(:tasks => "config/tasks")`.
|
282
330
|
|
283
331
|
These tasks are meant to be starting points. For example, if you want to save your environment files in a
|
284
|
-
place that's not your project root you can simply edit the task in
|
332
|
+
place that's not your project root you can simply edit the task in deploy.rake.
|
285
333
|
|
286
334
|
If you write a recipe that would be useful to other developers, please submit a pull request!
|
287
335
|
|
@@ -318,8 +366,8 @@ $ fez get rollback
|
|
318
366
|
[new] rollback.rake
|
319
367
|
```
|
320
368
|
|
321
|
-
Emergency! Rollback! Every deployment you make is saved on the server
|
322
|
-
You can move between these deployments (to roll back, for example), with
|
369
|
+
Emergency! Rollback! Every deployment you make is saved on the server if you use the default tasks defined in
|
370
|
+
deploy.rake. You can move between these deployments (to roll back, for example), with rollback.rake.
|
323
371
|
|
324
372
|
```
|
325
373
|
$ fez prod rollback
|
@@ -332,3 +380,47 @@ configuring for root@myapp.com
|
|
332
380
|
Rollback to release (0):
|
333
381
|
```
|
334
382
|
|
383
|
+
### Rake passthroughs
|
384
|
+
|
385
|
+
Because Fezzik is built on Rake it passes through some options directly to Rake. You can use these with the
|
386
|
+
`fez` command as if you were running `rake` directly:
|
387
|
+
|
388
|
+
```
|
389
|
+
--trace Turn on invoke/execute tracing, enable full backtrace.
|
390
|
+
--dry-run Do a dry run without executing actions.
|
391
|
+
```
|
392
|
+
|
393
|
+
<a name="upgrading"></a>
|
394
|
+
## Upgrading
|
395
|
+
|
396
|
+
### 0.8.0
|
397
|
+
|
398
|
+
Fezzik 0.8 replaces much of its internal piping with [Weave](https://github.com/cespare/weave), an excellent
|
399
|
+
parallel SSH library. This allows for cleaner output and faster task execution due to using a shared
|
400
|
+
connection pool, but necessarily introduces a few breaking changes. These are detailed below.
|
401
|
+
|
402
|
+
### Breaking changes
|
403
|
+
|
404
|
+
- The method `target_host` is gone and has been replaced by using `host` in a host task. The old method `host`
|
405
|
+
has been replaced with the new one defined in host tasks. There should no longer be a reason to use the old
|
406
|
+
`host` method.
|
407
|
+
- The `current_path` setting is no longer set automatically. To continue using it in your deployments, define
|
408
|
+
it manually:
|
409
|
+
|
410
|
+
```ruby
|
411
|
+
Fezzik.set :current_path, "#{Fezzik.get :deploy_to}/current`.
|
412
|
+
```
|
413
|
+
|
414
|
+
- The helper method `rsync` no longer exists. Instead of `rsync "..."` use `system("rsync -az ...")`
|
415
|
+
|
416
|
+
### Deprecations
|
417
|
+
|
418
|
+
- The `remote_task` method is deprecated. Use `host_task` instead.
|
419
|
+
- Using settings defined by `Fezzik.set` as top-level method calls is deprecated. Instead of `domain`, use
|
420
|
+
`Fezzik.get :domain` instead.
|
421
|
+
- Fezzik::Util.capture_output is deprecated. Pass options directly to `run` instead:
|
422
|
+
|
423
|
+
```ruby
|
424
|
+
run "echo 'hi'", :output => :capture
|
425
|
+
run "echo 'hi'", :output => :raw
|
426
|
+
```
|
data/bin/fez
CHANGED
@@ -7,15 +7,14 @@ require "fezzik"
|
|
7
7
|
module Fezzik
|
8
8
|
RAKE_AT_LEAST_090 = defined?(Rake::VERSION) &&
|
9
9
|
Gem.loaded_specs["rake"].version >= Gem::Version.create("0.9.0")
|
10
|
-
end
|
11
10
|
|
12
|
-
# Required for using rake/remote-task with rake >= 0.9.x
|
13
|
-
# TODO(caleb): Still necessary w/out RRT?
|
14
|
-
include Rake::DSL if Fezzik::RAKE_AT_LEAST_090
|
11
|
+
# Required for using rake/remote-task with rake >= 0.9.x
|
12
|
+
# TODO(caleb): Still necessary w/out RRT?
|
13
|
+
include Rake::DSL if Fezzik::RAKE_AT_LEAST_090
|
15
14
|
|
16
|
-
Fezzik.activated = true
|
15
|
+
Fezzik.activated = true
|
17
16
|
|
18
|
-
USAGE = <<EOF
|
17
|
+
USAGE = <<EOF
|
19
18
|
Version #{Fezzik::VERSION}
|
20
19
|
fez <destination> <tasks> # Run deployment tasks on destination servers
|
21
20
|
fez get <tasks> # Download tasks to use in your project
|
@@ -26,105 +25,146 @@ fez --task-names # Print all tasks names
|
|
26
25
|
fez --destinations # Print all destinations
|
27
26
|
EOF
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
COLORS = { :red => 1, :green => 2 }
|
29
|
+
def self.color_string(string, color)
|
30
|
+
return string unless STDOUT.isatty
|
31
|
+
"\e[01;#{COLORS[color]+30}m#{string}\e[m"
|
32
|
+
end
|
33
|
+
private_class_method :color_string
|
33
34
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def self.capture_output(&block)
|
36
|
+
output = StringIO.new
|
37
|
+
$stdout = output
|
38
|
+
block.call
|
39
|
+
output.string
|
40
|
+
ensure
|
41
|
+
$stdout = STDOUT
|
42
|
+
end
|
43
|
+
private_class_method :capture_output
|
38
44
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
+
def self.print_usage_and_exit
|
46
|
+
puts USAGE
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
private_class_method :print_usage_and_exit
|
45
50
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
Rake::application.options.show_tasks = :tasks
|
51
|
+
def self.print_version_and_exit
|
52
|
+
puts "Version #{Fezzik::VERSION}"
|
53
|
+
exit
|
50
54
|
end
|
51
|
-
|
52
|
-
Rake.application.load_rakefile
|
53
|
-
Rake.application.options.show_task_pattern = /^fezzik:/
|
54
|
-
output = Fezzik::Util.capture_output { Rake.application.display_tasks_and_comments }
|
55
|
-
output.gsub!(/^rake fezzik:/, "fez <destination> ")
|
56
|
-
output.gsub!(/^fez <destination> (\S+).*$/, "\\1") if hide_descriptions
|
57
|
-
output.strip.empty? ? $stderr.puts("(No Fezzik tasks with descriptions are defined.)") : puts(output)
|
58
|
-
exit 0
|
59
|
-
end
|
55
|
+
private_class_method :print_version_and_exit
|
60
56
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
if $? == 0
|
67
|
-
puts Fezzik.color_string(" [new]", :green) + " #{task}"
|
68
|
-
else
|
69
|
-
puts Fezzik.color_string(" [fail]", :red) + " #{task}"
|
70
|
-
end
|
57
|
+
def self.print_destinations_and_exit
|
58
|
+
Rake.application.init
|
59
|
+
Rake.application.load_rakefile
|
60
|
+
puts Fezzik.destinations.to_a.join("\n")
|
61
|
+
exit 0
|
71
62
|
end
|
72
|
-
|
73
|
-
end
|
63
|
+
private_class_method :print_destinations_and_exit
|
74
64
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
puts "
|
87
|
-
|
88
|
-
puts Fezzik.color_string("[fail]", :red)
|
89
|
-
exit 1
|
65
|
+
def self.display_tasks_and_exit(hide_descriptions = false)
|
66
|
+
if Fezzik::RAKE_AT_LEAST_090
|
67
|
+
Rake::TaskManager.record_task_metadata = true
|
68
|
+
Rake::application.options.show_tasks = :tasks
|
69
|
+
end
|
70
|
+
Rake.application.init
|
71
|
+
Rake.application.load_rakefile
|
72
|
+
Rake.application.options.show_task_pattern = /^fezzik:/
|
73
|
+
output = capture_output { Rake.application.display_tasks_and_comments }
|
74
|
+
output.gsub!(/^rake fezzik:/, "fez <destination> ")
|
75
|
+
output.gsub!(/^fez <destination> (\S+).*$/, "\\1") if hide_descriptions
|
76
|
+
output.strip.empty? ? $stderr.puts("(No Fezzik tasks with descriptions are defined.)") : puts(output)
|
77
|
+
exit 0
|
90
78
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
79
|
+
private_class_method :display_tasks_and_exit
|
80
|
+
|
81
|
+
TASKS_URL = "https://raw.github.com/dmacdougall/fezzik/master/tasks"
|
82
|
+
def self.download_tasks_and_exit
|
83
|
+
OPTIONS[1..-1].each do |task|
|
84
|
+
task += ".rake" unless task =~ /\.rake$/
|
85
|
+
system("curl -f #{TASKS_URL}/#{task} -o #{task} > /dev/null 2>&1")
|
86
|
+
if $? == 0
|
87
|
+
puts color_string(" [new]", :green) + " #{task}"
|
88
|
+
else
|
89
|
+
puts color_string(" [fail]", :red) + " #{task}"
|
90
|
+
end
|
96
91
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
92
|
+
exit 0
|
93
|
+
end
|
94
|
+
private_class_method :download_tasks_and_exit
|
95
|
+
|
96
|
+
def self.split_task_and_params(task_with_params)
|
97
|
+
params_match = /(.+)\[(.+)\]/.match(task_with_params)
|
98
|
+
if params_match
|
99
|
+
task = params_match[1]
|
100
|
+
params = params_match[2].split(",")
|
101
101
|
else
|
102
|
-
|
103
|
-
|
102
|
+
task = task_with_params
|
103
|
+
params = nil
|
104
104
|
end
|
105
|
-
|
106
|
-
puts e.message
|
107
|
-
puts e.backtrace
|
108
|
-
puts Fezzik.color_string("[fail]", :red)
|
109
|
-
fail
|
105
|
+
[task, params]
|
110
106
|
end
|
111
|
-
|
107
|
+
private_class_method :split_task_and_params
|
108
|
+
|
109
|
+
def self.run_fezzik_tasks
|
110
|
+
ENV["fezzik_destination"] = OPTIONS[0]
|
111
|
+
Fezzik.init
|
112
|
+
Rake.application.init
|
113
|
+
Rake.application.load_rakefile
|
114
|
+
set :domain, ENV["domain"].split(",") if ENV["domain"]
|
115
|
+
begin
|
116
|
+
host_list = Array(get :domain).join("\n ")
|
117
|
+
puts "Targeting hosts:"
|
118
|
+
puts " #{host_list}"
|
119
|
+
rescue NameError => e
|
120
|
+
puts "Invalid destination: #{Fezzik.target_destination}"
|
121
|
+
puts "Make sure this destination is configured and includes `set :domain, \"yourdomain.com\"`"
|
122
|
+
puts color_string("[fail]", :red)
|
123
|
+
exit 1
|
124
|
+
end
|
125
|
+
begin
|
126
|
+
tasks = OPTIONS[1..-1]
|
127
|
+
tasks.each do |task_with_params|
|
128
|
+
task_name, params = split_task_and_params(task_with_params)
|
129
|
+
Rake::Task["fezzik:#{task_name}"].invoke(*params)
|
130
|
+
end
|
131
|
+
puts color_string("[success]", :green)
|
132
|
+
rescue SystemExit => e
|
133
|
+
if e.status == 0
|
134
|
+
puts color_string("[success]", :green)
|
135
|
+
else
|
136
|
+
puts color_string("[fail]", :red)
|
137
|
+
exit e.status
|
138
|
+
end
|
139
|
+
rescue StandardError => e
|
140
|
+
puts e.message
|
141
|
+
puts e.backtrace
|
142
|
+
puts color_string("[fail]", :red)
|
143
|
+
exit 1
|
144
|
+
end
|
145
|
+
end
|
146
|
+
private_class_method :run_fezzik_tasks
|
147
|
+
|
148
|
+
OPTIONS = ARGV.dup
|
149
|
+
# Rake directly inspects ARGV and will crash if it doesn't recognize a flag that was passed to fez.
|
150
|
+
ARGV.clear
|
151
|
+
# Pass these options through to Rake.
|
152
|
+
# TODO: Pass full trace options through (e.g., --trace=STDOUT)
|
153
|
+
ARGV << "--trace" if OPTIONS.delete("--trace")
|
154
|
+
ARGV << "--dry-run" if OPTIONS.delete("--dry-run")
|
112
155
|
|
113
|
-
|
114
|
-
OPTIONS
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
when "-T", "--tasks" then display_tasks_and_exit
|
126
|
-
when "get" then download_tasks_and_exit
|
127
|
-
when "--task-names" then display_tasks_and_exit(hide_descriptions = true)
|
128
|
-
when "--destinations" then print_destinations_and_exit
|
129
|
-
else run_fezzik_tasks
|
156
|
+
def self.main
|
157
|
+
case OPTIONS[0]
|
158
|
+
when nil then abort USAGE
|
159
|
+
when "-h", "--help" then print_usage_and_exit
|
160
|
+
when "-v", "--version" then print_version_and_exit
|
161
|
+
when "-T", "--tasks" then display_tasks_and_exit
|
162
|
+
when "get" then download_tasks_and_exit
|
163
|
+
when "--task-names" then display_tasks_and_exit(hide_descriptions = true)
|
164
|
+
when "--destinations" then print_destinations_and_exit
|
165
|
+
else run_fezzik_tasks
|
166
|
+
end
|
167
|
+
end
|
130
168
|
end
|
169
|
+
|
170
|
+
Fezzik.main()
|
data/example/Gemfile
CHANGED
data/example/Rakefile
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require "fezzik"
|
2
2
|
include Fezzik::DSL
|
3
|
+
include Rake::DSL
|
3
4
|
|
4
5
|
Fezzik.init(:tasks => "../tasks")
|
5
6
|
|
6
7
|
set :app, "test"
|
7
|
-
set :deploy_to, "/opt/#{app}"
|
8
|
-
set :release_path, "#{deploy_to}/releases/#{Time.now.strftime("%Y%m%d%H%M")}"
|
9
|
-
set :
|
8
|
+
set :deploy_to, "/opt/#{get :app}"
|
9
|
+
set :release_path, "#{get :deploy_to}/releases/#{Time.now.strftime("%Y%m%d%H%M")}"
|
10
|
+
set :current_path, "#{get :deploy_to}/current"
|
10
11
|
set :user, "root"
|
11
12
|
|
12
13
|
destination :vagrant do
|
@@ -24,44 +25,44 @@ end
|
|
24
25
|
|
25
26
|
namespace :fezzik do
|
26
27
|
desc "Print information on the destination and environment"
|
27
|
-
|
28
|
+
host_task :info do
|
28
29
|
puts "Destination: #{Fezzik.target_destination.inspect}"
|
29
30
|
puts "Environment: #{Fezzik.environments.inspect}"
|
30
31
|
end
|
31
32
|
|
32
33
|
desc "An example of appending..."
|
33
|
-
|
34
|
+
host_task :append do
|
34
35
|
run "echo hi"
|
35
36
|
end
|
36
37
|
|
37
38
|
desc "...new actions to an existing task"
|
38
|
-
|
39
|
+
host_task :append do
|
39
40
|
run "echo bye"
|
40
41
|
end
|
41
42
|
|
42
43
|
desc "Tasks can take arguments"
|
43
|
-
|
44
|
+
host_task :argtest, :args => [:arg1, :arg2] do |t, args|
|
44
45
|
puts "args: #{args.inspect}"
|
45
46
|
end
|
46
47
|
|
47
48
|
desc "Tasks may print out the host and user."
|
48
|
-
|
49
|
+
host_task :host do
|
49
50
|
puts "#{user}@#{host}"
|
50
51
|
end
|
51
52
|
|
52
53
|
desc "Tasks can depend on other tasks"
|
53
|
-
|
54
|
+
host_task :depstest, :deps => :append do
|
54
55
|
puts "some other task just ran"
|
55
56
|
end
|
56
57
|
|
57
58
|
desc "If a server command fails the block should exist and fezzik should indicate failure"
|
58
|
-
|
59
|
+
host_task :fails do
|
59
60
|
run "cd i-dont-exist"
|
60
61
|
run "echo 'should not print'"
|
61
62
|
end
|
62
63
|
|
63
64
|
desc "Use roles to override settings"
|
64
|
-
|
65
|
+
host_task :roles, :roles => [:role1, :role2] do
|
65
66
|
puts "role_var: #{get :role_var}"
|
66
67
|
end
|
67
68
|
end
|
data/example/run_app.sh
ADDED
data/lib/fezzik.rb
CHANGED
data/lib/fezzik/base.rb
CHANGED
@@ -14,7 +14,8 @@ module Fezzik
|
|
14
14
|
end
|
15
15
|
|
16
16
|
Object.send :define_method, name do
|
17
|
-
|
17
|
+
warn "WARN [Fezzik]: accessing #{name} at the top-level is deprecated as of 0.8.0," +
|
18
|
+
" use Fezzik.get(:#{name}) instead"
|
18
19
|
Fezzik.get name
|
19
20
|
end
|
20
21
|
end
|
@@ -24,11 +25,10 @@ module Fezzik
|
|
24
25
|
@@settings[name]
|
25
26
|
end
|
26
27
|
|
27
|
-
# TODO(caleb): Private method?
|
28
28
|
def self.clear(name) @@settings.delete(name) end
|
29
29
|
|
30
|
-
# TODO: add deprecation warning for remote_task
|
31
30
|
def self.remote_task(*args, &block)
|
31
|
+
warn "WARN [Fezzik]: remote_task is deprecated as of 0.8.0, use host_task instead"
|
32
32
|
roles = (Hash === args.last && args.last[:roles]) ? args.pop[:roles] : []
|
33
33
|
name, args, deps = Rake.application.resolve_args(args)
|
34
34
|
host_task(name, { :args => Array(args), :deps => Array(deps), :roles => Array(roles) }, &block)
|
@@ -50,7 +50,9 @@ module Fezzik
|
|
50
50
|
@target_destination = ENV["fezzik_destination"].to_sym rescue nil
|
51
51
|
unless options[:tasks].nil?
|
52
52
|
$stderr.puts "Loading Fezzik tasks from #{@options[:tasks]}"
|
53
|
-
Dir[File.join(File.expand_path(@options[:tasks]), "**", "*.rake")].sort.each
|
53
|
+
Dir[File.join(File.expand_path(@options[:tasks]), "**", "*.rake")].sort.each do |lib|
|
54
|
+
Rake.application.add_import(lib)
|
55
|
+
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
data/lib/fezzik/role.rb
CHANGED
data/lib/fezzik/util.rb
CHANGED
@@ -1,24 +1,14 @@
|
|
1
1
|
module Fezzik
|
2
2
|
module Util
|
3
3
|
def self.capture_output(&block)
|
4
|
+
warn "WARN [Fezzik]: Fezzik::Util.capture_output is deprecated as of 0.8.0," +
|
5
|
+
" use `run \"...\", :output => capture` instead"
|
4
6
|
output = StringIO.new
|
5
|
-
|
7
|
+
$stdout = output
|
6
8
|
block.call
|
7
9
|
output.string
|
8
10
|
ensure
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.split_task_and_params(task_with_params)
|
13
|
-
params_match = /(.+)\[(.+)\]/.match(task_with_params)
|
14
|
-
if params_match
|
15
|
-
task = params_match[1]
|
16
|
-
params = params_match[2].split(",")
|
17
|
-
else
|
18
|
-
task = task_with_params
|
19
|
-
params = nil
|
20
|
-
end
|
21
|
-
[task, params]
|
11
|
+
$stdout = STDOUT
|
22
12
|
end
|
23
13
|
end
|
24
14
|
end
|
data/lib/fezzik/version.rb
CHANGED
data/tasks/command.rake
CHANGED
@@ -31,6 +31,8 @@ namespace :fezzik do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
desc "run a single command on destination servers"
|
34
|
-
|
34
|
+
host_task(:command_execute, :args => :command) do |t, args|
|
35
|
+
run args[:command], :continue_on_failure => true
|
36
|
+
end
|
35
37
|
end
|
36
38
|
|
data/tasks/deploy.rake
CHANGED
@@ -1,60 +1,79 @@
|
|
1
1
|
require "fileutils"
|
2
|
+
require "fezzik"
|
3
|
+
|
4
|
+
include Fezzik::DSL
|
2
5
|
|
3
6
|
namespace :fezzik do
|
7
|
+
desc "writes environment files on the server"
|
8
|
+
host_task :write_environment do
|
9
|
+
puts "writing environment files"
|
10
|
+
environment = Fezzik.environments[host]
|
11
|
+
staging_path = "/tmp/#{get :app}/environments/#{host}"
|
12
|
+
FileUtils.mkdir_p staging_path
|
13
|
+
File.open("#{staging_path}/environment.rb", "w") do |f|
|
14
|
+
environment.each do |key, value|
|
15
|
+
quote = value.is_a?(Numeric) ? '' : '"'
|
16
|
+
f.puts "#{key.to_s.upcase} = #{quote}#{value}#{quote}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
File.open("#{staging_path}/environment.sh", "w") do |f|
|
20
|
+
environment.each { |key, value| f.puts %[export #{key.to_s.upcase}="#{value}"] }
|
21
|
+
end
|
22
|
+
system "rsync -az #{staging_path}/environment.* #{user}@#{host}:#{get :release_path}"
|
23
|
+
end
|
24
|
+
|
4
25
|
desc "stages the project for deployment in /tmp"
|
5
26
|
task :stage do
|
6
|
-
puts "staging project in /tmp/#{app}"
|
7
|
-
FileUtils.rm_rf "/tmp/#{app}"
|
8
|
-
FileUtils.mkdir_p "/tmp/#{app}/staged"
|
27
|
+
puts "staging project in /tmp/#{get :app}"
|
28
|
+
FileUtils.rm_rf "/tmp/#{get :app}"
|
29
|
+
FileUtils.mkdir_p "/tmp/#{get :app}/staged"
|
9
30
|
# Use rsync to preserve executability and follow symlinks.
|
10
|
-
system("rsync -aqE
|
31
|
+
system("rsync -aqE ./ /tmp/#{get :app}/staged")
|
11
32
|
end
|
12
33
|
|
13
34
|
desc "performs any necessary setup on the destination servers prior to deployment"
|
14
|
-
|
35
|
+
host_task :setup do
|
15
36
|
puts "setting up servers"
|
16
|
-
run "mkdir -p #{deploy_to}/releases"
|
37
|
+
run "mkdir -p #{get :deploy_to}/releases"
|
17
38
|
end
|
18
39
|
|
19
40
|
desc "rsyncs the project from its staging location to each destination server"
|
20
|
-
|
21
|
-
puts "pushing to #{
|
41
|
+
host_task :push, :deps => [:stage, :setup] do
|
42
|
+
puts "pushing to #{user}@#{host}:#{get :release_path}"
|
22
43
|
# Copy on top of previous release to optimize rsync
|
23
|
-
rsync
|
44
|
+
system "rsync -azq --copy-dest=#{get :current_path} /tmp/#{get :app}/staged/" +
|
45
|
+
" #{user}@#{host}:#{get :release_path}"
|
24
46
|
end
|
25
47
|
|
26
48
|
desc "symlinks the latest deployment to /deploy_path/project/current"
|
27
|
-
|
28
|
-
puts "symlinking current to #{release_path}"
|
29
|
-
run "cd #{deploy_to} && ln -fns #{release_path} current"
|
49
|
+
host_task :symlink do
|
50
|
+
puts "symlinking current to #{get :release_path}"
|
51
|
+
run "cd #{get :deploy_to} && ln -fns #{get :release_path} current"
|
30
52
|
end
|
31
53
|
|
32
54
|
desc "runs the executable in project/bin"
|
33
|
-
|
34
|
-
|
35
|
-
|
55
|
+
host_task :start do
|
56
|
+
# A very simple run_app.sh might contain the following:
|
57
|
+
# #!/bin/sh
|
58
|
+
#
|
59
|
+
# yes &> /dev/null &
|
60
|
+
# echo $! > /tmp/app.pid
|
61
|
+
puts "starting from #{(run "readlink #{get :current_path}", :output => :capture)[:stdout] }"
|
62
|
+
run "cd #{get :current_path} && source environment.sh && ./run_app.sh"
|
36
63
|
end
|
37
64
|
|
38
65
|
desc "kills the application by searching for the specified process name"
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# in the start task and read the PID to kill here in the stop task.
|
43
|
-
# puts "stopping app"
|
44
|
-
# run "(kill -9 `ps aux | grep 'YOUR_APP_NAME' | grep -v grep | awk '{print $2}'` || true)"
|
66
|
+
host_task :stop do
|
67
|
+
puts "stopping app"
|
68
|
+
run "cd #{get :current_path} && touch /tmp/app.pid && kill `cat /tmp/app.pid` || true && rm /tmp/app.pid"
|
45
69
|
end
|
46
70
|
|
47
71
|
desc "restarts the application"
|
48
|
-
|
49
|
-
Rake::Task["fezzik:stop"].invoke
|
50
|
-
Rake::Task["fezzik:start"].invoke
|
72
|
+
host_task :restart, :deps => [:stop, :start] do
|
51
73
|
end
|
52
74
|
|
53
75
|
desc "full deployment pipeline"
|
54
|
-
task :deploy do
|
55
|
-
|
56
|
-
Rake::Task["fezzik:symlink"].invoke
|
57
|
-
Rake::Task["fezzik:restart"].invoke
|
58
|
-
puts "#{app} deployed!"
|
76
|
+
task :deploy => [:push, :write_environment, :symlink, :restart] do
|
77
|
+
puts "#{get :app} deployed!"
|
59
78
|
end
|
60
79
|
end
|
data/tasks/rollback.rake
CHANGED
@@ -8,12 +8,14 @@
|
|
8
8
|
namespace :fezzik do
|
9
9
|
desc "interactively roll back deployment"
|
10
10
|
task :rollback do
|
11
|
-
target_domain =
|
12
|
-
releases = `ssh #{target_domain} "cd #{File.dirname(release_path)} && ls"`.split(/\s+/).reverse
|
13
|
-
current_release = File.basename(`ssh #{target_domain} "cd #{deploy_to} && readlink current"`).strip
|
11
|
+
target_domain = Array(get :domain).first
|
12
|
+
releases = `ssh #{target_domain} "cd #{File.dirname(get :release_path)} && ls"`.split(/\s+/).reverse
|
13
|
+
current_release = File.basename(`ssh #{target_domain} "cd #{get :deploy_to} && readlink current"`).strip
|
14
14
|
puts "=== Releases ==="
|
15
15
|
puts "0: Abort"
|
16
|
-
releases.each_index
|
16
|
+
releases.each_index do |i|
|
17
|
+
puts "#{i+1}: #{releases[i]} #{releases[i] == current_release ? "(current)" : ""}"
|
18
|
+
end
|
17
19
|
print "Rollback to release (0): "
|
18
20
|
STDOUT.flush
|
19
21
|
release_num = STDIN.gets.chomp.to_i
|
@@ -29,10 +31,10 @@ namespace :fezzik do
|
|
29
31
|
|
30
32
|
desc "rolls back deployment to the previous release"
|
31
33
|
task :rollback_one do
|
32
|
-
target_domain =
|
33
|
-
current_release = File.basename(`ssh #{target_domain} "cd #{deploy_to} && readlink current"`).strip
|
34
|
+
target_domain = Array(get :domain).first
|
35
|
+
current_release = File.basename(`ssh #{target_domain} "cd #{get :deploy_to} && readlink current"`).strip
|
34
36
|
previous_release = %x{
|
35
|
-
|
37
|
+
ssh #{target_domain} "cd #{File.dirname(get :release_path)} && ls | grep "#{current_release}" -B 1 | head -1"
|
36
38
|
}.strip
|
37
39
|
|
38
40
|
if previous_release == current_release
|
@@ -44,10 +46,10 @@ namespace :fezzik do
|
|
44
46
|
end
|
45
47
|
|
46
48
|
desc "rolls back deployment to a specific release"
|
47
|
-
|
49
|
+
host_task :rollback_to_release, :args => :selected_release do |t, args|
|
48
50
|
selected_release = args[:selected_release]
|
49
|
-
puts "rolling #{
|
50
|
-
run "cd #{deploy_to} && ln -fns #{File.dirname(release_path)}/#{selected_release} current"
|
51
|
+
puts "rolling #{host} back to #{selected_release}"
|
52
|
+
run "cd #{get :deploy_to} && ln -fns #{File.dirname(get :release_path)}/#{selected_release} current"
|
51
53
|
Rake::Task["fezzik:restart"].invoke
|
52
54
|
end
|
53
55
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fezzik
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0.
|
4
|
+
version: 0.8.0.beta3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-02-
|
13
|
+
date: 2013-02-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -93,10 +93,10 @@ files:
|
|
93
93
|
- completions/_fez.zsh
|
94
94
|
- example/Gemfile
|
95
95
|
- example/Rakefile
|
96
|
+
- example/run_app.sh
|
96
97
|
- fezzik.gemspec
|
97
98
|
- lib/fezzik.rb
|
98
99
|
- lib/fezzik/base.rb
|
99
|
-
- lib/fezzik/colors.rb
|
100
100
|
- lib/fezzik/dsl.rb
|
101
101
|
- lib/fezzik/environment.rb
|
102
102
|
- lib/fezzik/host_task.rb
|
@@ -105,12 +105,10 @@ files:
|
|
105
105
|
- lib/fezzik/version.rb
|
106
106
|
- tasks/command.rake
|
107
107
|
- tasks/deploy.rake
|
108
|
-
- tasks/environment.rake
|
109
108
|
- tasks/rollback.rake
|
110
109
|
- test/integration/base_test.rb
|
111
110
|
- test/integration/environment_test.rb
|
112
111
|
- test/integration_test_helper.rb
|
113
|
-
- weave_todo.md
|
114
112
|
homepage: http://github.com/dmacdougall/fezzik
|
115
113
|
licenses: []
|
116
114
|
post_install_message:
|
@@ -123,6 +121,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
121
|
- - ! '>='
|
124
122
|
- !ruby/object:Gem::Version
|
125
123
|
version: '0'
|
124
|
+
segments:
|
125
|
+
- 0
|
126
|
+
hash: -2670329324762576840
|
126
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
128
|
none: false
|
128
129
|
requirements:
|
@@ -138,4 +139,3 @@ summary: Fezzik adds remote ssh capabilities to Rake. It simplifies running comm
|
|
138
139
|
on remote servers and can be used for anything from deploying code to installing
|
139
140
|
libraries remotely.
|
140
141
|
test_files: []
|
141
|
-
has_rdoc:
|
data/lib/fezzik/colors.rb
DELETED
data/tasks/environment.rake
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
|
3
|
-
# Any variables set in deploy.rb with `Fezzik.env` will be saved on the server in two files:
|
4
|
-
# environment.sh and environment.rb. The first can be loaded into the shell environment before the run script
|
5
|
-
# is called, and the second is made available to be required into your code. You can use your own
|
6
|
-
# environment.rb file for development and it will be overwritten by this task when the code deploys.
|
7
|
-
namespace :fezzik do
|
8
|
-
desc "saves variables set by `Fezzik.env` into a local staging area before deployment"
|
9
|
-
task :save_environment do
|
10
|
-
Fezzik.environments.each do |server, environment|
|
11
|
-
root_config_dir = "/tmp/#{app}/#{server}_config"
|
12
|
-
FileUtils.mkdir_p root_config_dir
|
13
|
-
File.open(File.join(root_config_dir, "environment.rb"), "w") do |file|
|
14
|
-
environment.each do |key, value|
|
15
|
-
quote = value.is_a?(Numeric) ? '' : '"'
|
16
|
-
file.puts "#{key.to_s.upcase} = #{quote}#{value}#{quote}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
File.open(File.join(root_config_dir, "environment.sh"), "w") do |file|
|
20
|
-
environment.each { |key, value| file.puts %[export #{key.to_s.upcase}="#{value}"] }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Append to existing actions defined in deploy.rake. This works because we import .rake files alphabetically,
|
26
|
-
# so the tasks defined in deploy.rake will be executed before these defined in environment.rake.
|
27
|
-
# TODO: Can these be handled through dependencies?
|
28
|
-
# task :stage => :save_environment
|
29
|
-
# task :push => :push_config
|
30
|
-
task :stage do
|
31
|
-
Rake::Task["fezzik:save_environment"].invoke
|
32
|
-
end
|
33
|
-
|
34
|
-
task :push do
|
35
|
-
# Copy over the appropriate configs for the target
|
36
|
-
server = target_host.gsub(/^.*@/, "")
|
37
|
-
config_directory = "/tmp/#{app}/#{server}_config"
|
38
|
-
if File.directory?(config_directory)
|
39
|
-
["environment.rb", "environment.sh"].each do |config_file|
|
40
|
-
rsync "-q", "#{config_directory}/#{config_file}",
|
41
|
-
"#{target_host}:#{release_path}/#{config_file}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/weave_todo.md
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
## Breaking changes in the weave branch
|
2
|
-
|
3
|
-
* `target_host` is gone
|
4
|
-
* `host` is now an alias for `target_host`, not a method
|
5
|
-
* `rsync` no longer exists (unless we write a new helper function)
|
6
|
-
|
7
|
-
## Other docs to write
|
8
|
-
|
9
|
-
* Call `warn` for deprecation notices
|
10
|
-
* document --trace and --dry-run passthrough flags
|
11
|
-
* puts is not thread-safe; instead, use print "" + "\n" (NOTE: Caleb -- this isn't actually true; the `puts`
|
12
|
-
you get in a `remote_task` is a Weave wrapper, which is thread-safe. However, if you use `STDERR.puts` or
|
13
|
-
`STDOUT.puts` or `print` or anything else, it's not going to be threadsafe. This may be worth pointing out
|
14
|
-
in the docs.)
|
15
|
-
* capture_output captures the host prefix on each line. Instead pass :capture => :output to `run`.
|
16
|
-
You can also use capture_output and pass :capture => raw
|
17
|
-
* We no longer provide `current_path`, which is a RRT-ism. However, this was kind of a convention anyway --
|
18
|
-
RRT sets it to "current" and we generally leave that alone. In fact, if you look at the default deploy task
|
19
|
-
(https://github.com/dmacdougall/fezzik/blob/master/tasks/deploy.rake) you'll see that we use `current_path`
|
20
|
-
in some places and the string "current" in others. The new convention should just be `set :current_path,
|
21
|
-
"#{get :deploy_to}/current"` and then use `current_path` as a normal setting.
|