capistrano-cul 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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