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,15 @@
1
+ module Dkdeploy
2
+ module Core
3
+ # Class for version number
4
+ #
5
+ class Version
6
+ MAJOR = 8
7
+ MINOR = 0
8
+ PATCH = 0
9
+
10
+ def self.to_s
11
+ [MAJOR, MINOR, PATCH].join('.')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module Dkdeploy
2
+ # TYPO3 dsl api
3
+ module DSL
4
+ # Execute a rake/capistrano task only for given server
5
+ #
6
+ # @param server [Capistrano::Configuration::Server] Server to execute task
7
+ # @param task [String] Name of rake/capistrano task
8
+ # @param args [Array] Arguments of rake/capistrano task
9
+ def invoke_for_server(server, task, *args) # rubocop:disable Metrics/AbcSize
10
+ backup_filter = fetch :filter, {}
11
+ new_server_filter = Marshal.load(Marshal.dump(backup_filter))
12
+ new_server_filter[:host] = server.hostname
13
+ set :filter, new_server_filter
14
+ env.setup_filters
15
+ info I18n.t('dsl.invoke_for_server.set_filter', task: task, host: server.hostname, scope: :dkdeploy)
16
+ invoke task, *args
17
+ Rake::Task[task].reenable
18
+ ensure
19
+ set :filter, backup_filter
20
+ env.setup_filters
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,50 @@
1
+ include Capistrano::DSL
2
+ include SSHKit::DSL
3
+
4
+ module Dkdeploy
5
+ module Helpers
6
+ # Helpers for Assets Tasks
7
+ module Assets
8
+ def assets_upload(name, folder = File.join('temp', 'assets')) # rubocop:disable Metrics/AbcSize
9
+ FileUtils.mkdir_p folder
10
+ on release_roles :web do
11
+ targz = name + '.tar.gz'
12
+ info I18n.t('tasks.assets.upload', file: targz, scope: :dkdeploy)
13
+ execute :mkdir, '-p', assets_path
14
+ upload! File.join(folder, targz), assets_path
15
+ within assets_path do
16
+ info I18n.t('tasks.assets.upload_extract', file: targz, scope: :dkdeploy)
17
+ execute :tar, 'xzfp', targz
18
+ execute :rm, '-f', targz
19
+ end
20
+ invoke 'file_access:set_custom_access'
21
+ end
22
+ end
23
+
24
+ def assets_download(folder) # rubocop:disable Metrics/AbcSize
25
+ FileUtils.mkdir_p File.join('temp', 'assets')
26
+ assets_exclude_file = fetch(:asset_exclude_file) || ''
27
+ on release_roles :web do
28
+ if File.exist?(assets_exclude_file)
29
+ exclude_filename = File.basename(assets_exclude_file)
30
+ execute :rm, '-f', File.join(assets_path, exclude_filename)
31
+ upload! assets_exclude_file, assets_path
32
+ exclude_option = "-X #{File.join(assets_path, exclude_filename)}"
33
+ else
34
+ info I18n.t('tasks.assets.exclude_file_not_found', scope: :dkdeploy)
35
+ end
36
+ within assets_path do
37
+ if test "[ -d #{assets_path}/#{folder} ]"
38
+ info I18n.t('tasks.assets.download', folder: folder, scope: :dkdeploy)
39
+ execute :tar, 'czfp', "#{folder}.tar.gz", exclude_option || '', folder
40
+ download! File.join(assets_path, "#{folder}.tar.gz"), File.join('temp', 'assets')
41
+ execute :rm, '-f', "#{folder}.tar.gz"
42
+ else
43
+ info I18n.t('tasks.assets.folder_not_found', folder: folder, scope: :dkdeploy)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ require 'highline'
2
+
3
+ module Dkdeploy
4
+ module Helpers
5
+ # common helpers, which are not task specific
6
+ module Common
7
+ def terminal
8
+ @terminal ||= HighLine.new
9
+ end
10
+
11
+ def ask_via_terminal(question_selector, &block)
12
+ question = I18n.t(question_selector, scope: :dkdeploy)
13
+ answer = terminal.ask(question, &block)
14
+ String.new(answer)
15
+ end
16
+
17
+ def ask_variable(args, variable_name_symbol, question_selector, &block)
18
+ ENV[variable_name_symbol.to_s.upcase] || args[variable_name_symbol] ||
19
+ fetch(variable_name_symbol) || ask_via_terminal(question_selector, &block)
20
+ end
21
+
22
+ def ask_array_variable(args, variable_name_symbol, question_selector, &block)
23
+ variable_content = ask_variable(args, variable_name_symbol, question_selector, &block)
24
+ return variable_content if variable_content.is_a?(Array)
25
+ return variable_content.split if variable_content.is_a?(String)
26
+
27
+ raise(I18n.t('errors.variable_content_is_neither_string_nor_array', variable_name: variable_name_symbol, scope: :dkdeploy))
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ require 'yaml'
2
+
3
+ include Capistrano::DSL
4
+
5
+ module Dkdeploy
6
+ module Helpers
7
+ # DB related helpers
8
+ module DB
9
+ def db_dump_file(infix = '')
10
+ date = DateTime.now.strftime(datetime_format)
11
+ ['database', fetch(:stage), infix, date].join('-') << '.sql'
12
+ end
13
+
14
+ def db_dump_file_content(table_name = nil)
15
+ db_dump_file ['content', table_name].compact.join('-')
16
+ end
17
+
18
+ def db_dump_file_structure(table_name = nil)
19
+ db_dump_file ['structure', table_name].compact.join('-')
20
+ end
21
+
22
+ def db_settings_hash
23
+ {
24
+ 'database' => {
25
+ 'host' => fetch(:db_host),
26
+ 'port' => fetch(:db_port),
27
+ 'name' => fetch(:db_name),
28
+ 'username' => fetch(:db_username),
29
+ 'password' => fetch(:db_password),
30
+ 'charset' => fetch(:db_charset)
31
+ }
32
+ }
33
+ end
34
+
35
+ # Read db settings for given context
36
+ #
37
+ # @param context [SSHKit::Backend::Netssh] SSHKit context
38
+ # @return [Hash] Hash with database settings
39
+ def read_db_settings_for_context(context)
40
+ unless context.test("[ -f #{remote_database_config_path} ]")
41
+ context.error I18n.t('errors.database_config_file_missing', scope: :dkdeploy)
42
+ return
43
+ end
44
+ json_string = context.download! remote_database_config_path
45
+ YAML.load(json_string).fetch('database')
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ include Capistrano::DSL
2
+
3
+ module Dkdeploy
4
+ module Helpers
5
+ # Class for the capistrano copy
6
+ #
7
+ module FileSystem
8
+ # Adds the absolute path prefix to the given relative path depending whether this needs to be in shared or release path.
9
+ #
10
+ # @param release_or_shared_path [Symbol] symbol of :shared_path or :release_path
11
+ # @param path [String] the relative path
12
+ # @return [String] absolute path
13
+ def map_path_in_release_or_shared_path(release_or_shared_path, path)
14
+ prefix_path = release_or_shared_path == :shared_path ? shared_path : release_path
15
+ prefix_path.join(path)
16
+ end
17
+
18
+ # Resolves the symlink path to its target, otherwise returns the path without any changing
19
+ # Note: the function can only be run within SSHKit context
20
+ #
21
+ # @param context [SSHKit::Backend::Netssh] SSHKit context
22
+ # @param path [String] path to resolve
23
+ # @return [String]
24
+ def resolve_path_if_symlink(context, path)
25
+ if context.test " [ -L #{path} ] "
26
+ return context.capture :readlink, '-f', path
27
+ end
28
+ path
29
+ end
30
+
31
+ # Iterates over the given paths' array, resolves symlinks and merges them together
32
+ # Example merge_paths_with_resolved_symlinks [p_1, symlink_1, p_2], 'dkdeploy-core.dev' -> [p_1, symlink_1, p_2, resolved_symlink_1]
33
+ # Note: the function can only be run within SSHKit context
34
+
35
+ # @param context [SSHKit::Backend::Netssh] SSHKit context
36
+ # @param paths [Array] array with paths to resolve
37
+ # @return [Array] the merged array with paths
38
+ def merge_paths_with_resolved_symlinks(context, *paths)
39
+ paths.each do |path|
40
+ resolved_path = resolve_path_if_symlink context, path
41
+ paths.push resolved_path unless paths.include? resolved_path
42
+ end
43
+ paths
44
+ end
45
+
46
+ # Applies file owner/group/mode permissions to path on host via Capistrano - optionally recursively
47
+ def apply_file_access_permissions(context, host, path, access_properties, force_recursive = false) # rubocop:disable Metrics/AbcSize
48
+ unless context.test " [ -e #{path} ] "
49
+ context.error I18n.t('resource.not_exists_on_host', resource: path, host: host.hostname, scope: :dkdeploy)
50
+ return
51
+ end
52
+
53
+ # if the access properties should be applied recursively
54
+ recursive = access_properties.fetch(:recursive, false) || force_recursive
55
+ recursive = recursive ? '-R' : ''
56
+
57
+ resolved_path = resolve_path_if_symlink(context, path)
58
+
59
+ # change owner if set
60
+ if access_properties.key?(:owner)
61
+ context.execute :chown, recursive, access_properties.fetch(:owner), resolved_path
62
+ end
63
+
64
+ # change group if set
65
+ if access_properties.key?(:group)
66
+ context.execute :chgrp, recursive, access_properties.fetch(:group), resolved_path
67
+ end
68
+
69
+ # change mode if set
70
+ if access_properties.key?(:mode) # rubocop:disable Style/GuardClause
71
+ context.execute :chmod, recursive, access_properties.fetch(:mode), resolved_path
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,143 @@
1
+ require 'i18n'
2
+
3
+ en = {
4
+ file: {
5
+ not_exists: 'File %{file} does not exist.',
6
+ not_exists_on_host: 'File %{file} does not exit on host %{host}.',
7
+ upload: 'Uploading %{file} to %{target}.',
8
+ download: 'Downloading %{file} to %{target}.',
9
+ copy: 'Copying %{file} to %{target}.',
10
+ remove: 'Removing %{path}.'
11
+ },
12
+ directory: {
13
+ create: 'Creating directory %{directory}.',
14
+ not_exists: 'Directory %{directory} does not exist.',
15
+ not_exists_on_host: 'Directory %{directory} does not exit on host %{host}.'
16
+ },
17
+ dsl: {
18
+ invoke_for_server: {
19
+ set_filter: "Invoking task '%{task}' for server '%{host}'"
20
+ }
21
+ },
22
+ resource: {
23
+ not_exists_on_host: 'The resource %{resource} does not exist on host %{host}.',
24
+ empty_selected_custom_file_access: "The variable 'selected_custom_file_access' is empty. Aborting task...",
25
+ skipping_selected_custom_file_access: "Skipped setting custom_file_access permissions for '%{path}' because it is not mentioned in selected_custom_file_access!"
26
+ },
27
+ configuration: {
28
+ argument_missing: "The '%{name}' argument missing.",
29
+ argument_or_configuration_missing: "The '%{name}' argument or '%{variable}' configuration variable missing."
30
+ },
31
+ questions: {
32
+ database: {
33
+ host: 'Please enter the hostname/IP of the database server',
34
+ port: 'Please enter the port of the database server',
35
+ name: 'Please enter the database name',
36
+ username: 'Please enter the database username',
37
+ password: 'Please enter the database password',
38
+ table_name: 'Please enter the table name',
39
+ table_names: 'Please enter a list of table names (entries separated by spaces)',
40
+ charset: 'Please enter the database character set',
41
+ zipped_db_file: 'Please enter the name of the zipped SQL script file'
42
+ },
43
+ bower: {
44
+ command: 'Please enter the command you want to run',
45
+ path: 'Please enter the path to the bower.json file',
46
+ paths: 'Please enter the paths bower.json files (separated by spaces)'
47
+ },
48
+ selected_custom_file_access: {
49
+ paths: 'Please enter a list of paths (entries separated by spaces)'
50
+ },
51
+ path: 'Please enter a local path',
52
+ file_name: 'Please enter a file name',
53
+ username: 'Please enter a username',
54
+ password: 'Please enter a password',
55
+ compass_sources: 'Please enter compass sources (entries separated by spaces)',
56
+ compass_compile_arguments: 'Please enter compass compile arguments (entries separated by spaces)',
57
+ asset_folders: 'Please enter asset folders (entries separated by spaces)',
58
+ asset_default_content: 'Please enter asset default content (entries separated by spaces)',
59
+ local_web_root_path: 'Please enter a local web root path',
60
+ version_file_path: 'Please enter a version file path',
61
+ dir_names: 'Please specify the direcotory names you wish to create'
62
+ },
63
+ success: {
64
+ settings_uploaded: 'The given database settings have been uploaded'
65
+ },
66
+ errors: {
67
+ file_not_found: 'File not found.',
68
+ password_was_empty: 'Password was empty. Please enter a password.',
69
+ connection_failed: 'Connection to database could not be established',
70
+ database_config_file_missing: 'Unable to locate database config file on remote server.',
71
+ variable_content_is_neither_string_nor_array: "Error setting value of variable '%{variable_name}'. This is neither a (by space splittable) string nor an array!"
72
+ },
73
+ info: {
74
+ local_md5: 'Local MD5 hash: %{md5_hash}',
75
+ remote_md5: 'Remote MD5 hash: %{md5_hash}',
76
+ md5_match: 'Local MD5 hash matches remote MD5 hash. Nothing to do!',
77
+ ignoring_current_folder: 'Ignoring current folder because either it does not exist or it is symlinked.'
78
+ },
79
+ tasks: {
80
+ apache: {
81
+ htaccess: {
82
+ render: 'Rendering .htaccess file.'
83
+ }
84
+ },
85
+ assets: {
86
+ add_htpasswd: {
87
+ successfully_created: 'htpasswd file successfully created.'
88
+ },
89
+ cleanup: 'Cleaning folder %{folder}.',
90
+ download: 'Downloading %{folder}',
91
+ upload: 'Uploading %{file}',
92
+ upload_extract: 'Extracting %{file}',
93
+ exclude_file_not_found: "No exclude file found. To use set variable 'assets_exclude_file'"
94
+ },
95
+ bower: {
96
+ skipping_missing_directory: 'Skipping directory %{bower_path} because it does not exist.',
97
+ skipping_directory_with_missing_bower_file: 'Skipping directory %{bower_path} because it does not contain a bower.json file.'
98
+ },
99
+ copy: {
100
+ archive: {
101
+ generate: 'Generating the tar archive.',
102
+ extract: 'Extracting archive to %{target}.'
103
+ }
104
+ },
105
+ maintenance: {
106
+ enabled: 'The %{mode} maintenance mode has successfully been enabled.',
107
+ disabled: 'The %{mode} maintenance mode has successfully been disabled.',
108
+ can_not_disable_by_reason_of_permanent: "Maintenance permanent mode has been enabled. Please call the task 'maintenance:disable_permanent'."
109
+ },
110
+ project_version: {
111
+ update: {
112
+ update: 'Updating the Version file.'
113
+ }
114
+ },
115
+ utils: {
116
+ rsync: {
117
+ no_host: 'No hosts for rsync found. Please check configuration "rsync_roles".',
118
+ use_host: "Use host '%{host}' for rsync."
119
+ }
120
+ }
121
+ },
122
+ log: {
123
+ revision_log_message: "Local deployment for directory '%{copy_source}' at '%{time}'"
124
+ },
125
+ error_during_deployment: 'Error occurred at deployment. Rollback to old release',
126
+ rollback_tasks: "Calling tasks '%{tasks_for_rollback}' for rollback action",
127
+ failing_on_purpose: 'Failing this deployment on purpose!',
128
+ rollback_finished: 'Rollback finished',
129
+ keep_rollback_archives: 'Keeping %{keep_rollback_archives} of %{rollback_archives} rolled back releases on %{host}',
130
+ setting_verbosity: 'Setting verbosity level to: %{verbosity_level} (from: %{old_verbosity})',
131
+ resetting_verbosity: 'Reset verbosity level to: %{old_verbosity} (from: %{verbosity_level})'
132
+ }
133
+
134
+ capistrano_i18n_overwritten = {
135
+ revision_log_message: "%{sha} on release '%{release}' by '%{user}'"
136
+ }
137
+
138
+ I18n.backend.store_translations(:en, dkdeploy: en)
139
+ I18n.backend.store_translations(:en, capistrano: capistrano_i18n_overwritten)
140
+
141
+ if I18n.respond_to?(:enforce_available_locales=)
142
+ I18n.enforce_available_locales = true
143
+ end
@@ -0,0 +1,27 @@
1
+ module Dkdeploy
2
+ module InteractionHandler
3
+ # Interaction handler for password
4
+ #
5
+ # @attr [String] password The password to send to terminal
6
+ class Password
7
+ def initialize(password)
8
+ @password = password
9
+ end
10
+
11
+ # Method to send password to terminal
12
+ #
13
+ # @param [SSHKit::Command] _command
14
+ # @param [Symbol] _stream_name
15
+ # @param [String] data
16
+ # @param [Net::SSH::Connection::Channel] channel
17
+ def on_data(_command, _stream_name, data, channel)
18
+ if data =~ /.*password.*/i
19
+ channel.send_data("#{@password}\n")
20
+ else
21
+ channel.close
22
+ raise 'Unexpected data from stream. Can not send password to undefined stream'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ module Dkdeploy
2
+ # The RollbackManager module is a mixin for managing rollback tasks.
3
+ module RollbackManager
4
+ # Getter for rollback_tasks
5
+ #
6
+ # @return [Array]
7
+ def rollback_tasks
8
+ @rollback_tasks ||= []
9
+ end
10
+
11
+ # Add new rollback task
12
+ #
13
+ # @param [String]
14
+ def add_rollback_task(task_name)
15
+ rollback_tasks << task_name if Rake::Task.task_defined? task_name
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ require 'erb'
2
+ require 'capistrano/i18n'
3
+ require 'dkdeploy/i18n'
4
+
5
+ include Capistrano::DSL
6
+ include SSHKit::DSL
7
+
8
+ namespace :apache do
9
+ desc 'Render .htaccess to web root from erb template(s)'
10
+ task :htaccess do |_, args|
11
+ local_web_root_path = ask_array_variable(args, :local_web_root_path, 'questions.local_web_root_path')
12
+
13
+ run_locally do
14
+ apache_configuration_path = File.join 'config', 'etc', 'apache2', 'conf'
15
+ htaccess_file_path = File.join apache_configuration_path, '.htaccess.erb'
16
+ destination_htaccess_file_path = File.join local_web_root_path, '.htaccess'
17
+
18
+ if File.exist? htaccess_file_path
19
+ info I18n.t('tasks.apache.htaccess.render', scope: :dkdeploy)
20
+ htaccess_template = ERB.new File.read(htaccess_file_path)
21
+
22
+ # write the new htaccess file content to the target .htaccess file
23
+ File.open(destination_htaccess_file_path, 'w') do |io|
24
+ io.write htaccess_template.result(binding)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end