wordpresstrano 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +5 -0
- data/lib/capistrano/wordpress/helpers/fixnum.rb +22 -0
- data/lib/capistrano/wordpress/helpers/hash.rb +10 -0
- data/lib/capistrano/wordpress/hooks.rb +95 -0
- data/lib/capistrano/wordpress/tasks/binaries.rake +35 -0
- data/lib/capistrano/wordpress/tasks/config.rake +85 -0
- data/lib/capistrano/wordpress/tasks/database.rake +355 -0
- data/lib/capistrano/wordpress/tasks/deploy.rake +24 -0
- data/lib/capistrano/wordpress/tasks/htaccess.rake +132 -0
- data/lib/capistrano/wordpress/tasks/maintenance.rake +68 -0
- data/lib/capistrano/wordpress/tasks/robots.rake +37 -0
- data/lib/capistrano/wordpress/tasks/uploads.rake +122 -0
- data/lib/capistrano/wordpress/tasks/webroot.rake +38 -0
- data/lib/capistrano/wordpress/tasks/wordpress.rake +89 -0
- data/lib/capistrano/wordpress.rb +13 -0
- data/lib/wordpresstrano.rb +1 -0
- data/wordpresstrano.gemspec +16 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5436061cb8fc9afe6050e4f86f69595e9259c791
|
4
|
+
data.tar.gz: 1513416e7fed88eaa04554fd21f9711dc60d0667
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3719edf22d551b9ff9d8dac8691b77123d2b3e3ecbf237742ed040d331f8ee81975d3bd3304edfc4122bcab4ec9869deeda8f51a81a1849fd481f1a88a9a5800
|
7
|
+
data.tar.gz: 644b5f81e4007e13770fce41c8cfb18f4b3a9f66320a99d0ff8364e1de837e7ab05928b7b34b075489e12adf303db08f378118b9dcfba91cc4b3171c284d9fd2
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Nialto Services
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class Fixnum
|
2
|
+
# Get the ordinal string of the integer value
|
3
|
+
def ordinal
|
4
|
+
abs_number = self.to_i.abs
|
5
|
+
|
6
|
+
if (11..13).include?(abs_number % 100)
|
7
|
+
"th"
|
8
|
+
else
|
9
|
+
case abs_number % 10
|
10
|
+
when 1; "st"
|
11
|
+
when 2; "nd"
|
12
|
+
when 3; "rd"
|
13
|
+
else "th"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the ordinal string prefixed with the integer value
|
19
|
+
def ordinalize
|
20
|
+
"#{self}#{self.ordinal}"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Check binaries before performing tasks
|
2
|
+
before "db:backup", "binaries:check"
|
3
|
+
before "db:create", "binaries:check"
|
4
|
+
before "db:list_backups", "binaries:check"
|
5
|
+
before "db:pull", "binaries:check"
|
6
|
+
before "db:push", "binaries:check"
|
7
|
+
before "db:reset", "binaries:check"
|
8
|
+
before "db:restore", "binaries:check"
|
9
|
+
before "deploy", "binaries:check"
|
10
|
+
before "htaccess:pull", "binaries:check"
|
11
|
+
before "htaccess:push", "binaries:check"
|
12
|
+
before "uploads:pull", "binaries:check"
|
13
|
+
before "uploads:push", "binaries:check"
|
14
|
+
before "uploads:setperms", "binaries:check"
|
15
|
+
before "wp:core:download", "binaries:check"
|
16
|
+
before "wp:core:remove", "binaries:check"
|
17
|
+
|
18
|
+
# Check directories before performing tasks
|
19
|
+
before "config:generate", "deploy:check:directories"
|
20
|
+
before "db:backup", "deploy:check:directories"
|
21
|
+
before "db:create", "deploy:check:directories"
|
22
|
+
before "db:list_backups", "deploy:check:directories"
|
23
|
+
before "db:pull", "deploy:check:directories"
|
24
|
+
before "db:push", "deploy:check:directories"
|
25
|
+
before "db:reset", "deploy:check:directories"
|
26
|
+
before "db:restore", "deploy:check:directories"
|
27
|
+
before "deploy:shared_configs", "deploy:check:directories"
|
28
|
+
before "htaccess:pull", "deploy:check:directories"
|
29
|
+
before "htaccess:push", "deploy:check:directories"
|
30
|
+
before "robots:generate", "deploy:check:directories"
|
31
|
+
before "uploads:pull", "deploy:check:directories"
|
32
|
+
before "uploads:push", "deploy:check:directories"
|
33
|
+
|
34
|
+
# Check if maintenance mode should be enabled before pushing the database
|
35
|
+
before "db:push", "db:check_maintenance_enable"
|
36
|
+
|
37
|
+
# Create the MySQL database before pushing content to it
|
38
|
+
before "db:push", "db:create"
|
39
|
+
|
40
|
+
# Backup the database before pushing
|
41
|
+
before "db:push", "db:backup"
|
42
|
+
|
43
|
+
# Check if maintenance mode should be enabled before restoring the database
|
44
|
+
before "db:restore", "db:check_maintenance_enable"
|
45
|
+
|
46
|
+
# Create the database before restoring
|
47
|
+
before "db:restore", "db:create"
|
48
|
+
|
49
|
+
# Deploy shared configuration files before deploying
|
50
|
+
before "deploy", "deploy:shared_configs"
|
51
|
+
|
52
|
+
# Move the database backup from the release we rolled away from
|
53
|
+
# into the release's root before it's archived
|
54
|
+
before "deploy:cleanup_rollback", "db:cleanup_rollback_database"
|
55
|
+
|
56
|
+
# Load the local WordPress version so that when downloading the
|
57
|
+
# WordPress core on a remote server, the version matches the local installation.
|
58
|
+
before "deploy:updated", "wp:core:load_local_version"
|
59
|
+
|
60
|
+
# Remove the existing WordPress core before downloading a new one
|
61
|
+
before "wp:core:download", "wp:core:remove"
|
62
|
+
|
63
|
+
# Download the WordPress core files before finishing deploy:updated
|
64
|
+
before "deploy:updated", "wp:core:download"
|
65
|
+
|
66
|
+
# Link the release into the website root
|
67
|
+
after "deploy:finished", "webroot:symlink"
|
68
|
+
|
69
|
+
# Touch the release directory after deploying
|
70
|
+
# This is required as after the first deployment, we enable
|
71
|
+
# maintenance mode for every subsequent deployment. This causes
|
72
|
+
# the previous release directory to have a newer timestamp than
|
73
|
+
# the new release directory which leads to issues with the rollback
|
74
|
+
# feature as the releases directory is sorted by modification time
|
75
|
+
# when capistrano looks for the release to rollback to.
|
76
|
+
after "deploy:finishing", "deploy:touch_release"
|
77
|
+
|
78
|
+
# Set permissions on the resources after deploying them
|
79
|
+
after "config:generate", "config:setperms"
|
80
|
+
after "htaccess:push", "htaccess:setperms"
|
81
|
+
after "robots:generate", "robots:setperms"
|
82
|
+
after "uploads:push", "uploads:setperms"
|
83
|
+
after "deploy:finished", "webroot:setperms"
|
84
|
+
|
85
|
+
# Check if maintenance mode should be disabled after pushing the database
|
86
|
+
after "db:push", "db:check_maintenance_disable"
|
87
|
+
|
88
|
+
# Check if maintenance mode should be disabled after restoring the database
|
89
|
+
after "db:restore", "db:check_maintenance_disable"
|
90
|
+
|
91
|
+
# Push the local resources after finishing deploy:updated
|
92
|
+
after "deploy:reverted", "db:rollback"
|
93
|
+
after "deploy:updated", "htaccess:push"
|
94
|
+
after "deploy:updated", "uploads:push"
|
95
|
+
after "deploy:updated", "db:push" # We want this to happen last so leave it here :)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
namespace :binaries do
|
2
|
+
desc "Check that all required binaries are installed"
|
3
|
+
task :check do
|
4
|
+
next if true == fetch(:checked_binaries)
|
5
|
+
|
6
|
+
required_binaries = {
|
7
|
+
local: [:php, :rm, :rsync, :wp],
|
8
|
+
remote: {
|
9
|
+
:all => [:chmod, :find, :rm, :wp],
|
10
|
+
:app => [:ln, :readlink, :rsync],
|
11
|
+
:db => [:du, :grep, :mysqlshow]
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
run_locally do
|
16
|
+
required_binaries[:local].each do |binary|
|
17
|
+
unless test :which, binary
|
18
|
+
abort "The binary '#{binary}' is missing from the local system"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
required_binaries[:remote].each do |role, binaries|
|
24
|
+
on roles(role) do |server|
|
25
|
+
binaries.each do |binary|
|
26
|
+
unless test :which, binary
|
27
|
+
abort "The binary '#{binary}' is missing from #{server.user}@#{server.hostname}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
set :checked_binaries, true
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
namespace :config do
|
2
|
+
desc "Generate a wp-config.php file"
|
3
|
+
task :generate do
|
4
|
+
file = "wp-config.php"
|
5
|
+
|
6
|
+
local_path = File.join(Dir.pwd, file)
|
7
|
+
remote_path = File.join(shared_path, file)
|
8
|
+
|
9
|
+
template_path = File.join("config", "templates", "#{file}.erb")
|
10
|
+
template_content = File.read(template_path)
|
11
|
+
|
12
|
+
run_locally do
|
13
|
+
database_config = fetch(:local_database_config)
|
14
|
+
|
15
|
+
unless database_config.has_keys? :hostname, :username, :database, :password
|
16
|
+
abort "The local database configuration is invalid"
|
17
|
+
end
|
18
|
+
|
19
|
+
database_hostname = database_config[:hostname]
|
20
|
+
database_username = database_config[:username]
|
21
|
+
database_name = database_config[:database]
|
22
|
+
database_password = database_config[:password]
|
23
|
+
|
24
|
+
secret_keys = Net::HTTP.get URI("https://api.wordpress.org/secret-key/1.1/salt")
|
25
|
+
|
26
|
+
if secret_keys.nil? or secret_keys.empty?
|
27
|
+
abort "Unable to fetch secret keys using the WordPress API"
|
28
|
+
end
|
29
|
+
|
30
|
+
configuration = ERB.new(template_content).result(binding)
|
31
|
+
|
32
|
+
if test("[ -f #{local_path} ]")
|
33
|
+
execute :rm, "-f", local_path
|
34
|
+
end
|
35
|
+
|
36
|
+
info "Writing local #{file} file"
|
37
|
+
|
38
|
+
File.write(local_path, configuration)
|
39
|
+
end
|
40
|
+
|
41
|
+
database_config = fetch(:database_config)
|
42
|
+
|
43
|
+
unless database_config.has_keys? :hostname, :username, :database, :password
|
44
|
+
abort "The #{fetch(:stage)} database configuration is invalid"
|
45
|
+
end
|
46
|
+
|
47
|
+
database_hostname = database_config[:hostname]
|
48
|
+
database_username = database_config[:username]
|
49
|
+
database_name = database_config[:database]
|
50
|
+
database_password = database_config[:password]
|
51
|
+
|
52
|
+
secret_keys = Net::HTTP.get URI("https://api.wordpress.org/secret-key/1.1/salt")
|
53
|
+
|
54
|
+
if secret_keys.nil? or secret_keys.empty?
|
55
|
+
abort "Unable to fetch secret keys using the WordPress API"
|
56
|
+
end
|
57
|
+
|
58
|
+
configuration = ERB.new(template_content).result(binding)
|
59
|
+
|
60
|
+
on roles(:app) do |server|
|
61
|
+
if test("[ -f #{remote_path} ]")
|
62
|
+
execute :rm, "-f", remote_path
|
63
|
+
end
|
64
|
+
|
65
|
+
upload! StringIO.new(configuration), remote_path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "Set permissions on the wp-config.php file"
|
70
|
+
task :setperms do
|
71
|
+
on roles(:app) do |server|
|
72
|
+
file = "wp-config.php"
|
73
|
+
|
74
|
+
remote_path = File.join(shared_path, file)
|
75
|
+
|
76
|
+
unless test("[ -f #{remote_path} ]")
|
77
|
+
error "A #{file} file does not exist on #{server.user}@#{server.hostname}"
|
78
|
+
end
|
79
|
+
|
80
|
+
info "Setting permissions for #{file} on #{server.user}@#{server.hostname}"
|
81
|
+
|
82
|
+
execute :chmod, 644, remote_path
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
namespace :db do
|
2
|
+
desc "Pull down the WordPress database"
|
3
|
+
task :pull do
|
4
|
+
file = "#{SecureRandom.hex(8)}.sql"
|
5
|
+
|
6
|
+
local_path = File.join(Dir.pwd, file)
|
7
|
+
remote_path = File.join(fetch(:tmp_dir), file)
|
8
|
+
|
9
|
+
next if 0 == roles(:db).count
|
10
|
+
|
11
|
+
if 1 < roles(:db).count
|
12
|
+
run_locally do
|
13
|
+
info "Found #{roles(:db).count} database servers"
|
14
|
+
|
15
|
+
roles(:db).each_with_index do |server, index|
|
16
|
+
info "#{index + 1}) #{server.user}@#{server.hostname} (Port #{server.port or 22})"
|
17
|
+
end
|
18
|
+
|
19
|
+
set :database_pull_server, ask("the number of the server to pull the database from", "1")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
set :database_pull_server, "1"
|
23
|
+
end
|
24
|
+
|
25
|
+
database_pull_server = fetch(:database_pull_server).to_i
|
26
|
+
|
27
|
+
if 1 > database_pull_server or roles(:db).count < database_pull_server
|
28
|
+
run_locally do
|
29
|
+
error "Unable to locate a server with an id '#{database_pull_server}'"
|
30
|
+
end
|
31
|
+
|
32
|
+
next
|
33
|
+
end
|
34
|
+
|
35
|
+
database_pull_server = roles(:db)[database_pull_server - 1]
|
36
|
+
|
37
|
+
on roles(:db) do |server|
|
38
|
+
next unless server.matches? database_pull_server
|
39
|
+
|
40
|
+
info "Pulling WordPress database from #{server.user}@#{server.hostname}"
|
41
|
+
|
42
|
+
within release_path do
|
43
|
+
execute :wp, "db", "export", remote_path
|
44
|
+
end
|
45
|
+
|
46
|
+
download! remote_path, local_path
|
47
|
+
|
48
|
+
execute :rm, "-f", remote_path
|
49
|
+
|
50
|
+
run_locally do
|
51
|
+
execute :wp, "db", "import", local_path
|
52
|
+
execute :rm, "-f", local_path
|
53
|
+
|
54
|
+
if fetch(:local_site_url) and fetch(:site_url)
|
55
|
+
execute :wp, "search-replace", fetch(:site_url), fetch(:local_site_url)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
set :database_pull_server, nil
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Push up the WordPress database"
|
64
|
+
task :push do
|
65
|
+
file = "#{SecureRandom.hex(8)}.sql"
|
66
|
+
|
67
|
+
local_path = File.join(Dir.pwd, file)
|
68
|
+
remote_path = File.join(fetch(:tmp_dir), file)
|
69
|
+
|
70
|
+
on roles(:db) do |server|
|
71
|
+
info "Pushing WordPress database to #{server.user}@#{server.hostname}"
|
72
|
+
|
73
|
+
run_locally do
|
74
|
+
execute :wp, "db", "export", local_path
|
75
|
+
end
|
76
|
+
|
77
|
+
upload! local_path, remote_path
|
78
|
+
|
79
|
+
run_locally do
|
80
|
+
execute :rm, "-f", local_path
|
81
|
+
end
|
82
|
+
|
83
|
+
within release_path do
|
84
|
+
execute :wp, "db", "import", remote_path
|
85
|
+
execute :rm, "-f", remote_path
|
86
|
+
|
87
|
+
if fetch(:local_site_url) and fetch(:site_url)
|
88
|
+
execute :wp, "search-replace", fetch(:local_site_url), fetch(:site_url)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "Create the MySQL database"
|
95
|
+
task :create do
|
96
|
+
database_config = fetch(:database_config)
|
97
|
+
|
98
|
+
unless database_config.has_keys? :hostname, :username, :database, :password
|
99
|
+
abort "The #{fetch(:stage)} database configuration is invalid"
|
100
|
+
end
|
101
|
+
|
102
|
+
database_name = database_config[:database]
|
103
|
+
database_hostname = database_config[:hostname]
|
104
|
+
database_username = database_config[:username]
|
105
|
+
database_password = database_config[:password]
|
106
|
+
|
107
|
+
on roles(:db) do |server|
|
108
|
+
within release_path do
|
109
|
+
if test("[ \"#{database_name}\" == $(mysqlshow --user=\"#{database_username}\" --password=\"#{database_password}\" #{database_name} | grep -v Wildcard | grep -o #{database_name}) ]")
|
110
|
+
info "The MySQL database already exists on #{server.user}@#{server.hostname}"
|
111
|
+
|
112
|
+
next
|
113
|
+
end
|
114
|
+
|
115
|
+
info "Creating MySQL database on #{server.user}@#{server.hostname}"
|
116
|
+
|
117
|
+
execute :wp, "db", "create"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
desc "Drop the MySQL database"
|
123
|
+
task :drop do
|
124
|
+
database_config = fetch(:database_config)
|
125
|
+
|
126
|
+
unless database_config.has_keys? :hostname, :username, :database, :password
|
127
|
+
abort "The #{fetch(:stage)} database configuration is invalid"
|
128
|
+
end
|
129
|
+
|
130
|
+
database_name = database_config[:database]
|
131
|
+
database_hostname = database_config[:hostname]
|
132
|
+
database_username = database_config[:username]
|
133
|
+
database_password = database_config[:password]
|
134
|
+
|
135
|
+
on roles(:db) do |server|
|
136
|
+
within release_path do
|
137
|
+
unless test("[ \"#{database_name}\" == $(mysqlshow --user=\"#{database_username}\" --password=\"#{database_password}\" #{database_name} | grep -v Wildcard | grep -o #{database_name}) ]")
|
138
|
+
info "The MySQL database does not exist on #{server.user}@#{server.hostname}"
|
139
|
+
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
info "Deleting MySQL database on #{server.user}@#{server.hostname}"
|
144
|
+
|
145
|
+
execute :wp, "db", "drop", "--yes"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
desc "Reset the MySQL database"
|
151
|
+
task :reset do
|
152
|
+
on roles(:db) do |server|
|
153
|
+
within release_path do
|
154
|
+
unless test :wp, "core", "is-installed"
|
155
|
+
info "The WordPress database does not appear to be installed on #{server.user}@#{server.hostname}"
|
156
|
+
|
157
|
+
next
|
158
|
+
end
|
159
|
+
|
160
|
+
info "Resetting the WordPress database on #{server.user}@#{server.hostname}"
|
161
|
+
|
162
|
+
execute :wp, "db", "reset", "--yes"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
desc "Create a backup of the WordPress database"
|
168
|
+
task :backup do
|
169
|
+
backups_directory = File.join(fetch(:deploy_to), "backups", "database")
|
170
|
+
|
171
|
+
on roles(:db) do |server|
|
172
|
+
next unless test("[ -d #{current_path} ]")
|
173
|
+
|
174
|
+
actual_current_path = capture("readlink -f #{current_path}").strip
|
175
|
+
|
176
|
+
file = File.basename(actual_current_path)
|
177
|
+
file = "#{file}.sql"
|
178
|
+
|
179
|
+
remote_path = File.join(backups_directory, file)
|
180
|
+
|
181
|
+
info "Backing up WordPress database on #{server.user}@#{server.hostname}"
|
182
|
+
|
183
|
+
execute :mkdir, "-p", backups_directory
|
184
|
+
|
185
|
+
if test("[ -f #{remote_path} ]")
|
186
|
+
execute :rm, "-f", remote_path
|
187
|
+
end
|
188
|
+
|
189
|
+
within release_path do
|
190
|
+
execute :wp, "db", "export", remote_path
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
desc "Restore a backup of the WordPress database"
|
196
|
+
task :restore do
|
197
|
+
backups_directory = File.join(fetch(:deploy_to), "backups", "database")
|
198
|
+
|
199
|
+
backup_id = fetch(:rollback_timestamp, ENV["id"])
|
200
|
+
|
201
|
+
unless backup_id
|
202
|
+
run_locally do
|
203
|
+
info "No backup id provided to restore database backup"
|
204
|
+
end
|
205
|
+
|
206
|
+
next
|
207
|
+
end
|
208
|
+
|
209
|
+
on roles(:db) do |server|
|
210
|
+
file = "#{backup_id}.sql"
|
211
|
+
|
212
|
+
remote_path = File.join(backups_directory, file)
|
213
|
+
|
214
|
+
unless test("[ -f #{remote_path} ]")
|
215
|
+
info "Could not find database backup #{backup_id} on #{server.user}@#{server.hostname}"
|
216
|
+
|
217
|
+
next
|
218
|
+
end
|
219
|
+
|
220
|
+
info "Restoring WordPress database #{backup_id} on #{server.user}@#{server.hostname}"
|
221
|
+
|
222
|
+
within release_path do
|
223
|
+
execute :wp, "db", "import", remote_path
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
desc "List all WordPress database backups"
|
229
|
+
task :list_backups do
|
230
|
+
on roles(:db) do |server|
|
231
|
+
next unless server.matches? roles(:db).first # Hack to make sure we run only once
|
232
|
+
|
233
|
+
backups_directory = File.join(fetch(:deploy_to), "backups", "database")
|
234
|
+
|
235
|
+
unless test("[ -d #{backups_directory} ]")
|
236
|
+
info "No database backups found"
|
237
|
+
|
238
|
+
next
|
239
|
+
end
|
240
|
+
|
241
|
+
backup_paths = capture("find #{backups_directory} -name '*.sql' -maxdepth 1")
|
242
|
+
|
243
|
+
if backup_paths.nil? or backup_paths.empty?
|
244
|
+
info "No database backups found"
|
245
|
+
|
246
|
+
next
|
247
|
+
end
|
248
|
+
|
249
|
+
if 1 == backup_paths.lines.count
|
250
|
+
info "Found 1 database backup"
|
251
|
+
else
|
252
|
+
info "Found #{backup_paths.lines.count} database backups"
|
253
|
+
end
|
254
|
+
|
255
|
+
backup_paths.each_line do |backup_path|
|
256
|
+
backup_path = backup_path.strip
|
257
|
+
|
258
|
+
backup_basename = File.basename(backup_path).gsub(".sql", "").strip
|
259
|
+
|
260
|
+
backup_time = Time.parse(backup_basename)
|
261
|
+
backup_time = backup_time.strftime("%A #{backup_time.day.ordinalize} %B %Y at %H:%M:%S")
|
262
|
+
|
263
|
+
backup_size = capture("du -h #{backup_path} | awk '{ print \$1 }'")
|
264
|
+
|
265
|
+
info "#{backup_time} - #{backup_size} (ID: #{backup_basename})"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Rollback the WordPress database
|
271
|
+
# This is only useful when called during a deploy:rollback task
|
272
|
+
task :rollback do
|
273
|
+
actual_current_path = nil
|
274
|
+
actual_release_path = nil
|
275
|
+
|
276
|
+
on roles(:db) do |server|
|
277
|
+
next unless server.matches? roles(:db).first # Hack to make sure we run only once
|
278
|
+
|
279
|
+
actual_current_path = capture("readlink -f #{current_path}").strip
|
280
|
+
actual_release_path = capture("readlink -f #{release_path}").strip
|
281
|
+
end
|
282
|
+
|
283
|
+
if actual_current_path == actual_release_path
|
284
|
+
run_locally do
|
285
|
+
error "This task is only useful when called during a deploy:rollback task!"
|
286
|
+
end
|
287
|
+
|
288
|
+
next
|
289
|
+
end
|
290
|
+
|
291
|
+
invoke 'db:backup'
|
292
|
+
invoke 'db:restore'
|
293
|
+
|
294
|
+
set :rollback_from_timestamp, File.basename(actual_current_path)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Move the database backup from the release we rolled away from
|
298
|
+
# into the release's root before it's archived
|
299
|
+
task :cleanup_rollback_database do
|
300
|
+
rollback_from_timestamp = fetch(:rollback_from_timestamp)
|
301
|
+
|
302
|
+
unless :rollback_from_timestamp
|
303
|
+
run_locally do
|
304
|
+
error "No timestamp set for the release we rolled away from"
|
305
|
+
end
|
306
|
+
|
307
|
+
next
|
308
|
+
end
|
309
|
+
|
310
|
+
file = "#{rollback_from_timestamp}.sql"
|
311
|
+
|
312
|
+
backups_directory = File.join(fetch(:deploy_to), "backups", "database")
|
313
|
+
|
314
|
+
source_path = File.join(backups_directory, file)
|
315
|
+
destination_path = File.join(releases_path, rollback_from_timestamp, file)
|
316
|
+
|
317
|
+
on roles(:db) do |server|
|
318
|
+
unless test("[ -f #{source_path} ]")
|
319
|
+
error "The database backup file does not exist on #{server.user}@#{server.hostname}"
|
320
|
+
|
321
|
+
next
|
322
|
+
end
|
323
|
+
|
324
|
+
info "Moving database backup #{rollback_from_timestamp} into release on #{server.user}@#{server.hostname}"
|
325
|
+
|
326
|
+
execute :mv, source_path, destination_path
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# Enable maintenance mode if WordPress is already installed (used by db:push)
|
331
|
+
task :check_maintenance_enable do
|
332
|
+
maintenance_path = File.join(current_path, ".maintenance")
|
333
|
+
|
334
|
+
on roles(:db) do
|
335
|
+
next unless test("[ -d #{current_path} ]")
|
336
|
+
next if test("[ -f #{maintenance_path} ]")
|
337
|
+
next if true == fetch(:db_enabled_maintenance_mode)
|
338
|
+
|
339
|
+
within current_path do
|
340
|
+
if test :wp, "core", "is-installed"
|
341
|
+
set :db_enabled_maintenance_mode, true
|
342
|
+
|
343
|
+
invoke 'maintenance:enable'
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
# Disable maintenance mode if it was enabled by check_maintenance_enable
|
350
|
+
task :check_maintenance_disable do
|
351
|
+
next unless true == fetch(:db_enabled_maintenance_mode)
|
352
|
+
|
353
|
+
invoke 'maintenance:disable'
|
354
|
+
end
|
355
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
namespace :deploy do
|
2
|
+
task :shared_configs do
|
3
|
+
config_path = File.join(shared_path, "wp-config.php")
|
4
|
+
robots_path = File.join(shared_path, "robots.txt")
|
5
|
+
|
6
|
+
on roles(:app) do
|
7
|
+
unless test("[ -f #{config_path} ]")
|
8
|
+
invoke "config:generate"
|
9
|
+
end
|
10
|
+
|
11
|
+
unless test("[ -f #{robots_path} ]")
|
12
|
+
invoke "robots:generate"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
task :touch_release do
|
18
|
+
on roles(:app) do |server|
|
19
|
+
info "Touching release directory on #{server.user}@#{server.hostname}"
|
20
|
+
|
21
|
+
execute :touch, release_path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
namespace :htaccess do
|
2
|
+
desc "Pull down the .htaccess file"
|
3
|
+
task :pull do
|
4
|
+
file = ".htaccess"
|
5
|
+
|
6
|
+
remote_file = File.join(release_path, file)
|
7
|
+
|
8
|
+
next if 0 == roles(:app).count
|
9
|
+
|
10
|
+
if 1 < roles(:app).count
|
11
|
+
run_locally do
|
12
|
+
info "Found #{roles(:app).count} application servers"
|
13
|
+
|
14
|
+
roles(:app).each_with_index do |server, index|
|
15
|
+
info "#{index + 1}) #{server.user}@#{server.hostname} (Port #{server.port or 22})"
|
16
|
+
end
|
17
|
+
|
18
|
+
set :htaccess_pull_server, ask("the number of the server to pull the #{file} file from", "1")
|
19
|
+
end
|
20
|
+
else
|
21
|
+
set :htaccess_pull_server, "1"
|
22
|
+
end
|
23
|
+
|
24
|
+
htaccess_pull_server = fetch(:htaccess_pull_server).to_i
|
25
|
+
|
26
|
+
if 1 > htaccess_pull_server or roles(:app).count < htaccess_pull_server
|
27
|
+
run_locally do
|
28
|
+
error "Unable to locate a server with an id '#{htaccess_pull_server}'"
|
29
|
+
end
|
30
|
+
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
htaccess_pull_server = roles(:app)[htaccess_pull_server - 1]
|
35
|
+
|
36
|
+
on roles(:app) do |server|
|
37
|
+
next unless server.matches? htaccess_pull_server
|
38
|
+
|
39
|
+
unless test("[ -f #{remote_file} ]")
|
40
|
+
error "There isn't a #{file} file on #{server.user}@#{server.hostname}"
|
41
|
+
|
42
|
+
next
|
43
|
+
end
|
44
|
+
|
45
|
+
if File.file? file
|
46
|
+
local_sha256sum = Digest::SHA256.hexdigest(File.read(file))
|
47
|
+
remote_sha256sum = capture("sha256sum #{remote_file}").split(' ').first
|
48
|
+
|
49
|
+
if local_sha256sum == remote_sha256sum
|
50
|
+
info "No changes detected in #{file} file on #{server.user}@#{server.hostname}"
|
51
|
+
|
52
|
+
next
|
53
|
+
end
|
54
|
+
|
55
|
+
unless fetch(:confirm_pull_htaccess)
|
56
|
+
set :confirm_pull_htaccess, ask("confirmation for local #{file} file overwrite", "Y/n")
|
57
|
+
end
|
58
|
+
|
59
|
+
next unless [true, "y", "yes"].include? fetch(:confirm_pull_htaccess).downcase
|
60
|
+
end
|
61
|
+
|
62
|
+
info "Pulling #{file} file from #{server.user}@#{server.hostname}"
|
63
|
+
|
64
|
+
download! remote_file, file
|
65
|
+
|
66
|
+
break
|
67
|
+
end
|
68
|
+
|
69
|
+
set :htaccess_pull_server, nil
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Push up the .htaccess file"
|
73
|
+
task :push do
|
74
|
+
file = ".htaccess"
|
75
|
+
|
76
|
+
local_path = File.join(Dir.pwd, file)
|
77
|
+
remote_path = File.join(release_path, file)
|
78
|
+
|
79
|
+
unless File.file? file
|
80
|
+
run_locally do
|
81
|
+
htaccess = "# BEGIN WordPress\n"
|
82
|
+
htaccess << "<IfModule mod_rewrite.c>\n"
|
83
|
+
htaccess << "RewriteEngine On\n"
|
84
|
+
htaccess << "RewriteBase /\n"
|
85
|
+
htaccess << "RewriteRule ^index\.php$ - [L]\n"
|
86
|
+
htaccess << "RewriteCond %{REQUEST_FILENAME} !-f\n"
|
87
|
+
htaccess << "RewriteCond %{REQUEST_FILENAME} !-d\n"
|
88
|
+
htaccess << "RewriteRule . /index.php [L]\n"
|
89
|
+
htaccess << "</IfModule>\n"
|
90
|
+
htaccess << "# END WordPress\n"
|
91
|
+
|
92
|
+
File.write(local_path, htaccess)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
on roles(:app) do |server|
|
97
|
+
if test("[ -f #{remote_path} ]")
|
98
|
+
local_sha256sum = Digest::SHA256.hexdigest(File.read(local_path))
|
99
|
+
remote_sha256sum = capture("sha256sum #{remote_path}").split(' ').first
|
100
|
+
|
101
|
+
if local_sha256sum == remote_sha256sum
|
102
|
+
info "No changes detected in #{file} on #{server.user}@#{server.hostname}"
|
103
|
+
|
104
|
+
next
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
info "Pushing #{file} file to #{server.user}@#{server.hostname}"
|
109
|
+
|
110
|
+
upload! local_path, remote_path
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Set permissions on the .htaccess file"
|
115
|
+
task :setperms do
|
116
|
+
file = ".htaccess"
|
117
|
+
|
118
|
+
remote_path = File.join(release_path, file)
|
119
|
+
|
120
|
+
on roles(:app) do |server|
|
121
|
+
unless test("[ -f #{remote_path} ]")
|
122
|
+
info "No #{file} file found on #{server.user}@#{server.hostname}"
|
123
|
+
|
124
|
+
next
|
125
|
+
end
|
126
|
+
|
127
|
+
info "Setting permissions for #{file} on #{server.user}@#{server.hostname}"
|
128
|
+
|
129
|
+
execute :chmod, 644, remote_path
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
namespace :maintenance do
|
2
|
+
desc "Enable maintenance mode on the WordPress site"
|
3
|
+
task :enable do
|
4
|
+
file = ".maintenance"
|
5
|
+
|
6
|
+
on roles(:app) do |server|
|
7
|
+
actual_current_path = capture("readlink -f #{current_path}").strip
|
8
|
+
|
9
|
+
remote_path = File.join(actual_current_path, file)
|
10
|
+
|
11
|
+
if test("[ -f #{remote_path} ]")
|
12
|
+
info "Maintenance mode is already enabled on #{server.user}@#{server.hostname}"
|
13
|
+
|
14
|
+
next
|
15
|
+
end
|
16
|
+
|
17
|
+
maintenance_info = fetch(:maintenance_info, {
|
18
|
+
title: "Maintenance",
|
19
|
+
header: "This site is currently undergoing maintenance.",
|
20
|
+
body: "Please check back in a moment."
|
21
|
+
})
|
22
|
+
|
23
|
+
file_content = "<?php header('HTTP/1.1 503 Service Unavailable'); ?>\n"
|
24
|
+
file_content << "<?php header('Content-Type: text/html'); ?>\n"
|
25
|
+
file_content << "<!DOCTYPE html>\n"
|
26
|
+
file_content << "<html>\n"
|
27
|
+
file_content << " <head>\n"
|
28
|
+
file_content << " <meta charset=\"utf-8\">\n"
|
29
|
+
file_content << " <meta name=\"viewport\" content=\"initial-scale=1.0\">\n"
|
30
|
+
file_content << " <title>#{maintenance_info[:title]}</title>\n" if maintenance_info.has_key? :title
|
31
|
+
file_content << " </head>\n"
|
32
|
+
file_content << " <body class=\"body\">\n"
|
33
|
+
file_content << " <h1>#{maintenance_info[:header]}</h1>\n" if maintenance_info.has_key? :header
|
34
|
+
file_content << " <h3>#{maintenance_info[:subheader]}</h3>\n" if maintenance_info.has_key? :subheader
|
35
|
+
file_content << " <p>#{maintenance_info[:body]}</p>\n" if maintenance_info.has_key? :body
|
36
|
+
file_content << " </body>\n"
|
37
|
+
file_content << "</html>\n"
|
38
|
+
file_content << "<?php exit; ?>\n"
|
39
|
+
|
40
|
+
info "Enabling WordPress maintenance mode on #{server.user}@#{server.hostname}"
|
41
|
+
|
42
|
+
upload! StringIO.new(file_content), remote_path
|
43
|
+
|
44
|
+
execute :chmod, 644, remote_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Disable maintenance mode on the WordPress site"
|
49
|
+
task :disable do
|
50
|
+
file = ".maintenance"
|
51
|
+
|
52
|
+
on roles(:app) do |server|
|
53
|
+
actual_current_path = capture("readlink -f #{current_path}").strip
|
54
|
+
|
55
|
+
remote_path = File.join(actual_current_path, file)
|
56
|
+
|
57
|
+
unless test("[ -f #{remote_path} ]")
|
58
|
+
info "Maintenance mode is not enabled on #{server.user}@#{server.hostname}"
|
59
|
+
|
60
|
+
next
|
61
|
+
end
|
62
|
+
|
63
|
+
info "Disabling WordPress maintenance mode on #{server.user}@#{server.hostname}"
|
64
|
+
|
65
|
+
execute :rm, "-f", remote_path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
namespace :robots do
|
2
|
+
desc "Generate a robots.txt file"
|
3
|
+
task :generate do
|
4
|
+
file = "robots.txt"
|
5
|
+
|
6
|
+
remote_path = File.join(shared_path, file)
|
7
|
+
|
8
|
+
on roles(:app) do |server|
|
9
|
+
info "Generating a #{file} file on #{server.user}@#{server.hostname}"
|
10
|
+
|
11
|
+
if :production != fetch(:stage)
|
12
|
+
debug "Disallowing all user agents in #{file} on #{server.user}@#{server.hostname}"
|
13
|
+
|
14
|
+
upload! StringIO.new("User-agent: *\nDisallow: /"), remote_path
|
15
|
+
else
|
16
|
+
upload! StringIO.new, remote_path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Set permissions on the robots.txt file"
|
22
|
+
task :setperms do
|
23
|
+
file = "robots.txt"
|
24
|
+
|
25
|
+
remote_path = File.join(shared_path, file)
|
26
|
+
|
27
|
+
on roles(:app) do |server|
|
28
|
+
unless test("[ -f #{remote_path} ]")
|
29
|
+
error "A #{file} file does not exist on #{server.user}@#{server.hostname}"
|
30
|
+
end
|
31
|
+
|
32
|
+
info "Setting permissions for #{file} on #{server.user}@#{server.hostname}"
|
33
|
+
|
34
|
+
execute :chmod, 644, remote_path
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
namespace :uploads do
|
2
|
+
desc "Pull down the uploads directory"
|
3
|
+
task :pull do
|
4
|
+
directory = File.join("wp-content", "uploads")
|
5
|
+
|
6
|
+
local_path = File.join(Dir.pwd, directory)
|
7
|
+
remote_path = File.join(release_path, directory)
|
8
|
+
|
9
|
+
next if 0 == roles(:app).count
|
10
|
+
|
11
|
+
if 1 < roles(:app).count
|
12
|
+
run_locally do
|
13
|
+
info "Found #{roles(:app).count} application servers"
|
14
|
+
|
15
|
+
roles(:app).each_with_index do |server, index|
|
16
|
+
info "#{index + 1}) #{server.user}@#{server.hostname} (Port #{server.port or 22})"
|
17
|
+
end
|
18
|
+
|
19
|
+
set :uploads_pull_server, ask("the number of the server to pull the #{directory} directory from", "1")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
set :uploads_pull_server, "1"
|
23
|
+
end
|
24
|
+
|
25
|
+
uploads_pull_server = fetch(:uploads_pull_server).to_i
|
26
|
+
|
27
|
+
if 1 > uploads_pull_server or roles(:app).count < uploads_pull_server
|
28
|
+
run_locally do
|
29
|
+
error "Unable to locate a server with an id '#{uploads_pull_server}'"
|
30
|
+
end
|
31
|
+
|
32
|
+
next
|
33
|
+
end
|
34
|
+
|
35
|
+
uploads_pull_server = roles(:app)[uploads_pull_server - 1]
|
36
|
+
|
37
|
+
on roles(:app) do |server|
|
38
|
+
next unless server.matches? uploads_pull_server
|
39
|
+
|
40
|
+
unless test("[ -d #{remote_path} ]")
|
41
|
+
error "There isn't a #{directory} directory on #{server.user}@#{server.hostname}"
|
42
|
+
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
run_locally do
|
47
|
+
execute :mkdir, "-p", local_path
|
48
|
+
end
|
49
|
+
|
50
|
+
info "Pulling #{directory} directory from #{server.user}@#{server.hostname}"
|
51
|
+
|
52
|
+
# Fix for rsync
|
53
|
+
remote_path += "/"
|
54
|
+
|
55
|
+
run_locally do
|
56
|
+
execute :rsync, "-lrtvzO", "--delete-before", (server.port ? "-e 'ssh -p #{server.port}'" : nil), "#{server.user}@#{server.hostname}:#{remote_path}", local_path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
set :uploads_pull_server, nil
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Push up the uploads directory"
|
64
|
+
task :push do
|
65
|
+
directory = File.join("wp-content", "uploads")
|
66
|
+
|
67
|
+
local_path = File.join(Dir.pwd, directory)
|
68
|
+
remote_path = File.join(release_path, directory)
|
69
|
+
|
70
|
+
unless File.directory? local_path
|
71
|
+
error "No local uploads directory exists"
|
72
|
+
|
73
|
+
next
|
74
|
+
end
|
75
|
+
|
76
|
+
on roles(:app) do |server|
|
77
|
+
if test("[ -d #{current_path} ]") and (ENV["clone_uploads"].nil? or ENV["clone_uploads"].empty? or [true, "true", "yes", "y"].include? ENV["clone_uploads"].downcase)
|
78
|
+
actual_current_path = capture("readlink -f #{current_path}").strip
|
79
|
+
actual_release_path = capture("readlink -f #{release_path}").strip
|
80
|
+
|
81
|
+
previous_remote_path = File.join(actual_current_path, directory)
|
82
|
+
|
83
|
+
if actual_current_path != actual_release_path and test("[ -d #{previous_remote_path} ]")
|
84
|
+
debug "Cloning uploads directory from current release on #{server.user}@#{server.hostname}"
|
85
|
+
|
86
|
+
execute :cp, "-R", "--preserve=timestamps", previous_remote_path, remote_path
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
execute :mkdir, "-p", remote_path
|
91
|
+
|
92
|
+
info "Pushing #{directory} directory to #{server.user}@#{server.hostname}"
|
93
|
+
|
94
|
+
# Fix for rsync
|
95
|
+
local_path += "/"
|
96
|
+
|
97
|
+
run_locally do
|
98
|
+
execute :rsync, "-lrtvzO", "--delete-before", (server.port ? "-e 'ssh -p #{server.port}'" : nil), local_path, "#{server.user}@#{server.hostname}:#{remote_path}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "Set permissions on the uploads directory"
|
104
|
+
task :setperms do
|
105
|
+
directory = File.join("wp-content", "uploads")
|
106
|
+
|
107
|
+
remote_path = File.join(release_path, directory)
|
108
|
+
|
109
|
+
on roles(:app) do |server|
|
110
|
+
unless test("[ -d #{remote_path} ]")
|
111
|
+
error "No uploads directory exists on #{server.user}@#{server.hostname}"
|
112
|
+
|
113
|
+
next
|
114
|
+
end
|
115
|
+
|
116
|
+
info "Setting permissions for the uploads directory on #{server.user}@#{server.hostname}"
|
117
|
+
|
118
|
+
execute :find, remote_path, "-type d", "-exec", :chmod, 755, "{}", "\\;"
|
119
|
+
execute :find, remote_path, "-type f", "-exec", :chmod, 644, "{}", "\\;"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
namespace :webroot do
|
2
|
+
desc "Symlink the current release into the website root"
|
3
|
+
task :symlink do
|
4
|
+
remote_path = fetch(:website_root)
|
5
|
+
|
6
|
+
next unless remote_path
|
7
|
+
|
8
|
+
on roles(:app) do |server|
|
9
|
+
if test("[ -d #{remote_path} ]")
|
10
|
+
execute :rm, "-rf", remote_path
|
11
|
+
end
|
12
|
+
|
13
|
+
info "Symlinking the current release into the website root on #{server.user}@#{server.hostname}"
|
14
|
+
|
15
|
+
execute :ln, "-nfs", release_path, remote_path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Set permissions on the uploads directory"
|
20
|
+
task :setperms do
|
21
|
+
remote_path = fetch(:website_root)
|
22
|
+
|
23
|
+
next unless remote_path
|
24
|
+
|
25
|
+
on roles(:app) do |server|
|
26
|
+
unless test("[ -d #{remote_path} ]")
|
27
|
+
error "No website root directory exists on #{server.user}@#{server.hostname}"
|
28
|
+
|
29
|
+
next
|
30
|
+
end
|
31
|
+
|
32
|
+
info "Setting permissions for the website root directory on #{server.user}@#{server.hostname}"
|
33
|
+
|
34
|
+
execute :find, remote_path, "-type d", "-exec", :chmod, 755, "{}", "\\;"
|
35
|
+
execute :find, remote_path, "-type f", "-exec", :chmod, 644, "{}", "\\;"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
namespace :wp do
|
2
|
+
namespace :core do
|
3
|
+
# Load the local version (for use with wp:core:deploy)
|
4
|
+
task :load_local_version do
|
5
|
+
run_locally do
|
6
|
+
version_script_path = File.join(Dir.pwd, "wp-includes", "version.php")
|
7
|
+
|
8
|
+
unless File.file? version_script_path
|
9
|
+
abort "No valid WordPress installation could be found locally"
|
10
|
+
end
|
11
|
+
|
12
|
+
set :wp_version, capture("php -r \"include '#{version_script_path}'; echo \\$wp_version;\"")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Download the WordPress core files into the release"
|
17
|
+
task :download do
|
18
|
+
on roles(:app) do |server|
|
19
|
+
version = fetch(:wp_version, ENV["version"])
|
20
|
+
|
21
|
+
info "Downloading WordPress Core" + (version ? " (Version #{version})" : "")
|
22
|
+
|
23
|
+
tmp_dir = File.join(fetch(:tmp_dir), SecureRandom.hex(8))
|
24
|
+
|
25
|
+
execute :mkdir, "-p", tmp_dir
|
26
|
+
|
27
|
+
within tmp_dir do
|
28
|
+
execute :wp, "core", "download", (version ? "--version=#{version}" : "")
|
29
|
+
|
30
|
+
excludes = [".", "license.txt", "readme.html", "wp-config-sample.php", "wp-content"]
|
31
|
+
excludes = excludes.map { |e| "! -name '#{e}' " }.join(" ").squeeze(" ").strip
|
32
|
+
|
33
|
+
paths = capture :find, ".", "-maxdepth 1", excludes
|
34
|
+
paths = paths.split("\n")
|
35
|
+
paths.each do |path|
|
36
|
+
execute :cp, "-R", path, release_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
execute :rm, "-rf", tmp_dir
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Remove the WordPress core files from the release"
|
45
|
+
task :remove do
|
46
|
+
on roles(:app) do
|
47
|
+
within release_path do
|
48
|
+
paths = []
|
49
|
+
|
50
|
+
excludes = [".", "wp-config.php", "wp-content"]
|
51
|
+
excludes = excludes.map { |e| "! -name '#{e}' " }.join(" ").squeeze(" ").strip
|
52
|
+
|
53
|
+
["index.php", "wp-*", "xmlrpc.php"].each do |glob|
|
54
|
+
find_output = capture :find, ".", "-maxdepth 1", "-name '#{glob}'", excludes
|
55
|
+
|
56
|
+
paths.concat(find_output.split("\n"))
|
57
|
+
end
|
58
|
+
|
59
|
+
next if 1 > paths.length
|
60
|
+
|
61
|
+
info "Removing #{paths.length} WordPress core file(s)"
|
62
|
+
|
63
|
+
paths.each do |path|
|
64
|
+
execute :rm, "-rf", path
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Execute a WordPress CLI command"
|
72
|
+
task :exec do
|
73
|
+
set :wp_exec_command, ask("The WordPress CLI command to execute", "help")
|
74
|
+
|
75
|
+
unless fetch(:wp_exec_command)
|
76
|
+
abort "You didn't enter a command to execute"
|
77
|
+
end
|
78
|
+
|
79
|
+
on roles(:all) do |server|
|
80
|
+
next if ENV["role"] and !server.roles.map { |role| role.to_s }.include? ENV["role"]
|
81
|
+
|
82
|
+
within release_path do
|
83
|
+
puts capture :wp, fetch(:wp_exec_command)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
set :wp_exec_command, nil
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "securerandom"
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
# Load all helpers and capistrano tasks
|
6
|
+
["wordpress/helpers/**/*.rb", "wordpress/tasks/**/*.rake", "wordpress/hooks.rb"].each do |glob|
|
7
|
+
Dir.glob(File.expand_path(File.join('..', glob), __FILE__)).each do |file_path|
|
8
|
+
load file_path
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Tell capistrano about files we want linked into releases
|
13
|
+
set :linked_files, fetch(:linked_files, []).push("robots.txt", "wp-config.php")
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'capistrano/wordpress'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'wordpresstrano'
|
3
|
+
s.version = '0.2.0'
|
4
|
+
s.date = '2015-08-09'
|
5
|
+
s.authors = ['Nialto Services']
|
6
|
+
s.email = 'support@nialtoservices.co.uk'
|
7
|
+
s.summary = 'Deploy WordPress sites to web servers using Capistrano'
|
8
|
+
s.description = 'Deploy your WordPress sites to web servers like cPanel using the Capistrano deployment tool'
|
9
|
+
s.homepage = 'http://rubygems.org/gems/wordpresstrano'
|
10
|
+
s.files = `git ls-files`.split($/)
|
11
|
+
s.require_paths = ['lib']
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.required_ruby_version = '>= 2.0.0'
|
15
|
+
s.add_dependency 'capistrano', '~> 3.0', '>= 3.4.0'
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wordpresstrano
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nialto Services
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.4.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.4.0
|
33
|
+
description: Deploy your WordPress sites to web servers like cPanel using the Capistrano
|
34
|
+
deployment tool
|
35
|
+
email: support@nialtoservices.co.uk
|
36
|
+
executables: []
|
37
|
+
extensions: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
files:
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- lib/capistrano/wordpress.rb
|
43
|
+
- lib/capistrano/wordpress/helpers/fixnum.rb
|
44
|
+
- lib/capistrano/wordpress/helpers/hash.rb
|
45
|
+
- lib/capistrano/wordpress/hooks.rb
|
46
|
+
- lib/capistrano/wordpress/tasks/binaries.rake
|
47
|
+
- lib/capistrano/wordpress/tasks/config.rake
|
48
|
+
- lib/capistrano/wordpress/tasks/database.rake
|
49
|
+
- lib/capistrano/wordpress/tasks/deploy.rake
|
50
|
+
- lib/capistrano/wordpress/tasks/htaccess.rake
|
51
|
+
- lib/capistrano/wordpress/tasks/maintenance.rake
|
52
|
+
- lib/capistrano/wordpress/tasks/robots.rake
|
53
|
+
- lib/capistrano/wordpress/tasks/uploads.rake
|
54
|
+
- lib/capistrano/wordpress/tasks/webroot.rake
|
55
|
+
- lib/capistrano/wordpress/tasks/wordpress.rake
|
56
|
+
- lib/wordpresstrano.rb
|
57
|
+
- wordpresstrano.gemspec
|
58
|
+
homepage: http://rubygems.org/gems/wordpresstrano
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 2.0.0
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.4.8
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Deploy WordPress sites to web servers using Capistrano
|
82
|
+
test_files: []
|