capifony 0.4.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/CHANGELOG +6 -0
  2. data/bin/capifony +47 -12
  3. data/lib/capifony.rb +3 -565
  4. data/lib/symfony1.rb +569 -0
  5. data/lib/symfony2.rb +215 -0
  6. metadata +11 -9
@@ -0,0 +1,569 @@
1
+ require 'yaml'
2
+ load Gem.required_location('capifony', 'capifony.rb')
3
+
4
+ # Dirs that need to remain the same between deploys (shared dirs)
5
+ set :shared_children, %w(log web/uploads)
6
+
7
+ # Files that need to remain the same between deploys
8
+ set :shared_files, %w(config/databases.yml)
9
+
10
+ # Asset folders (that need to be timestamped)
11
+ set :asset_children, %w(web/css web/images web/js)
12
+
13
+ # Use ORM
14
+ set :use_orm, true
15
+
16
+ # Symfony default ORM
17
+ set(:symfony_orm) { guess_symfony_orm }
18
+
19
+ # Symfony lib path
20
+ set(:symfony_lib) { guess_symfony_lib }
21
+
22
+ def guess_symfony_orm
23
+ databases = YAML::load(IO.read('config/databases.yml'))
24
+
25
+ if databases[symfony_env_local]
26
+ databases[symfony_env_local].keys[0].to_s
27
+ else
28
+ databases['all'].keys[0].to_s
29
+ end
30
+ end
31
+
32
+ def guess_symfony_lib
33
+ symfony_version = capture("#{php_bin} #{latest_release}/symfony -V")
34
+
35
+ /\((.*)\)/.match(symfony_version)[1]
36
+ end
37
+
38
+ def load_database_config(data, env)
39
+ databases = YAML::load(data)
40
+
41
+ if databases[env]
42
+ db_param = databases[env][symfony_orm]['param']
43
+ else
44
+ db_param = databases['all'][symfony_orm]['param']
45
+ end
46
+
47
+ {
48
+ 'type' => /(\w+)\:/.match(db_param['dsn'])[1],
49
+ 'user' => db_param['username'],
50
+ 'pass' => db_param['password'],
51
+ 'db' => /dbname=([^;$]+)/.match(db_param['dsn'])[1]
52
+ }
53
+ end
54
+
55
+ namespace :deploy do
56
+ desc "Customize migrate task because symfony doesn't need it."
57
+ task :migrate do
58
+ symfony.orm.migrate
59
+ end
60
+
61
+ desc "Symlink static directories and static files that need to remain between deployments."
62
+ task :share_childs do
63
+ if shared_children
64
+ shared_children.each do |link|
65
+ run "mkdir -p #{shared_path}/#{link}"
66
+ run "if [ -d #{release_path}/#{link} ] ; then rm -rf #{release_path}/#{link}; fi"
67
+ run "ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
68
+ end
69
+ end
70
+ if shared_files
71
+ shared_files.each do |link|
72
+ link_dir = File.dirname("#{shared_path}/#{link}")
73
+ run "mkdir -p #{link_dir}"
74
+ run "touch #{shared_path}/#{link}"
75
+ run "ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
76
+ end
77
+ end
78
+ end
79
+
80
+ desc "Customize the finalize_update task to work with symfony."
81
+ task :finalize_update, :except => { :no_release => true } do
82
+ run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
83
+ run "mkdir -p #{latest_release}/cache"
84
+
85
+ # Share common files & folders
86
+ share_childs
87
+
88
+ if fetch(:normalize_asset_timestamps, true)
89
+ stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
90
+ asset_paths = asset_children.map { |p| "#{latest_release}/#{p}" }.join(" ")
91
+ run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }
92
+ end
93
+ end
94
+
95
+ desc "Need to overwrite the deploy:cold task so it doesn't try to run the migrations."
96
+ task :cold do
97
+ update
98
+ symfony.orm.build_db_and_load
99
+ start
100
+ end
101
+
102
+ desc "Deploy the application and run the test suite."
103
+ task :testall do
104
+ update_code
105
+ symlink
106
+ symfony.orm.build_db_and_load
107
+ symfony.tests.all
108
+ end
109
+ end
110
+
111
+ namespace :symfony do
112
+ desc "Runs custom symfony task"
113
+ task :default do
114
+ prompt_with_default(:task_arguments, "cache:clear")
115
+
116
+ stream "#{php_bin} #{latest_release}/symfony #{task_arguments}"
117
+ end
118
+
119
+ desc "Downloads & runs check_configuration.php on remote"
120
+ task :check_configuration do
121
+ prompt_with_default(:version, "1.4")
122
+
123
+ run "wget http://sf-to.org/#{version}/check.php -O /tmp/check_configuration.php"
124
+ stream "#{php_bin} /tmp/check_configuration.php"
125
+ run "rm /tmp/check_configuration.php"
126
+ end
127
+
128
+ desc "Clears the cache"
129
+ task :cc do
130
+ run "#{php_bin} #{latest_release}/symfony cache:clear"
131
+ end
132
+
133
+ namespace :configure do
134
+ desc "Configure database DSN"
135
+ task :database do
136
+ prompt_with_default(:dsn, "mysql:host=localhost;dbname=#{application}")
137
+ prompt_with_default(:db_username, "root")
138
+ db_password = Capistrano::CLI.password_prompt("db_password : ")
139
+
140
+ # surpress debug log output to hide the password
141
+ current_logger_level = self.logger.level
142
+ if current_logger_level >= Capistrano::Logger::DEBUG
143
+ logger.debug %(executing "#{php_bin} #{latest_release}/symfony configure:database '#{dsn}' '#{db_username}' ***")
144
+ self.logger.level = Capistrano::Logger::INFO
145
+ end
146
+
147
+ run "#{php_bin} #{latest_release}/symfony configure:database '#{dsn}' '#{db_username}' '#{db_password}'"
148
+
149
+ # restore logger level
150
+ self.logger.level = current_logger_level
151
+ end
152
+ end
153
+
154
+ namespace :project do
155
+ desc "Disables an application in a given environment"
156
+ task :disable do
157
+ run "#{php_bin} #{latest_release}/symfony project:disable #{symfony_env_prod}"
158
+ end
159
+
160
+ desc "Enables an application in a given environment"
161
+ task :enable do
162
+ run "#{php_bin} #{latest_release}/symfony project:enable #{symfony_env_prod}"
163
+ end
164
+
165
+ desc "Fixes symfony directory permissions"
166
+ task :permissions do
167
+ run "#{php_bin} #{latest_release}/symfony project:permissions"
168
+ end
169
+
170
+ desc "Optimizes a project for better performance"
171
+ task :optimize do
172
+ prompt_with_default(:application, "frontend")
173
+
174
+ run "#{php_bin} #{latest_release}/symfony project:optimize #{application}"
175
+ end
176
+
177
+ desc "Clears all non production environment controllers"
178
+ task :clear_controllers do
179
+ run "#{php_bin} #{latest_release}/symfony project:clear-controllers"
180
+ end
181
+
182
+ desc "Sends emails stored in a queue"
183
+ task :send_emails do
184
+ prompt_with_default(:message_limit, 10)
185
+ prompt_with_default(:time_limit, 10)
186
+
187
+ stream "#{php_bin} #{latest_release}/symfony project:send-emails --message-limit=#{message_limit} --time-limit=#{time_limit} --env=#{symfony_env_prod}"
188
+ end
189
+
190
+ desc 'Task to set all front controllers to a specific environment'
191
+ task :set_environment do
192
+ if (env = fetch(:symfony_env_prod, nil)) && env != 'prod'
193
+ cmd = []
194
+ apps = fetch(:symfony_apps, ['frontend'])
195
+
196
+ # First application listed becomes index.php
197
+ if app = apps.shift
198
+ cmd << "cp #{release_path}/web/#{app}_#{env}.php #{release_path}/web/index.php"
199
+ end
200
+
201
+ # All other apps are copied to their default controllers
202
+ for app in apps
203
+ cmd << "cp #{release_path}/web/#{app}_#{env}.php #{release_path}/web/#{app}.php"
204
+ end
205
+
206
+ run cmd.join(';') if cmd.join(';')
207
+ end
208
+ end
209
+ end
210
+
211
+ namespace :plugin do
212
+ desc "Publishes web assets for all plugins"
213
+ task :publish_assets do
214
+ run "#{php_bin} #{latest_release}/symfony plugin:publish-assets"
215
+ end
216
+ end
217
+
218
+ namespace :log do
219
+ desc "Clears log files"
220
+ task :clear do
221
+ run "#{php_bin} #{latest_release}/symfony log:clear"
222
+ end
223
+
224
+ desc "Rotates an application's log files"
225
+ task :rotate do
226
+ prompt_with_default(:application, "frontend")
227
+
228
+ run "#{php_bin} #{latest_release}/symfony log:rotate #{application} #{symfony_env_prod}"
229
+ end
230
+ end
231
+
232
+ namespace :tests do
233
+ desc "Launches all tests"
234
+ task :all do
235
+ run "#{php_bin} #{latest_release}/symfony test:all"
236
+ end
237
+
238
+ desc "Launches functional tests"
239
+ task :functional do
240
+ prompt_with_default(:application, "frontend")
241
+
242
+ run "#{php_bin} #{latest_release}/symfony test:functional #{application}"
243
+ end
244
+
245
+ desc "Launches unit tests"
246
+ task :unit do
247
+ run "#{php_bin} #{latest_release}/symfony test:unit"
248
+ end
249
+ end
250
+
251
+ namespace :orm do
252
+ desc "Ensure symfony ORM is properly configured"
253
+ task :setup do
254
+ find_and_execute_task("symfony:#{symfony_orm}:setup")
255
+ end
256
+
257
+ desc "Migrates database to current version"
258
+ task :migrate do
259
+ find_and_execute_task("symfony:#{symfony_orm}:migrate")
260
+ end
261
+
262
+ desc "Generate model lib form and filters classes based on your schema"
263
+ task :build_classes do
264
+ find_and_execute_task("symfony:#{symfony_orm}:build_classes")
265
+ end
266
+
267
+ desc "Generate code & database based on your schema"
268
+ task :build_all do
269
+ find_and_execute_task("symfony:#{symfony_orm}:build_all")
270
+ end
271
+
272
+ desc "Generate code & database based on your schema & load fixtures"
273
+ task :build_all_and_load do
274
+ find_and_execute_task("symfony:#{symfony_orm}:build_all_and_load")
275
+ end
276
+
277
+ desc "Generate sql & database based on your schema"
278
+ task :build_db do
279
+ find_and_execute_task("symfony:#{symfony_orm}:build_db")
280
+ end
281
+
282
+ desc "Generate sql & database based on your schema & load fixtures"
283
+ task :build_db_and_load do
284
+ find_and_execute_task("symfony:#{symfony_orm}:build_db_and_load")
285
+ end
286
+ end
287
+
288
+ namespace :doctrine do
289
+ desc "Compile doctrine"
290
+ task :compile do
291
+ run "#{php_bin} #{latest_release}/symfony doctrine:compile"
292
+ end
293
+
294
+ desc "Ensure Doctrine is correctly configured"
295
+ task :setup do
296
+ conf_files_exists = capture("if test -s #{shared_path}/config/databases.yml ; then echo 'exists' ; fi").strip
297
+ if (!conf_files_exists.eql?("exists"))
298
+ symfony.configure.database
299
+ end
300
+ end
301
+
302
+ desc "Execute a DQL query and view the results"
303
+ task :dql do
304
+ prompt_with_default(:query, "")
305
+
306
+ stream "#{php_bin} #{latest_release}/symfony doctrine:dql #{query} --env=#{symfony_env_prod}"
307
+ end
308
+
309
+ desc "Dumps data to the fixtures directory"
310
+ task :data_dump do
311
+ run "#{php_bin} #{latest_release}/symfony doctrine:data-dump --env=#{symfony_env_prod}"
312
+ end
313
+
314
+ desc "Loads YAML fixture data"
315
+ task :data_load do
316
+ run "#{php_bin} #{latest_release}/symfony doctrine:data-load --env=#{symfony_env_prod}"
317
+ end
318
+
319
+ desc "Loads YAML fixture data without remove"
320
+ task :data_load_append do
321
+ run "#{php_bin} #{latest_release}/symfony doctrine:data-load --append --env=#{symfony_env_prod}"
322
+ end
323
+
324
+ desc "Migrates database to current version"
325
+ task :migrate do
326
+ run "#{php_bin} #{latest_release}/symfony doctrine:migrate --env=#{symfony_env_prod}"
327
+ end
328
+
329
+ desc "Generate model lib form and filters classes based on your schema"
330
+ task :build_classes do
331
+ run "#{php_bin} #{latest_release}/symfony doctrine:build --all-classes --env=#{symfony_env_prod}"
332
+ end
333
+
334
+ desc "Generate code & database based on your schema"
335
+ task :build_all do
336
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database? (y/N)")
337
+ run "#{php_bin} #{latest_release}/symfony doctrine:build --all --no-confirmation --env=#{symfony_env_prod}"
338
+ end
339
+ end
340
+
341
+ desc "Generate code & database based on your schema & load fixtures"
342
+ task :build_all_and_load do
343
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database and load #{symfony_env_prod}'s fixtures? (y/N)")
344
+ run "#{php_bin} #{latest_release}/symfony doctrine:build --all --and-load --no-confirmation --env=#{symfony_env_prod}"
345
+ end
346
+ end
347
+
348
+ desc "Generate sql & database based on your schema"
349
+ task :build_db do
350
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database? (y/N)")
351
+ run "#{php_bin} #{latest_release}/symfony doctrine:build --sql --db --no-confirmation --env=#{symfony_env_prod}"
352
+ end
353
+ end
354
+
355
+ desc "Generate sql & database based on your schema & load fixtures"
356
+ task :build_db_and_load do
357
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database and load #{symfony_env_prod}'s fixtures? (y/N)")
358
+ run "#{php_bin} #{latest_release}/symfony doctrine:build --sql --db --and-load --no-confirmation --env=#{symfony_env_prod}"
359
+ end
360
+ end
361
+ end
362
+
363
+ namespace :propel do
364
+ desc "Ensure Propel is correctly configured"
365
+ task :setup do
366
+ conf_files_exists = capture("if test -s #{shared_path}/config/propel.ini -a -s #{shared_path}/config/databases.yml ; then echo 'exists' ; fi").strip
367
+
368
+ # share childs again (for propel.ini file)
369
+ shared_files << "config/propel.ini"
370
+ deploy.share_childs
371
+
372
+ if (!conf_files_exists.eql?("exists"))
373
+ run "cp #{symfony_lib}/plugins/sfPropelPlugin/config/skeleton/config/propel.ini #{shared_path}/config/propel.ini"
374
+ symfony.configure.database
375
+ end
376
+ end
377
+
378
+ desc "Migrates database to current version"
379
+ task :migrate do
380
+ puts "propel doesn't have built-in migration for now"
381
+ end
382
+
383
+ desc "Generate model lib form and filters classes based on your schema"
384
+ task :build_classes do
385
+ run "php #{latest_release}/symfony propel:build --all-classes --env=#{symfony_env_prod}"
386
+ end
387
+
388
+ desc "Generate code & database based on your schema"
389
+ task :build_all do
390
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database? (y/N)")
391
+ run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --no-confirmation --env=#{symfony_env_prod}"
392
+ end
393
+ end
394
+
395
+ desc "Generate code & database based on your schema & load fixtures"
396
+ task :build_all_and_load do
397
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database and load #{symfony_env_prod}'s fixtures? (y/N)")
398
+ run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --and-load --no-confirmation --env=#{symfony_env_prod}"
399
+ end
400
+ end
401
+
402
+ desc "Generate sql & database based on your schema"
403
+ task :build_db do
404
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database? (y/N)")
405
+ run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --no-confirmation --env=#{symfony_env_prod}"
406
+ end
407
+ end
408
+
409
+ desc "Generate sql & database based on your schema & load fixtures"
410
+ task :build_db_and_load do
411
+ if Capistrano::CLI.ui.agree("Do you really want to rebuild #{symfony_env_prod}'s database and load #{symfony_env_prod}'s fixtures? (y/N)")
412
+ run "#{php_bin} #{latest_release}/symfony propel:build --sql --db --and-load --no-confirmation --env=#{symfony_env_prod}"
413
+ end
414
+ end
415
+ end
416
+ end
417
+
418
+ namespace :database do
419
+ namespace :dump do
420
+ desc "Dump remote database"
421
+ task :remote do
422
+ filename = "#{application}.remote_dump.#{Time.now.to_i}.sql.bz2"
423
+ file = "/tmp/#{filename}"
424
+ sqlfile = "#{application}_dump.sql"
425
+ config = ""
426
+
427
+ run "cat #{shared_path}/config/databases.yml" do |ch, st, data|
428
+ config = load_database_config data, symfony_env_prod
429
+ end
430
+
431
+ case config['type']
432
+ when 'mysql'
433
+ run "mysqldump -u#{config['user']} --password='#{config['pass']}' #{config['db']} | bzip2 -c > #{file}" do |ch, stream, data|
434
+ puts data
435
+ end
436
+ when 'pgsql'
437
+ run "pg_dump -U #{config['user']} --password='#{config['pass']}' #{config['db']} | bzip2 -c > #{file}" do |ch, stream, data|
438
+ puts data
439
+ end
440
+ end
441
+
442
+ `mkdir -p backups`
443
+ get file, "backups/#{filename}"
444
+ `cd backups && ln -nfs #{filename} #{application}.remote_dump.latest.sql.bz2`
445
+ run "rm #{file}"
446
+ end
447
+
448
+ desc "Dump local database"
449
+ task :local do
450
+ filename = "#{application}.local_dump.#{Time.now.to_i}.sql.bz2"
451
+ file = "backups/#{filename}"
452
+ config = load_database_config IO.read('config/databases.yml'), symfony_env_local
453
+ sqlfile = "#{application}_dump.sql"
454
+
455
+ `mkdir -p backups`
456
+ case config['type']
457
+ when 'mysql'
458
+ `mysqldump -u#{config['user']} --password='#{config['pass']}' #{config['db']} | bzip2 -c > #{file}`
459
+ when 'pgsql'
460
+ `pg_dump -U #{config['user']} --password='#{config['pass']}' #{config['db']} | bzip2 -c > #{file}`
461
+ end
462
+
463
+ `cd backups && ln -nfs #{filename} #{application}.local_dump.latest.sql.bz2`
464
+ end
465
+ end
466
+
467
+ namespace :move do
468
+ desc "Dump remote database, download it to local & populate here"
469
+ task :to_local do
470
+ filename = "#{application}.remote_dump.latest.sql.bz2"
471
+ config = load_database_config IO.read('config/databases.yml'), symfony_env_local
472
+ sqlfile = "#{application}_dump.sql"
473
+
474
+ database.dump.remote
475
+
476
+ `bunzip2 -kc backups/#{filename} > backups/#{sqlfile}`
477
+ case config['type']
478
+ when 'mysql'
479
+ `mysql -u#{config['user']} --password='#{config['pass']}' #{config['db']} < backups/#{sqlfile}`
480
+ when 'pgsql'
481
+ `psql -U #{config['user']} --password='#{config['pass']}' #{config['db']} < backups/#{sqlfile}`
482
+ end
483
+ `rm backups/#{sqlfile}`
484
+ end
485
+
486
+ desc "Dump local database, load it to remote & populate there"
487
+ task :to_remote do
488
+ filename = "#{application}.local_dump.latest.sql.bz2"
489
+ file = "backups/#{filename}"
490
+ sqlfile = "#{application}_dump.sql"
491
+ config = ""
492
+
493
+ database.dump.local
494
+
495
+ upload(file, "/tmp/#{filename}", :via => :scp)
496
+ run "bunzip2 -kc /tmp/#{filename} > /tmp/#{sqlfile}"
497
+
498
+ run "cat #{shared_path}/config/databases.yml" do |ch, st, data|
499
+ config = load_database_config data, symfony_env_prod
500
+ end
501
+
502
+ case config['type']
503
+ when 'mysql'
504
+ run "mysql -u#{config['user']} --password='#{config['pass']}' #{config['db']} < /tmp/#{sqlfile}" do |ch, stream, data|
505
+ puts data
506
+ end
507
+ when 'pgsql'
508
+ run "psql -U #{config['user']} --password='#{config['pass']}' #{config['db']} < /tmp/#{sqlfile}" do |ch, stream, data|
509
+ puts data
510
+ end
511
+ end
512
+
513
+ run "rm /tmp/#{filename}"
514
+ run "rm /tmp/#{sqlfile}"
515
+ end
516
+ end
517
+ end
518
+
519
+ namespace :shared do
520
+ namespace :databases do
521
+ desc "Download config/databases.yml from remote server"
522
+ task :to_local do
523
+ download("#{shared_path}/config/databases.yml", "config/databases.yml", :via => :scp)
524
+ end
525
+
526
+ desc "Upload config/databases.yml to remote server"
527
+ task :to_remote do
528
+ upload("config/databases.yml", "#{shared_path}/config/databases.yml", :via => :scp)
529
+ end
530
+ end
531
+
532
+ namespace :log do
533
+ desc "Download all logs from remote folder to local one"
534
+ task :to_local do
535
+ download("#{shared_path}/log", "./", :via => :scp, :recursive => true)
536
+ end
537
+
538
+ desc "Upload all logs from local folder to remote one"
539
+ task :to_remote do
540
+ upload("log", "#{shared_path}/", :via => :scp, :recursive => true)
541
+ end
542
+ end
543
+
544
+ namespace :uploads do
545
+ desc "Download all files from remote web/uploads folder to local one"
546
+ task :to_local do
547
+ download("#{shared_path}/web/uploads", "web", :via => :scp, :recursive => true)
548
+ end
549
+
550
+ desc "Upload all files from local web/uploads folder to remote one"
551
+ task :to_remote do
552
+ upload("web/uploads", "#{shared_path}/web", :via => :scp, :recursive => true)
553
+ end
554
+ end
555
+ end
556
+
557
+ # After finalizing update:
558
+ after "deploy:finalize_update" do
559
+ if use_orm
560
+ symfony.orm.setup # 1. Ensure that ORM is configured
561
+ symfony.orm.build_classes # 2. (Re)build the model
562
+ end
563
+ symfony.cc # 3. Clear cache
564
+ symfony.plugin.publish_assets # 4. Publish plugin assets
565
+ symfony.project.permissions # 5. Fix project permissions
566
+ if symfony_env_prod.eql?("prod")
567
+ symfony.project.clear_controllers # 6. Clear controllers in production environment
568
+ end
569
+ end