redmine-installer 1.0.7 → 2.0.0.rc1

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +3 -15
  5. data/README.md +49 -177
  6. data/bin/redmine +4 -5
  7. data/lib/redmine-installer/backup.rb +13 -40
  8. data/lib/redmine-installer/cli.rb +92 -61
  9. data/lib/redmine-installer/command.rb +63 -117
  10. data/lib/redmine-installer/configuration.rb +148 -0
  11. data/lib/redmine-installer/database.rb +204 -0
  12. data/lib/redmine-installer/environment.rb +21 -0
  13. data/lib/redmine-installer/errors.rb +7 -0
  14. data/lib/redmine-installer/install.rb +37 -42
  15. data/lib/redmine-installer/logger.rb +83 -0
  16. data/lib/redmine-installer/package.rb +180 -0
  17. data/lib/redmine-installer/patches/ruby.rb +35 -0
  18. data/lib/redmine-installer/patches/tty.rb +16 -0
  19. data/lib/redmine-installer/profile.rb +24 -55
  20. data/lib/redmine-installer/redmine.rb +551 -0
  21. data/lib/redmine-installer/spec/spec.rb +81 -0
  22. data/lib/redmine-installer/task.rb +18 -77
  23. data/lib/redmine-installer/task_module.rb +12 -0
  24. data/lib/redmine-installer/upgrade.rb +51 -59
  25. data/lib/redmine-installer/utils.rb +46 -233
  26. data/lib/redmine-installer/version.rb +2 -4
  27. data/lib/redmine-installer.rb +69 -56
  28. data/redmine-installer.gemspec +20 -19
  29. data/spec/custom_matchers.rb +21 -0
  30. data/spec/installer_helper.rb +107 -0
  31. data/spec/installer_process.rb +82 -0
  32. data/spec/lib/backup_restore_spec.rb +81 -0
  33. data/spec/lib/install_spec.rb +125 -36
  34. data/spec/lib/upgrade_spec.rb +73 -52
  35. data/spec/packages/redmine-3.1.0.zip +0 -0
  36. data/spec/packages/redmine-3.2.0.zip +0 -0
  37. data/spec/packages/redmine-3.3.0-bad-migration.zip +0 -0
  38. data/spec/packages/redmine-3.3.0.zip +0 -0
  39. data/spec/packages/something-else.zip +0 -0
  40. data/spec/packages_helper.rb +19 -0
  41. data/spec/shared_contexts.rb +13 -0
  42. data/spec/spec_helper.rb +34 -18
  43. metadata +62 -63
  44. data/lib/redmine-installer/config_param.rb +0 -100
  45. data/lib/redmine-installer/error.rb +0 -5
  46. data/lib/redmine-installer/exec.rb +0 -158
  47. data/lib/redmine-installer/ext/module.rb +0 -7
  48. data/lib/redmine-installer/ext/string.rb +0 -15
  49. data/lib/redmine-installer/git.rb +0 -51
  50. data/lib/redmine-installer/helper.rb +0 -5
  51. data/lib/redmine-installer/helpers/generate_config.rb +0 -29
  52. data/lib/redmine-installer/locales/cs.yml +0 -147
  53. data/lib/redmine-installer/locales/en.yml +0 -154
  54. data/lib/redmine-installer/plugin.rb +0 -9
  55. data/lib/redmine-installer/plugins/base.rb +0 -24
  56. data/lib/redmine-installer/plugins/database.rb +0 -180
  57. data/lib/redmine-installer/plugins/email_sending.rb +0 -82
  58. data/lib/redmine-installer/plugins/redmine_plugin.rb +0 -82
  59. data/lib/redmine-installer/plugins/web_server.rb +0 -26
  60. data/lib/redmine-installer/step.rb +0 -16
  61. data/lib/redmine-installer/steps/backup.rb +0 -125
  62. data/lib/redmine-installer/steps/base.rb +0 -79
  63. data/lib/redmine-installer/steps/database_config.rb +0 -15
  64. data/lib/redmine-installer/steps/email_config.rb +0 -11
  65. data/lib/redmine-installer/steps/env_check.rb +0 -20
  66. data/lib/redmine-installer/steps/install.rb +0 -23
  67. data/lib/redmine-installer/steps/load_package.rb +0 -226
  68. data/lib/redmine-installer/steps/move_redmine.rb +0 -22
  69. data/lib/redmine-installer/steps/redmine_root.rb +0 -52
  70. data/lib/redmine-installer/steps/upgrade.rb +0 -57
  71. data/lib/redmine-installer/steps/validation.rb +0 -38
  72. data/lib/redmine-installer/steps/webserver_config.rb +0 -22
  73. data/spec/load_redmine.rb +0 -24
@@ -1,82 +0,0 @@
1
- module Redmine::Installer::Plugin
2
- class RedminePlugin < Base
3
-
4
- # Search plugins folder
5
- def self.am_i_there?
6
- records = Dir.glob(File.join('plugins', '*'))
7
- records.map! do |record|
8
- File.basename(record)
9
- end
10
-
11
- records.include?(self.class_name.downcase)
12
- end
13
-
14
- def self.final(*)
15
- end
16
-
17
- end
18
- end
19
-
20
- ##
21
- # EasyProject
22
- #
23
- # http://www.easyredmine.com
24
- #
25
- # Easy Redmine is complex project management web application best suited to project teams between
26
- # 10 - 100 users. Whether you manage just yourself or a huge team of software developers,
27
- # Easy Redmine will provide all necessary project management features to complete your projects
28
- # on time, scope and budget.
29
- #
30
- class EasyProject < Redmine::Installer::Plugin::RedminePlugin
31
-
32
- class Redmine::Installer::Command
33
- def rake_easyproject_install(env)
34
- run(RAKE, 'easyproject:install', get_rails_env(env), :'plugin.redmine_plugin.easyproject.install')
35
- end
36
- end
37
-
38
- def self.install(base)
39
- command.rake_easyproject_install(base.env) if am_i_there?
40
- end
41
-
42
- def self.upgrade(base)
43
- # Copy client modification folders
44
- # plugins/easyproject/easy_plugins/modification_*
45
- unless base.options['skip-old-modifications']
46
- easy_plugins_dir = File.join('plugins', 'easyproject', 'easy_plugins')
47
- old_modifications = Dir.glob(File.join(base.redmine_root, easy_plugins_dir, 'modification_*'))
48
- new_modifications = Dir.glob(File.join(base.tmp_redmine_root, easy_plugins_dir, 'modification_*'))
49
-
50
- # Modifications which are on old redmine but not new
51
- missing_modifications = old_modifications - new_modifications
52
-
53
- FileUtils.cp_r(missing_modifications, File.join(base.tmp_redmine_root, easy_plugins_dir))
54
- end
55
-
56
- install(base)
57
- end
58
-
59
- def self.final(base)
60
- return unless am_i_there?
61
-
62
- say %{
63
- <bright>EasyRedmine notes:</bright>
64
- You should create a maintenance task to CRON (on Linux) or Scheduled Tasks (on Windows)
65
- that will be running every 5-15 minutes. This one task aggregates all required tasks
66
- such as mail receiving, alerts evaluation etc. You should set up required parameters via
67
- administration -> scheduled tasks.
68
- Do not run this task under root, use same user that is used for web server.:
69
-
70
- <bright>bundle exec rake easyproject:scheduler:run_tasks RAILS_ENV=production</bright>
71
-
72
- For example:
73
- 1. Edit crontab
74
- crontab -e
75
-
76
- 2. Add:
77
- */15 * * * * cd #{base.redmine_root} && bundle exec rake easyproject:scheduler:run_tasks RAILS_ENV=production
78
-
79
-
80
- }
81
- end
82
- end
@@ -1,26 +0,0 @@
1
- module Redmine::Installer::Plugin
2
- class WebServer < Base
3
-
4
- # Generate config based on class and redmine_root.
5
- # Texts are in lang files.
6
- def self.generate_config(redmine_root)
7
- translate("plugin.#{self.superclass.class_name.downcase}.#{self.class_name.downcase}.configuration", redmine_root: redmine_root)
8
- end
9
-
10
- class Webrick < WebServer
11
- end
12
-
13
- class Thin < WebServer
14
- end
15
-
16
- class ApachePassenger < WebServer
17
- end
18
-
19
- class NginxPassenger < WebServer
20
- end
21
-
22
- class Puma < WebServer
23
- end
24
-
25
- end
26
- end
@@ -1,16 +0,0 @@
1
- module Redmine::Installer
2
- module Step
3
- autoload :Base, 'redmine-installer/steps/base'
4
- autoload :LoadPackage, 'redmine-installer/steps/load_package'
5
- autoload :DatabaseConfig, 'redmine-installer/steps/database_config'
6
- autoload :EmailConfig, 'redmine-installer/steps/email_config'
7
- autoload :Install, 'redmine-installer/steps/install'
8
- autoload :MoveRedmine, 'redmine-installer/steps/move_redmine'
9
- autoload :WebserverConfig, 'redmine-installer/steps/webserver_config'
10
- autoload :Validation, 'redmine-installer/steps/validation'
11
- autoload :Backup, 'redmine-installer/steps/backup'
12
- autoload :Upgrade, 'redmine-installer/steps/upgrade'
13
- autoload :RedmineRoot, 'redmine-installer/steps/redmine_root'
14
- autoload :EnvCheck, 'redmine-installer/steps/env_check'
15
- end
16
- end
@@ -1,125 +0,0 @@
1
- require 'fileutils'
2
- require 'zip'
3
-
4
- module Redmine::Installer::Step
5
- class Backup < Base
6
-
7
- DEFAULT_BACKUP_DIR = File.join(Dir.home, 'redmine-backups')
8
-
9
- def up
10
- choices = {}
11
- choices[:full_backup] = t(:full_backup)
12
- choices[:backup] = t(:backup)
13
- choices[:only_database] = t(:only_database)
14
- choices[:skip] = t(:skip)
15
-
16
- @backup_type ||= choose(:do_you_want_backup_redmine, choices, default: :backup)
17
-
18
- case @backup_type
19
- when :full_backup
20
- do_full_backup
21
- when :backup
22
- do_backup
23
- when :only_database
24
- database_backup
25
- end
26
- end
27
-
28
- def down
29
- # It could be dangerous
30
- #
31
- # if @database_backed_up
32
- # say(:restoring_database)
33
- # database_restore
34
- # end
35
- end
36
-
37
- def final
38
- if @current_backup_dir
39
- say t(:backup_is_stored_at, dir: @current_backup_dir), 2
40
- end
41
- end
42
-
43
- def save(configuration)
44
- configuration['backup_type'] = @backup_type
45
- configuration['backup_dir'] = @backup_dir
46
- end
47
-
48
- def load(configuration)
49
- @backup_type = configuration['backup_type']
50
- @backup_dir = configuration['backup_dir']
51
- end
52
-
53
- private
54
-
55
- def check_backup_dir
56
- if @backup_dir.nil?
57
- dir = ask(:what_dir_for_backups, default: DEFAULT_BACKUP_DIR)
58
- dir = File.expand_path(dir)
59
-
60
- try_create_dir(dir) unless Dir.exist?(dir)
61
-
62
- @backup_dir = dir
63
- end
64
- end
65
-
66
- def create_current_backup_dir
67
- return if @current_backup_dir
68
-
69
- check_backup_dir
70
- @current_backup_dir = File.join(@backup_dir, Time.now.strftime('backup_%d%m%Y_%H%M%S'))
71
- try_create_dir(@current_backup_dir)
72
- end
73
-
74
- def database_backup
75
- create_current_backup_dir
76
-
77
- plugin::Database.backup_all(base.redmine_root, @current_backup_dir)
78
- @database_backed_up = true
79
- end
80
-
81
- def database_restore
82
- plugin::Database.restore_all(base.redmine_root, @current_backup_dir)
83
- end
84
-
85
- def do_full_backup
86
- create_current_backup_dir
87
-
88
- zipfile_name = File.join(@current_backup_dir, 'redmine.zip')
89
-
90
- Dir.chdir(base.redmine_root) do
91
- Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
92
- Dir.glob(File.join('**', '{*,.*}')).each do |entry|
93
- next if entry.end_with?('.') || entry.end_with?('..')
94
-
95
- zipfile.add(entry, entry)
96
- end
97
- end
98
- end
99
-
100
- database_backup
101
- end
102
-
103
- def do_backup
104
- create_current_backup_dir
105
-
106
- # create config dir
107
- config_dir = File.join(@current_backup_dir, 'config')
108
- FileUtils.mkdir(config_dir)
109
-
110
- # database.yml
111
- database_file = File.join(base.redmine_root, plugin::Database::DATABASE_YML_PATH)
112
- FileUtils.cp(database_file, config_dir) if File.exist?(database_file)
113
-
114
- # configuration.yml
115
- configuration_file = File.join(base.redmine_root, plugin::EmailSending::CONFIGURATION_YML_PATH)
116
- FileUtils.cp(configuration_file, config_dir) if File.exist?(configuration_file)
117
-
118
- # files
119
- FileUtils.cp_r(File.join(base.redmine_root, 'files'), @current_backup_dir)
120
-
121
- database_backup
122
- end
123
-
124
- end
125
- end
@@ -1,79 +0,0 @@
1
- module Redmine::Installer::Step
2
- ##
3
- # Base
4
- #
5
- # == Steps:
6
- # prepare::
7
- # used for argument validation
8
- #
9
- # up::
10
- # actions
11
- #
12
- # final::
13
- # for printing informations
14
- #
15
- # down::
16
- # if something went wrong
17
- #
18
- class Base
19
-
20
- include Redmine::Installer::Utils
21
-
22
- attr_accessor :index
23
- attr_accessor :base
24
- attr_accessor :ran
25
-
26
- def initialize(index, base)
27
- self.index = index
28
- self.base = base
29
- self.ran = false
30
- end
31
-
32
- def print_title
33
- title = '<bright><on_black><white>'
34
- title << "#{index}. "
35
- title << translate("step.#{self.class.class_name.underscore}.title"
36
- )
37
- title << '</white></on_black></bright>'
38
-
39
- say(title, 1)
40
- end
41
-
42
- def print_header
43
- end
44
-
45
- def print_footer
46
- end
47
-
48
- def prepare
49
- end
50
-
51
- def up
52
- end
53
-
54
- def final
55
- end
56
-
57
- def down
58
- end
59
-
60
- def save(*)
61
- end
62
-
63
- def load(*)
64
- end
65
-
66
- def redmine_plugins
67
- @redmine_plugins ||= _redmine_plugins
68
- end
69
-
70
- private
71
-
72
- def _redmine_plugins
73
- Dir.glob(File.join(base.redmine_root, 'plugins', '*')).select do |entry|
74
- File.directory?(entry)
75
- end
76
- end
77
-
78
- end
79
- end
@@ -1,15 +0,0 @@
1
- module Redmine::Installer::Step
2
- class DatabaseConfig < Base
3
-
4
- include Redmine::Installer::Helper::GenerateConfig
5
-
6
- def up
7
- if create_for(plugin::Database)
8
- # continue
9
- else
10
- base.settings[:skip_migration] = true
11
- end
12
- end
13
-
14
- end
15
- end
@@ -1,11 +0,0 @@
1
- module Redmine::Installer::Step
2
- class EmailConfig < Base
3
-
4
- include Redmine::Installer::Helper::GenerateConfig
5
-
6
- def up
7
- create_for(plugin::EmailSending)
8
- end
9
-
10
- end
11
- end
@@ -1,20 +0,0 @@
1
- module Redmine::Installer::Step
2
- class EnvCheck < Base
3
-
4
- def prepare
5
- # Check if windows
6
- # if windows?
7
- # confirm(:do_you_want_continue_if_windows, false)
8
- # end
9
-
10
- if root? && !confirm(:installer_run_as_root, false)
11
- error(:terminated_by_user)
12
- end
13
- end
14
-
15
- def up
16
- say '<green>... OK</green>', 1
17
- end
18
-
19
- end
20
- end
@@ -1,23 +0,0 @@
1
- module Redmine::Installer::Step
2
- class Install < Base
3
-
4
- def up
5
- Dir.chdir(base.tmp_redmine_root) do
6
- command.bundle_install(base.env)
7
-
8
- return if base.settings[:skip_migration]
9
-
10
- command.rake_db_create(base.env)
11
- command.rake_db_migrate(base.env)
12
- command.rake_redmine_plugin_migrate(base.env) if some_plugins?
13
- command.rake_generate_secret_token(base.env)
14
-
15
- # Other plugins can have post-install procedure
16
- plugin::RedminePlugin.all.each do |plugin|
17
- plugin.install(base)
18
- end
19
- end
20
- end
21
-
22
- end
23
- end
@@ -1,226 +0,0 @@
1
- require 'rubygems/package'
2
- require 'ruby-progressbar'
3
- require 'fileutils'
4
- require 'net/http'
5
- require 'tmpdir'
6
- require 'zlib'
7
- require 'zip'
8
- require 'uri'
9
-
10
- module Redmine::Installer::Step
11
- class LoadPackage < Base
12
-
13
- SUPPORTED_ARCHIVE_FORMATS = ['.zip', '.gz', '.tgz']
14
- TAR_LONGLINK = '././@LongLink'
15
- PROGRESSBAR_FORMAT = '%a [%b>%i] %p%% %t'
16
-
17
- def prepare
18
- case base.options[:source]
19
- when 'file'
20
-
21
- unless File.exist?(base.package)
22
- if base.package =~ /\Av?(\d\.\d\.\d)\Z/
23
- download_redmine($1)
24
- end
25
- end
26
-
27
- unless File.exist?(base.package)
28
- error :file_not_exist, file: base.package
29
- end
30
-
31
- @type = File.extname(base.package)
32
- unless SUPPORTED_ARCHIVE_FORMATS.include?(@type)
33
- error :file_must_have_format, file: base.package, formats: SUPPORTED_ARCHIVE_FORMATS.join(', ')
34
- end
35
-
36
- when 'git'
37
- nil
38
- else
39
- error :error_unsupported_source, source: base.options[:source]
40
- end
41
- end
42
-
43
- def up
44
- case base.options[:source]
45
- when 'file'
46
- load_from_archive
47
- when 'git'
48
- load_from_git
49
- end
50
- end
51
-
52
- def down
53
- FileUtils.remove_entry_secure(@tmpdir) if @tmpdir
54
- FileUtils.safe_unlink(@tmpfile) if @tmpfile
55
- end
56
-
57
- def final
58
- down
59
- say(t(:redmine_was_installed_to, dir: base.redmine_root), 1)
60
- end
61
-
62
- private
63
-
64
- # =======================================================================
65
- # General
66
-
67
- # Move files from temp dir to target. First check
68
- # if folder contains redmine or contains
69
- # folder which contains redmine :-)
70
- #
71
- # Package can have format:
72
- # |-- redmine-2
73
- # |-- app
74
- # `-- config
75
- # ...
76
- #
77
- def get_tmp_redmine_root
78
- base.tmp_redmine_root = @tmpdir
79
-
80
- loop {
81
- ls = Dir.glob(File.join(base.tmp_redmine_root, '*'))
82
-
83
- if ls.size == 1
84
- base.tmp_redmine_root = ls.first
85
- else
86
- break
87
- end
88
- }
89
- end
90
-
91
-
92
- # =======================================================================
93
- # File
94
-
95
- def load_from_archive
96
- # Make temp directory and extract archive + move it to the redmine_folder
97
- extract_to_tmp
98
-
99
- # Locate redmine_root in tmpdir
100
- get_tmp_redmine_root
101
- end
102
-
103
- def download_redmine(version)
104
- @tmpfile = Tempfile.new(['redmine', '.zip'])
105
- @tmpfile.binmode
106
-
107
- uri = URI("http://www.redmine.org/releases/redmine-#{version}.zip")
108
-
109
- Net::HTTP.start(uri.host, uri.port) do |http|
110
- head = http.request_head(uri)
111
-
112
- unless head.is_a?(Net::HTTPSuccess)
113
- error :cannot_download_redmine_version, version: version
114
- end
115
-
116
- say(:redmine_downloading, 1)
117
- progressbar = ProgressBar.create(format: PROGRESSBAR_FORMAT, total: head['content-length'].to_i)
118
-
119
- http.get(uri) do |data|
120
- @tmpfile.write(data)
121
- progressbar.progress += data.size
122
- end
123
-
124
- progressbar.finish
125
- say(nil, 1)
126
- end
127
-
128
- @tmpfile.close
129
-
130
- base.package = @tmpfile.path
131
- end
132
-
133
- def extract_to_tmp
134
- @tmpdir = Dir.mktmpdir
135
-
136
- case @type
137
- when '.zip'
138
- extract_zip
139
- when '.gz', '.tgz'
140
- extract_tar_gz
141
- end
142
- end
143
-
144
- def extract_zip
145
- Zip::File.open(base.package) do |zip_file|
146
- # Progressbar
147
- progressbar = ProgressBar.create(format: PROGRESSBAR_FORMAT, total: zip_file.size)
148
-
149
- zip_file.each do |entry|
150
- dest_file = File.join(@tmpdir, entry.name)
151
- FileUtils.mkdir_p(File.dirname(dest_file))
152
-
153
- entry.extract(dest_file)
154
- progressbar.increment
155
- end
156
- end
157
- end
158
-
159
- # Extract .tar.gz archive
160
- # based on http://dracoater.blogspot.cz/2013/10/extracting-files-from-targz-with-ruby.html
161
- #
162
- # Originally tar did not support paths longer than 100 chars. GNU tar is better and they
163
- # implemented support for longer paths, but it was made through a hack called ././@LongLink.
164
- # Shortly speaking, if you stumble upon an entry in tar archive which path equals to above
165
- # mentioned ././@LongLink, that means that the following entry path is longer than 100 chars and
166
- # is truncated. The full path of the following entry is actually the value of the current entry.
167
- #
168
- def extract_tar_gz
169
- Gem::Package::TarReader.new(Zlib::GzipReader.open(base.package)) do |tar|
170
-
171
- # Progressbar
172
- progressbar = ProgressBar.create(format: PROGRESSBAR_FORMAT, total: tar.count)
173
-
174
- # tar.count move position pointer to end
175
- tar.rewind
176
-
177
- dest_file = nil
178
- tar.each do |entry|
179
- if entry.full_name == TAR_LONGLINK
180
- dest_file = File.join(@tmpdir, entry.read.strip)
181
- next
182
- end
183
- dest_file ||= File.join(@tmpdir, entry.full_name)
184
- if entry.directory?
185
- FileUtils.rm_rf(dest_file) unless File.directory?(dest_file)
186
- FileUtils.mkdir_p(dest_file, mode: entry.header.mode, verbose: false)
187
- elsif entry.file?
188
- FileUtils.rm_rf(dest_file) unless File.file?(dest_file)
189
- File.open(dest_file, 'wb') do |f|
190
- f.write(entry.read)
191
- end
192
- FileUtils.chmod(entry.header.mode, dest_file, verbose: false)
193
- elsif entry.header.typeflag == '2' # symlink
194
- File.symlink(entry.header.linkname, dest_file)
195
- end
196
-
197
- dest_file = nil
198
- progressbar.increment
199
- end
200
- end
201
- end
202
-
203
-
204
- # =======================================================================
205
- # Git
206
-
207
- def load_from_git
208
- @tmpdir = Dir.mktmpdir
209
-
210
- # Package is remote url to git repository
211
- remote = base.package
212
-
213
- if remote
214
- # Clone repository
215
- Git.clone(remote, @tmpdir, base.options['branch'])
216
- else
217
- # Copy current repository to tmp and run pull
218
- Git.copy_and_fetch(base.redmine_root, @tmpdir)
219
- end
220
-
221
- # Locate redmine_root in tmpdir
222
- get_tmp_redmine_root
223
- end
224
-
225
- end
226
- end