wordmove 5.2.2 → 6.0.0.alpha.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +12 -5
- data/.rubocop.yml +2 -5
- data/.ruby-version +1 -1
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +15 -0
- data/Rakefile +4 -3
- data/exe/wordmove +2 -1
- data/lib/wordmove/actions/adapt_local_db.rb +95 -0
- data/lib/wordmove/actions/adapt_remote_db.rb +87 -0
- data/lib/wordmove/actions/backup_local_db.rb +54 -0
- data/lib/wordmove/actions/delete_local_file.rb +34 -0
- data/lib/wordmove/actions/delete_remote_file.rb +43 -0
- data/lib/wordmove/actions/filter_and_setup_tasks_to_run.rb +42 -0
- data/lib/wordmove/actions/ftp/backup_remote_db.rb +54 -0
- data/lib/wordmove/actions/ftp/cleanup_after_adapt.rb +70 -0
- data/lib/wordmove/actions/ftp/download_remote_db.rb +69 -0
- data/lib/wordmove/actions/ftp/get_directory.rb +67 -0
- data/lib/wordmove/actions/ftp/helpers.rb +91 -0
- data/lib/wordmove/actions/ftp/pull_wordpress.rb +56 -0
- data/lib/wordmove/actions/ftp/push_wordpress.rb +54 -0
- data/lib/wordmove/actions/ftp/put_and_import_dump_remotely.rb +74 -0
- data/lib/wordmove/actions/ftp/put_directory.rb +67 -0
- data/lib/wordmove/actions/get_file.rb +38 -0
- data/lib/wordmove/actions/helpers.rb +142 -0
- data/lib/wordmove/actions/put_file.rb +48 -0
- data/lib/wordmove/actions/run_after_pull_hook.rb +26 -0
- data/lib/wordmove/actions/run_after_push_hook.rb +26 -0
- data/lib/wordmove/actions/run_before_pull_hook.rb +26 -0
- data/lib/wordmove/actions/run_before_push_hook.rb +26 -0
- data/lib/wordmove/actions/run_local_command.rb +34 -0
- data/lib/wordmove/actions/setup_context_for_db.rb +79 -0
- data/lib/wordmove/actions/ssh/backup_remote_db.rb +49 -0
- data/lib/wordmove/actions/ssh/cleanup_after_adapt.rb +42 -0
- data/lib/wordmove/actions/ssh/download_remote_db.rb +76 -0
- data/lib/wordmove/actions/ssh/get_directory.rb +76 -0
- data/lib/wordmove/actions/ssh/helpers.rb +128 -0
- data/lib/wordmove/actions/ssh/pull_wordpress.rb +56 -0
- data/lib/wordmove/actions/ssh/push_wordpress.rb +54 -0
- data/lib/wordmove/actions/ssh/put_and_import_dump_remotely.rb +70 -0
- data/lib/wordmove/actions/ssh/put_directory.rb +76 -0
- data/lib/wordmove/actions/ssh/run_remote_command.rb +39 -0
- data/lib/wordmove/assets/dump.php.erb +6 -6
- data/lib/wordmove/assets/import.php.erb +7 -7
- data/lib/wordmove/assets/wordmove_schema_global.yml +2 -0
- data/lib/wordmove/cli.rb +152 -91
- data/lib/wordmove/db_paths_config.rb +44 -0
- data/lib/wordmove/doctor/movefile.rb +8 -8
- data/lib/wordmove/doctor/mysql.rb +18 -15
- data/lib/wordmove/doctor/rsync.rb +2 -2
- data/lib/wordmove/doctor/ssh.rb +3 -3
- data/lib/wordmove/doctor/wpcli.rb +4 -4
- data/lib/wordmove/environments_list.rb +4 -4
- data/lib/wordmove/exceptions.rb +13 -0
- data/lib/wordmove/generators/movefile.rb +7 -5
- data/lib/wordmove/generators/movefile_adapter.rb +11 -5
- data/lib/wordmove/guardian.rb +5 -5
- data/lib/wordmove/hook.rb +13 -14
- data/lib/wordmove/logger.rb +11 -10
- data/lib/wordmove/movefile.rb +63 -59
- data/lib/wordmove/organizers/ftp/pull.rb +52 -0
- data/lib/wordmove/organizers/ftp/push.rb +53 -0
- data/lib/wordmove/organizers/ssh/pull.rb +52 -0
- data/lib/wordmove/organizers/ssh/push.rb +53 -0
- data/lib/wordmove/version.rb +1 -1
- data/lib/wordmove/wordpress_directory.rb +76 -8
- data/lib/wordmove/wpcli.rb +85 -0
- data/lib/wordmove.rb +33 -11
- data/wordmove.gemspec +37 -30
- metadata +139 -35
- data/lib/wordmove/deployer/base.rb +0 -193
- data/lib/wordmove/deployer/ftp.rb +0 -160
- data/lib/wordmove/deployer/ssh/default_sql_adapter.rb +0 -47
- data/lib/wordmove/deployer/ssh/wpcli_sql_adapter.rb +0 -55
- data/lib/wordmove/deployer/ssh.rb +0 -169
- data/lib/wordmove/sql_adapter/default.rb +0 -68
- data/lib/wordmove/sql_adapter/wpcli.rb +0 -54
- data/lib/wordmove/wordpress_directory/path.rb +0 -11
@@ -0,0 +1,67 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
# Syncs a whole directory over FTP protocol from the remote server to local host
|
5
|
+
class GetDirectory
|
6
|
+
extend LightService::Action
|
7
|
+
include Wordmove::Actions::Helpers
|
8
|
+
include WordpressDirectory::RemoteHelperMethods
|
9
|
+
include WordpressDirectory::LocalHelperMethods
|
10
|
+
|
11
|
+
# :folder_task is expected to be one symbol from Wordmove::CLI.wordpress_options array
|
12
|
+
expects :logger,
|
13
|
+
:local_options,
|
14
|
+
:remote_options,
|
15
|
+
:cli_options,
|
16
|
+
:photocopier,
|
17
|
+
:folder_task
|
18
|
+
|
19
|
+
# @!method execute
|
20
|
+
# @param logger [Wordmove::Logger]
|
21
|
+
# @param local_options [Hash] Local host options fetched from
|
22
|
+
# movefile (with symbolized keys)
|
23
|
+
# @param remote_options [Hash] Remote host options fetched from
|
24
|
+
# movefile (with symbolized keys)
|
25
|
+
# @param cli_options [Hash] Command line options (with symbolized keys)
|
26
|
+
# @param photocopier [Photocopier::FTP]
|
27
|
+
# @param folder_task [Symbol] Symbolazied folder name
|
28
|
+
# @!scope class
|
29
|
+
# @return [LightService::Context] Action's context
|
30
|
+
executed do |context|
|
31
|
+
context.logger.task "Pulling #{context.folder_task}"
|
32
|
+
|
33
|
+
next context if simulate?(cli_options: context.cli_options)
|
34
|
+
|
35
|
+
command = 'get_directory'
|
36
|
+
|
37
|
+
# This action can generate `command_args` by itself,
|
38
|
+
# but it gives the context the chance to ovveride it.
|
39
|
+
# By the way this variable is not `expects`ed.
|
40
|
+
# Note that we do not use the second argument to `fetch`
|
41
|
+
# to express a default value, because it would be greedly interpreted
|
42
|
+
# but if `command_args` is already defined by context, then it's
|
43
|
+
# possible that `"remote_#{context.folder_task}_dir"` could
|
44
|
+
# not be defined.
|
45
|
+
command_args = context.fetch(:command_args) || [
|
46
|
+
send(
|
47
|
+
"remote_#{context.folder_task}_dir",
|
48
|
+
remote_options: context.remote_options
|
49
|
+
).path,
|
50
|
+
send(
|
51
|
+
"local_#{context.folder_task}_dir",
|
52
|
+
local_options: context.local_options
|
53
|
+
).path,
|
54
|
+
paths_to_exclude(remote_options: context.remote_options)
|
55
|
+
]
|
56
|
+
|
57
|
+
context.logger.task_step false, "#{command}: #{command_args.join(' ')}"
|
58
|
+
result = context.photocopier.send(command, *command_args)
|
59
|
+
|
60
|
+
next context if result == true
|
61
|
+
|
62
|
+
context.fail!("Failed to pull #{context.folder_task}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
module Helpers
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do # rubocop:disable Metrics/BlockLength
|
8
|
+
#
|
9
|
+
# (In)Utility method to retrieve ftp options from the superset of remote options
|
10
|
+
#
|
11
|
+
# @param [Hash] remote_options Remote host options fetched from movefile
|
12
|
+
# (with symbolized keys)
|
13
|
+
#
|
14
|
+
# @return [Hash] Ftp options from the movefile
|
15
|
+
#
|
16
|
+
def ftp_options(remote_options:)
|
17
|
+
remote_options[:ftp]
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Escape a string to be printed into PHP files
|
22
|
+
#
|
23
|
+
# @param [String] string The string to escape
|
24
|
+
#
|
25
|
+
# @return [String] The escaped string
|
26
|
+
#
|
27
|
+
def escape_php(string:)
|
28
|
+
return '' unless string
|
29
|
+
|
30
|
+
# replaces \ with \\
|
31
|
+
# replaces ' with \'
|
32
|
+
string.gsub('\\', '\\\\\\').gsub(/'/, '\\\\\'')
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Generate a token
|
37
|
+
#
|
38
|
+
# @return [String] A random hexadecimal string
|
39
|
+
#
|
40
|
+
def remote_php_scripts_token
|
41
|
+
SecureRandom.hex(40)
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Generate THE PHP dump script, protected by a token to ensure only Wordmove will run it
|
46
|
+
#
|
47
|
+
# @param [Hash] remote_db_options The remote DB configurations fetched from movefile
|
48
|
+
# @param [String] token The token that will be used to protect the execution of the script
|
49
|
+
#
|
50
|
+
# @return [String] The PHP file as string
|
51
|
+
#
|
52
|
+
def generate_dump_script(remote_db_options:, token:)
|
53
|
+
template = ERB.new(
|
54
|
+
File.read(File.join(File.dirname(__FILE__), '../../assets/dump.php.erb'))
|
55
|
+
)
|
56
|
+
template.result(binding)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Generate THE PHP import script, protected by a token to ensure only Wordmove will run it
|
61
|
+
#
|
62
|
+
# @param [Hash] remote_db_options The remote DB configurations fetched from movefile
|
63
|
+
# @param [String] token The token that will be used to protect the execution of the script
|
64
|
+
#
|
65
|
+
# @return [String] The PHP file as string
|
66
|
+
#
|
67
|
+
def generate_import_script(remote_db_options:, token:)
|
68
|
+
template = ERB.new(
|
69
|
+
File.read(File.join(File.dirname(__FILE__), '../../assets/import.php.erb'))
|
70
|
+
)
|
71
|
+
template.result(binding)
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Download a file from the internet making a simple GET request
|
76
|
+
#
|
77
|
+
# @param [String] url The URL of the resource to download
|
78
|
+
# @param [String] local_path The local path where the resource will be saved
|
79
|
+
#
|
80
|
+
# @return [nil]
|
81
|
+
#
|
82
|
+
def download(url:, local_path:)
|
83
|
+
File.open(local_path, 'w') do |file|
|
84
|
+
file << URI.parse(url).read
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
# Syncs wordpress folder (usually root folder), exluding +wp-content/+ folder, over FTP
|
5
|
+
# protocol from the remote server to local host
|
6
|
+
class PullWordpress
|
7
|
+
extend ::LightService::Action
|
8
|
+
include Wordmove::Actions::Helpers
|
9
|
+
include WordpressDirectory::RemoteHelperMethods
|
10
|
+
|
11
|
+
expects :remote_options,
|
12
|
+
:local_options,
|
13
|
+
:logger,
|
14
|
+
:photocopier
|
15
|
+
|
16
|
+
# @!method execute
|
17
|
+
# @param remote_options [Hash] Remote host options fetched from
|
18
|
+
# movefile (with symbolized keys)
|
19
|
+
# @param local_options [Hash] Local host options fetched from
|
20
|
+
# movefile (with symbolized keys)
|
21
|
+
# @param logger [Wordmove::Logger]
|
22
|
+
# @param photocopier [Photocopier::FTP]
|
23
|
+
# @!scope class
|
24
|
+
# @return [LightService::Context] Action's context
|
25
|
+
executed do |context|
|
26
|
+
local_path = context.local_options[:wordpress_path]
|
27
|
+
|
28
|
+
remote_path = context.remote_options[:wordpress_path]
|
29
|
+
|
30
|
+
wp_content_relative_path = remote_wp_content_dir(
|
31
|
+
remote_options: context.remote_options
|
32
|
+
).relative_path
|
33
|
+
|
34
|
+
exclude_wp_content = exclude_dir_contents(
|
35
|
+
path: wp_content_relative_path
|
36
|
+
)
|
37
|
+
|
38
|
+
exclude_paths = paths_to_exclude(
|
39
|
+
remote_options: context.remote_options
|
40
|
+
).push(exclude_wp_content)
|
41
|
+
|
42
|
+
result = Wordmove::Actions::Ftp::GetDirectory.execute(
|
43
|
+
photocopier: context.photocopier,
|
44
|
+
logger: context.logger,
|
45
|
+
command_args: [remote_path, local_path, exclude_paths],
|
46
|
+
folder_task: :wordpress,
|
47
|
+
local_options: context.local_options,
|
48
|
+
remote_options: context.remote_options,
|
49
|
+
cli_options: context.cli_options
|
50
|
+
)
|
51
|
+
context.fail!(result.message) if result.failure?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
# Syncs wordpress folder (usually root folder), exluding +wp-content/+ folder, over FTP
|
5
|
+
# protocol from local host to the remote server
|
6
|
+
class PushWordpress
|
7
|
+
extend ::LightService::Action
|
8
|
+
include Wordmove::Actions::Helpers
|
9
|
+
include WordpressDirectory::LocalHelperMethods
|
10
|
+
|
11
|
+
expects :remote_options,
|
12
|
+
:local_options,
|
13
|
+
:logger,
|
14
|
+
:photocopier
|
15
|
+
|
16
|
+
# @!method execute
|
17
|
+
# @param remote_options [Hash] Remote host options fetched from
|
18
|
+
# movefile (with symbolized keys)
|
19
|
+
# @param local_options [Hash] Local host options fetched from
|
20
|
+
# movefile (with symbolized keys)
|
21
|
+
# @param logger [Wordmove::Logger]
|
22
|
+
# @param photocopier [Photocopier::FTP]
|
23
|
+
# @!scope class
|
24
|
+
# @return [LightService::Context] Action's context
|
25
|
+
executed do |context|
|
26
|
+
local_path = context.local_options[:wordpress_path]
|
27
|
+
|
28
|
+
remote_path = context.remote_options[:wordpress_path]
|
29
|
+
|
30
|
+
wp_content_relative_path = local_wp_content_dir(
|
31
|
+
local_options: context.local_options
|
32
|
+
).relative_path
|
33
|
+
|
34
|
+
exclude_wp_content = exclude_dir_contents(path: wp_content_relative_path)
|
35
|
+
|
36
|
+
exclude_paths = paths_to_exclude(
|
37
|
+
remote_options: context.remote_options
|
38
|
+
).push(exclude_wp_content)
|
39
|
+
|
40
|
+
result = Wordmove::Actions::Ftp::PutDirectory.execute(
|
41
|
+
photocopier: context.photocopier,
|
42
|
+
logger: context.logger,
|
43
|
+
command_args: [local_path, remote_path, exclude_paths],
|
44
|
+
folder_task: :wordpress,
|
45
|
+
local_options: context.local_options,
|
46
|
+
remote_options: context.remote_options,
|
47
|
+
cli_options: context.cli_options
|
48
|
+
)
|
49
|
+
context.fail!(result.message) if result.failure?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
# Uploads a DB dump to remote host and import it in the remote database over FTP protocol
|
5
|
+
class PutAndImportDumpRemotely
|
6
|
+
extend ::LightService::Action
|
7
|
+
include Wordmove::Actions::Helpers
|
8
|
+
include Wordmove::Actions::Ftp::Helpers
|
9
|
+
include WordpressDirectory::RemoteHelperMethods
|
10
|
+
include WordpressDirectory::LocalHelperMethods
|
11
|
+
|
12
|
+
expects :remote_options,
|
13
|
+
:cli_options,
|
14
|
+
:logger,
|
15
|
+
:photocopier,
|
16
|
+
:db_paths
|
17
|
+
|
18
|
+
# @!method execute
|
19
|
+
# @param logger [Wordmove::Logger]
|
20
|
+
# @param cli_options [Hash] Command line options (with symbolized keys)
|
21
|
+
# @param remote_options [Hash] Remote host options fetched from
|
22
|
+
# movefile (with symbolized keys)
|
23
|
+
# @param db_paths [BbPathsConfig] Configuration object for database
|
24
|
+
# @param photocopier [Photocopier::FTP]
|
25
|
+
# @!scope class
|
26
|
+
# @return [LightService::Context] Action's context
|
27
|
+
executed do |context| # rubocop:disable Metrics/BlockLength
|
28
|
+
context.logger.task 'Upload and import adapted DB'
|
29
|
+
|
30
|
+
result = Wordmove::Actions::PutFile.execute(
|
31
|
+
logger: context.logger,
|
32
|
+
photocopier: context.photocopier,
|
33
|
+
cli_options: context.cli_options,
|
34
|
+
command_args: [
|
35
|
+
context.db_paths.local.adapted_path,
|
36
|
+
context.db_paths.remote.path
|
37
|
+
]
|
38
|
+
)
|
39
|
+
context.fail_and_return!(result.message) if result.failure?
|
40
|
+
|
41
|
+
result = Wordmove::Actions::PutFile.execute(
|
42
|
+
logger: context.logger,
|
43
|
+
photocopier: context.photocopier,
|
44
|
+
cli_options: context.cli_options,
|
45
|
+
command_args: [
|
46
|
+
context.db_paths.ftp.local.generated_import_script_path,
|
47
|
+
context.db_paths.ftp.remote.import_script_path
|
48
|
+
]
|
49
|
+
)
|
50
|
+
context.fail_and_return!(result.message) if result.failure?
|
51
|
+
|
52
|
+
import_url = [
|
53
|
+
context.db_paths.ftp.remote.import_script_url,
|
54
|
+
'?shared_key=',
|
55
|
+
context.db_paths.ftp.token,
|
56
|
+
'&start=1&foffset=0&totalqueries=0&fn=dump.sql'
|
57
|
+
].join
|
58
|
+
|
59
|
+
download(url: import_url, local_path: context.db_paths.ftp.local.temp_path)
|
60
|
+
|
61
|
+
if context.cli_options[:debug]
|
62
|
+
context.logger.debug "Operation log located at: #{context.db_paths.ftp.local.temp_path}"
|
63
|
+
else
|
64
|
+
Wordmove::Actions::DeleteLocalFile.execute(
|
65
|
+
cli_options: context.cli_options,
|
66
|
+
logger: context.logger,
|
67
|
+
file_path: context.db_paths.ftp.local.temp_path
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
module Ftp
|
4
|
+
# Syncs a whole directory over FTP protocol from local host to remote server
|
5
|
+
class PutDirectory
|
6
|
+
extend LightService::Action
|
7
|
+
include Wordmove::Actions::Helpers
|
8
|
+
include WordpressDirectory::LocalHelperMethods
|
9
|
+
include WordpressDirectory::RemoteHelperMethods
|
10
|
+
|
11
|
+
# :folder_task is expected to be one symbol from Wordmove::CLI.wordpress_options array
|
12
|
+
expects :logger,
|
13
|
+
:local_options,
|
14
|
+
:remote_options,
|
15
|
+
:cli_options,
|
16
|
+
:photocopier,
|
17
|
+
:folder_task
|
18
|
+
|
19
|
+
# @!method execute
|
20
|
+
# @param logger [Wordmove::Logger]
|
21
|
+
# @param local_options [Hash] Local host options fetched from
|
22
|
+
# movefile (with symbolized keys)
|
23
|
+
# @param remote_options [Hash] Remote host options fetched from
|
24
|
+
# movefile (with symbolized keys)
|
25
|
+
# @param cli_options [Hash] Command line options (with symbolized keys)
|
26
|
+
# @param photocopier [Photocopier::FTP]
|
27
|
+
# @param folder_task [Symbol] Symbolazied folder name
|
28
|
+
# @!scope class
|
29
|
+
# @return [LightService::Context] Action's context
|
30
|
+
executed do |context|
|
31
|
+
context.logger.task "Pushing #{context.folder_task}"
|
32
|
+
|
33
|
+
next context if simulate?(cli_options: context.cli_options)
|
34
|
+
|
35
|
+
command = 'put_directory'
|
36
|
+
|
37
|
+
# This action can generate `command_args` by itself,
|
38
|
+
# but it gives the context the chance to ovveride it.
|
39
|
+
# By the way this variable is not `expects`ed.
|
40
|
+
# Note that we do not use the second argument to `fetch`
|
41
|
+
# to express a default value, because it would be greedly interpreted
|
42
|
+
# but if `command_args` is already defined by context, then it's
|
43
|
+
# possible that `"local_#{context.folder_task}_dir"` could
|
44
|
+
# not be defined.
|
45
|
+
command_args = context.fetch(:command_args) || [
|
46
|
+
send(
|
47
|
+
"local_#{context.folder_task}_dir",
|
48
|
+
local_options: context.local_options
|
49
|
+
).path,
|
50
|
+
send(
|
51
|
+
"remote_#{context.folder_task}_dir",
|
52
|
+
remote_options: context.remote_options
|
53
|
+
).path,
|
54
|
+
paths_to_exclude(remote_options: context.remote_options)
|
55
|
+
]
|
56
|
+
|
57
|
+
context.logger.task_step false, "#{command}: #{command_args.join(' ')}"
|
58
|
+
result = context.photocopier.send(command, *command_args)
|
59
|
+
|
60
|
+
next context if result == true
|
61
|
+
|
62
|
+
context.fail!("Failed to push #{context.folder_task}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
# Download a single file from the remote server.
|
4
|
+
#
|
5
|
+
# @note The remote server is already configured inside the Photocopier object
|
6
|
+
# @note This action is *not* meant to be organized, but as a standalone one.
|
7
|
+
class GetFile
|
8
|
+
extend LightService::Action
|
9
|
+
include Wordmove::Actions::Helpers
|
10
|
+
|
11
|
+
expects :photocopier,
|
12
|
+
:logger,
|
13
|
+
:cli_options,
|
14
|
+
:command_args
|
15
|
+
|
16
|
+
# @!method execute
|
17
|
+
# @param photocopier [Photocopier::SSH|Photocopier::FTP]
|
18
|
+
# @param logger [Wordmove::Logger]
|
19
|
+
# @param cli_options [Hash] Command line options (with symbolized keys)
|
20
|
+
# @param command_args ((String) remote file path, (String) local file path)
|
21
|
+
# @!scope class
|
22
|
+
# @return [LightService::Context] Action's context
|
23
|
+
executed do |context|
|
24
|
+
command = 'get'
|
25
|
+
|
26
|
+
context.logger.task_step false, "#{command}: #{context.command_args.join(' ')}"
|
27
|
+
|
28
|
+
next context if simulate?(cli_options: context.cli_options)
|
29
|
+
|
30
|
+
result = context.photocopier.send(command, *context.command_args)
|
31
|
+
|
32
|
+
next context if result == true
|
33
|
+
|
34
|
+
context.fail! "Failed to download file: #{context.command_args.first}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
# Helpers for +Wordmove::Actions+
|
4
|
+
#
|
5
|
+
# All helpers methos are class methods; this way we force avoiding the use
|
6
|
+
# of persistence. All actions have to be approached more as functional code
|
7
|
+
# than OO code. Thus helpers are condidered as functional code too.
|
8
|
+
module Helpers
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
# rubocop:disable Metrics/BlockLength
|
12
|
+
class_methods do
|
13
|
+
# Determines if we're running a simulated command. Actually this is a
|
14
|
+
# wrapper around command line arguments set by the user.
|
15
|
+
#
|
16
|
+
# @param cli_options [Hash] Command line options hash (deep symbolized).
|
17
|
+
# Generally you will find this into action's context
|
18
|
+
# @return [Boolean]
|
19
|
+
# @!scope class
|
20
|
+
def simulate?(cli_options:)
|
21
|
+
cli_options.fetch(:simulate, false)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the path to be excluded as per movefile.yml configuration.
|
25
|
+
# `remote_options` is always valid for both push and pull actions,
|
26
|
+
# because path exclusions are configured only on remote environments
|
27
|
+
#
|
28
|
+
# @param remote_options [Hash] The options hash for the selected remote
|
29
|
+
# remote environment. Generally you will find this into action's context.
|
30
|
+
# @return [Array<String>]
|
31
|
+
# @!scope class
|
32
|
+
def paths_to_exclude(remote_options:)
|
33
|
+
remote_options.fetch(:exclude, [])
|
34
|
+
end
|
35
|
+
|
36
|
+
# Given a path, it will append the `/*` string to it. This is how
|
37
|
+
# folder content - thus not the folder itself - is represented by rsync.
|
38
|
+
# The name of this method is not explicative nor expressive, but we retain
|
39
|
+
# it for backward compatibility.
|
40
|
+
#
|
41
|
+
# @param path [String]
|
42
|
+
# @return [String]
|
43
|
+
# @!scope class
|
44
|
+
def exclude_dir_contents(path:)
|
45
|
+
"#{path}/*"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Construct the mysql dump command as a string
|
49
|
+
#
|
50
|
+
# @param env_db_options [Hash] This hash is defined by the user through movefile.yml
|
51
|
+
# @param save_to_path [String] The path where the db dump will be saved
|
52
|
+
# @return [String] The full composed mysql command
|
53
|
+
# @!scope class
|
54
|
+
def mysql_dump_command(env_db_options:, save_to_path:)
|
55
|
+
command = ['mysqldump']
|
56
|
+
|
57
|
+
if env_db_options[:host].present?
|
58
|
+
command << "--host=#{Shellwords.escape(env_db_options[:host])}"
|
59
|
+
end
|
60
|
+
|
61
|
+
if env_db_options[:port].present?
|
62
|
+
command << "--port=#{Shellwords.escape(env_db_options[:port])}"
|
63
|
+
end
|
64
|
+
|
65
|
+
if env_db_options[:user].present?
|
66
|
+
command << "--user=#{Shellwords.escape(env_db_options[:user])}"
|
67
|
+
end
|
68
|
+
|
69
|
+
if env_db_options[:password].present?
|
70
|
+
command << "--password=#{Shellwords.escape(env_db_options[:password])}"
|
71
|
+
end
|
72
|
+
|
73
|
+
command << "--result-file=\"#{save_to_path}\""
|
74
|
+
|
75
|
+
if env_db_options[:mysqldump_options].present?
|
76
|
+
command << Shellwords.split(env_db_options[:mysqldump_options])
|
77
|
+
end
|
78
|
+
|
79
|
+
command << Shellwords.escape(env_db_options[:name])
|
80
|
+
|
81
|
+
command.join(' ')
|
82
|
+
end
|
83
|
+
|
84
|
+
# Construct the mysql import command as a string
|
85
|
+
#
|
86
|
+
# @param dump_path [String] The path where the dump to import is located
|
87
|
+
# @param env_db_options [Hash] This hash is defined by the user through movefile.yml
|
88
|
+
# @return [String] The full composed mysql command
|
89
|
+
# @!scope class
|
90
|
+
def mysql_import_command(dump_path:, env_db_options:)
|
91
|
+
command = ['mysql']
|
92
|
+
%i[host port user].each do |option|
|
93
|
+
if env_db_options[option].present?
|
94
|
+
command << "--#{option}=#{Shellwords.escape(env_db_options[option])}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
if env_db_options[:password].present?
|
98
|
+
command << "--password=#{Shellwords.escape(env_db_options[:password])}"
|
99
|
+
end
|
100
|
+
command << "--database=#{Shellwords.escape(env_db_options[:name])}"
|
101
|
+
if env_db_options[:mysql_options].present?
|
102
|
+
command << Shellwords.split(env_db_options[:mysql_options])
|
103
|
+
end
|
104
|
+
command << "--execute=\"SET autocommit=0;SOURCE #{dump_path};COMMIT\""
|
105
|
+
command.join(' ')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Construct the command to compress a file as a string. The command will be wrapped
|
109
|
+
# as argument to the +nice+ command, in order to lower the process priority and do
|
110
|
+
# not lock the system while compressing large files.
|
111
|
+
#
|
112
|
+
# @param file_path [String] The path where the file to be compressed is located
|
113
|
+
# @return [String] the command
|
114
|
+
# @!scope class
|
115
|
+
def compress_command(file_path:)
|
116
|
+
command = ['nice']
|
117
|
+
command << '-n'
|
118
|
+
command << '0'
|
119
|
+
command << 'gzip'
|
120
|
+
command << '-9'
|
121
|
+
command << '-f'
|
122
|
+
command << "\"#{file_path}\""
|
123
|
+
command.join(' ')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Construct the command to deflate a compressed file as a string.
|
127
|
+
#
|
128
|
+
# @param file_path [String] The path where the file to be deflated is located
|
129
|
+
# @return [String] the command
|
130
|
+
# @!scope class
|
131
|
+
def uncompress_command(file_path:)
|
132
|
+
command = ['gzip']
|
133
|
+
command << '-d'
|
134
|
+
command << '-f'
|
135
|
+
command << "\"#{file_path}\""
|
136
|
+
command.join(' ')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
# rubocop:enable Metrics/BlockLength
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
# Upload a single file to the remote server.
|
4
|
+
#
|
5
|
+
# @note The remote server is already configured inside the Photocopier object
|
6
|
+
# @note This action is *not* meant to be organized, but as a standalone one.
|
7
|
+
class PutFile
|
8
|
+
extend LightService::Action
|
9
|
+
include Wordmove::Actions::Helpers
|
10
|
+
|
11
|
+
expects :photocopier,
|
12
|
+
:logger,
|
13
|
+
:command_args,
|
14
|
+
:cli_options
|
15
|
+
|
16
|
+
# @!method execute
|
17
|
+
# @param photocopier [Photocopier]
|
18
|
+
# @param logger [Wordmove::Logger]
|
19
|
+
# @param command_args ((String) local file path, (String) remote file path)
|
20
|
+
# @return [LightService::Context] Action's context
|
21
|
+
executed do |context|
|
22
|
+
command = 'put'
|
23
|
+
|
24
|
+
# First argument could be a file or a content string. Do not log if the latter
|
25
|
+
message = if File.exist?(context.command_args.first)
|
26
|
+
context.command_args.join(' ')
|
27
|
+
else
|
28
|
+
context.command_args.second
|
29
|
+
end
|
30
|
+
|
31
|
+
context.logger.task_step false, "#{command}: #{message}"
|
32
|
+
|
33
|
+
result = if simulate?(cli_options: context.cli_options)
|
34
|
+
true
|
35
|
+
else
|
36
|
+
context.photocopier.send(command, *context.command_args)
|
37
|
+
end
|
38
|
+
|
39
|
+
next context if result == true
|
40
|
+
# We can't trust the return from the fotocopier method when using FTP. Keep on
|
41
|
+
# and have faith.
|
42
|
+
next context if context.photocopier.is_a? Photocopier::FTP
|
43
|
+
|
44
|
+
context.fail! "Failed to upload file: #{context.command_args.first}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Wordmove
|
2
|
+
module Actions
|
3
|
+
# Runs before push hooks by invoking the external service
|
4
|
+
# Wordmove::Hook
|
5
|
+
class RunAfterPullHook
|
6
|
+
extend ::LightService::Action
|
7
|
+
include Wordmove::Actions::Helpers
|
8
|
+
|
9
|
+
expects :movefile,
|
10
|
+
:cli_options
|
11
|
+
|
12
|
+
# @!method execute
|
13
|
+
# @param movefile [Wordmove::Movefile]
|
14
|
+
# @param cli_options [Hash]
|
15
|
+
# @return [LightService::Context] Action's context
|
16
|
+
executed do |context|
|
17
|
+
Wordmove::Hook.run(
|
18
|
+
:pull,
|
19
|
+
:after,
|
20
|
+
movefile: context.movefile,
|
21
|
+
simulate: simulate?(cli_options: context.cli_options)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|