dkdeploy-core 8.0.0

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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rubocop.yml +18 -0
  4. data/Berksfile +3 -0
  5. data/Berksfile.lock +46 -0
  6. data/CONTRIBUTORS.md +16 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +7 -0
  9. data/README.md +88 -0
  10. data/Rakefile +5 -0
  11. data/Vagrantfile +60 -0
  12. data/config/vm/cookbooks/dkdeploy-core/metadata.rb +10 -0
  13. data/config/vm/cookbooks/dkdeploy-core/recipes/default.rb +56 -0
  14. data/dkdeploy-core.gemspec +34 -0
  15. data/features/apache.feature +35 -0
  16. data/features/assets.feature +100 -0
  17. data/features/bower.feature +52 -0
  18. data/features/current_folder.feature +17 -0
  19. data/features/db.feature +93 -0
  20. data/features/deploy.feature +48 -0
  21. data/features/enhanced_symlinks.feature +17 -0
  22. data/features/error_handlers.feature +59 -0
  23. data/features/file_access.feature +120 -0
  24. data/features/maintenance.feature +25 -0
  25. data/features/project_version.feature +42 -0
  26. data/features/support/env.rb +22 -0
  27. data/features/utils.feature +81 -0
  28. data/lib/capistrano/copy.rb +2 -0
  29. data/lib/capistrano/dkdeploy/core.rb +88 -0
  30. data/lib/dkdeploy/constants.rb +156 -0
  31. data/lib/dkdeploy/copy.rb +121 -0
  32. data/lib/dkdeploy/core/version.rb +15 -0
  33. data/lib/dkdeploy/dsl.rb +23 -0
  34. data/lib/dkdeploy/helpers/assets.rb +50 -0
  35. data/lib/dkdeploy/helpers/common.rb +31 -0
  36. data/lib/dkdeploy/helpers/db.rb +49 -0
  37. data/lib/dkdeploy/helpers/file_system.rb +76 -0
  38. data/lib/dkdeploy/i18n.rb +143 -0
  39. data/lib/dkdeploy/interaction_handler/password.rb +27 -0
  40. data/lib/dkdeploy/rollback_manager.rb +18 -0
  41. data/lib/dkdeploy/tasks/apache.rake +29 -0
  42. data/lib/dkdeploy/tasks/assets.rake +96 -0
  43. data/lib/dkdeploy/tasks/bower.rake +54 -0
  44. data/lib/dkdeploy/tasks/copy.rake +26 -0
  45. data/lib/dkdeploy/tasks/current_folder.rake +16 -0
  46. data/lib/dkdeploy/tasks/db.rake +412 -0
  47. data/lib/dkdeploy/tasks/deploy.rake +77 -0
  48. data/lib/dkdeploy/tasks/enhanced_symlinks.rake +74 -0
  49. data/lib/dkdeploy/tasks/fail.rake +8 -0
  50. data/lib/dkdeploy/tasks/file_access.rake +89 -0
  51. data/lib/dkdeploy/tasks/maintenance.rake +73 -0
  52. data/lib/dkdeploy/tasks/project_version.rake +32 -0
  53. data/lib/dkdeploy/tasks/utils.rake +141 -0
  54. data/lib/dkdeploy.rb +1 -0
  55. data/spec/fixtures/application/Capfile +11 -0
  56. data/spec/fixtures/application/Gemfile +11 -0
  57. data/spec/fixtures/application/Version +1 -0
  58. data/spec/fixtures/application/config/assets_exclude_file.txt +1 -0
  59. data/spec/fixtures/application/config/deploy/dev.rb +35 -0
  60. data/spec/fixtures/application/config/deploy.rb +18 -0
  61. data/spec/fixtures/application/config/etc/apache2/conf/.htaccess.erb +12 -0
  62. data/spec/fixtures/application/config/etc/apache2/conf/dev.htaccess.erb +3 -0
  63. data/spec/fixtures/application/config/preseed/default_content.sql.gz +0 -0
  64. data/spec/fixtures/application/config/preseed/default_structure.sql.gz +0 -0
  65. data/spec/fixtures/application/config/preseed/fileadmin.tar.gz +0 -0
  66. data/spec/fixtures/application/config/preseed/uploads.tar.gz +0 -0
  67. data/spec/fixtures/application/htdocs/.hidden/.gitkeep +0 -0
  68. data/spec/fixtures/application/htdocs/Gemfile +0 -0
  69. data/spec/fixtures/application/htdocs/bower.json +15 -0
  70. data/spec/fixtures/application/htdocs/catalog/.hidden/.gitkeep +0 -0
  71. data/spec/fixtures/application/htdocs/catalog/index.html +1 -0
  72. data/spec/fixtures/application/htdocs/index.html +1 -0
  73. data/spec/fixtures/application/htdocs/stylesheets/test1/config.rb +3 -0
  74. data/spec/fixtures/application/htdocs/stylesheets/test1/css/.gitkeep +0 -0
  75. data/spec/fixtures/application/htdocs/stylesheets/test1/src/source.scss +5 -0
  76. data/spec/fixtures/application/htdocs/stylesheets/test2/config.rb +3 -0
  77. data/spec/fixtures/application/htdocs/stylesheets/test2/css/.gitkeep +0 -0
  78. data/spec/fixtures/application/htdocs/stylesheets/test2/src/source.scss +5 -0
  79. data/spec/fixtures/application/temp/dkdeploy_core.sql.gz +0 -0
  80. data/spec/fixtures/capistrano/configuration/add_output_after_create_symlink.rb +7 -0
  81. data/spec/fixtures/capistrano/configuration/custom_compass_sources.rb +4 -0
  82. data/spec/fixtures/capistrano/configuration/custom_file_access.rb +13 -0
  83. data/spec/fixtures/capistrano/configuration/default_deployment_behaviour.rb +9 -0
  84. metadata +346 -0
@@ -0,0 +1,77 @@
1
+ require 'dkdeploy/dsl'
2
+
3
+ include Capistrano::DSL
4
+ include Dkdeploy::DSL
5
+ include Dkdeploy::RollbackManager
6
+
7
+ namespace :deploy do
8
+ desc 'Generate the new release path name'
9
+ task :new_release_path do
10
+ jenkins_suffix = ''
11
+ # Add jenkins build name and number to release path
12
+ if ENV['BUILD_TAG']
13
+ jenkins_suffix = "-#{ENV['JOB_NAME']}-#{ENV['BUILD_NUMBER']}"
14
+ end
15
+ set_release_path releases_path.join(Time.now.utc.strftime('%Y-%m-%d-%H-%M-%S') + jenkins_suffix)
16
+ end
17
+
18
+ desc 'Handle deployment errors'
19
+ task :failed do
20
+ # Rollback tasks. Reverse sorting for rollback
21
+ tasks_for_rollback = rollback_tasks.reverse
22
+
23
+ run_locally do
24
+ error I18n.t('error_during_deployment', scope: :dkdeploy)
25
+ end
26
+
27
+ # Check if symlink is created at host
28
+ on release_roles(:all) do |host|
29
+ if test "[ `readlink #{current_path}` == #{release_path} ]"
30
+ invoke_for_server host, 'deploy:revert_release'
31
+ invoke_for_server host, 'deploy:symlink:release'
32
+ end
33
+ end
34
+ # Backup and remove last release
35
+ invoke 'deploy:cleanup_rollback'
36
+
37
+ run_locally do
38
+ error I18n.t('rollback_tasks', tasks_for_rollback: tasks_for_rollback.join(', '), scope: :dkdeploy) unless tasks_for_rollback.empty?
39
+ end
40
+
41
+ # Call rollback task after reset release
42
+ tasks_for_rollback.each do |task_name|
43
+ next unless Rake::Task.task_defined? task_name
44
+
45
+ # call rollback task
46
+ Rake::Task[task_name].reenable
47
+ invoke task_name
48
+ end
49
+
50
+ run_locally do
51
+ error I18n.t('rollback_finished', scope: :dkdeploy)
52
+ end
53
+ end
54
+
55
+ desc 'Remove and archive rolled-back release'
56
+ task :cleanup_rollback do
57
+ # Only keep x rolled-back releases as archive
58
+ on release_roles(:all) do
59
+ begin
60
+ rollback_archives = capture(:ls, '-x', deploy_path.join('rolled-back-release-*.tar.gz')).split
61
+ rescue
62
+ rollback_archives = []
63
+ end
64
+
65
+ next if rollback_archives.count <= fetch(:keep_rollback_archives)
66
+ info I18n.t('keep_rollback_archives',
67
+ scope: :dkdeploy,
68
+ host: host.to_s,
69
+ keep_rollback_archives: fetch(:keep_rollback_archives),
70
+ rollback_archives: rollback_archives.count)
71
+
72
+ list_of_deleteable_directories = rollback_archives - rollback_archives.last(fetch(:keep_rollback_archives))
73
+ string_of_deleteable_directories = list_of_deleteable_directories.map { |rollback_archive| current_path.join(rollback_archive) }.join(' ')
74
+ execute :rm, '-rf', string_of_deleteable_directories
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,74 @@
1
+ include Capistrano::DSL
2
+
3
+ namespace :deploy do
4
+ namespace :enhanced_symlinks do
5
+ namespace :check do
6
+ desc "Check directories to be linked exist in shared using the given hash 'enhanced_linked_dirs'"
7
+ task :linked_dirs do
8
+ next unless any? :enhanced_linked_dirs
9
+ fetch(:enhanced_linked_dirs).each do |source, _|
10
+ on release_roles :all do
11
+ execute :mkdir, '-pv', shared_path.join(source)
12
+ end
13
+ end
14
+ end
15
+
16
+ desc "Check directories of files to be linked exist in shared using the given hash 'enhanced_linked_files'"
17
+ task :make_linked_dirs do
18
+ next unless any? :enhanced_linked_files
19
+ fetch(:enhanced_linked_files).each do |_, target|
20
+ on release_roles :all do
21
+ execute :mkdir, '-pv', shared_path.join(target).dirname
22
+ end
23
+ end
24
+ end
25
+
26
+ desc "Check files to be linked exist in shared using the given hash 'enhanced_linked_files'"
27
+ task :linked_files do
28
+ next unless any? :enhanced_linked_files
29
+ fetch(:enhanced_linked_files).each do |source, _|
30
+ on release_roles :all do |host|
31
+ unless test "[ -f #{shared_path.join source} ]"
32
+ error t(:linked_file_does_not_exist, file: source, host: host)
33
+ exit 1
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ namespace :symlink do
41
+ desc "Symlink linked directories using the given hash 'enhanced_linked_dirs'"
42
+ task :linked_dirs do
43
+ next unless any? :enhanced_linked_dirs
44
+ fetch(:enhanced_linked_dirs).each do |source, target|
45
+ target = release_path.join(target)
46
+ source = shared_path.join(source)
47
+ on release_roles :all do
48
+ execute :mkdir, '-pv', target.dirname
49
+ unless test "[ -L #{target} ]"
50
+ execute :rm, '-rf', target if test "[ -d #{target} ]"
51
+ execute :ln, '-s', source, target
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ desc "Symlink linked files using the given hash 'enhanced_linked_files'"
58
+ task :linked_files do
59
+ next unless any? :enhanced_linked_files
60
+ fetch(:enhanced_linked_files).each do |source, target|
61
+ target = release_path.join(target)
62
+ source = shared_path.join(source)
63
+ on release_roles :all do
64
+ execute :mkdir, '-pv', target.dirname
65
+ unless test "[ -L #{target} ]"
66
+ execute :rm, target if test "[ -f #{target} ]"
67
+ execute :ln, '-s', source, target
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,8 @@
1
+ include Capistrano::DSL
2
+
3
+ namespace :deploy do
4
+ desc 'Deployment task which fails every time'
5
+ task :fail do
6
+ raise I18n.t('failing_on_purpose', scope: :dkdeploy)
7
+ end
8
+ end
@@ -0,0 +1,89 @@
1
+ require 'capistrano/i18n'
2
+ require 'dkdeploy/i18n'
3
+ require 'dkdeploy/helpers/file_system'
4
+
5
+ include Capistrano::DSL
6
+ include SSHKit::DSL
7
+ include Dkdeploy::Helpers::FileSystem
8
+
9
+ namespace :file_access do
10
+ desc 'Set standard defined owner and group on the shared and release path'
11
+ task set_owner_group: [:set_owner_group_of_shared_path, :set_owner_group_of_release_path]
12
+
13
+ desc 'Set standard defined owner and group on the shared path'
14
+ task :set_owner_group_of_shared_path do
15
+ on release_roles :app do
16
+ paths = merge_paths_with_resolved_symlinks self, shared_path
17
+ execute :chown, "#{fetch(:default_file_access_owner_of_shared_path)}:#{fetch(:default_file_access_group_of_shared_path)}", paths
18
+ end
19
+ end
20
+
21
+ desc 'Set recursively standard defined owner and group on the release path'
22
+ task :set_owner_group_of_release_path do
23
+ on release_roles :app do
24
+ paths = merge_paths_with_resolved_symlinks self, release_path
25
+ execute :chown, '-R', "#{fetch(:default_file_access_owner_of_release_path)}:#{fetch(:default_file_access_group_of_release_path)}", paths
26
+ end
27
+ end
28
+
29
+ desc 'Set standard defined file permissions on the shared and release path'
30
+ task set_permissions: [:set_permissions_of_shared_path, :set_permissions_of_release_path]
31
+
32
+ desc 'Set standard defined file permissions on the shared path'
33
+ task :set_permissions_of_shared_path do
34
+ on release_roles :app do
35
+ paths = merge_paths_with_resolved_symlinks self, shared_path
36
+ execute :chmod, fetch(:default_file_access_mode_of_shared_path), paths
37
+ end
38
+ end
39
+
40
+ desc 'Set recursively standard defined file permissions on the release path'
41
+ task :set_permissions_of_release_path do
42
+ on release_roles :app do
43
+ paths = merge_paths_with_resolved_symlinks self, release_path
44
+ execute :chmod, '-R', fetch(:default_file_access_mode_of_release_path), paths
45
+ end
46
+ end
47
+
48
+ desc 'Set custom defined owner, group and mode on paths'
49
+ task :set_custom_access do
50
+ fetch(:custom_file_access, {}).each do |role, paths_hash|
51
+ on release_roles role do |host|
52
+ release_or_shared_paths = paths_hash.select { |k, _| [:release_path, :shared_path].include? k } # allow only :release_path and :shared_path entries
53
+ release_or_shared_paths.each do |release_or_shared_path, paths|
54
+ paths.each do |path, access_properties|
55
+ path = map_path_in_release_or_shared_path(release_or_shared_path, path.to_s) # build absolute path
56
+ apply_file_access_permissions(self, host, path, access_properties)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ desc 'Set custom defined owner, group and mode on paths positively selected by a list of paths'
64
+ task :set_selected_custom_access, :selected_custom_file_access do |_, args|
65
+ list_of_selected_paths = ask_array_variable(args, :selected_custom_file_access, 'questions.selected_custom_file_access.paths')
66
+ if list_of_selected_paths.empty?
67
+ run_locally do
68
+ error I18n.t('resource.empty_selected_custom_file_access', scope: :dkdeploy)
69
+ exit 1
70
+ end
71
+ end
72
+
73
+ fetch(:custom_file_access, {}).each do |role, paths_hash|
74
+ on release_roles role do |host|
75
+ release_or_shared_paths = paths_hash.select { |k, _| [:release_path, :shared_path].include? k } # allow only :release_path and :shared_path entries
76
+ release_or_shared_paths.each do |release_or_shared_path, paths|
77
+ paths.each do |path, access_properties|
78
+ unless list_of_selected_paths.include?(path)
79
+ info I18n.t('resource.skipping_selected_custom_file_access', path: path, scope: :dkdeploy)
80
+ next
81
+ end
82
+ path = map_path_in_release_or_shared_path(release_or_shared_path, path.to_s) # build absolute path
83
+ apply_file_access_permissions(self, host, path, access_properties, true)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,73 @@
1
+ require 'json'
2
+ require 'i18n'
3
+ require 'dkdeploy/i18n'
4
+ require 'sshkit/dsl'
5
+ require 'capistrano/dsl'
6
+
7
+ include Capistrano::DSL
8
+ include SSHKit::DSL
9
+ include Dkdeploy::RollbackManager
10
+
11
+ namespace :maintenance do
12
+ # Remote maintenance config file path
13
+ #
14
+ # @return [String]
15
+ def maintenance_config_file_path
16
+ File.join shared_path, 'config/maintenance.json'
17
+ end
18
+
19
+ desc 'Enables the maintenance mode. In a regular case it should be disabled after deployment.'
20
+ task :enable do
21
+ # Define rollback behaviour
22
+ add_rollback_task 'maintenance:disable'
23
+
24
+ on release_roles :app, :web do
25
+ # create remote maintenance config file (and directory if not exists)
26
+ execute :mkdir, '-p', File.dirname(maintenance_config_file_path)
27
+ content_json = JSON.pretty_generate enabled_permanent: false
28
+ # scp-net::upload! expects StringIO object
29
+ content = StringIO.new content_json
30
+ upload! content, maintenance_config_file_path
31
+ info I18n.t('tasks.maintenance.enabled', mode: 'regular', scope: :dkdeploy)
32
+ end
33
+ end
34
+
35
+ desc "Enables the maintenance permanent mode. The 'maintenance:disable' will require 'maintenance:disable_permanent'."
36
+ task :enable_permanent do
37
+ invoke 'maintenance:enable'
38
+ on release_roles :app, :web do
39
+ content_json = JSON.pretty_generate enabled_permanent: true
40
+ # scp-net::upload! expects StringIO object
41
+ content = StringIO.new content_json
42
+ upload! content, maintenance_config_file_path
43
+ info I18n.t('tasks.maintenance.enabled', mode: 'permanent', scope: :dkdeploy)
44
+ end
45
+ end
46
+
47
+ desc "Disables the maintenance mode, if the 'maintenance:enabled_permanent' has not been enabled."
48
+ task :disable do
49
+ on release_roles :app, :web do
50
+ # noinspection RubyArgCount
51
+ if test %([ -f "#{maintenance_config_file_path}" ])
52
+ if test "[ -s #{maintenance_config_file_path} ]"
53
+ config_file_content = download! maintenance_config_file_path
54
+ config_file_content = JSON.parse config_file_content
55
+ if config_file_content.fetch 'enabled_permanent'
56
+ warn I18n.t('tasks.maintenance.can_not_disable_by_reason_of_permanent', scope: :dkdeploy)
57
+ next
58
+ end
59
+ end
60
+ execute :rm, '-f', maintenance_config_file_path
61
+ end
62
+ info I18n.t('tasks.maintenance.disabled', mode: 'regular', scope: :dkdeploy)
63
+ end
64
+ end
65
+
66
+ desc "Disables the maintenance permanent mode. The 'maintenance:disable' will work in a regular way again."
67
+ task :disable_permanent do
68
+ on release_roles :app, :web do
69
+ execute :rm, '-f', maintenance_config_file_path
70
+ info I18n.t('tasks.maintenance.disabled', mode: 'permanent', scope: :dkdeploy)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,32 @@
1
+ require 'capistrano/i18n'
2
+ require 'dkdeploy/i18n'
3
+ require 'dkdeploy/constants'
4
+
5
+ include Capistrano::DSL
6
+ include SSHKit::DSL
7
+
8
+ namespace :project_version do
9
+ desc 'Update Version file on server'
10
+ task :update, :version_file_path do |_, args|
11
+ version_file_path = ask_variable(args, :version_file_path, 'questions.version_file_path')
12
+ remote_version_file = File.join release_path, version_file_path, 'Version'
13
+ local_version_file = 'Version'
14
+
15
+ unless File.exist? local_version_file # check if the local version file exists
16
+ run_locally do
17
+ error I18n.t('file.not_exists', file: local_version_file, scope: :dkdeploy)
18
+ exit 1
19
+ end
20
+ end
21
+
22
+ on release_roles :app do
23
+ info I18n.t('tasks.project_version.update.update', scope: :dkdeploy)
24
+ # remove the to be replaced remote version file
25
+ if test " [ -f #{remote_version_file} ] "
26
+ execute :rm, '-f', remote_version_file
27
+ end
28
+ # upload the current version file
29
+ upload! local_version_file, remote_version_file
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,141 @@
1
+ require 'capistrano/i18n'
2
+ require 'dkdeploy/i18n'
3
+
4
+ include Capistrano::DSL
5
+ include SSHKit::DSL
6
+
7
+ namespace :utils do
8
+ desc 'Get current webroot path in releases'
9
+ task :get_current_path do
10
+ on primary :app do
11
+ info capture :readlink, '-f', current_path
12
+ end
13
+ end
14
+
15
+ desc 'Upload a file to current stage.'
16
+ task :upload_file, :file_name do |_, args|
17
+ file_name = ask_variable(args, :file_name, 'questions.file_name')
18
+ run_locally do
19
+ if file_name.empty?
20
+ error I18n.t('configuration.argument_missing', name: 'file_name', scope: :dkdeploy)
21
+ exit 1
22
+ end
23
+ # noinspection RubyArgCount
24
+ unless test "[ -f #{file_name} ]"
25
+ error I18n.t('file.not_exists', file: file_name, scope: :dkdeploy)
26
+ exit 1
27
+ end
28
+ end
29
+ regular_expression = "^#{fetch(:copy_source)}"
30
+ server_filename = File.join current_path, file_name.sub(Regexp.new(regular_expression), '')
31
+ on roles :app, :web do
32
+ directory_name = File.dirname server_filename
33
+ # noinspection RubyArgCount
34
+ unless test "[ -d #{directory_name} ]"
35
+ info I18n.t('directory.create', directory: directory_name, scope: :dkdeploy)
36
+ execute :mkdir, '-p', directory_name
37
+ end
38
+ info I18n.t('file.upload', file: file_name, target: server_filename, scope: :dkdeploy)
39
+ upload! file_name, server_filename
40
+ end
41
+ end
42
+
43
+ desc 'Download a file to current stage.'
44
+ task :download_file, :download_filename do |_, args|
45
+ filename = ask_variable(args, :download_filename, 'questions.file_name')
46
+ if filename.empty?
47
+ run_locally do
48
+ error I18n.t('configuration.argument_missing', name: 'download_filename', scope: :dkdeploy)
49
+ exit 1
50
+ end
51
+ end
52
+ remote_filename = File.join current_path, filename
53
+ on roles :app, :web do |server|
54
+ # noinspection RubyArgCount
55
+ unless test "[ -f #{remote_filename} ]"
56
+ error I18n.t('file.not_exists', file: remote_filename, scope: :dkdeploy)
57
+ next
58
+ end
59
+ local_filename = File.join local_dump_path, "#{File.basename(filename, '.*')}.#{server.hostname}#{File.extname(filename)}"
60
+ info I18n.t('file.download', file: remote_filename, target: local_filename, scope: :dkdeploy)
61
+ download! remote_filename, local_filename
62
+ end
63
+ end
64
+
65
+ desc 'Watch file on server'
66
+ task :watch_file, :file_name do |_, args|
67
+ file_name = args[:file_name] || fetch(:watch_file_name)
68
+ on roles :all do |host|
69
+ unless file_name
70
+ error I18n.t('configuration.argument_or_configuration_missing', name: 'file_name', variable: 'watch_file_name', scope: :dkdeploy)
71
+ exit 1
72
+ end
73
+ # noinspection RubyArgCount
74
+ if test " [ -f #{file_name} ] "
75
+ execute :tail, '-f', file_name
76
+ else
77
+ warn I18n.t('file.not_exists_on_host', file: file_name, host: host.hostname, scope: :dkdeploy)
78
+ end
79
+ end
80
+ end
81
+
82
+ desc 'Copy data to server with rsync'
83
+ task :rsync do
84
+ # Define local variables
85
+ rsync_roles = fetch :rsync_roles, :app
86
+ rsync_exclude = fetch :rsync_exclude, []
87
+ rsync_path = fetch :rsync_path, fetch(:copy_source)
88
+ # Append '/' to source directory
89
+ rsync_path = File.join(rsync_path, '')
90
+
91
+ rsync_command = %w(--verbose --recursive --perms --times --perms --perms --compress --force --cvs-exclude)
92
+
93
+ # Build exclude parameter
94
+ rsync_exclude.each do |exclude|
95
+ rsync_command << '--exclude "' + exclude + '"'
96
+ end
97
+ # Add local source directory
98
+ rsync_command << rsync_path
99
+
100
+ capistrano_ssh_option = fetch(:ssh_options, {})
101
+
102
+ run_locally do
103
+ # Fetch hosts for rsync command
104
+ hosts = roles rsync_roles
105
+ if hosts.empty?
106
+ error I18n.t('tasks.utils.rsync.no_host', scope: :dkdeploy)
107
+ exit 1
108
+ end
109
+
110
+ hosts.each do |host|
111
+ info I18n.t('tasks.utils.rsync.use_host', host: host.hostname, scope: :dkdeploy)
112
+ ssh_option = 'ssh'
113
+ ssh_option += ' -p ' + host.port.to_s unless host.port.nil?
114
+ if capistrano_ssh_option.key? :keys
115
+ capistrano_ssh_option[:keys].each do |file|
116
+ ssh_option += " -i '#{file}'"
117
+ end
118
+ end
119
+
120
+ user = host.user || capistrano_ssh_option[:user]
121
+
122
+ ssh_host = ''
123
+ ssh_host += user + '@' unless user.empty?
124
+ ssh_host += host.hostname
125
+
126
+ execute :rsync, rsync_command + ['--rsh="' + ssh_option + '"', ssh_host + ':' + release_path.to_s]
127
+ end
128
+ end
129
+ end
130
+
131
+ desc 'Create custom directories in shared path'
132
+ task :create_custom_directories, :directories do |_, args|
133
+ directories = ask_array_variable(args, :directories, 'questions.dir_names')
134
+
135
+ on release_roles :app do
136
+ directories.each do |directory|
137
+ execute :mkdir, '-p', File.join(shared_path, directory)
138
+ end
139
+ end
140
+ end
141
+ end