capistrano-cul 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
- require 'tempfile'
2
1
  require 'json'
2
+ require 'tempfile'
3
3
 
4
4
  namespace :cul do
5
5
  namespace :wp do
@@ -7,44 +7,25 @@ namespace :cul do
7
7
 
8
8
  desc "Copies the WordPress installation from one environment to another (e.g. prod to dev)"
9
9
  task :copy_from do
10
- # Need to store path as local variable so it can be referenced in `on roles(:web) do` portion of script
11
- path_to_allowed_upload_types_plugin = cul_allowed_upload_types_plugin_path
12
-
13
- require_cap_params!([:wp_docroot, :wp_content_path])
10
+ require_cap_variables!([:wp_docroot])
14
11
 
15
- if fetch(:multisite, false)
16
- puts "Since this is a multisite, you'll need to specify the source multisite instance domain to continue:"
17
- set :source_site_multisite_url, ask('source multisite instance domain (e.g. blogs.cul.columbia.edu)')
18
- fetch(:source_site_multisite_url)
19
-
20
- puts "And you'll also need to specify the destination multisite instance domain to continue:"
21
- set :destination_site_multisite_url, ask('destination multisite instance domain (e.g. blogs-dev.cul.columbia.edu)')
22
- fetch(:destination_site_multisite_url)
23
- end
12
+ require_src_wp_domain_if_multisite!
13
+ require_dest_wp_domain_if_multisite!
24
14
 
25
- # TODO: Would be nice to verify that destination wordpress has already had the setup and deploy tasks run for it
15
+ set :src_wp_server, ask("source WordPress server (e.g. ldpd-nginx-prod1.cul.columbia.edu)")
26
16
  set :src_wp_docroot, ask("server path to source WordPress installation (to copy from)")
27
17
 
28
- # Confirm operation because it is destructive
29
- puts "\nWARNING: This operation will obliterate all content in environment [#{fetch(:stage)}] and replace it with content from [#{fetch(:src_wp_docroot)}]."
30
- puts "Are you sure you want to continue?"
31
- set :confirm, ask('"y" or "yes" to continue')
32
- unless ['y', 'yes'].include?(fetch(:confirm))
33
- puts 'Copy operation has been cancelled because neither "y" nor "yes" were entered.'
34
- next
35
- end
36
-
37
- # Don't really care about maintenance mode because we're completely destroying the target environment
38
- # Enter maintenance mode
39
- #invoke 'cul:wp:enable_maintenance_mode'
18
+ puts "Checking #{fetch(:src_wp_server)} for version of WordPress instance at #{fetch(:src_wp_docroot)}..."
40
19
 
41
- # Check WP version on source WordPress instance
20
+ # Check WP version on source WordPress instance. We require latest version because we always download the latest version for the new instance.
42
21
  failure = false
43
- on roles(:web) do
22
+ on fetch(:remote_user) + '@' + fetch(:src_wp_server) do
44
23
  within fetch(:src_wp_docroot) do
45
24
  # Ensure that source WordPress is running the latest version
46
- result = capture :wp, (fetch(:multisite, false) ? "--url=#{fetch(:source_site_multisite_url)}" : ''), 'core', 'check-update'
47
- unless result.index('Success')
25
+ result = capture :wp, (fetch(:multisite, false) ? "--url=#{fetch(:src_multisite_domain)}" : ''), 'core', 'check-update'
26
+ if result.index('Success')
27
+ puts "Running latest version of WordPress!"
28
+ else
48
29
  puts 'Could not copy from source WordPress because it is not running the latest version of WordPress. Please update source before running a copy operation.'
49
30
  failure = true
50
31
  end
@@ -52,161 +33,225 @@ namespace :cul do
52
33
  end
53
34
  next if failure # End if the previous checks failed
54
35
 
55
- on roles(:web) do
56
- # Destroy current wp_docroot
57
- execute :rm, '-rf', fetch(:wp_docroot)
58
- execute :mkdir, fetch(:wp_docroot)
59
- end
60
-
61
- # Download new copy of wordpress
36
+ # Run setup task to destroy current docroot and download new copy of WordPress
37
+ # Note: The setup task enables maintenance mode during intermediate deployment
38
+ # step, and then disables maintenance mode before it completes.
62
39
  invoke 'cul:wp:setup'
63
40
 
64
- path_to_list_of_files_to_copy = ''
41
+ # Enable maintenance mode AGAIN
42
+ invoke! 'cul:wp:enable_maintenance_mode'
65
43
 
66
- on roles(:web) do
67
- # In source site's wp-content directory, generate file list to copy
68
- within File.join(fetch(:src_wp_docroot), 'wp-content') do
69
- # We're going to be copying wp-content in two parts
70
- # 1. Everything else under wp-content EXCEPT uploads, blogs.dir,
71
- # plugins, themes, mu-plugins
72
- # 2. Everything under uploads AND wpblogs.dir with
73
- # cul-allowed-upload-types file extension filter applied
74
-
75
- # Make sure find command handles non-ASCII chars
76
- #execute 'LC_ALL=en_US.iso885915'
77
-
78
- # Generate two find commands for the above searches
79
- find_non_upload_dirs = '. -type f ' +
80
- # EXCLUDE plugins, themes, mu-plugins, uploads, and blogs.dir
81
- "-not \\( -path './plugins/*' -o -path './mu-plugins/*' -o -path './themes/*' -o -path './uploads/*' -o -path './blogs.dir/*' \\) " +
82
- # EXCLUDE certain unwanted files and paths
83
- "-a -not \\( -name '.nfs*' -o -name '*.tmp.*' \\) " +
84
- "-a -not \\( -path '*/.git*' -o -path '*/.svn*' -o -path '*/.hg*' \\) "
85
-
86
- find_upload_dirs = '. -type f ' +
87
- # INCLUDE ONLY uploads and blogs.dir
88
- "\\( -path './uploads/*' -o -path './blogs.dir/*' \\) " +
89
- # EXCLUDE certain unwanted files and paths
90
- "-a -not \\( -name '.nfs*' -o -name '*.tmp.*' \\) " +
91
- "-a -not \\( -path '*/.git*' -o -path '*/.svn*' -o -path '*/.hg*' \\) " +
92
- # INCLUDE ONLY certain file extensions
93
- "-a \\( " + JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:source_site_multisite_url)}" : ''), 'eval', '"echo cul_allowed_upload_file_extensions_as_json();"')).map{ |allowed_file_extension|
94
- "-iname '*.#{allowed_file_extension}'"
95
- }.join(' -o ') + " \\) "
96
-
97
- path_to_list_of_files_to_copy = '/tmp/WP' + fetch(:wp_docroot).gsub('/', '-') + '-' + Time.now.to_i.to_s + '-files.txt'
98
- execute :find, find_non_upload_dirs, ' > ', path_to_list_of_files_to_copy
99
- execute :find, find_upload_dirs, ' >> ', path_to_list_of_files_to_copy
100
-
101
- # Print out which files won't be copied
102
- files_not_copied = capture(:comm, '-23', "<(find . -type f \\( -path './uploads/*' -o -path './blogs.dir/*' \\) | sort)", "<(find #{find_upload_dirs} | sort)")
44
+ # Run wp-content copy task to sync certain wp-content files (everything other than plugins, themes, mu-plugins) from src instance to dest instance
45
+ invoke 'cul:wp:migrate:copy_wp_content'
103
46
 
104
- puts (
105
- "The following files will not be copied:\n" +
106
- "-------------------------\n" +
107
- "./plugins\n" +
108
- "./mu-plugins\n" +
109
- "./themes\n" +
110
- files_not_copied + "\n" +
111
- "-------------------------"
112
- )
113
- end
47
+ # Copy database
48
+ invoke 'cul:wp:migrate:copy_database'
114
49
 
115
- # For destination wordpress, delete and recreate the wp-content directory
116
- execute :rm, '-rf', fetch(:wp_content_path)
117
- execute :mkdir, fetch(:wp_content_path)
50
+ # Run cul:wp:searchreplace one or more times
51
+ invoke 'cul:wp:migrate:post_database_copy_searchreplace'
118
52
 
119
- # Copy wp-content files (from path_to_list_of_files_to_copy) from source WP to destination WP
120
- # Note that because we have the '--copy-links' flag below, we're transforming all symlinks into real file copies
121
- rsync_params = [
122
- '--recursive',
123
- '--perms',
124
- '--times',
125
- '--devices',
126
- '--specials',
127
- '--copy-links',
128
- '--prune-empty-dirs'
129
- ]
53
+ # Download non-repo-managed plugins and themes
54
+ invoke 'cul:wp:migrate:download_plugins_and_themes'
130
55
 
131
- # we're only copying files from the given file list
132
- rsync_params << "--files-from=#{path_to_list_of_files_to_copy}"
56
+ # Disable maintenance mode
57
+ invoke! 'cul:wp:disable_maintenance_mode'
133
58
 
134
- src_wp_content_dir = File.join(fetch(:src_wp_docroot), 'wp-content/')
135
- # Run a find operation on the wp-content dir to pre-cache all non-UTF compliant files prior to our rsync operation (to handle files with smart quotes, em dashes, foreign characters, etc.)
136
- execute :find, src_wp_content_dir, '-print0', '|', 'perl', '-n0e', '\'chomp; print $_, "\n" if /[[:^ascii:][:cntrl:]]/\''
59
+ puts 'Copy complete!'
60
+ end
137
61
 
138
- # src directory (--files-from values are relative to this src directory)
139
- rsync_params << src_wp_content_dir
140
- # dest directory
141
- rsync_params << fetch(:wp_content_path) + '/'
62
+ desc "Copies certain wp-content (everything other than plugins, themes, and mu-plugins) from one environment to another (e.g. prod to dev). This task is part of the :copy_from task and isn't meant to be called directly."
63
+ task :copy_wp_content do
64
+ # Define src and dest wp content paths, for later use
65
+ src_wp_content_path = File.join(fetch(:src_wp_docroot), 'wp-content')
66
+ dest_wp_content_path = File.join(fetch(:wp_docroot), 'wp-content')
142
67
 
143
- puts 'Copying wp-content. This may take a while for sites with a lot of uploads...'
68
+ allowed_file_extensions = []
144
69
 
145
- puts 'rsync args:'
146
- puts rsync_params.join(' ')
70
+ # Get list of allowed file extensions to copy from source WP instance
71
+ on fetch(:remote_user) + '@' + fetch(:src_wp_server) do
72
+ within fetch(:src_wp_docroot) do
73
+ allowed_file_extensions = JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:src_multisite_domain)}" : ''), 'eval', '"echo cul_allowed_upload_file_extensions_as_json();"'))
74
+ end
75
+ end
147
76
 
148
- execute :rsync, *rsync_params
77
+ # Copy certain files from src wp-content to dest wp-content
78
+ on roles(:web) do
79
+ within fetch(:wp_docroot) do
149
80
 
150
- # clean up path_to_list_of_files_to_copy file
151
- execute :rm, path_to_list_of_files_to_copy
81
+ # Note that because we have the '--copy-links' flag below, we're transforming all symlinks into real file copies
82
+ rsync_base_params = [
83
+ '--recursive',
84
+ '--perms',
85
+ '--times',
86
+ '--devices',
87
+ '--specials',
88
+ '--copy-links',
89
+ '--prune-empty-dirs',
90
+ # Always exclude certain file and directory patterns
91
+ '--exclude=".nfs*"',
92
+ '--exclude="*.tmp.*"',
93
+ '--exclude=".git*"',
94
+ '--exclude=".svn*"',
95
+ '--exclude=".hg*"'
96
+ ]
97
+
98
+ # First copy all files and folders OTHER THAN
99
+ # plugins, themes, mu-plugins, uploads, and blogs.dir
100
+ execute :rsync, (
101
+ rsync_base_params + [
102
+ # Apply exclusions, relative to the rsync src directory
103
+ '--exclude="plugins"',
104
+ '--exclude="mu-plugins"',
105
+ '--exclude="themes"',
106
+ '--exclude="uploads"',
107
+ '--exclude="blogs.dir"'
108
+ ] +
109
+ # Apply user-defined exclusion filters, if present
110
+ fetch(:wp_content_rsync_exclude_filters, []).map{ |filter_value| "--exclude=\"#{filter_value}\"" } +
111
+ [
112
+ # src directory
113
+ fetch(:remote_user) + '@' + fetch(:src_wp_server) + ':' + src_wp_content_path + '/', # trailing slash so we only copy content within dir, but not dir itself
114
+ # dest directory
115
+ dest_wp_content_path
116
+ ]
117
+ )
152
118
 
153
- # Next, create symlinks to repo-managed plugins and themes, which will also recreate plugins, mu-plugins, and themes directories
119
+ # Then copy all files and folders from uploads AND blogs.dir,
120
+ # (with cul-allowed-upload-types file extension filter applied)
121
+ execute :rsync, (
122
+ rsync_base_params +
123
+ # Apply user-defined exclusion filters, if present
124
+ fetch(:wp_content_rsync_exclude_filters, []).map{ |filter_value| "--exclude=\"#{filter_value}\"" } +
125
+ [
126
+ # Apply inclusion filters, relative to the rsync src directory
127
+ '--include="/uploads**/"',
128
+ '--include="/blogs.dir**/"',
129
+ ] +
130
+ # Apply inclusion filters based on file extension
131
+ allowed_file_extensions.map{ |allowed_file_extension| "--include=\"*.#{allowed_file_extension}\"" } +
132
+ [
133
+ # Exclude everything else not included by --include filters
134
+ '--exclude="*"',
135
+ # src directory
136
+ fetch(:remote_user) + '@' + fetch(:src_wp_server) + ':' + src_wp_content_path + '/', # trailing slash so we only copy content within dir, but not dir itself
137
+ # dest directory
138
+ dest_wp_content_path
139
+ ]
140
+ )
154
141
 
155
- within fetch(:wp_docroot) do
156
- # Regenerate symlinks
157
- invoke! 'cul:wp:symlink_custom_plugins_and_themes'
158
142
  end
143
+ end
159
144
 
160
- # Now it's time to copy the database
145
+ # Compare copied files and tell use which files were not copied
146
+ puts 'Comparing file lists between environments...'
161
147
 
162
- db_export_tempfile_path = ''
148
+ on roles(:web) do
149
+ within dest_wp_content_path do
150
+ files_not_copied = capture(:comm, '-23',
151
+ "<(ssh #{fetch(:remote_user)}@#{fetch(:src_wp_server)} \"cd #{src_wp_content_path} && find . -type f \\( -path '*/uploads/*' -o -path '*/blogs.dir/*' \\) | sort\")",
152
+ "<(cd #{dest_wp_content_path} && find . -type f \\( -path '*/uploads/*' -o -path '*/blogs.dir/*' \\) | sort)"
153
+ )
163
154
 
164
- within fetch(:src_wp_docroot) do
165
- # On source WordPress...
155
+ # Generate list of files that weren't copied. Display this list to the user.
156
+ puts (
157
+ "The following files were not copied because of file and directory filters:\n" +
158
+ "-------------------------\n" +
159
+ "./plugins\n" +
160
+ "./mu-plugins\n" +
161
+ "./themes\n" +
162
+ (files_not_copied.length > 0 ? files_not_copied + "\n" : '') +
163
+ "-------------------------"
164
+ )
165
+ end
166
+ end
167
+
168
+ end
166
169
 
167
- puts 'Exporting database from source site. This may take a while for large sites...'
170
+ desc "Copies certain wp-content (everything other than plugins, themes, and mu-plugins) from one environment to another (e.g. prod to dev). This task is part of the :copy_from task and isn't meant to be called directly."
171
+ task :copy_database do
172
+
173
+ db_export_tempfile = 'db_export_tempfile.sql'
174
+ remote_server_db_export_tempfile_path = Dir::Tmpname.make_tmpname '/tmp/', db_export_tempfile
175
+ local_server_db_export_file_path = File.join(fetch(:wp_docroot), db_export_tempfile)
176
+
177
+ # Export database from source WordPress instance
178
+ on fetch(:remote_user) + '@' + fetch(:src_wp_server) do
179
+ within fetch(:src_wp_docroot) do
180
+ puts 'Exporting database from source site. This might take a while for large sites...'
168
181
  # Export source WP DB to a temporary file
169
- db_export_tempfile_path = Dir::Tmpname.make_tmpname '/tmp/', 'db_export_tempfile.sql'
170
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:source_site_multisite_url)}" : ''), 'db', 'export', db_export_tempfile_path
182
+ execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:src_multisite_domain)}" : ''), 'db', 'export', remote_server_db_export_tempfile_path
171
183
  end
184
+ end
172
185
 
173
- within fetch(:wp_docroot) do
174
- # On destination WordPress...
186
+ begin
187
+ on roles(:web) do
188
+ # Import database to destination WordPress instance
189
+ within fetch(:wp_docroot) do
190
+ puts 'Importing database. This may take a while for large sites...'
175
191
 
176
- puts 'Importing database. This may take a while for large sites...'
192
+ # Copy database export from other server to this server
193
+ execute :rsync,
194
+ fetch(:remote_user) + '@' + fetch(:src_wp_server) + ':' + remote_server_db_export_tempfile_path,
195
+ local_server_db_export_file_path
177
196
 
178
- # Drop all tables
179
- execute :wp, 'db', 'reset', '--yes'
180
197
 
181
- # Read in db file
182
- execute :wp, 'db', 'import', db_export_tempfile_path
198
+ # Drop all tables
199
+ execute :wp, 'db', 'reset', '--yes'
183
200
 
184
- # Delete db file now that we're done with it
185
- execute :rm, db_export_tempfile_path
201
+ # Read in db file
202
+ execute :wp, 'db', 'import', local_server_db_export_file_path
203
+ end
204
+ end
205
+ ensure
206
+ # Regardless of whether the db import was successful, make sure to
207
+ # delete DB temp files on remote server and local server.
208
+
209
+ # Delete on remote server
210
+ on fetch(:remote_user) + '@' + fetch(:src_wp_server) do
211
+ within fetch(:src_wp_docroot) do
212
+ execute :rm, remote_server_db_export_tempfile_path
213
+ end
214
+ end
186
215
 
187
- # Invoke searchreplace task to update URL
188
- puts "\nYou'll probably want to run the cul:wp:searchreplace command now, since it's likely that your WP URL differs between environments."
189
- puts "Do you want to run a search and replace operation?"
190
- set :confirm_searchreplace, ask('"y" or "yes" to continue')
191
- if ['y', 'yes'].include?(fetch(:confirm_searchreplace))
192
- invoke 'cul:wp:searchreplace'
193
- else
194
- puts '- Skipping search and replace because neither "y" nor "yes" were entered.'
216
+ # Delete on local server
217
+ on roles(:web) do
218
+ within fetch(:wp_docroot) do
219
+ execute :rm, local_server_db_export_file_path
195
220
  end
196
221
  end
222
+ end
223
+ end
224
+
225
+ desc "Runs one or more cul:wp:searchreplace operations after a database copy"
226
+ task :post_database_copy_searchreplace do
227
+
228
+ # Invoke searchreplace task to update URL
229
+ puts "\nYou'll probably want to run the cul:wp:searchreplace command now, since it's likely that your WP URL differs between environments."
230
+ if enter_y_to_continue(color_text("Do you want to run cul:wp:searchreplace?"))
231
+ invoke! 'cul:wp:searchreplace'
232
+ while enter_y_to_continue(color_text("Do you want to run cul:wp:searchreplace again?"))
233
+ invoke! 'cul:wp:searchreplace'
234
+ end
235
+ end
236
+
237
+ end
197
238
 
198
- # Next, install all plugins and themes from src wordpress, matching all versions and active vs. inactive plugin and theme states
239
+ desc "Gets a list of all non-mu plugins and themes on SOURCE WP instance and installs them to DESTINATION WP instance, but does not activate them. Activation status is already determined by the copied-over database."
240
+ task :download_plugins_and_themes do
199
241
 
200
- data_for_plugins = []
201
- data_for_themes = []
242
+ data_for_plugins = []
243
+ data_for_themes = []
202
244
 
203
- # Within src wp instance, get list of all plugins and themes with version
245
+ # Within src wp instance, get list of all plugins and themes with version
246
+ on fetch(:remote_user) + '@' + fetch(:src_wp_server) do
204
247
  within File.join(fetch(:src_wp_docroot)) do
205
- data_for_plugins = JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:source_site_multisite_url)}" : ''), 'plugin', 'list', '--fields=name,version,status', '--format=json'))
206
- data_for_themes = JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:source_site_multisite_url)}" : ''), 'theme', 'list', '--fields=name,version,status', '--format=json'))
248
+ data_for_plugins = JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:src_multisite_domain)}" : ''), 'plugin', 'list', '--fields=name,version,status', '--format=json'))
249
+ data_for_themes = JSON.parse(capture(:wp, (fetch(:multisite, false) ? "--url=#{fetch(:src_multisite_domain)}" : ''), 'theme', 'list', '--fields=name,version,status', '--format=json'))
207
250
  end
251
+ end
208
252
 
209
- # Within dest wp instance, install specifically versioned plugins and themes
253
+ # Within dest wp instance, install specifically versioned plugins and themes
254
+ on roles(:web) do
210
255
  within File.join(fetch(:wp_docroot)) do
211
256
  # Get list of repo-managed plugins and themes so that we don't attempt to overwrite these directories
212
257
  repo_managed_plugin_names = fetch(:wp_custom_plugins, {}).keys
@@ -220,12 +265,8 @@ namespace :cul do
220
265
  status = plugin_info['status']
221
266
 
222
267
  case status
223
- when 'active'
224
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:destination_site_multisite_url)}" : ''), 'plugin', 'install', name, "--version=#{version}", '--activate'
225
- when 'active-network'
226
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:destination_site_multisite_url)}" : ''), 'plugin', 'install', name, "--version=#{version}", '--activate-network'
227
- when 'inactive'
228
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:destination_site_multisite_url)}" : ''), 'plugin', 'install', name, "--version=#{version}"
268
+ when 'active', 'active-network', 'inactive'
269
+ execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:dest_multisite_domain)}" : ''), 'plugin', 'install', name, "--version=#{version}"
229
270
  when 'must-use'
230
271
  puts "--- WARNING: must-use plugin #{name} was not migrated over. It should be put in your blog's repository and deployed through a regular deployment."
231
272
  end
@@ -238,26 +279,25 @@ namespace :cul do
238
279
 
239
280
  case status
240
281
  when 'active'
241
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:destination_site_multisite_url)}" : ''), 'theme', 'install', name, "--version=#{version}", '--activate'
282
+ execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:dest_multisite_domain)}" : ''), 'theme', 'install', name, "--version=#{version}", '--activate'
242
283
  when 'inactive', 'parent'
243
- execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:destination_site_multisite_url)}" : ''), 'theme', 'install', name, "--version=#{version}"
284
+ execute :wp, (fetch(:multisite, false) ? "--url=#{fetch(:dest_multisite_domain)}" : ''), 'theme', 'install', name, "--version=#{version}"
244
285
  end
245
286
  end
246
287
  end
247
-
248
- within fetch(:wp_docroot) do
249
- # Make docroot readable and executable for "other" user so nginx, which runs as "nobody", can read
250
- # Use -L flag because we want to follow symlinks. The whole deployment relies on symlinks.
251
- execute :find, '-L', File.join(fetch(:wp_docroot), 'wp-content'), '-type d -exec chmod o+rx "{}" \;'
252
- execute :find, '-L', File.join(fetch(:wp_docroot), 'wp-content'), '-type f -exec chmod o+r "{}" \;'
253
- # Make sure that wp-config file is not world readable
254
- execute :chmod, 'o-r', shared_path.join('wp-config.php')
255
- end
256
-
257
288
  end
289
+
258
290
  end
259
291
 
260
- #after 'cul:wp:migrate:copy_from', 'cul:wp:disable_maintenance_mode'
292
+ desc 'Sets correct permissions for files in the WP docroot.'
293
+ task :set_correct_wp_docroot_permissions do
294
+ # Make wp-content readable and executable for "other" user so nginx, which runs as "nobody", can read wp-files.
295
+ # Use -L flag because we want to follow symlinks. The deployment relies on symlinks.
296
+ execute :find, '-L', File.join(fetch(:wp_docroot), 'wp-content'), '-type d -exec chmod o+rx "{}" \;'
297
+ execute :find, '-L', File.join(fetch(:wp_docroot), 'wp-content'), '-type f -exec chmod o+r "{}" \;'
298
+ # Make sure that wp-config.php is not world readable. It's only run by php, not nginx.
299
+ execute :chmod, 'o-r', File.join(fetch(:wp_docroot), 'wp-config.php')
300
+ end
261
301
 
262
302
  end
263
303
  end
@@ -0,0 +1,73 @@
1
+ namespace :cul do
2
+ namespace :wp do
3
+
4
+ task :setup do
5
+ desc "Downloads a new copy of wordpress, completely overwriting any existing site files. To install WordPress, follow this setup task with the cul:wp:install task."
6
+ require_cap_variables!([:wp_docroot])
7
+
8
+ unless enter_y_to_continue(color_text("This will delete all content at #{fetch(:wp_docroot)}."))
9
+ puts 'Operation cancelled because "y" was not entered.'
10
+ next
11
+ end
12
+
13
+ on roles(:web) do
14
+ within(deploy_path) do
15
+
16
+ # Destroy and recreate the docroot
17
+ execute :rm, '-rf', fetch(:wp_docroot), '&&', 'mkdir', fetch(:wp_docroot)
18
+
19
+ # Create nginx logs directory if it doesn't already exist
20
+ execute :mkdir, '-p', deploy_path.join('logs')
21
+
22
+ # Download and unpack latest version of WP to wp_docroot
23
+ execute :wp, 'core', ['download', "--version=latest", "--path=#{fetch(:wp_docroot)}"]
24
+
25
+ # Create a limited-content wp-config.php file that requires our shared
26
+ # wp-config-include.php file. We do this so that wordpress still has a
27
+ # wp-config.php file at the expected location, and that file correctly
28
+ # sets the ABSPATH constant based on the wp-config.php file location.
29
+
30
+ # Our limited-content wp-config file will only contain the following:
31
+ # ----------------------------------------------------------
32
+ # require dirname(__DIR__) . '/conf/the-real-conf.php';
33
+ #
34
+ #/* That's all, stop editing! Happy blogging. */
35
+ #
36
+ #/** WordPress absolute path to the Wordpress directory. */
37
+ #if ( !defined('ABSPATH') )
38
+ # define('ABSPATH', dirname(__FILE__) . '/');
39
+ #
40
+ #/** Sets up WordPress vars and included files. */
41
+ #require_once(ABSPATH . 'wp-settings.php');
42
+ #?>
43
+ # ----------------------------------------------------------
44
+ execute :echo, '-e', '"' +
45
+ "<?php" +
46
+ '\\n' +
47
+ "require dirname(__DIR__) . '/shared/wp-config-include.php';" +
48
+ '\\n\\n' +
49
+ "/* That's all, stop editing! Happy blogging. */" +
50
+ '\\n' +
51
+ "/** WordPress absolute path to the Wordpress directory. */" +
52
+ '\\n' +
53
+ "if ( !defined('ABSPATH') ) { define('ABSPATH', dirname(__FILE__) . '/'); }" +
54
+ '\\n\\n' +
55
+ "/** Sets up WordPress vars and included files. */" +
56
+ '\\n' +
57
+ "require_once(ABSPATH . 'wp-settings.php');" +
58
+ '\\n' +
59
+ "?>" +
60
+ '"',
61
+ '>',
62
+ File.join(fetch(:wp_docroot), 'wp-config.php')
63
+ end
64
+ end
65
+
66
+ # After setup, do a deployment so we have the latest plugins and themes
67
+ # available and symlinked in wp-content
68
+ invoke 'deploy'
69
+
70
+ end
71
+
72
+ end
73
+ end