capifony 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/README +1 -0
- data/bin/capifony +3 -3
- data/lib/capifony.rb +238 -59
- metadata +5 -5
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.4.0 / June 16, 2010
|
2
|
+
|
3
|
+
* added propel tasks (thanks to http://github.com/arlo)
|
4
|
+
* added orm abstraction
|
5
|
+
* added doctrine/symfony tasks
|
6
|
+
* huge refactoring of mostly everything (thanks to http://github.com/arlo)
|
7
|
+
|
1
8
|
== 0.3.3 / June 13, 2010
|
2
9
|
|
3
10
|
* added ability to change called php binary (thanks to http://github.com/xgorse)
|
data/README
CHANGED
@@ -136,3 +136,4 @@ Contributors
|
|
136
136
|
* everzet (owner): [http://github.com/everzet](http://github.com/everzet)
|
137
137
|
* Travis Roberts (creator of improved version): [http://blog.centresource.com/author/troberts/](http://blog.centresource.com/author/troberts/)
|
138
138
|
* Arlo (contributor): [http://github.com/arlo](http://github.com/arlo)
|
139
|
+
* Xavier Gorse (contributor): [http://github.com/xgorse](http://github.com/xgorse)
|
data/bin/capifony
CHANGED
@@ -38,16 +38,16 @@ end
|
|
38
38
|
files = {
|
39
39
|
"Capfile" => unindent(<<-FILE),
|
40
40
|
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
|
41
|
-
Dir['
|
41
|
+
Dir['plugins/*/lib/recipes/*.rb'].each { |plugin| load(plugin) }
|
42
42
|
load Gem.required_location('capifony', 'capifony.rb')
|
43
43
|
load 'config/deploy' # remove this line to skip loading any of the default tasks
|
44
44
|
FILE
|
45
45
|
|
46
46
|
"config/deploy.rb" => 'set :application, "set your application name here"
|
47
47
|
set :domain, "#{application}.com"
|
48
|
-
set :deploy_to, "/
|
48
|
+
set :deploy_to, "/var/www/#{domain}"
|
49
49
|
|
50
|
-
set :repository, "#{domain}:/
|
50
|
+
set :repository, "#{domain}:/var/repos/#{application}.git"
|
51
51
|
set :scm, :git
|
52
52
|
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `subversion`, `mercurial`, `perforce`, `subversion` or `none`
|
53
53
|
|
data/lib/capifony.rb
CHANGED
@@ -2,9 +2,25 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
# Dirs that need to remain the same between deploys (shared dirs)
|
4
4
|
set :shared_children, %w(log web/uploads)
|
5
|
+
|
6
|
+
# Files that need to remain the same between deploys
|
7
|
+
set :shared_files, %w(config/databases.yml)
|
8
|
+
|
9
|
+
# Asset folders (that need to be timestamped)
|
10
|
+
set :asset_children, %w(web/css web/images web/js)
|
11
|
+
|
5
12
|
# PHP binary to execute
|
6
13
|
set :php_bin, "php"
|
7
14
|
|
15
|
+
# Symfony environment
|
16
|
+
set :symfony_env, "prod"
|
17
|
+
|
18
|
+
# Symfony default ORM
|
19
|
+
set(:symfony_orm) { guess_symfony_orm }
|
20
|
+
|
21
|
+
# Symfony lib path
|
22
|
+
set(:symfony_lib) { guess_symfony_lib }
|
23
|
+
|
8
24
|
def prompt_with_default(var, default)
|
9
25
|
set(var) do
|
10
26
|
Capistrano::CLI.ui.ask "#{var} [#{default}] : "
|
@@ -12,13 +28,29 @@ def prompt_with_default(var, default)
|
|
12
28
|
set var, default if eval("#{var.to_s}.empty?")
|
13
29
|
end
|
14
30
|
|
15
|
-
def
|
31
|
+
def guess_symfony_orm
|
32
|
+
databases = YAML::load(IO.read('config/databases.yml'))
|
33
|
+
|
34
|
+
if databases['dev']
|
35
|
+
databases['dev'].keys[0].to_s
|
36
|
+
else
|
37
|
+
databases['all'].keys[0].to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def guess_symfony_lib
|
42
|
+
symfony_version = capture("#{php_bin} #{latest_release}/symfony -V")
|
43
|
+
|
44
|
+
/\((.*)\)/.match(symfony_version)[1]
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_database_config(data, env)
|
16
48
|
databases = YAML::load(data)
|
17
49
|
|
18
50
|
if databases[env]
|
19
|
-
db_param = databases[env][
|
51
|
+
db_param = databases[env][symfony_orm]['param']
|
20
52
|
else
|
21
|
-
db_param = databases['all'][
|
53
|
+
db_param = databases['all'][symfony_orm]['param']
|
22
54
|
end
|
23
55
|
|
24
56
|
{
|
@@ -30,12 +62,8 @@ def load_database_config(data, env = 'prod')
|
|
30
62
|
end
|
31
63
|
|
32
64
|
namespace :deploy do
|
33
|
-
desc "Overwrite the start task
|
34
|
-
task :start do
|
35
|
-
symfony.configure.database
|
36
|
-
symfony.project.permissions
|
37
|
-
doctrine.build_all_and_load
|
38
|
-
end
|
65
|
+
desc "Overwrite the start task because symfony doesn't need it."
|
66
|
+
task :start do ; end
|
39
67
|
|
40
68
|
desc "Overwrite the restart task because symfony doesn't need it."
|
41
69
|
task :restart do ; end
|
@@ -45,32 +73,39 @@ namespace :deploy do
|
|
45
73
|
|
46
74
|
desc "Customize migrate task because symfony doesn't need it."
|
47
75
|
task :migrate do
|
48
|
-
|
76
|
+
symfony.orm.migrate
|
49
77
|
end
|
50
78
|
|
51
|
-
desc "Symlink static directories that need to remain between deployments."
|
52
|
-
task :
|
79
|
+
desc "Symlink static directories and static files that need to remain between deployments."
|
80
|
+
task :share_childs do
|
53
81
|
if shared_children
|
54
82
|
shared_children.each do |link|
|
55
|
-
run "if [ -d #{release_path}/#{link} ] ; then rm -rf #{release_path}/#{link}; fi"
|
56
83
|
run "mkdir -p #{shared_path}/#{link}"
|
84
|
+
run "if [ -d #{release_path}/#{link} ] ; then rm -rf #{release_path}/#{link}; fi"
|
85
|
+
run "ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
if shared_files
|
89
|
+
shared_files.each do |link|
|
90
|
+
link_dir = File.dirname("#{shared_path}/#{link}")
|
91
|
+
run "mkdir -p #{link_dir}"
|
92
|
+
run "touch #{shared_path}/#{link}"
|
57
93
|
run "ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
|
58
94
|
end
|
59
95
|
end
|
60
|
-
|
61
|
-
run "mkdir -p #{shared_path}/config"
|
62
|
-
run "touch #{shared_path}/config/databases.yml"
|
63
96
|
end
|
64
97
|
|
65
98
|
desc "Customize the finalize_update task to work with symfony."
|
66
99
|
task :finalize_update, :except => { :no_release => true } do
|
67
100
|
run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
|
68
101
|
run "mkdir -p #{latest_release}/cache"
|
69
|
-
|
102
|
+
|
103
|
+
# Share common files & folders
|
104
|
+
share_childs
|
70
105
|
|
71
106
|
if fetch(:normalize_asset_timestamps, true)
|
72
107
|
stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
|
73
|
-
asset_paths =
|
108
|
+
asset_paths = asset_children.map { |p| "#{latest_release}/#{p}" }.join(" ")
|
74
109
|
run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }
|
75
110
|
end
|
76
111
|
end
|
@@ -78,6 +113,7 @@ namespace :deploy do
|
|
78
113
|
desc "Need to overwrite the deploy:cold task so it doesn't try to run the migrations."
|
79
114
|
task :cold do
|
80
115
|
update
|
116
|
+
symfony.orm.build_db_and_load
|
81
117
|
start
|
82
118
|
end
|
83
119
|
|
@@ -85,25 +121,25 @@ namespace :deploy do
|
|
85
121
|
task :testall do
|
86
122
|
update_code
|
87
123
|
symlink
|
88
|
-
|
124
|
+
symfony.orm.build_db_and_load
|
89
125
|
symfony.tests.all
|
90
126
|
end
|
91
127
|
end
|
92
128
|
|
93
|
-
namespace :
|
94
|
-
desc "
|
95
|
-
task :
|
96
|
-
|
129
|
+
namespace :symfony do
|
130
|
+
desc "Runs custom symfony task"
|
131
|
+
task :default do
|
132
|
+
prompt_with_default(:task_arguments, "cache:clear")
|
133
|
+
|
134
|
+
stream "#{php_bin} #{latest_release}/symfony #{task_arguments}"
|
97
135
|
end
|
98
|
-
end
|
99
136
|
|
100
|
-
namespace :symfony do
|
101
137
|
desc "Downloads & runs check_configuration.php on remote"
|
102
138
|
task :check_configuration do
|
103
139
|
prompt_with_default(:version, "1.4")
|
104
140
|
|
105
141
|
run "wget http://sf-to.org/#{version}/check.php -O /tmp/check_configuration.php"
|
106
|
-
|
142
|
+
stream "#{php_bin} /tmp/check_configuration.php"
|
107
143
|
run "rm /tmp/check_configuration.php"
|
108
144
|
end
|
109
145
|
|
@@ -112,26 +148,28 @@ namespace :symfony do
|
|
112
148
|
run "#{php_bin} #{latest_release}/symfony cache:clear"
|
113
149
|
end
|
114
150
|
|
115
|
-
desc "Runs custom symfony task"
|
116
|
-
task :run_task do
|
117
|
-
prompt_with_default(:task_arguments, "cache:clear")
|
118
|
-
|
119
|
-
run "#{php_bin} #{latest_release}/symfony #{task_arguments}"
|
120
|
-
end
|
121
|
-
|
122
151
|
namespace :configure do
|
123
152
|
desc "Configure database DSN"
|
124
153
|
task :database do
|
125
|
-
prompt_with_default(:dsn,
|
126
|
-
prompt_with_default(:user,
|
127
|
-
prompt_with_default(:pass,
|
128
|
-
dbclass = "sfDoctrineDatabase"
|
154
|
+
prompt_with_default(:dsn, "mysql:host=localhost;dbname=example_dev")
|
155
|
+
prompt_with_default(:user, "root")
|
156
|
+
prompt_with_default(:pass, "")
|
129
157
|
|
130
|
-
run "#{php_bin} #{latest_release}/symfony configure:database
|
158
|
+
run "#{php_bin} #{latest_release}/symfony configure:database '#{dsn}' '#{user}' '#{pass}'"
|
131
159
|
end
|
132
160
|
end
|
133
161
|
|
134
162
|
namespace :project do
|
163
|
+
desc "Disables an application in a given environment"
|
164
|
+
task :disable do
|
165
|
+
run "#{php_bin} #{latest_release}/symfony project:disable #{symfony_env}"
|
166
|
+
end
|
167
|
+
|
168
|
+
desc "Enables an application in a given environment"
|
169
|
+
task :enable do
|
170
|
+
run "#{php_bin} #{latest_release}/symfony project:enable #{symfony_env}"
|
171
|
+
end
|
172
|
+
|
135
173
|
desc "Fixes symfony directory permissions"
|
136
174
|
task :permissions do
|
137
175
|
run "#{php_bin} #{latest_release}/symfony project:permissions"
|
@@ -148,6 +186,14 @@ namespace :symfony do
|
|
148
186
|
task :clear_controllers do
|
149
187
|
run "#{php_bin} #{latest_release}/symfony project:clear-controllers"
|
150
188
|
end
|
189
|
+
|
190
|
+
desc "Sends emails stored in a queue"
|
191
|
+
task :send_emails do
|
192
|
+
prompt_with_default(:message_limit, 10)
|
193
|
+
prompt_with_default(:time_limit, 10)
|
194
|
+
|
195
|
+
stream "#{php_bin} #{latest_release}/symfony project:send-emails --message-limit=#{message_limit} --time-limit=#{time_limit} --env=#{symfony_env}"
|
196
|
+
end
|
151
197
|
end
|
152
198
|
|
153
199
|
namespace :plugin do
|
@@ -166,39 +212,171 @@ namespace :symfony do
|
|
166
212
|
desc "Rotates an application's log files"
|
167
213
|
task :rotate do
|
168
214
|
prompt_with_default(:application, "frontend")
|
169
|
-
prompt_with_default(:env, "prod")
|
170
215
|
|
171
|
-
run "#{php_bin} #{latest_release}/symfony log:rotate #{application} #{
|
216
|
+
run "#{php_bin} #{latest_release}/symfony log:rotate #{application} #{symfony_env}"
|
172
217
|
end
|
173
218
|
end
|
174
219
|
|
175
220
|
namespace :tests do
|
176
|
-
desc "
|
221
|
+
desc "Launches all tests"
|
177
222
|
task :all do
|
178
223
|
run "#{php_bin} #{latest_release}/symfony test:all"
|
179
224
|
end
|
180
|
-
end
|
181
|
-
end
|
182
225
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
226
|
+
desc "Launches functional tests"
|
227
|
+
task :functional do
|
228
|
+
prompt_with_default(:application, "frontend")
|
229
|
+
|
230
|
+
run "#{php_bin} #{latest_release}/symfony test:functional #{application}"
|
231
|
+
end
|
232
|
+
|
233
|
+
desc "Launches unit tests"
|
234
|
+
task :unit do
|
235
|
+
run "#{php_bin} #{latest_release}/symfony test:unit"
|
236
|
+
end
|
187
237
|
end
|
188
238
|
|
189
|
-
|
190
|
-
|
191
|
-
|
239
|
+
namespace :orm do
|
240
|
+
desc "Ensure symfony ORM is properly configured"
|
241
|
+
task :setup do
|
242
|
+
find_and_execute_task("symfony:#{symfony_orm}:setup")
|
243
|
+
end
|
244
|
+
|
245
|
+
desc "Migrates database to current version"
|
246
|
+
task :migrate do
|
247
|
+
find_and_execute_task("symfony:#{symfony_orm}:migrate")
|
248
|
+
end
|
249
|
+
|
250
|
+
desc "Generate model lib form and filters classes based on your schema"
|
251
|
+
task :build_classes do
|
252
|
+
find_and_execute_task("symfony:#{symfony_orm}:build_classes")
|
253
|
+
end
|
254
|
+
|
255
|
+
desc "Generate code & database based on your schema"
|
256
|
+
task :build_all do
|
257
|
+
find_and_execute_task("symfony:#{symfony_orm}:build_all")
|
258
|
+
end
|
259
|
+
|
260
|
+
desc "Generate code & database based on your schema & load fixtures"
|
261
|
+
task :build_all_and_load do
|
262
|
+
find_and_execute_task("symfony:#{symfony_orm}:build_all_and_load")
|
263
|
+
end
|
264
|
+
|
265
|
+
desc "Generate sql & database based on your schema"
|
266
|
+
task :build_db do
|
267
|
+
find_and_execute_task("symfony:#{symfony_orm}:build_db")
|
268
|
+
end
|
269
|
+
|
270
|
+
desc "Generate sql & database based on your schema & load fixtures"
|
271
|
+
task :build_db_and_load do
|
272
|
+
find_and_execute_task("symfony:#{symfony_orm}:build_db_and_load")
|
273
|
+
end
|
192
274
|
end
|
193
275
|
|
194
|
-
|
195
|
-
|
196
|
-
|
276
|
+
namespace :doctrine do
|
277
|
+
desc "Ensure Doctrine is correctly configured"
|
278
|
+
task :setup do
|
279
|
+
conf_files_exists = capture("if test -s #{shared_path}/config/databases.yml ; then echo 'exists' ; fi").strip
|
280
|
+
if (!conf_files_exists.eql?("exists"))
|
281
|
+
symfony.configure.database
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
desc "Execute a DQL query and view the results"
|
286
|
+
task :dql do
|
287
|
+
prompt_with_default(:query, "")
|
288
|
+
|
289
|
+
stream "#{php_bin} #{latest_release}/symfony doctrine:dql #{query} --env=#{symfony_env}"
|
290
|
+
end
|
291
|
+
|
292
|
+
desc "Dumps data to the fixtures directory"
|
293
|
+
task :data_dump do
|
294
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:data-dump --env=#{symfony_env}"
|
295
|
+
end
|
296
|
+
|
297
|
+
desc "Loads YAML fixture data"
|
298
|
+
task :data_load do
|
299
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:data-load --env=#{symfony_env}"
|
300
|
+
end
|
301
|
+
|
302
|
+
desc "Loads YAML fixture data without remove"
|
303
|
+
task :data_load_append do
|
304
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:data-load --append --env=#{symfony_env}"
|
305
|
+
end
|
306
|
+
|
307
|
+
desc "Migrates database to current version"
|
308
|
+
task :migrate do
|
309
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:migrate --env=#{symfony_env}"
|
310
|
+
end
|
311
|
+
|
312
|
+
desc "Generate model lib form and filters classes based on your schema"
|
313
|
+
task :build_classes do
|
314
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:build --all-classes --env=#{symfony_env}"
|
315
|
+
end
|
316
|
+
|
317
|
+
desc "Generate code & database based on your schema"
|
318
|
+
task :build_all do
|
319
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:build --all --no-confirmation --env=#{symfony_env}"
|
320
|
+
end
|
321
|
+
|
322
|
+
desc "Generate code & database based on your schema & load fixtures"
|
323
|
+
task :build_all_and_load do
|
324
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:build --all --and-load --no-confirmation --env=#{symfony_env}"
|
325
|
+
end
|
326
|
+
|
327
|
+
desc "Generate sql & database based on your schema"
|
328
|
+
task :build_db do
|
329
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:build --sql --db --no-confirmation --env=#{symfony_env}"
|
330
|
+
end
|
331
|
+
|
332
|
+
desc "Generate sql & database based on your schema & load fixtures"
|
333
|
+
task :build_db_and_load do
|
334
|
+
run "#{php_bin} #{latest_release}/symfony doctrine:build --sql --db --and-load --no-confirmation --env=#{symfony_env}"
|
335
|
+
end
|
197
336
|
end
|
198
337
|
|
199
|
-
|
200
|
-
|
201
|
-
|
338
|
+
namespace :propel do
|
339
|
+
desc "Ensure Propel is correctly configured"
|
340
|
+
task :setup do
|
341
|
+
conf_files_exists = capture("if test -s #{shared_path}/config/propel.ini -a -s #{shared_path}/config/databases.yml ; then echo 'exists' ; fi").strip
|
342
|
+
if (!conf_files_exists.eql?("exists"))
|
343
|
+
run "cp #{symfony_lib}/plugins/sfPropelPlugin/config/skeleton/config/propel.ini #{shared_path}/config/propel.ini"
|
344
|
+
symfony.configure.database
|
345
|
+
end
|
346
|
+
# share childs again (for propel.ini file)
|
347
|
+
shared_files << "config/propel.ini"
|
348
|
+
deploy.share_childs
|
349
|
+
end
|
350
|
+
|
351
|
+
desc "Migrates database to current version"
|
352
|
+
task :migrate do
|
353
|
+
puts "propel doesn't have built-in migration for now"
|
354
|
+
end
|
355
|
+
|
356
|
+
desc "Generate model lib form and filters classes based on your schema"
|
357
|
+
task :build_classes do
|
358
|
+
run "php #{latest_release}/symfony propel:build --all-classes --env=#{symfony_env}"
|
359
|
+
end
|
360
|
+
|
361
|
+
desc "Generate code & database based on your schema"
|
362
|
+
task :build_all do
|
363
|
+
run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --no-confirmation --env=#{symfony_env}"
|
364
|
+
end
|
365
|
+
|
366
|
+
desc "Generate code & database based on your schema & load fixtures"
|
367
|
+
task :build_all_and_load do
|
368
|
+
run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --and-load --no-confirmation --env=#{symfony_env}"
|
369
|
+
end
|
370
|
+
|
371
|
+
desc "Generate sql & database based on your schema"
|
372
|
+
task :build_db do
|
373
|
+
run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --no-confirmation --env=#{symfony_env}"
|
374
|
+
end
|
375
|
+
|
376
|
+
desc "Generate sql & database based on your schema & load fixtures"
|
377
|
+
task :build_db_and_load do
|
378
|
+
run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --and-load --no-confirmation --env=#{symfony_env}"
|
379
|
+
end
|
202
380
|
end
|
203
381
|
end
|
204
382
|
|
@@ -212,7 +390,7 @@ namespace :database do
|
|
212
390
|
config = ""
|
213
391
|
|
214
392
|
run "cat #{shared_path}/config/databases.yml" do |ch, st, data|
|
215
|
-
config = load_database_config data,
|
393
|
+
config = load_database_config data, symfony_env
|
216
394
|
end
|
217
395
|
|
218
396
|
case config['type']
|
@@ -283,7 +461,7 @@ namespace :database do
|
|
283
461
|
run "bunzip2 -kc /tmp/#{filename} > /tmp/#{sqlfile}"
|
284
462
|
|
285
463
|
run "cat #{shared_path}/config/databases.yml" do |ch, st, data|
|
286
|
-
config = load_database_config data,
|
464
|
+
config = load_database_config data, symfony_env
|
287
465
|
end
|
288
466
|
|
289
467
|
case config['type']
|
@@ -342,7 +520,8 @@ namespace :shared do
|
|
342
520
|
end
|
343
521
|
|
344
522
|
after "deploy:finalize_update", # After finalizing update:
|
345
|
-
"
|
523
|
+
"symfony:orm:setup", # 0. Ensure that ORM is configured
|
524
|
+
"symfony:orm:build_classes", # 1. (Re)build the model
|
346
525
|
"symfony:cc", # 2. Clear cache
|
347
526
|
"symfony:plugin:publish_assets", # 3. Publish plugin assets
|
348
527
|
"symfony:project:permissions", # 4. Fix project permissions
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capifony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Konstantin Kudryashov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-16 00:00:00 +03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|