wordpress-deploy 1.0.0.alpha1 → 1.0.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +26 -1
- data/.rspec +1 -0
- data/.rvmrc +48 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -5
- data/Gemfile.lock +40 -28
- data/Guardfile +24 -0
- data/README.md +22 -7
- data/bin/wp-deploy +1 -4
- data/lib/wordpress_deploy.rb +22 -48
- data/lib/wordpress_deploy/cli/helpers.rb +27 -14
- data/lib/wordpress_deploy/cli/utility.rb +86 -37
- data/lib/wordpress_deploy/database/mysql.rb +22 -136
- data/lib/wordpress_deploy/environment.rb +68 -0
- data/lib/wordpress_deploy/errors.rb +54 -0
- data/lib/wordpress_deploy/logger.rb +28 -50
- data/lib/wordpress_deploy/transfer_protocols/ftp.rb +305 -0
- data/lib/wordpress_deploy/version.rb +1 -1
- data/lib/wordpress_deploy/wordpress/configuration.rb +196 -0
- data/spec/data/ftp.yml +4 -0
- data/spec/data/wp-config-sample.php +90 -0
- data/spec/data/wp-config.yml +128 -0
- data/spec/database/mysql_spec.rb +93 -0
- data/spec/environment_spec.rb +35 -0
- data/spec/spec_helper.rb +36 -1
- data/spec/transfer_protocols/ftp_spec.rb +193 -0
- data/spec/wordpress/configuration_spec.rb +202 -0
- data/wordpress_deploy.gemspec +13 -10
- metadata +63 -47
- data/lib/wordpress_deploy/config.rb +0 -68
- data/lib/wordpress_deploy/database/base.rb +0 -53
- data/lib/wordpress_deploy/pipeline.rb +0 -110
- data/lib/wordpress_deploy/storage/base.rb +0 -99
- data/lib/wordpress_deploy/storage/ftp.rb +0 -133
- data/lib/wordpress_deploy/storage/local.rb +0 -82
- data/lib/wordpress_deploy/storage/scp.rb +0 -99
- data/lib/wordpress_deploy/storage/sftp.rb +0 -108
- data/spec/config_spec.rb +0 -16
@@ -1,53 +1,102 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
##
|
4
2
|
# Build the WordpressDeploy Command Line Interface using Thor
|
3
|
+
#
|
5
4
|
module WordpressDeploy
|
6
|
-
module
|
5
|
+
module Cli
|
7
6
|
class Utility < Thor
|
8
7
|
include Thor::Actions
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
# These options apply to all commands
|
10
|
+
class_option :root_dir, type: :string, default: '', aliases: '-r'
|
11
|
+
class_option :wp_dir, type: :string, default: '', aliases: '-w'
|
12
|
+
class_option :environment, type: :string, default: 'production', aliases: '-e'
|
13
|
+
class_option :verbose, type: :boolean, default: false, aliases: '-v'
|
14
|
+
|
15
|
+
|
12
16
|
desc "generate", "Generate the wp-config.php file. Accepted environments are production or development."
|
13
17
|
def generate
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
config =
|
23
|
-
|
24
|
-
# Salt the wp-config.php file if none are provided
|
25
|
-
Config.salt_keys.each do |key|
|
26
|
-
config[key] = Config.salt_array.sample(64).join("") unless config.has_key? key
|
27
|
-
end
|
28
|
-
|
29
|
-
out = File.open(Config.wp_config_output, 'w')
|
30
|
-
File.open(Config.wp_config_sample, 'r') do |file|
|
31
|
-
file.each_line do |line|
|
32
|
-
match = /^define\(['"](?<parameter>\w*)['"]/.match(line)
|
33
|
-
unless match.nil?
|
34
|
-
param = match[:parameter]
|
35
|
-
if config.has_key?(param)
|
36
|
-
# The Wordpress Config file has the key
|
37
|
-
# So now set the value from the config
|
38
|
-
line.gsub!(/['"]((?!#{param})[\s\w\d\!\@\#\$\%\^\&\*\-\(\)]+)?['"]/, "'#{config[param]}'")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
out.puts(line)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
18
|
+
##
|
19
|
+
# Set Logger into verbose mode (if the user requested it)
|
20
|
+
Logger.verbose = options[:verbose]
|
21
|
+
|
22
|
+
# Set environment options
|
23
|
+
Environment.set_options options
|
24
|
+
|
25
|
+
# Create a configuration file
|
26
|
+
config = Wordpress::Configuration.new
|
45
27
|
|
28
|
+
# Save the configuration file
|
29
|
+
config.save!
|
30
|
+
rescue => err
|
31
|
+
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
46
32
|
|
47
|
-
|
33
|
+
# Exit with an error
|
34
|
+
exit(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "deploy", "Deploy via FTP to configuration hostname."
|
48
38
|
def deploy
|
39
|
+
##
|
40
|
+
# Set Logger into verbose mode (if the user requested it)
|
41
|
+
Logger.verbose = options[:verbose]
|
42
|
+
|
43
|
+
# Set environment options
|
44
|
+
Environment.set_options options
|
45
|
+
|
46
|
+
# Create a new FTP client for sending the files
|
47
|
+
ftp_client = TransferProtocols::Ftp.new options[:environment]
|
48
|
+
|
49
|
+
# Now transmit the files
|
50
|
+
ftp_client.transmit!
|
51
|
+
|
52
|
+
rescue => err
|
53
|
+
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
49
54
|
|
55
|
+
# Exit with an error
|
56
|
+
exit(1)
|
57
|
+
ensure
|
58
|
+
puts "Closing connection.".colorize(color: :red, background: :yellow) if ftp_client.close
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "backup", "Pull down the remote files over FTP."
|
62
|
+
def backup
|
63
|
+
##
|
64
|
+
# Set Logger into verbose mode (if the user requested it)
|
65
|
+
Logger.verbose = options[:verbose]
|
66
|
+
|
67
|
+
# Set environment options
|
68
|
+
Environment.set_options options
|
69
|
+
|
70
|
+
# Create a new FTP client for receiving the files
|
71
|
+
ftp_client = TransferProtocols::Ftp.new options[:environment]
|
72
|
+
|
73
|
+
# Now receive the files
|
74
|
+
ftp_client.receive!
|
75
|
+
|
76
|
+
rescue => err
|
77
|
+
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
78
|
+
|
79
|
+
# Exit with an error
|
80
|
+
exit(1)
|
81
|
+
ensure
|
82
|
+
puts "Closing connection.".colorize(color: :red, background: :yellow) if ftp_client.close
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "mirror", "Mirror database between two locations"
|
86
|
+
def mirror(from, to)
|
87
|
+
##
|
88
|
+
# Set Logger into verbose mode (if the user requested it)
|
89
|
+
Logger.verbose = options[:verbose]
|
90
|
+
|
91
|
+
# Set environment options
|
92
|
+
Environment.set_options options
|
93
|
+
rescue => err
|
94
|
+
Logger.error Errors::Cli::Utility::Error.wrap(err)
|
95
|
+
|
96
|
+
# Exit with an error
|
97
|
+
exit(1)
|
50
98
|
end
|
51
99
|
end
|
52
100
|
end
|
53
101
|
end
|
102
|
+
|
@@ -1,159 +1,45 @@
|
|
1
|
-
|
1
|
+
require 'tmpdir'
|
2
2
|
|
3
3
|
module WordpressDeploy
|
4
4
|
module Database
|
5
|
-
class MySQL < Base
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
# To dump all databases, set this to `:all` or leave blank.
|
10
|
-
attr_accessor :name
|
11
|
-
|
12
|
-
##
|
13
|
-
# Credentials for the specified database
|
14
|
-
attr_accessor :username, :password
|
15
|
-
|
16
|
-
##
|
17
|
-
# Connectivity options
|
18
|
-
attr_accessor :host, :port, :socket
|
19
|
-
|
20
|
-
##
|
21
|
-
# Tables to skip while dumping the database
|
22
|
-
attr_accessor :skip_tables
|
23
|
-
|
24
|
-
##
|
25
|
-
# Tables to dump, tables that aren't specified won't get dumped
|
26
|
-
attr_accessor :only_tables
|
27
|
-
|
28
|
-
##
|
29
|
-
# Additional "mysqldump" options
|
30
|
-
attr_accessor :additional_options
|
6
|
+
class MySql
|
7
|
+
include WordpressDeploy::Cli::Helpers
|
31
8
|
|
32
|
-
|
33
|
-
# Path to mysqldump utility (optional)
|
34
|
-
attr_accessor :mysqldump_utility
|
35
|
-
|
36
|
-
attr_deprecate :utility_path, :version => '3.0.21',
|
37
|
-
:replacement => :mysqldump_utility
|
38
|
-
|
39
|
-
##
|
40
|
-
# Creates a new instance of the MySQL adapter object
|
41
|
-
def initialize(model, &block)
|
42
|
-
super(model)
|
43
|
-
|
44
|
-
@skip_tables ||= Array.new
|
45
|
-
@only_tables ||= Array.new
|
46
|
-
@additional_options ||= Array.new
|
47
|
-
|
48
|
-
instance_eval(&block) if block_given?
|
9
|
+
attr_reader :configuration
|
49
10
|
|
50
|
-
|
51
|
-
@
|
11
|
+
def initialize
|
12
|
+
@yaml = YAML.load_file(File.join(Environment.config_dir, "wp-config.yml"))
|
52
13
|
end
|
53
14
|
|
54
|
-
##
|
55
|
-
# Performs the mysqldump command and outputs the
|
56
|
-
# data to the specified path based on the 'trigger'
|
57
|
-
def perform!
|
58
|
-
super
|
59
|
-
|
60
|
-
pipeline = Pipeline.new
|
61
|
-
dump_ext = 'sql'
|
62
|
-
|
63
|
-
pipeline << mysqldump
|
64
|
-
if @model.compressor
|
65
|
-
@model.compressor.compress_with do |command, ext|
|
66
|
-
pipeline << command
|
67
|
-
dump_ext << ext
|
68
|
-
end
|
69
|
-
end
|
70
|
-
pipeline << "cat > '#{ File.join(@dump_path, dump_filename) }.#{ dump_ext }'"
|
71
|
-
|
72
|
-
pipeline.run
|
73
|
-
if pipeline.success?
|
74
|
-
Logger.message "#{ database_name } Complete!"
|
75
|
-
else
|
76
|
-
raise Errors::Database::PipelineError,
|
77
|
-
"#{ database_name } Dump Failed!\n" +
|
78
|
-
pipeline.error_messages
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
##
|
85
|
-
# Builds the full mysqldump string based on all attributes
|
86
15
|
def mysqldump
|
87
|
-
"#{
|
88
|
-
"#{ user_options } #{ db_name } #{ tables_to_dump } #{ tables_to_skip }"
|
16
|
+
"#{utility("mysqldump")} #{arguments}"
|
89
17
|
end
|
90
18
|
|
91
|
-
|
92
|
-
|
93
|
-
def dump_filename
|
94
|
-
dump_all? ? 'all-databases' : name
|
95
|
-
end
|
96
|
-
|
97
|
-
##
|
98
|
-
# Builds the credentials MySQL syntax to authenticate the user
|
99
|
-
# to perform the database dumping process
|
100
|
-
def credential_options
|
101
|
-
%w[username password].map do |option|
|
102
|
-
next if send(option).to_s.empty?
|
103
|
-
"--#{option}='#{send(option)}'".gsub('--username', '--user')
|
104
|
-
end.compact.join(' ')
|
105
|
-
end
|
106
|
-
|
107
|
-
##
|
108
|
-
# Builds the MySQL connectivity options syntax to connect the user
|
109
|
-
# to perform the database dumping process
|
110
|
-
def connectivity_options
|
111
|
-
%w[host port socket].map do |option|
|
112
|
-
next if send(option).to_s.empty?
|
113
|
-
"--#{option}='#{send(option)}'"
|
114
|
-
end.compact.join(' ')
|
19
|
+
def configuration=(new_config)
|
20
|
+
@configuration = new_config if new_config.instance_of? WordpressDeploy::Wordpress::Configuration
|
115
21
|
end
|
116
22
|
|
117
|
-
|
118
|
-
# Builds a MySQL compatible string for the additional options
|
119
|
-
# specified by the user
|
120
|
-
def user_options
|
121
|
-
additional_options.join(' ')
|
122
|
-
end
|
123
|
-
|
124
|
-
##
|
125
|
-
# Returns the database name to use in the mysqldump command.
|
126
|
-
# When dumping all databases, the database name is replaced
|
127
|
-
# with the command option to dump all databases.
|
128
|
-
def db_name
|
129
|
-
dump_all? ? '--all-databases' : name
|
130
|
-
end
|
23
|
+
private
|
131
24
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
25
|
+
def arguments
|
26
|
+
host = configuration.host
|
27
|
+
port = configuration.port
|
28
|
+
username = configuration.DB_USER
|
29
|
+
password = configuration.DB_PASSWORD
|
30
|
+
db_name = configuration.DB_NAME
|
138
31
|
|
139
|
-
|
140
|
-
# Builds the MySQL syntax for specifying which tables to skip
|
141
|
-
# during the dumping of the database
|
142
|
-
def tables_to_skip
|
143
|
-
skip_tables.map do |table|
|
144
|
-
table = (dump_all? || table['.']) ? table : "#{ name }.#{ table }"
|
145
|
-
"--ignore-table='#{ table }'"
|
146
|
-
end.join(' ')
|
32
|
+
"-P \"#{port}\" -h \"#{host}\" -u \"#{username}\" -p#{password} -B \"#{db_name}\""
|
147
33
|
end
|
148
34
|
|
149
35
|
##
|
150
|
-
#
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
name == :all
|
36
|
+
# A temporary directory for installing the executable to
|
37
|
+
def tmp_dir
|
38
|
+
@tmp_dir ||= Dir.mktmpdir
|
39
|
+
File.expand_path(@tmp_dir)
|
155
40
|
end
|
156
41
|
|
157
42
|
end
|
158
43
|
end
|
159
44
|
end
|
45
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module WordpressDeploy
|
2
|
+
##
|
3
|
+
# Environment defines all of the locations of input and
|
4
|
+
# output files. Specifically, the locations of the test
|
5
|
+
# definitions, the locations of the test results, and
|
6
|
+
# the locations of the build applications.
|
7
|
+
module Environment
|
8
|
+
|
9
|
+
##
|
10
|
+
# Setup required paths based on the given options
|
11
|
+
def self.set_options(options = {})
|
12
|
+
options.each do |option, value|
|
13
|
+
method = "#{option}="
|
14
|
+
send(method, value) if respond_to? method and !value.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.logging=(new_log)
|
19
|
+
# Only set @@logging if new_log is a boolean
|
20
|
+
if !!new_log == new_log
|
21
|
+
@@logging = new_log
|
22
|
+
else
|
23
|
+
@@logging = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.logging?
|
28
|
+
@@logging ||= false
|
29
|
+
@@logging
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.root_dir=(new_root)
|
33
|
+
@@root_dir = new_root
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.root_dir
|
37
|
+
@@root_dir ||= Dir.pwd
|
38
|
+
File.expand_path @@root_dir
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.config_dir=(new_config_dir)
|
42
|
+
@@config_dir = new_config_dir
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.config_dir
|
46
|
+
@@config_dir ||= "config"
|
47
|
+
File.expand_path File.join(root_dir, @@config_dir)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.wp_dir=(new_wp_dir)
|
51
|
+
@@wp_dir = new_wp_dir
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.wp_dir
|
55
|
+
@@wp_dir ||= "site"
|
56
|
+
File.expand_path File.join(root_dir, @@wp_dir)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.log_file
|
60
|
+
@@log_file ||= "#{Time.now.strftime("%Y_%m_%d_%H_%M_%S")}.log"
|
61
|
+
File.expand_path File.join(root_dir, @@log_file)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.clean!
|
65
|
+
FileUtils.rm Dir.glob(File.join(root_dir, "*.log"))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,7 +1,61 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module WordpressDeploy
|
4
|
+
##
|
5
|
+
# - automatically defines module namespaces referenced under WordpressDeploy::Errors
|
6
|
+
# - any constant name referenced that ends with 'Error' will be created
|
7
|
+
# as a subclass of WordpressDeploy::Errors::Error
|
8
|
+
# e.g.
|
9
|
+
# err = WordpressDeploy::Errors::Foo::Bar::FooError.new('error message')
|
10
|
+
# err.message => "Foo::Bar::FooError: error message"
|
11
|
+
#
|
12
|
+
module ErrorsHelper
|
13
|
+
def const_missing(const)
|
14
|
+
if const.to_s.end_with?('Error')
|
15
|
+
module_eval("class #{const} < WordpressDeploy::Errors::Error; end")
|
16
|
+
else
|
17
|
+
module_eval("module #{const}; extend WordpressDeploy::ErrorsHelper; end")
|
18
|
+
end
|
19
|
+
const_get(const)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# provides cascading errors with formatted messages
|
25
|
+
# see the specs for details
|
26
|
+
#
|
27
|
+
# e.g.
|
28
|
+
# module WordpressDeploy
|
29
|
+
# begin
|
30
|
+
# begin
|
31
|
+
# begin
|
32
|
+
# raise Errors::ZoneAError, 'an error occurred in Zone A'
|
33
|
+
# rescue => err
|
34
|
+
# raise Errors::ZoneBError.wrap(err, <<-EOS)
|
35
|
+
# an error occurred in Zone B
|
36
|
+
#
|
37
|
+
# the following error should give a reason
|
38
|
+
# EOS
|
39
|
+
# end
|
40
|
+
# rescue => err
|
41
|
+
# raise Errors::ZoneCError.wrap(err)
|
42
|
+
# end
|
43
|
+
# rescue => err
|
44
|
+
# puts Errors::ZoneDError.wrap(err, 'an error occurred in Zone D')
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# Outputs:
|
49
|
+
# ZoneDError: an error occurred in Zone D
|
50
|
+
# Reason: ZoneCError
|
51
|
+
# ZoneBError: an error occurred in Zone B
|
52
|
+
#
|
53
|
+
# the following error should give a reason
|
54
|
+
# Reason: ZoneAError
|
55
|
+
# an error occurred in Zone A
|
56
|
+
#
|
4
57
|
module Errors
|
58
|
+
extend ErrorsHelper
|
5
59
|
|
6
60
|
class Error < StandardError
|
7
61
|
|