wordpress-deploy 1.0.0.alpha1 → 1.0.0.alpha2
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.
- 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
|
|