fezzik 0.8.0.beta2 → 0.8.0.beta3
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/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.
|