derpy 1.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. checksums.yaml +7 -0
  2. data/README.markdown +18 -0
  3. data/VERSION +1 -0
  4. data/derpy.gemspec +29 -0
  5. data/lib/derpy.rb +388 -0
  6. metadata +77 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ data.tar.gz: 58f7a8c72bc4157d3d23022069ad0c3898e7ec63
4
+ metadata.gz: a2b754b92c8b0696f040d13373eb65df68d97ed0
5
+ SHA512:
6
+ data.tar.gz: 267d501f86e3e75f348d690e8fe17637cfacf03b896788f2416da4100cdb2ac7478410ee7d265eaefdb824827f3909d981cb3df0b6dfe7e9af480a2ad62a2a2e
7
+ metadata.gz: fe5994238bed6c115e306d90561f20b2646aaf1fa17daad159d7c87555fe22c706e4978e4cbb3316f8a7e247d8e235a1b8ff041450401b29af757a6d9724dc68
data/README.markdown ADDED
@@ -0,0 +1,18 @@
1
+ # Derpy
2
+
3
+ This gem provides a number of tasks which are useful for deploying Drupal projects with [Capistrano](https://github.com/capistrano/capistrano).
4
+
5
+
6
+ ## Installation
7
+ [gems](http://rubygems.org) must be installed on your system first.
8
+
9
+ ### From RubyGems.org
10
+
11
+ $ gem install derpy
12
+
13
+ ### From Github
14
+
15
+ $ git clone git://github.com/3sign/derpy.git
16
+ $ cd derpy
17
+ $ gem build derpy.gemspec
18
+ $ gem install derpy-{version}.gem
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/derpy.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'derpy'
5
+ s.version = '1.0.0'
6
+ s.platform = Gem::Platform::RUBY
7
+ s.description = <<-DESC
8
+ A set of tasks for deploying Drupal projects with Capistrano and the help of Drush.
9
+ DESC
10
+ s.summary = 'A set of tasks for deploying Drupal projects with Capistrano'
11
+
12
+ s.extra_rdoc_files = [
13
+ "README.markdown"
14
+ ]
15
+ s.files = [
16
+ "README.markdown",
17
+ "VERSION",
18
+ "derpy.gemspec",
19
+ "lib/derpy.rb"
20
+ ]
21
+ s.require_path = 'lib'
22
+
23
+ s.add_dependency 'capistrano', ">= 2.13.5","<= 2.15.4"
24
+ s.add_dependency 'railsless-deploy', "~> 1.1.2"
25
+
26
+ s.authors = [ "Robin De Langhe" ]
27
+ s.email = 'robin@3sign.com'
28
+ s.homepage = %q{http://github.com/3sign/derpy/}
29
+ end
data/lib/derpy.rb ADDED
@@ -0,0 +1,388 @@
1
+ Capistrano::Configuration.instance(:must_exist).load do
2
+
3
+ require 'capistrano/recipes/deploy/scm'
4
+ require 'capistrano/recipes/deploy/strategy'
5
+ require 'railsless-deploy'
6
+
7
+ # =========================================================================
8
+ # These variables MUST be set in the client capfiles. If they are not set,
9
+ # the deploy will fail with an error.
10
+ # =========================================================================
11
+
12
+ _cset(:db_type) { abort "Please specify the Drupal database type (:db_type)." }
13
+ _cset(:db_name) { abort "Please specify the Drupal database name (:db_name)." }
14
+ _cset(:db_username) { abort "Please specify the Drupal database username (:db_username)." }
15
+ _cset(:db_password) { abort "Please specify the Drupal database password (:db_password)." }
16
+ _cset(:db_host) { abort "Please specify the Drupal database host (:db_host)." }
17
+
18
+ # =========================================================================
19
+ # These variables may be set in the client capfile if their default values
20
+ # are not sufficient.
21
+ # =========================================================================
22
+
23
+ set :use_sudo, false
24
+ set :scm, :git
25
+ set :deploy_via, :remote_cache
26
+ set :branch, "master"
27
+ set :git_enable_submodules, true
28
+ set :keep_releases, 5
29
+
30
+ set :runner_group, "www-data"
31
+ set :group_writable, false
32
+
33
+ set (:deploy_to) {"/var/www/#{application}"}
34
+ set :app_path, "drupal"
35
+ set :shared_children, ['sites/default/files']
36
+ set :shared_files, ['sites/default/settings.php']
37
+
38
+ set :backup_database, true
39
+ set :dbbackups, "db_backups"
40
+ _cset(:dbbackups_path) { File.join(deploy_to, dbbackups) }
41
+
42
+ set :local_database, nil
43
+ set :push_dump_enabled, false
44
+
45
+ set :download_drush, false
46
+ _cset(:drush_cmd) { download_drush ? "#{shared_path}/drush/drush" : "drush" }
47
+
48
+ default_run_options[:pty] = true
49
+ ssh_options[:forward_agent] = true
50
+
51
+ if download_drush
52
+ depend :remote, :command, "curl"
53
+ end
54
+
55
+ # This is an optional step that can be defined.
56
+ #after "deploy", "git:push_deploy_tag"
57
+
58
+ # =========================
59
+ # Deploy methods
60
+ # =========================
61
+
62
+ namespace :deploy do
63
+ desc <<-DESC
64
+ Prepares one or more servers for deployment. Before you can use any \
65
+ of the Capistrano deployment tasks with your project, you will need to \
66
+ make sure all of your servers have been prepared with `cap deploy:setup'. When \
67
+ you add a new server to your cluster, you can easily run the setup task \
68
+ on just that server by specifying the HOSTS environment variable:
69
+
70
+ $ cap HOSTS=new.server.com deploy:setup
71
+
72
+ It is safe to run this task on servers that have already been set up; it \
73
+ will not destroy any deployed revisions or data.
74
+ DESC
75
+ task :setup, :except => { :no_release => true } do
76
+ if download_drush
77
+ drush.get
78
+ end
79
+
80
+ dirs = [deploy_to, releases_path, shared_path, dbbackups].join(' ')
81
+ run "#{try_sudo} mkdir -p #{releases_path} #{shared_path} #{dbbackups_path}"
82
+ run "#{try_sudo} chown -R #{user}:#{runner_group} #{deploy_to}"
83
+ if shared_children.size > 0
84
+ sub_dirs = shared_children.map { |d| File.join(shared_path, d) }
85
+ run "#{try_sudo} mkdir -p #{sub_dirs.join(' ')}"
86
+ run "#{try_sudo} chmod 2775 #{sub_dirs.join(' ')}"
87
+ end
88
+
89
+ #create drupal config file
90
+ configuration = drupal_settings()
91
+ put configuration, "#{shared_path}/#{shared_files[0]}"
92
+
93
+ end
94
+
95
+ desc <<-DESC
96
+ Deploys your Drupal site, runs drush:update. It supposes that the Setup task was already executed.
97
+ This overrides the default Capistrano Deploy task to handle database operations and backups,
98
+ all of them via Drush.
99
+ DESC
100
+ task :default do
101
+ update
102
+ manage.dbdump_previous
103
+ end
104
+ after "deploy:default", "deploy:cc"
105
+
106
+ desc "Setup a drupal site from scratch"
107
+ task :cold do
108
+ setup
109
+ update
110
+ manage.push_dump
111
+ end
112
+ after "deploy:cold", "deploy:cc"
113
+
114
+ desc "[internal] Rebuild files and settings symlinks"
115
+ task :finalize_update, :except => { :no_release => true } do
116
+ if shared_children
117
+ # Creating symlinks for shared directories
118
+ shared_children.each do |link|
119
+ run "#{try_sudo} sh -c 'if [ -d #{release_path}/#{link} ] ; then rm -rf #{release_path}/#{link}; fi'"
120
+ run "#{try_sudo} ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
121
+ end
122
+ end
123
+
124
+ if shared_files
125
+ # Creating symlinks for shared files
126
+ shared_files.each do |link|
127
+ link_dir = File.dirname("#{shared_path}/#{link}")
128
+ run "#{try_sudo} ln -nfs #{shared_path}/#{link} #{release_path}/#{link}"
129
+ end
130
+ end
131
+ end
132
+
133
+ desc <<-DESC
134
+ Removes old releases and corresponding DB backups.
135
+ DESC
136
+ task :cleanup, :except => { :no_release => true } do
137
+ count = fetch(:keep_releases, 5).to_i
138
+ if count >= releases.length
139
+ logger.important "No old releases to clean up"
140
+ else
141
+ logger.info "keeping #{count} of #{releases.length} deployed releases"
142
+ old_releases = (releases - releases.last(count))
143
+ directories = old_releases.map { |release| File.join(releases_path, release) }.join(" ")
144
+ databases = old_releases.map { |release| File.join(dbbackups_path, "#{release}.sql")}.join(" ") if backup_database
145
+ run "rm -rf #{directories} #{databases}"
146
+ end
147
+ end
148
+
149
+ task :cc do
150
+ drush.site_offline
151
+ drush.updatedb
152
+ drush.cache_clear
153
+ drush.site_online
154
+ drush.cache_clear
155
+ end
156
+
157
+ namespace :rollback do
158
+
159
+ desc <<-DESC
160
+ Go back to the previous release (code and database)
161
+ DESC
162
+ task :default do
163
+ revision
164
+ db_rollback if domain.to_a.size == 1
165
+ cleanup
166
+ end
167
+
168
+ desc <<-DESC
169
+ [internal] Removes the most recently deployed release.
170
+ This is called by the rollback sequence, and should rarely
171
+ (if ever) need to be called directly.
172
+ DESC
173
+ task :cleanup, :except => { :no_release => true } do
174
+ run "if [ `readlink #{current_path}` != #{current_release} ]; then rm -rf #{current_release}; fi"
175
+ end
176
+
177
+ desc <<-DESC
178
+ [internal] Points the current, files, and settings symlinks at the previous revision.
179
+ DESC
180
+ task :revision, :except => { :no_release => true } do
181
+ if previous_release
182
+ run "rm #{current_path}"
183
+ run "ln -s #{previous_release} #{current_path}"
184
+ else
185
+ abort "could not rollback the code because there is no prior release"
186
+ end
187
+ end
188
+
189
+
190
+ desc <<-DESC
191
+ [internal] If a database backup from the previous release is found, dump the current
192
+ database and import the backup. This task should NEVER be called standalone.
193
+ DESC
194
+ task :db_rollback, :except => { :no_release => true } do
195
+ if previous_release
196
+ logger.info "Dumping current database and importing previous one (If one is found)."
197
+ previous_db = File.join(dbbackups_path, "#{releases[-2]}.sql")
198
+ import_cmd = "cd #{current_path}/#{app_path} && #{drush_cmd} sql-drop -y && #{drush_cmd} sql-cli < #{previous_db} && rm #{previous_db}"
199
+ run "if [ -e #{previous_db} ]; then #{import_cmd}; fi"
200
+ else
201
+ abort "could not rollback the database because there is no prior release db backups"
202
+ end
203
+ end
204
+ end
205
+ end
206
+
207
+ # =========================
208
+ # Files methods
209
+ # =========================
210
+
211
+ namespace :files do
212
+ desc "Pull drupal sites files (from remote to local)"
213
+ task :pull, :roles => :app, :except => { :no_release => true } do
214
+ remote_files_dir = "#{current_path}/sites/default/files/"
215
+ local_files_dir = "sites/default/files/"
216
+
217
+ run_locally("rsync --recursive --times --rsh=ssh --compress --human-readable --progress #{user}@#{roles[:app].servers[0].host}:#{remote_files_dir} #{local_files_dir}")
218
+ end
219
+
220
+ desc "Push drupal sites files (from local to remote)"
221
+ task :push, :roles => :app, :except => { :no_release => true } do
222
+ remote_files_dir = "#{current_path}/sites/default/files/"
223
+ local_files_dir = "sites/default/files/"
224
+
225
+ run_locally("rsync --recursive --times --rsh=ssh --compress --human-readable --progress #{local_files_dir} #{user}@#{roles[:app].servers[0].host}:#{remote_files_dir}")
226
+
227
+ end
228
+ end
229
+
230
+ # =========================
231
+ # Git methods
232
+ # =========================
233
+
234
+ namespace :git do
235
+
236
+ desc "Place release tag into Git and push it to origin server."
237
+ task :push_deploy_tag do
238
+ user = `git config --get user.name`
239
+ email = `git config --get user.email`
240
+ tag = "release_#{release_name}"
241
+ if exists?(:stage)
242
+ tag = "#{stage}_#{tag}"
243
+ end
244
+ puts `git tag #{tag} #{revision} -m "Deployed by #{user} <#{email}>"`
245
+ puts `git push origin tag #{tag}`
246
+ end
247
+
248
+ end
249
+
250
+ # =========================
251
+ # Drush methods
252
+ # =========================
253
+
254
+ namespace :drush do
255
+
256
+ desc "Gets drush and installs it"
257
+ task :get, :roles => :app, :except => { :no_release => true } do
258
+ run "#{try_sudo} cd #{shared_path} && curl -O -s http://ftp.drupal.org/files/projects/drush-7.x-5.8.tar.gz && tar -xf drush-7.x-5.8.tar.gz && rm drush-7.x-5.8.tar.gz"
259
+ run "#{try_sudo} cd #{shared_path} && chmod u+x drush/drush"
260
+ end
261
+
262
+ desc "Set the site offline"
263
+ task :site_offline, :on_error => :continue do
264
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} vset site_offline 1 -y"
265
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} vset maintenance_mode 1 -y"
266
+ end
267
+
268
+ desc "Backup the database"
269
+ task :backupdb, :on_error => :continue do
270
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} bam-backup"
271
+ end
272
+
273
+ desc "Run Drupal database migrations if required"
274
+ task :updatedb, :on_error => :continue do
275
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} updatedb -y"
276
+ end
277
+
278
+ desc "Clear the drupal cache"
279
+ task :cache_clear, :on_error => :continue do
280
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} cache-clear all"
281
+ end
282
+
283
+ desc "Revert feature"
284
+ task :feature_revert, :on_error => :continue do
285
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} features-revert-all -y"
286
+ end
287
+
288
+ desc "Set the site online"
289
+ task :site_online, :on_error => :continue do
290
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} vset site_offline 0 -y"
291
+ run "#{drush_cmd} -r #{latest_release}/#{app_path} vset maintenance_mode 0 -y"
292
+ end
293
+
294
+ end
295
+
296
+ # =========================
297
+ # Manage methods
298
+ # =========================
299
+
300
+ namespace :manage do
301
+
302
+ desc "Block bots via robots.txt"
303
+ task :block_robots do
304
+ put "User-agent: *\nDisallow: /", "#{current_path}/#{app_path}/robots.txt"
305
+ end
306
+
307
+ task :dbdump_previous do
308
+ #Backup the previous release's database
309
+ if previous_release && backup_database
310
+ run "cd #{current_path}/#{app_path} && #{drush_cmd} sql-dump > #{ File.join(dbbackups_path, "#{releases[-2]}.sql") }"
311
+ end
312
+ end
313
+
314
+ desc 'Dump remote database and restore locally'
315
+ task :pull_dump do
316
+ abort("NO LOCAL DATABASE FOUND, set :local_database in the config file..") unless local_database
317
+
318
+ set(:runit, Capistrano::CLI.ui.ask("WARNING!! will overwrite this local database: '#{local_database}', type 'yes' to continue: "))
319
+ if runit == 'yes'
320
+ sql_file = File.join(dbbackups_path, "#{releases.last}-pull.sql")
321
+ # dump & gzip remote file
322
+ run "cd #{current_path}/#{app_path} && #{drush_cmd} sql-dump > #{sql_file} && gzip -f #{sql_file}"
323
+ # copy to local
324
+ system "if [ ! -d build ]; then mkdir build; fi" # create build folder locally if needed
325
+ download "#{sql_file}.gz", "build/", :once => true, :via => :scp
326
+ run "rm #{sql_file}.gz"
327
+ # extract and restore
328
+ system "gunzip -f build/#{File.basename(sql_file)}.gz && drush sql-drop -y && drush sql-cli < build/#{File.basename(sql_file)}" if local_database
329
+ system "rm build/#{File.basename(sql_file)}"
330
+ end
331
+ end
332
+
333
+ desc 'Dump local database and restore remote'
334
+ task :push_dump do
335
+ abort("NO LOCAL DATABASE FOUND, set :local_database in the config file..") unless local_database
336
+ abort("THIS STAGE: #{stage} DOES NOT SUPPORT manage:push_dump") unless push_dump_enabled
337
+
338
+ set(:runit, Capistrano::CLI.ui.ask("WARNING!! will overwrite this REMOTE database: '#{db_name}', type 'yes' to continue: "))
339
+ if runit == 'yes'
340
+ sql_file = "#{Time.now.to_i}.sql"
341
+ system "if [ ! -d build ]; then mkdir build; fi" # create build folder locally if needed
342
+ # dump & gzip local file
343
+ system "drush sql-dump > ./build/#{sql_file} && gzip ./build/#{sql_file}"
344
+ # copy to remote
345
+ upload "build/#{sql_file}.gz", File.join(dbbackups_path, "#{sql_file}.gz"), :once => true, :via => :scp
346
+ system "rm build/#{sql_file}.gz"
347
+ # extract and restore
348
+ run "gunzip -f #{File.join(dbbackups_path, "#{sql_file}.gz")} && cd #{current_path}/#{app_path} && #{drush_cmd} sql-drop -y && #{drush_cmd} sql-cli < #{File.join(dbbackups_path, "#{sql_file}")}"
349
+ run "rm #{File.join(dbbackups_path, "#{sql_file}")}"
350
+ end
351
+ end
352
+ end
353
+
354
+ # =========================
355
+ # Helper methods
356
+ # =========================
357
+
358
+ # Builds initial contents of the Drupal website's settings file
359
+ def drupal_settings()
360
+ settings = <<-STRING
361
+ <?php
362
+ $databases = array ('default' => array ('default' => array (
363
+ 'database' => '#{db_name}',
364
+ 'username' => '#{db_username}',
365
+ 'password' => '#{db_password}',
366
+ 'host' => '#{db_host}',
367
+ 'port' => '',
368
+ 'driver' => '#{db_type}',
369
+ 'prefix' => '',
370
+ )));
371
+ ini_set('session.gc_probability', 1);
372
+ ini_set('session.gc_divisor', 100);
373
+ ini_set('session.gc_maxlifetime', 200000);
374
+ ini_set('session.cookie_lifetime', 2000000);
375
+
376
+ $conf['404_fast_paths_exclude'] = '/\/(?:styles)\//';
377
+ $conf['404_fast_paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i';
378
+ $conf['404_fast_html'] = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>';
379
+
380
+ // Allow local env to override settings by creating a local.settings.php.
381
+ $path = str_replace('settings.php', 'local.settings.php', __FILE__);
382
+
383
+ if (file_exists($path)) {
384
+ include_once($path);
385
+ }
386
+ STRING
387
+ end
388
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: derpy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Robin De Langhe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2014-03-17 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: 2.13.5
22
+ - - <=
23
+ - !ruby/object:Gem::Version
24
+ version: 2.15.4
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: railsless-deploy
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.1.2
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ description: " A set of tasks for deploying Drupal projects with Capistrano and the help of Drush.\n"
38
+ email: robin@3sign.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - README.markdown
45
+ files:
46
+ - README.markdown
47
+ - VERSION
48
+ - derpy.gemspec
49
+ - lib/derpy.rb
50
+ homepage: http://github.com/3sign/derpy/
51
+ licenses: []
52
+
53
+ metadata: {}
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - &id003
63
+ - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - *id003
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 2.0.4
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: A set of tasks for deploying Drupal projects with Capistrano
76
+ test_files: []
77
+