wpify 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in wpify.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,596 @@
1
+ require 'benchmark'
2
+ require 'yaml'
3
+ require 'capistrano/recipes/deploy/scm'
4
+ require 'capistrano/recipes/deploy/strategy'
5
+
6
+ Capistrano::Configuration.instance(:must_exist).load do
7
+
8
+ def _cset(name, *args, &block)
9
+ unless exists?(name)
10
+ set(name, *args, &block)
11
+ end
12
+ end
13
+
14
+ # =========================================================================
15
+ # These variables MUST be set in the client capfiles. If they are not set,
16
+ # the deploy will fail with an error.
17
+ # =========================================================================
18
+
19
+ _cset(:application) { abort "Please specify the name of your application, set :application, 'foo'" }
20
+ _cset(:repository) { abort "Please specify the repository that houses your application's code, set :repository, 'foo'" }
21
+ _cset(:deploy_to) { abort "Please specify deploy to location, set :deploy_to, '/home/deploy/app'" }
22
+
23
+ # =========================================================================
24
+ # These variables may be set in the client capfile if their default values
25
+ # are not sufficient.
26
+ # =========================================================================
27
+
28
+ _cset :scm, :git
29
+ _cset :deploy_via, :remote_cache
30
+ _cset :use_sudo, false
31
+
32
+ _cset(:revision) { source.head }
33
+
34
+ _cset :rake, "rake"
35
+
36
+ _cset :maintenance_basename, "maintenance"
37
+
38
+ # =========================================================================
39
+ # These variables should NOT be changed unless you are very confident in
40
+ # what you are doing. Make sure you understand all the implications of your
41
+ # changes if you do decide to muck with these!
42
+ # =========================================================================
43
+
44
+ _cset(:source) { Capistrano::Deploy::SCM.new(scm, self) }
45
+ _cset(:real_revision) { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } } }
46
+
47
+ _cset(:strategy) { Capistrano::Deploy::Strategy.new(deploy_via, self) }
48
+
49
+ # If overriding release name, please also select an appropriate setting for :releases below.
50
+ _cset(:release_name) { set :deploy_timestamped, true; Time.now.utc.strftime("%Y%m%d%H%M%S") }
51
+
52
+ _cset :version_dir, "releases"
53
+ _cset :shared_dir, "shared"
54
+ _cset :shared_children, %w(config)
55
+ _cset :current_dir, "current"
56
+
57
+ _cset(:releases_path) { File.join(deploy_to, version_dir) }
58
+ _cset(:shared_path) { File.join(deploy_to, shared_dir) }
59
+ _cset(:current_path) { File.join(deploy_to, current_dir) }
60
+ _cset(:release_path) { File.join(releases_path, release_name) }
61
+
62
+ _cset(:releases) { capture("ls -x #{releases_path}", :except => { :no_release => true }).split.sort }
63
+ _cset(:current_release) { releases.length > 0 ? File.join(releases_path, releases.last) : nil }
64
+ _cset(:previous_release) { releases.length > 1 ? File.join(releases_path, releases[-2]) : nil }
65
+
66
+ _cset(:current_revision) { capture("cat #{current_path}/REVISION", :except => { :no_release => true }).chomp }
67
+ _cset(:latest_revision) { capture("cat #{current_release}/REVISION", :except => { :no_release => true }).chomp }
68
+ _cset(:previous_revision) { capture("cat #{previous_release}/REVISION", :except => { :no_release => true }).chomp if previous_release }
69
+
70
+ _cset(:run_method) { fetch(:use_sudo, true) ? :sudo : :run }
71
+
72
+ # some tasks, like symlink, need to always point at the latest release, but
73
+ # they can also (occassionally) be called standalone. In the standalone case,
74
+ # the timestamped release_path will be inaccurate, since the directory won't
75
+ # actually exist. This variable lets tasks like symlink work either in the
76
+ # standalone case, or during deployment.
77
+ _cset(:latest_release) { exists?(:deploy_timestamped) ? release_path : current_release }
78
+
79
+ # Set default run options
80
+ default_run_options[:pty] = true
81
+
82
+ # The directories from the release that are linked into wp-content
83
+ _cset :link_dirs, %w(themes plugins)
84
+ _cset :group_writable, true
85
+
86
+ # =========================================================================
87
+ # These are helper methods that will be available to your recipes.
88
+ # =========================================================================
89
+
90
+ # Auxiliary helper method for the `deploy:check' task. Lets you set up your
91
+ # own dependencies.
92
+ def depend(location, type, *args)
93
+ deps = fetch(:dependencies, {})
94
+ deps[location] ||= {}
95
+ deps[location][type] ||= []
96
+ deps[location][type] << args
97
+ set :dependencies, deps
98
+ end
99
+
100
+ # Temporarily sets an environment variable, yields to a block, and restores
101
+ # the value when it is done.
102
+ def with_env(name, value)
103
+ saved, ENV[name] = ENV[name], value
104
+ yield
105
+ ensure
106
+ ENV[name] = saved
107
+ end
108
+
109
+ # logs the command then executes it locally.
110
+ # returns the command output as a string
111
+ def run_locally(cmd)
112
+ logger.trace "executing locally: #{cmd.inspect}" if logger
113
+ output_on_stdout = nil
114
+ elapsed = Benchmark.realtime do
115
+ output_on_stdout = `#{cmd}`
116
+ end
117
+ if $?.to_i > 0 # $? is command exit code (posix style)
118
+ raise Capistrano::LocalArgumentError, "Command #{cmd} returned status code #{$?}"
119
+ end
120
+ logger.trace "command finished in #{(elapsed * 1000).round}ms" if logger
121
+ output_on_stdout
122
+ end
123
+
124
+
125
+ # If a command is given, this will try to execute the given command, as
126
+ # described below. Otherwise, it will return a string for use in embedding in
127
+ # another command, for executing that command as described below.
128
+ #
129
+ # If :run_method is :sudo (or :use_sudo is true), this executes the given command
130
+ # via +sudo+. Otherwise is uses +run+. If :as is given as a key, it will be
131
+ # passed as the user to sudo as, if using sudo. If the :as key is not given,
132
+ # it will default to whatever the value of the :admin_runner variable is,
133
+ # which (by default) is unset.
134
+ #
135
+ # THUS, if you want to try to run something via sudo, and what to use the
136
+ # root user, you'd just to try_sudo('something'). If you wanted to try_sudo as
137
+ # someone else, you'd just do try_sudo('something', :as => "bob"). If you
138
+ # always wanted sudo to run as a particular user, you could do
139
+ # set(:admin_runner, "bob").
140
+ def try_sudo(*args)
141
+ options = args.last.is_a?(Hash) ? args.pop : {}
142
+ command = args.shift
143
+ raise ArgumentError, "too many arguments" if args.any?
144
+
145
+ as = options.fetch(:as, fetch(:admin_runner, nil))
146
+ via = fetch(:run_method, :sudo)
147
+ if command
148
+ invoke_command(command, :via => via, :as => as)
149
+ elsif via == :sudo
150
+ sudo(:as => as)
151
+ else
152
+ ""
153
+ end
154
+ end
155
+
156
+ # Same as sudo, but tries sudo with :as set to the value of the :runner
157
+ # variable (which defaults to "app").
158
+ def try_runner(*args)
159
+ options = args.last.is_a?(Hash) ? args.pop : {}
160
+ args << options.merge(:as => fetch(:runner, "app"))
161
+ try_sudo(*args)
162
+ end
163
+
164
+ # =========================================================================
165
+ # These are the tasks that are available to help with deploying web apps,
166
+ # and specifically, Rails applications. You can have cap give you a summary
167
+ # of them with `cap -T'.
168
+ # =========================================================================
169
+
170
+ namespace :deploy do
171
+ desc <<-DESC
172
+ Deploys your project. This calls both `update' and `restart'. Note that \
173
+ this will generally only work for applications that have already been deployed \
174
+ once. For a "cold" deploy, you'll want to take a look at the `deploy:cold' \
175
+ task, which handles the cold start specifically.
176
+ DESC
177
+ task :default do
178
+ update
179
+ end
180
+
181
+ desc <<-DESC
182
+ Prepares one or more servers for deployment. Before you can use any \
183
+ of the Capistrano deployment tasks with your project, you will need to \
184
+ make sure all of your servers have been prepared with `cap deploy:setup'. When \
185
+ you add a new server to your cluster, you can easily run the setup task \
186
+ on just that server by specifying the HOSTS environment variable:
187
+
188
+ $ cap HOSTS=new.server.com deploy:setup
189
+
190
+ It is safe to run this task on servers that have already been set up; it \
191
+ will not destroy any deployed revisions or data.
192
+ DESC
193
+ task :setup, :except => { :no_release => true } do
194
+ dirs = [deploy_to, releases_path, shared_path]
195
+ dirs += shared_children.map { |d| File.join(shared_path, d) }
196
+ run "#{try_sudo} mkdir -p #{dirs.join(' ')}"
197
+ run "#{try_sudo} chmod g+w #{dirs.join(' ')}" if fetch(:group_writable, true)
198
+ # Install wordpress latest
199
+ run "cd #{deploy_to}; curl -s -O http://wordpress.org/latest.tar.gz; tar zxf latest.tar.gz; rm latest.tar.gz"
200
+ run "chmod -R g+w #{deploy_to}/wordpress" if fetch(:group_writable, true)
201
+ end
202
+
203
+ desc <<-DESC
204
+ Copies your project and updates the symlink. It does this in a \
205
+ transaction, so that if either `update_code' or `symlink' fail, all \
206
+ changes made to the remote servers will be rolled back, leaving your \
207
+ system in the same state it was in before `update' was invoked. Usually, \
208
+ you will want to call `deploy' instead of `update', but `update' can be \
209
+ handy if you want to deploy, but not immediately restart your application.
210
+ DESC
211
+ task :update do
212
+ transaction do
213
+ update_code
214
+ symlink
215
+ end
216
+ end
217
+
218
+ desc <<-DESC
219
+ Copies your project to the remote servers. This is the first stage \
220
+ of any deployment; moving your updated code and assets to the deployment \
221
+ servers. You will rarely call this task directly, however; instead, you \
222
+ should call the `deploy' task (to do a complete deploy) or the `update' \
223
+ task (if you want to perform the `restart' task separately).
224
+
225
+ You will need to make sure you set the :scm variable to the source \
226
+ control software you are using (it defaults to :subversion), and the \
227
+ :deploy_via variable to the strategy you want to use to deploy (it \
228
+ defaults to :checkout).
229
+ DESC
230
+ task :update_code, :except => { :no_release => true } do
231
+ on_rollback { run "rm -rf #{release_path}; true" }
232
+ strategy.deploy!
233
+ finalize_update
234
+ end
235
+
236
+ desc <<-DESC
237
+ [internal] Touches up the released code. This is called by update_code \
238
+ after the basic deploy finishes. It assumes a Rails project was deployed, \
239
+ so if you are deploying something else, you may want to override this \
240
+ task with your own environment's requirements.
241
+
242
+ This task will make the release group-writable (if the :group_writable \
243
+ variable is set to true, which is the default). It will then set up \
244
+ symlinks to the shared directory for the log, system, and tmp/pids \
245
+ directories, and will lastly touch all assets in public/images, \
246
+ public/stylesheets, and public/javascripts so that the times are \
247
+ consistent (so that asset timestamping works). This touch process \
248
+ is only carried out if the :normalize_asset_timestamps variable is \
249
+ set to true, which is the default The asset directories can be overridden \
250
+ using the :public_children variable.
251
+ DESC
252
+ task :finalize_update, :except => { :no_release => true } do
253
+ run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
254
+ end
255
+
256
+ desc <<-DESC
257
+ Updates the symlink to the most recently deployed version. Capistrano works \
258
+ by putting each new release of your application in its own directory. When \
259
+ you deploy a new version, this task's job is to update the `current' symlink \
260
+ to point at the new version. You will rarely need to call this task \
261
+ directly; instead, use the `deploy' task (which performs a complete \
262
+ deploy, including `restart') or the 'update' task (which does everything \
263
+ except `restart').
264
+ DESC
265
+ task :symlink, :except => { :no_release => true } do
266
+ on_rollback do
267
+ if previous_release
268
+ run "rm -f #{current_path}; ln -s #{previous_release} #{current_path}; true"
269
+ else
270
+ logger.important "no previous release to rollback to, rollback of symlink skipped"
271
+ end
272
+ end
273
+
274
+ run "rm -f #{current_path} && ln -s #{latest_release} #{current_path}"
275
+ # Link the wordpress stuff to current path
276
+ # wp_links
277
+ wp_copy_content
278
+ end
279
+
280
+ desc "Link the wordpress assets into the wordpress serve folder"
281
+ task :wp_links do
282
+ link_dirs.each do |d|
283
+ run <<-EOB
284
+ if [ -d #{current_path}/wordpress/wp-content/#{d}/ ]; then
285
+ for i in `find #{current_path}/wordpress/wp-content/#{d}/ -maxdepth 1 -mindepth 1 -type d`;
286
+ do ln -nfs $i #{deploy_to}/wordpress/wp-content/#{d}/;
287
+ done;
288
+ fi;
289
+ EOB
290
+ end
291
+ end
292
+
293
+ desc "Copy content"
294
+ task :wp_copy_content do
295
+ source = "#{current_path}/wordpress/wp-content/"
296
+ dest = "#{deploy_to}/wordpress/wp-content/"
297
+ run "if [ -d #{source} ] && [ -d #{dest} ]; then cp -Rf #{source}* #{dest}; fi"
298
+ end
299
+
300
+ desc <<-DESC
301
+ Copy files to the currently deployed version. This is useful for updating \
302
+ files piecemeal, such as when you need to quickly deploy only a single \
303
+ file. Some files, such as updated templates, images, or stylesheets, \
304
+ might not require a full deploy, and especially in emergency situations \
305
+ it can be handy to just push the updates to production, quickly.
306
+
307
+ To use this task, specify the files and directories you want to copy as a \
308
+ comma-delimited list in the FILES environment variable. All directories \
309
+ will be processed recursively, with all files being pushed to the \
310
+ deployment servers.
311
+
312
+ $ cap deploy:upload FILES=templates,controller.rb
313
+
314
+ Dir globs are also supported:
315
+
316
+ $ cap deploy:upload FILES='config/apache/*.conf'
317
+ DESC
318
+ task :upload, :except => { :no_release => true } do
319
+ files = (ENV["FILES"] || "").split(",").map { |f| Dir[f.strip] }.flatten
320
+ abort "Please specify at least one file or directory to update (via the FILES environment variable)" if files.empty?
321
+
322
+ files.each { |file| top.upload(file, File.join(current_path, file)) }
323
+ end
324
+
325
+ namespace :rollback do
326
+ desc <<-DESC
327
+ [internal] Points the current symlink at the previous revision.
328
+ This is called by the rollback sequence, and should rarely (if
329
+ ever) need to be called directly.
330
+ DESC
331
+ task :revision, :except => { :no_release => true } do
332
+ if previous_release
333
+ run "rm #{current_path}; ln -s #{previous_release} #{current_path}"
334
+ else
335
+ abort "could not rollback the code because there is no prior release"
336
+ end
337
+ end
338
+
339
+ desc <<-DESC
340
+ [internal] Removes the most recently deployed release.
341
+ This is called by the rollback sequence, and should rarely
342
+ (if ever) need to be called directly.
343
+ DESC
344
+ task :cleanup, :except => { :no_release => true } do
345
+ run "if [ `readlink #{current_path}` != #{current_release} ]; then rm -rf #{current_release}; fi"
346
+ end
347
+
348
+ desc <<-DESC
349
+ Rolls back to the previously deployed version. The `current' symlink will \
350
+ be updated to point at the previously deployed version, and then the \
351
+ current release will be removed from the servers. You'll generally want \
352
+ to call `rollback' instead, as it performs a `restart' as well.
353
+ DESC
354
+ task :code, :except => { :no_release => true } do
355
+ revision
356
+ cleanup
357
+ end
358
+
359
+ desc <<-DESC
360
+ Rolls back to a previous version and restarts. This is handy if you ever \
361
+ discover that you've deployed a lemon; `cap rollback' and you're right \
362
+ back where you were, on the previously deployed version.
363
+ DESC
364
+ task :default do
365
+ revision
366
+ cleanup
367
+ end
368
+ end
369
+
370
+ desc <<-DESC
371
+ Clean up old releases. By default, the last 5 releases are kept on each \
372
+ server (though you can change this with the keep_releases variable). All \
373
+ other deployed revisions are removed from the servers. By default, this \
374
+ will use sudo to clean up the old releases, but if sudo is not available \
375
+ for your environment, set the :use_sudo variable to false instead.
376
+ DESC
377
+ task :cleanup, :except => { :no_release => true } do
378
+ count = fetch(:keep_releases, 5).to_i
379
+ if count >= releases.length
380
+ logger.important "no old releases to clean up"
381
+ else
382
+ logger.info "keeping #{count} of #{releases.length} deployed releases"
383
+
384
+ directories = (releases - releases.last(count)).map { |release|
385
+ File.join(releases_path, release) }.join(" ")
386
+
387
+ try_sudo "rm -rf #{directories}"
388
+ end
389
+ end
390
+
391
+ desc <<-DESC
392
+ Test deployment dependencies. Checks things like directory permissions, \
393
+ necessary utilities, and so forth, reporting on the things that appear to \
394
+ be incorrect or missing. This is good for making sure a deploy has a \
395
+ chance of working before you actually run `cap deploy'.
396
+
397
+ You can define your own dependencies, as well, using the `depend' method:
398
+
399
+ depend :remote, :gem, "tzinfo", ">=0.3.3"
400
+ depend :local, :command, "svn"
401
+ depend :remote, :directory, "/u/depot/files"
402
+ DESC
403
+ task :check, :except => { :no_release => true } do
404
+ dependencies = strategy.check!
405
+
406
+ other = fetch(:dependencies, {})
407
+ other.each do |location, types|
408
+ types.each do |type, calls|
409
+ if type == :gem
410
+ dependencies.send(location).command(fetch(:gem_command, "gem")).or("`gem' command could not be found. Try setting :gem_command")
411
+ end
412
+
413
+ calls.each do |args|
414
+ dependencies.send(location).send(type, *args)
415
+ end
416
+ end
417
+ end
418
+
419
+ if dependencies.pass?
420
+ puts "You appear to have all necessary dependencies installed"
421
+ else
422
+ puts "The following dependencies failed. Please check them and try again:"
423
+ dependencies.reject { |d| d.pass? }.each do |d|
424
+ puts "--> #{d.message}"
425
+ end
426
+ abort
427
+ end
428
+ end
429
+
430
+ namespace :pending do
431
+ desc <<-DESC
432
+ Displays the `diff' since your last deploy. This is useful if you want \
433
+ to examine what changes are about to be deployed. Note that this might \
434
+ not be supported on all SCM's.
435
+ DESC
436
+ task :diff, :except => { :no_release => true } do
437
+ system(source.local.diff(current_revision))
438
+ end
439
+
440
+ desc <<-DESC
441
+ Displays the commits since your last deploy. This is good for a summary \
442
+ of the changes that have occurred since the last deploy. Note that this \
443
+ might not be supported on all SCM's.
444
+ DESC
445
+ task :default, :except => { :no_release => true } do
446
+ from = source.next_revision(current_revision)
447
+ system(source.local.log(from))
448
+ end
449
+ end
450
+
451
+ namespace :web do
452
+ desc <<-DESC
453
+ Present a maintenance page to visitors. Disables your application's web \
454
+ interface by writing a "#{maintenance_basename}.html" file to each web server. The \
455
+ servers must be configured to detect the presence of this file, and if \
456
+ it is present, always display it instead of performing the request.
457
+
458
+ By default, the maintenance page will just say the site is down for \
459
+ "maintenance", and will be back "shortly", but you can customize the \
460
+ page by specifying the REASON and UNTIL environment variables:
461
+
462
+ $ cap deploy:web:disable \\
463
+ REASON="hardware upgrade" \\
464
+ UNTIL="12pm Central Time"
465
+
466
+ Further customization will require that you write your own task.
467
+ DESC
468
+ task :disable, :roles => :web, :except => { :no_release => true } do
469
+ require 'erb'
470
+ on_rollback { run "rm #{shared_path}/system/#{maintenance_basename}.html" }
471
+
472
+ warn <<-EOHTACCESS
473
+
474
+ # Please add something like this to your site's htaccess to redirect users to the maintenance page.
475
+ # More Info: http://www.shiftcommathree.com/articles/make-your-rails-maintenance-page-respond-with-a-503
476
+
477
+ ErrorDocument 503 /system/#{maintenance_basename}.html
478
+ RewriteEngine On
479
+ RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|png)$
480
+ RewriteCond %{DOCUMENT_ROOT}/system/#{maintenance_basename}.html -f
481
+ RewriteCond %{SCRIPT_FILENAME} !#{maintenance_basename}.html
482
+ RewriteRule ^.*$ - [redirect=503,last]
483
+ EOHTACCESS
484
+
485
+ reason = ENV['REASON']
486
+ deadline = ENV['UNTIL']
487
+
488
+ template = File.read(File.join(File.dirname(__FILE__), "templates", "maintenance.rhtml"))
489
+ result = ERB.new(template).result(binding)
490
+
491
+ put result, "#{shared_path}/system/#{maintenance_basename}.html", :mode => 0644
492
+ end
493
+
494
+ desc <<-DESC
495
+ Makes the application web-accessible again. Removes the \
496
+ "#{maintenance_basename}.html" page generated by deploy:web:disable, which (if your \
497
+ web servers are configured correctly) will make your application \
498
+ web-accessible again.
499
+ DESC
500
+ task :enable, :roles => :web, :except => { :no_release => true } do
501
+ run "rm #{shared_path}/system/#{maintenance_basename}.html"
502
+ end
503
+ end
504
+ end
505
+
506
+ # Wpify commands
507
+ namespace :wpify do
508
+ # Get Version Helper
509
+ def get_version(opts = {:remote => false})
510
+ dir = opts[:remote] ? deploy_to : Dir.getwd
511
+ command = "php -r 'include(\"#{dir}/wordpress/wp-includes/version.php\"); print trim(\$wp_version);'"
512
+ opts[:remote] ? capture(command) : run_locally(command)
513
+ end
514
+
515
+ # Return an array of remote plugins that are symlinks
516
+ def remote_linked_plugins
517
+ capture("find #{deploy_to}/wordpress/wp-content/plugins/ -type l").split("\n").map {|f| File.basename(f).gsub(/\s+$/, '') }
518
+ end
519
+
520
+ # Remote tasks
521
+ namespace :remote do
522
+ desc "Display the version of Wordpress installed on the first server"
523
+ task :wp_version do
524
+ wp_version = get_version(:remote => true)
525
+ logger.important "Remote WP version: #{wp_version}"
526
+ end
527
+ end
528
+
529
+ # Local tasks
530
+ namespace :local do
531
+ desc "Display the version of Wordpress installed locally"
532
+ task :wp_version do
533
+ wp_version = get_version
534
+ logger.important "Local WP version: #{wp_version}"
535
+ end
536
+
537
+ desc "Download the wordpress version installed on the server"
538
+ task :download_wp do
539
+ if(wp_version = get_version(:remote => true))
540
+ logger.info "Download wordpress #{wp_version}"
541
+ run_locally("curl -O http://wordpress.org/wordpress-#{wp_version}.tar.gz")
542
+ end
543
+ end
544
+
545
+ desc "Get remote uploads"
546
+ task :get_uploads do
547
+ server = find_servers(:roles => :app, :except => { :no_release => true }).first
548
+ logger.info "Getting uploads from #{server.host}"
549
+ run_locally("rsync -avz #{user}@#{server.host}:#{deploy_to}/wordpress/wp-content/uploads/ #{Dir.getwd}/wordpress/wp-content/uploads/")
550
+ end
551
+
552
+ desc "Locally install the Wordpress version installed on the server."
553
+ task :install_wp do
554
+ if(wp_version = get_version(:remote => true))
555
+ logger.info "Downloading wordpress #{wp_version}"
556
+ run_locally("curl -o wp.tar.gz http://wordpress.org/wordpress-#{wp_version}.tar.gz")
557
+ logger.info "Extracting wordpress #{wp_version}"
558
+ run_locally("tar zxf wp.tar.gz; rm wp.tar.gz")
559
+ end
560
+ end
561
+
562
+ desc "Rsync remote plugins that aren't tracked in revision control"
563
+ task :sync_untracked_plugins do
564
+ server = find_servers(:roles => :app, :except => { :no_release => true }).first
565
+ logger.info "Syncing non-linked plugins from #{server.host}"
566
+ run_locally("rsync -avz --no-links #{user}@#{server.host}:#{deploy_to}/wordpress/wp-content/plugins/ #{Dir.getwd}/wordpress/wp-content/plugins/")
567
+ end
568
+
569
+ desc <<-DESC
570
+ Install wordpress locally based on the remote version. \
571
+ Sync untracked plugins from the remote servers to the local \
572
+ server. Sync uploads from the remote server to the local \
573
+ server.
574
+ DESC
575
+ task :bootstrap do
576
+ # This tasks is a collector for various other tasks
577
+ install_wp
578
+ sync_untracked_plugins
579
+ sync_uploads
580
+ end
581
+ end
582
+
583
+ # Tasks that perform local and remote operations
584
+ desc "Pull and pushes wp-content/uploads files (2-way operation)"
585
+ task :sync_uploads do
586
+ servers = find_servers(:roles => :app, :except => { :no_release => true })
587
+ logger.info "Syncing uploads from #{servers.first.host}"
588
+ run_locally("rsync -avz --update #{user}@#{servers.first.host}:#{deploy_to}/wordpress/wp-content/uploads/ #{Dir.getwd}/wordpress/wp-content/uploads/")
589
+ # Push files to each remote server
590
+ servers.each do |server|
591
+ logger.info "Pushing files to #{server.host}"
592
+ run_locally("rsync -avz --update #{Dir.getwd}/wordpress/wp-content/uploads/ #{user}@#{server.host}:#{deploy_to}/wordpress/wp-content/uploads/")
593
+ end
594
+ end
595
+ end
596
+ end
@@ -0,0 +1,47 @@
1
+ module Wpify
2
+ # Parses the contents of a wp-config.php file into a Hash
3
+ # reasonably well.
4
+ class Parser
5
+ # Loader
6
+ def self.load(*args)
7
+ load = self.new(*args)
8
+ load.wpconfig
9
+ end
10
+
11
+ attr_reader :options, :files, :wpconfig
12
+
13
+ # Provide a comma separated list or files
14
+ # and a hash of options at the end (not yet used)
15
+ def initialize(*args)
16
+ @options = args.last.kind_of?(Hash) ? args.pop : Hash.new
17
+ @files = args
18
+ parse
19
+ end
20
+
21
+ # Parse all the files in @files and
22
+ # add the configuration hash to @wpconfig
23
+ def parse
24
+ @wpconfig = Hash.new
25
+ @files.each do |f|
26
+ f = File.expand_path(f)
27
+ next if not File.exist?(f)
28
+ raw = File.open(f).read
29
+ raw.scan(constant_pattern).each {|c| @wpconfig[c[0].downcase.to_sym] = c[1] }
30
+ raw.scan(var_pattern).each {|v| @wpconfig[v[0].downcase.to_sym] = v[1] }
31
+ end
32
+ @wpconfig
33
+ end
34
+
35
+ private
36
+
37
+ # Pattern to find $table_prefix = "wp_"; strings
38
+ def var_pattern
39
+ /\$(\w+)\s*=\s*['"]([^'"]+)['"]\s*;/
40
+ end
41
+
42
+ # Pattern to find define('DB_NAME', 'wordpress'); strings
43
+ def constant_pattern
44
+ /define\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*\)/
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Wpify
2
+ VERSION = "0.0.7"
3
+ end
data/lib/wpify.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "wpify/version"
2
+
3
+ module Wpify
4
+ autoload :Parser, "wpify/parser"
5
+ end
data/wpify.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "wpify/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "wpify"
7
+ s.version = Wpify::VERSION
8
+ s.authors = ["Bryan Shelton"]
9
+ s.email = ["bryan@sheltonopensolutions.com"]
10
+ s.homepage = "https://github.com/bshelton229/wpify"
11
+ s.summary = %q{Wordpress deploy tools, including a capistrano recipe}
12
+ s.description = %q{Wordpress deploy tools, including a capistrano recipe. This project is still in early development}
13
+
14
+ s.rubyforge_project = "wpify"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "capistrano", ">= 2"
24
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wpify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bryan Shelton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: &70214813382080 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70214813382080
25
+ description: Wordpress deploy tools, including a capistrano recipe. This project is
26
+ still in early development
27
+ email:
28
+ - bryan@sheltonopensolutions.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - Rakefile
36
+ - lib/wpify.rb
37
+ - lib/wpify/capistrano/recipes/wp.rb
38
+ - lib/wpify/parser.rb
39
+ - lib/wpify/version.rb
40
+ - wpify.gemspec
41
+ homepage: https://github.com/bshelton229/wpify
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project: wpify
61
+ rubygems_version: 1.8.11
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Wordpress deploy tools, including a capistrano recipe
65
+ test_files: []