wordpress-deploy 1.0.0.alpha1

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 ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ # RubyGems Source
4
+ source 'http://rubygems.org'
5
+
6
+ # Include gem dependencies from the gemspec for development purposes
7
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,71 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ wordpress-deploy (1.0.0)
5
+ actionpack (~> 3.2.6)
6
+ colorize (~> 0.5.8)
7
+ open4 (~> 1.3.0)
8
+ thor (~> 0.14.6)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ actionpack (3.2.6)
14
+ activemodel (= 3.2.6)
15
+ activesupport (= 3.2.6)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.1)
19
+ rack (~> 1.4.0)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.1.3)
23
+ activemodel (3.2.6)
24
+ activesupport (= 3.2.6)
25
+ builder (~> 3.0.0)
26
+ activesupport (3.2.6)
27
+ i18n (~> 0.6)
28
+ multi_json (~> 1.0)
29
+ builder (3.0.0)
30
+ colorize (0.5.8)
31
+ diff-lcs (1.1.3)
32
+ erubis (2.7.0)
33
+ hike (1.2.1)
34
+ i18n (0.6.0)
35
+ journey (1.0.4)
36
+ metaclass (0.0.1)
37
+ mocha (0.11.4)
38
+ metaclass (~> 0.0.1)
39
+ multi_json (1.3.6)
40
+ open4 (1.3.0)
41
+ rack (1.4.1)
42
+ rack-cache (1.2)
43
+ rack (>= 0.4)
44
+ rack-test (0.6.1)
45
+ rack (>= 1.0)
46
+ rake (0.9.2.2)
47
+ rspec (2.10.0)
48
+ rspec-core (~> 2.10.0)
49
+ rspec-expectations (~> 2.10.0)
50
+ rspec-mocks (~> 2.10.0)
51
+ rspec-core (2.10.1)
52
+ rspec-expectations (2.10.0)
53
+ diff-lcs (~> 1.1.3)
54
+ rspec-mocks (2.10.1)
55
+ sprockets (2.1.3)
56
+ hike (~> 1.2)
57
+ rack (~> 1.0)
58
+ tilt (~> 1.1, != 1.3.0)
59
+ thor (0.14.6)
60
+ tilt (1.3.3)
61
+ timecop (0.3.5)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ mocha
68
+ rake
69
+ rspec
70
+ timecop
71
+ wordpress-deploy!
data/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+
2
+ Copyright (c) 2012 Ryan Lovelett ( [@rlovelett](http://twitter.com/#!/rlovelett) )
3
+ =================================================================================================
4
+
5
+ The "Wordpress Deploy" RubyGem is released under the **MIT LICENSE**
6
+ ----------------------------------------------------------
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ Wordpress Deploy
2
+ ======
3
+
4
+ Wordpress Deploy is a RubyGem, written for Linux and Mac OSX, that allows you to easily perform Wordpress deployment operations. It provides you with an elegant DSL in Ruby for modeling your deployments.
5
+
6
+ ### Author
7
+
8
+ **[Ryan Lovelett](http://ryan.lovelett.me/) ( [@rlovelett](http://twitter.com/#!/rlovelett) )**
9
+
10
+ Drop me a message for any questions, suggestions, requests, bugs or submit them to the [issue log](https://github.com/rlovelett/wordpress-deploy/issues).
11
+
12
+
13
+ ### Installation
14
+
15
+ To get the latest stable version
16
+
17
+ gem install wordpress-deploy
18
+
19
+ You can view the list of released versions over at [RubyGems.org (Backup)](https://rubygems.org/gems/wordpress-deploy/versions)
20
+
21
+
22
+ ### Getting Started
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
data/bin/wp-deploy ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # Load the WordpressDeploy core library
5
+ require File.expand_path("../../lib/wordpress_deploy", __FILE__)
6
+
7
+ # Load the WordpressDeploy command line interface utility
8
+ require File.expand_path("../../lib/wordpress_deploy/cli/utility", __FILE__)
9
+
10
+ # Initialize the WordpressDeploy command line utility
11
+ WordpressDeploy::CLI::Utility.start
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ module WordpressDeploy
4
+ module CLI
5
+ module Helpers
6
+ UTILITY = {}
7
+
8
+ ##
9
+ # Runs a system command
10
+ #
11
+ # All messages generated by the command will be logged.
12
+ # Messages on STDERR will be logged as warnings.
13
+ #
14
+ # If the command fails to execute, or returns a non-zero exit status
15
+ # an Error will be raised.
16
+ #
17
+ # Returns nil
18
+ def run(command)
19
+ name = command_name(command)
20
+ Logger.message "Running system utility '#{ name }'..."
21
+
22
+ begin
23
+ out, err = '', ''
24
+ ps = Open4.popen4(command) do |pid, stdin, stdout, stderr|
25
+ stdin.close
26
+ out, err = stdout.read.strip, stderr.read.strip
27
+ end
28
+ rescue Exception => e
29
+ raise Errors::CLI::SystemCallError.wrap(e, <<-EOS)
30
+ Failed to execute system command on #{ RUBY_PLATFORM }
31
+ Command was: #{ command }
32
+ EOS
33
+ end
34
+
35
+ if ps.success?
36
+ unless out.empty?
37
+ Logger.message(
38
+ out.lines.map {|line| "#{ name }:STDOUT: #{ line }" }.join
39
+ )
40
+ end
41
+
42
+ unless err.empty?
43
+ Logger.warn(
44
+ err.lines.map {|line| "#{ name }:STDERR: #{ line }" }.join
45
+ )
46
+ end
47
+
48
+ return nil
49
+ else
50
+ raise Errors::CLI::SystemCallError, <<-EOS
51
+ '#{ name }' Failed on #{ RUBY_PLATFORM }
52
+ The following information should help to determine the problem:
53
+ Command was: #{ command }
54
+ Exit Status: #{ ps.exitstatus }
55
+ STDOUT Messages: #{ out.empty? ? 'None' : "\n#{ out }" }
56
+ STDERR Messages: #{ err.empty? ? 'None' : "\n#{ err }" }
57
+ EOS
58
+ end
59
+ end
60
+
61
+
62
+ ##
63
+ # Returns the full path to the specified utility.
64
+ # Raises an error if utility can not be found in the system's $PATH
65
+ def utility(name)
66
+ name = name.to_s.strip
67
+ raise Errors::CLI::UtilityNotFoundError,
68
+ 'Utility Name Empty' if name.empty?
69
+
70
+ path = UTILITY[name] || %x[which #{ name } 2>/dev/null].chomp
71
+ if path.empty?
72
+ raise Errors::CLI::UtilityNotFoundError, <<-EOS
73
+ Could not locate '#{ name }'.
74
+ Make sure the specified utility is installed
75
+ and available in your system's $PATH.
76
+ EOS
77
+ end
78
+ UTILITY[name] = path
79
+ end
80
+
81
+ ##
82
+ # Returns the name of the command name from the given command line
83
+ def command_name(command)
84
+ i = command =~ /\s/
85
+ command = command.slice(0, i) if i
86
+ command.split('/')[-1]
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Build the WordpressDeploy Command Line Interface using Thor
5
+ module WordpressDeploy
6
+ module CLI
7
+ class Utility < Thor
8
+ include Thor::Actions
9
+
10
+ method_option :base, type: :string, aliases: ['-b']
11
+ method_option :env, type: :string, required: true, default: 'production', aliases: ['-e']
12
+ desc "generate", "Generate the wp-config.php file. Accepted environments are production or development."
13
+ def generate
14
+ unless %w{production development}.include? options[:env]
15
+ raise Errors::CLI::SystemCallError.wrap(e, <<-EOS)
16
+ Failed to execute system command on #{ RUBY_PLATFORM }
17
+ Command was: #{ command }
18
+ EOS
19
+ end
20
+
21
+ Config.environment = options[:env]
22
+ config = Config.wp_config[Config.env]
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
45
+
46
+
47
+ desc "deploy", "Deploy #{Config.sites_dir} via FTP to #{Config.ftp_config['hostname']}"
48
+ def deploy
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module WordpressDeploy
4
+ module Config
5
+ DEFAULTS = {
6
+ :config_file => 'config.rb',
7
+ :data_path => 'data',
8
+ :log_path => 'log',
9
+ :cache_path => '.cache',
10
+ :tmp_path => '.tmp'
11
+ }
12
+
13
+ class << self
14
+ # These paths are the basis for all scripts
15
+ attr_reader :base_dir
16
+ def base_dir
17
+ @base_dir ||= Dir.pwd
18
+ end
19
+ attr_reader :config_dir
20
+ def config_dir
21
+ @config_dir ||= File.join(base_dir, "config")
22
+ end
23
+ attr_reader :sites_dir
24
+ def sites_dir
25
+ @sites_dir ||= File.join(base_dir, "site")
26
+ end
27
+
28
+ attr_reader :ftp_config
29
+ def ftp_config
30
+ @ftp_config ||= YAML.load_file(File.join(config_dir, "ftp.yml"))
31
+ end
32
+
33
+ attr_reader :wp_config
34
+ def wp_config
35
+ @wp_config ||= YAML.load_file(File.join(config_dir, "wp-config.yml"))
36
+ end
37
+
38
+ attr_reader :wp_config_sample
39
+ def wp_config_sample
40
+ @wp_config_sample ||= File.join(sites_dir, "wp-config-sample.php")
41
+ end
42
+ attr_reader :wp_config_output
43
+ def wp_config_output
44
+ @wp_config_output ||= File.join(sites_dir, "wp-config.php")
45
+ end
46
+
47
+ attr_reader :environment
48
+ def environment
49
+ @environment ||= "production"
50
+ end
51
+ alias :env :environment
52
+
53
+ def environment=(new_env)
54
+ @environment = new_env.downcase
55
+ end
56
+
57
+ # The Salting array
58
+ def salt_array
59
+ @salt_array ||= %w{0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ! @ # $ % ^ & * ( ) - ~ + = | / { } : ; , . ? < > [ ]}
60
+ end
61
+
62
+ def salt_keys
63
+ @salt_keys ||= %w{AUTH_KEY SECURE_AUTH_KEY LOGGED_IN_KEY NONCE_KEY AUTH_SALT SECURE_AUTH_SALT LOGGED_IN_SALT NONCE_SALT}
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ module WordpressDeploy
4
+ module Database
5
+ class Base
6
+ include WordpressDeploy::CLI::Helpers
7
+ include WordpressDeploy::Configuration::Helpers
8
+
9
+ ##
10
+ # Creates a new instance of the MongoDB database object
11
+ # * Called using super(model) from subclasses *
12
+ def initialize(model)
13
+ @model = model
14
+ load_defaults!
15
+ end
16
+
17
+ ##
18
+ # Super method for all child (database) objects. Every database object's #perform!
19
+ # method should call #super before anything else to prepare
20
+ def perform!
21
+ prepare!
22
+ log!
23
+ end
24
+
25
+ private
26
+
27
+ ##
28
+ # Defines the @dump_path and ensures it exists by creating it
29
+ def prepare!
30
+ @dump_path = File.join(
31
+ Config.tmp_path,
32
+ @model.trigger,
33
+ 'databases',
34
+ self.class.name.split('::').last
35
+ )
36
+ FileUtils.mkdir_p(@dump_path)
37
+ end
38
+
39
+ ##
40
+ # Return the database name, with WordpressDeploy namespace removed
41
+ def database_name
42
+ self.class.to_s.sub('WordpressDeploy::', '')
43
+ end
44
+
45
+ ##
46
+ # Logs a message to the console and log file to inform
47
+ # the client that WordpressDeploy is dumping the database
48
+ def log!
49
+ Logger.message "#{ database_name } started dumping and archiving '#{ name }'."
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,159 @@
1
+ # encoding: utf-8
2
+
3
+ module WordpressDeploy
4
+ module Database
5
+ class MySQL < Base
6
+
7
+ ##
8
+ # Name of the database that needs to get dumped
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
31
+
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?
49
+
50
+ @name ||= :all
51
+ @mysqldump_utility ||= utility(:mysqldump)
52
+ end
53
+
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
+ def mysqldump
87
+ "#{ mysqldump_utility } #{ credential_options } #{ connectivity_options } " +
88
+ "#{ user_options } #{ db_name } #{ tables_to_dump } #{ tables_to_skip }"
89
+ end
90
+
91
+ ##
92
+ # Returns the filename to use for dumping the database(s)
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(' ')
115
+ end
116
+
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
131
+
132
+ ##
133
+ # Builds the MySQL syntax for specifying which tables to dump
134
+ # during the dumping of the database
135
+ def tables_to_dump
136
+ only_tables.join(' ') unless dump_all?
137
+ end
138
+
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(' ')
147
+ end
148
+
149
+ ##
150
+ # Return true if we're dumping all databases.
151
+ # `name` will be set to :all if it is not set,
152
+ # so this will be true by default
153
+ def dump_all?
154
+ name == :all
155
+ end
156
+
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ module WordpressDeploy
4
+ module Errors
5
+
6
+ class Error < StandardError
7
+
8
+ def self.wrap(orig_err, msg = nil)
9
+ new(msg, orig_err)
10
+ end
11
+
12
+ def initialize(msg = nil, orig_err = nil)
13
+ super(msg)
14
+ set_backtrace(orig_err.backtrace) if @orig_err = orig_err
15
+ end
16
+
17
+ def to_s
18
+ return @to_s if @to_s
19
+ orig_to_s = super()
20
+
21
+ if orig_to_s == self.class.to_s
22
+ msg = orig_err_msg ?
23
+ "#{orig_err_class}: #{orig_err_msg}" : orig_err_class
24
+ else
25
+ msg = format_msg(orig_to_s)
26
+ msg << "\n Reason: #{orig_err_class}" + (orig_err_msg ?
27
+ "\n #{orig_err_msg}" : ' (no message given)') if @orig_err
28
+ end
29
+
30
+ @to_s = msg ? msg_prefix + msg : class_name
31
+ end
32
+
33
+ private
34
+
35
+ def msg_prefix
36
+ @msg_prefix ||= class_name + ': '
37
+ end
38
+
39
+ def orig_msg
40
+ @orig_msg ||= to_s.sub(msg_prefix, '')
41
+ end
42
+
43
+ def class_name
44
+ @class_name ||= self.class.to_s.sub('WordpressDeploy::Errors::', '')
45
+ end
46
+
47
+ def orig_err_class
48
+ return unless @orig_err
49
+
50
+ @orig_err_class ||= @orig_err.is_a?(Errors::Error) ?
51
+ @orig_err.send(:class_name) : @orig_err.class.to_s
52
+ end
53
+
54
+ def orig_err_msg
55
+ return unless @orig_err
56
+ return @orig_err_msg unless @orig_err_msg.nil?
57
+
58
+ msg = @orig_err.is_a?(Errors::Error) ?
59
+ @orig_err.send(:orig_msg) : @orig_err.to_s
60
+ @orig_err_msg = (msg == orig_err_class) ?
61
+ false : format_msg(msg)
62
+ end
63
+
64
+ def format_msg(msg)
65
+ msg.gsub(/^ */, ' ').strip
66
+ end
67
+ end
68
+
69
+ end
70
+ end