redmine-installer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/Gemfile +19 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +273 -0
  6. data/Rakefile +7 -0
  7. data/bin/redmine +8 -0
  8. data/lib/redmine-installer.rb +72 -0
  9. data/lib/redmine-installer/backup.rb +48 -0
  10. data/lib/redmine-installer/cli.rb +90 -0
  11. data/lib/redmine-installer/command.rb +142 -0
  12. data/lib/redmine-installer/config_param.rb +90 -0
  13. data/lib/redmine-installer/error.rb +5 -0
  14. data/lib/redmine-installer/exec.rb +158 -0
  15. data/lib/redmine-installer/ext/module.rb +7 -0
  16. data/lib/redmine-installer/ext/string.rb +15 -0
  17. data/lib/redmine-installer/git.rb +51 -0
  18. data/lib/redmine-installer/helper.rb +5 -0
  19. data/lib/redmine-installer/helpers/generate_config.rb +29 -0
  20. data/lib/redmine-installer/install.rb +56 -0
  21. data/lib/redmine-installer/locales/cs.yml +145 -0
  22. data/lib/redmine-installer/locales/en.yml +146 -0
  23. data/lib/redmine-installer/plugin.rb +9 -0
  24. data/lib/redmine-installer/plugins/base.rb +28 -0
  25. data/lib/redmine-installer/plugins/database.rb +168 -0
  26. data/lib/redmine-installer/plugins/email_sending.rb +82 -0
  27. data/lib/redmine-installer/plugins/redmine_plugin.rb +30 -0
  28. data/lib/redmine-installer/plugins/web_server.rb +26 -0
  29. data/lib/redmine-installer/profile.rb +74 -0
  30. data/lib/redmine-installer/step.rb +15 -0
  31. data/lib/redmine-installer/steps/backup.rb +120 -0
  32. data/lib/redmine-installer/steps/base.rb +60 -0
  33. data/lib/redmine-installer/steps/database_config.rb +15 -0
  34. data/lib/redmine-installer/steps/email_config.rb +11 -0
  35. data/lib/redmine-installer/steps/install.rb +21 -0
  36. data/lib/redmine-installer/steps/load_package.rb +180 -0
  37. data/lib/redmine-installer/steps/move_redmine.rb +22 -0
  38. data/lib/redmine-installer/steps/redmine_root.rb +29 -0
  39. data/lib/redmine-installer/steps/upgrade.rb +55 -0
  40. data/lib/redmine-installer/steps/validation.rb +38 -0
  41. data/lib/redmine-installer/steps/webserver_config.rb +22 -0
  42. data/lib/redmine-installer/task.rb +85 -0
  43. data/lib/redmine-installer/upgrade.rb +68 -0
  44. data/lib/redmine-installer/utils.rb +233 -0
  45. data/lib/redmine-installer/version.rb +5 -0
  46. data/redmine-installer.gemspec +25 -0
  47. data/spec/lib/install_spec.rb +46 -0
  48. data/spec/lib/upgrade_spec.rb +62 -0
  49. data/spec/load_redmine.rb +24 -0
  50. data/spec/spec_helper.rb +30 -0
  51. metadata +130 -0
@@ -0,0 +1,90 @@
1
+ require 'gli'
2
+
3
+ module Redmine::Installer
4
+ class CLI
5
+ extend GLI::App
6
+
7
+ def self.spec
8
+ @spec ||= Gem::Specification::load('redmine-installer.gemspec')
9
+ end
10
+
11
+ def self.start(argv)
12
+ # Program settings
13
+ program_desc I18n.translate(:redmine_installer_summary)
14
+ version Redmine::Installer::VERSION
15
+
16
+ # Global options
17
+
18
+ # Verbose
19
+ desc I18n.translate(:cli_show_verbose_output)
20
+ default_value false
21
+ switch [:d, :v, :debug, :verbose], negatable: false
22
+
23
+ # Locale
24
+ default_value 'en'
25
+ flag [:l, :locale]
26
+
27
+ # Before all action
28
+ pre do |global_options, command, options, args|
29
+ $verbose = global_options[:debug]
30
+ I18n.locale = global_options[:locale]
31
+ true
32
+ end
33
+
34
+ # Install command
35
+ desc I18n.translate(:cli_install_desc)
36
+ arg :package
37
+ command [:i, :install] do |c|
38
+ c.flag [:s, :source], default_value: 'file',
39
+ must_match: ['file', 'git'],
40
+ desc: I18n.translate(:cli_flag_source)
41
+
42
+ c.flag [:b, :branch], default_value: 'master',
43
+ desc: I18n.translate(:cli_flag_branch)
44
+
45
+ c.flag [:e, :env, :environment], default_value: ['production'],
46
+ desc: I18n.translate(:cli_flag_environment),
47
+ type: Array
48
+
49
+ c.action do |global_options, options, args|
50
+ run_action('install', args.first, options)
51
+ end
52
+ end
53
+
54
+ # Upgrade command
55
+ desc I18n.translate(:cli_upgrade_desc)
56
+ arg :package
57
+ command [:u, :upgrade] do |c|
58
+ c.flag [:p, :profile]
59
+ c.flag [:s, :source], default_value: 'file',
60
+ must_match: ['file', 'git'],
61
+ desc: I18n.translate(:cli_flag_source)
62
+
63
+ c.flag [:e, :env, :environment], default_value: ['production'],
64
+ desc: I18n.translate(:cli_flag_environment),
65
+ type: Array
66
+
67
+ c.action do |global_options, options, args|
68
+ run_action('upgrade', args.first, options)
69
+ end
70
+ end
71
+
72
+ # Backup command
73
+ desc I18n.translate(:cli_backup_desc)
74
+ arg :redmine_root
75
+ command [:b, :backup] do |c|
76
+ c.flag [:p, :profile]
77
+ c.action do |global_options, options, args|
78
+ run_action('backup', args.first, options)
79
+ end
80
+ end
81
+
82
+ run(argv)
83
+ end
84
+
85
+ def self.run_action(action, *args)
86
+ Redmine::Installer.const_get(action.capitalize).new(*args).run
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,142 @@
1
+ require 'singleton'
2
+
3
+ module Redmine::Installer
4
+ class Command
5
+ include Singleton
6
+ include Redmine::Installer::Utils
7
+
8
+ RAKE = 'bundle exec rake'
9
+
10
+ def bundle_install(env)
11
+ run('bundle install', get_bundle_env(env), :'command.bundle_install')
12
+ end
13
+
14
+ def rake_db_create(env)
15
+ run(RAKE, 'db:create', get_rails_env(env), :'command.rake_db_create')
16
+ end
17
+
18
+ def rake_db_migrate(env)
19
+ run(RAKE, 'db:migrate', get_rails_env(env), :'command.rake_db_migrate')
20
+ end
21
+
22
+ def rake_redmine_plugin_migrate(env)
23
+ run(RAKE, 'redmine:plugins:migrate', get_rails_env(env), :'command.rake_redmine_plugin_migrate')
24
+ end
25
+
26
+ def rake_generate_secret_token(env)
27
+ run(RAKE, 'generate_secret_token', get_rails_env(env), :'command.rake_generate_secret_token')
28
+ end
29
+
30
+ private
31
+
32
+ def run(*args)
33
+ _args = args.dup
34
+
35
+ # Last element is title
36
+ title = args.pop
37
+ title = translate(title) if title.is_a?(Symbol)
38
+ title = "--> <yellow>#{title}</yellow>"
39
+ colorize(title)
40
+
41
+ command = args.join(' ')
42
+
43
+ puts '-->'
44
+ puts title
45
+ puts '-->'
46
+ success = Kernel.system(command)
47
+
48
+ unless success
49
+ if confirm(:do_you_want_repeat_command, false)
50
+ return run(*_args)
51
+ end
52
+ end
53
+
54
+ return success
55
+ end
56
+
57
+ def get_rails_env(env)
58
+ if env.include?('production'); 'RAILS_ENV=production'
59
+ elsif env.include?('development'); 'RAILS_ENV=development'
60
+ elsif env.include?('test'); 'RAILS_ENV=test'
61
+ else
62
+ ''
63
+ end
64
+ end
65
+
66
+ def get_bundle_env(env)
67
+ if env.include?('production')
68
+ '--without development test'
69
+ else
70
+ ''
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Class for easier create complex command
79
+ #
80
+ # == Examples:
81
+ #
82
+ # Instead of this:
83
+ # exec('rake redmine:plugins:migrate RAILS_ENV=production')
84
+ #
85
+ # you can write:
86
+ # rake.plugin_migrate.production.run
87
+ #
88
+ # module Redmine::Installer
89
+ # module Command
90
+ # class Base
91
+ # # Register main command only for child class
92
+ # def self.command(cmd)
93
+ # self.class_variable_set('@@command', cmd)
94
+ # end
95
+
96
+ # # Register new argument and method name
97
+ # def self.add(name, cmd)
98
+ # self.class_eval <<-EVAL
99
+ # def #{name}
100
+ # arguments << '#{cmd}'
101
+ # self
102
+ # end
103
+ # EVAL
104
+ # end
105
+
106
+ # def initialize(command=nil)
107
+ # @command = self.class.class_variable_get('@@command')
108
+ # end
109
+
110
+ # def arguments
111
+ # @arguments ||= []
112
+ # end
113
+
114
+ # def command
115
+ # %{#{@command} #{arguments.join(' ')}}
116
+ # end
117
+
118
+ # def run(title=nil, with_timer=false)
119
+ # Redmine::Installer::Exec.new(command, title, with_timer).run
120
+ # end
121
+
122
+ # def repeatable_run(title=nil, with_timer=false)
123
+ # Redmine::Installer::Exec.new(command, title, with_timer).repeatable_run
124
+ # end
125
+ # end
126
+
127
+ # class Rake < Base
128
+ # command 'bundle exec rake'
129
+ # add 'db_create', 'db:create'
130
+ # add 'db_migrate', 'db:migrate'
131
+ # add 'generate_secret_token', 'generate_secret_token'
132
+ # add 'redmine_plugin_migrate', 'redmine:plugins:migrate'
133
+ # add 'production', 'RAILS_ENV=production'
134
+ # end
135
+
136
+ # class Bundle < Base
137
+ # command 'bundle'
138
+ # add 'install', 'install'
139
+ # add 'production', '--without development test'
140
+ # end
141
+ # end
142
+ # end
@@ -0,0 +1,90 @@
1
+ ##
2
+ # Class for easyier handle configuration parameters
3
+ #
4
+ # == Examples:
5
+ #
6
+ # params = Redmine::Installer::ConfigParams.new
7
+ # params.add('database')
8
+ # params.add('host').note('this is a host').default('localhost')
9
+ #
10
+ module Redmine::Installer
11
+ class ConfigParams
12
+ def initialize
13
+ @params = []
14
+ end
15
+
16
+ def [](key)
17
+ @params.detect{|p| p.name == key}
18
+ end
19
+
20
+ def for_asking
21
+ @for_asking ||= @params.select{|p| p.ask}
22
+ end
23
+
24
+ def add(name)
25
+ param = ConfigParam.new(name)
26
+ @params << param
27
+ param
28
+ end
29
+
30
+ def each(&block)
31
+ @params.each(&block)
32
+ end
33
+
34
+ def map(&block)
35
+ @params.map(&block)
36
+ end
37
+ end
38
+
39
+ class ConfigParam
40
+
41
+ @@attributes = []
42
+
43
+ def self.attribute(name, default=nil)
44
+ eval <<-EVAL
45
+ def #{name}(value=nil)
46
+ return @#{name} if value.nil?
47
+ self.#{name} = value
48
+ end
49
+
50
+ def #{name}=(value)
51
+ @#{name} = value
52
+ end
53
+ EVAL
54
+
55
+ @@attributes << [name, default]
56
+ end
57
+
58
+ attribute :name
59
+ attribute :note
60
+ attribute :default
61
+ attribute :value
62
+ attribute :ask, true
63
+
64
+ def initialize(name)
65
+ # Default
66
+ @@attributes.each{|(k,v)| set(k,v)}
67
+
68
+ set(:name, name)
69
+ end
70
+
71
+ # Return string for print
72
+ def title
73
+ out = name.capitalize
74
+ out << " (#{note})" if note
75
+ out
76
+ end
77
+
78
+ def set(key, value)
79
+ self.send("#{key}=", value)
80
+ end
81
+
82
+ def default(value=nil)
83
+ return @default if value.nil?
84
+
85
+ self.default = value
86
+ self.value = value if self.value.nil?
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ module Redmine::Installer
2
+ # Package does not exist
3
+ class Error < StandardError
4
+ end
5
+ end
@@ -0,0 +1,158 @@
1
+ require 'open3'
2
+
3
+ ##
4
+ # Executions commands with timer and error handling
5
+ #
6
+ module Redmine::Installer
7
+ class Exec
8
+
9
+ include Redmine::Installer::Utils
10
+
11
+ REFRESH_TIMER = 1 # in s
12
+
13
+ attr_reader :stdout, :stderr
14
+
15
+ def initialize(command, title=nil, timer=true)
16
+ @command = command
17
+
18
+ with_title(title)
19
+ with_timer(timer)
20
+ end
21
+
22
+ def with_title(title)
23
+ if title.is_a?(Symbol)
24
+ title = I18n.translate(title)
25
+ end
26
+
27
+ @title = title
28
+ self
29
+ end
30
+
31
+ def with_timer(yes_no)
32
+ if $stdout.tty?
33
+ @with_timer = yes_no
34
+ else
35
+ @with_timer = false
36
+ end
37
+ self
38
+ end
39
+
40
+ def run(repeatable=false)
41
+ show_title
42
+
43
+ Open3.popen3(@command) do |stdin, stdout, stderr, wait_thr|
44
+ # log = StringIO.new
45
+ # redirect_stream(stdout, log)
46
+ # redirect_stream(stderr, log)
47
+
48
+ # For example: rake db:create can ask for root login
49
+ # if current setting does not work
50
+ # stdin.closes
51
+
52
+ exit_status = wait_thr.value
53
+ @stdout = stdout.read
54
+ @stderr = stderr.read
55
+
56
+ stop_timer
57
+ if exit_status.success?
58
+ print_result(true)
59
+ @return_value = true
60
+ else
61
+ print_result(false)
62
+ @return_value = false
63
+ # raise Redmine::Installer::Error, stderr.read
64
+ end
65
+ end
66
+
67
+ unless success
68
+ # print_error
69
+ if repeatable && repeat?
70
+ return run(repeatable)
71
+ end
72
+ end
73
+
74
+ return success
75
+ ensure
76
+ # stop_timer
77
+ end
78
+
79
+ private
80
+
81
+ def print_error
82
+ message = '<red>'
83
+ message << '--------------------------------------------------------------'
84
+ message << "\n"
85
+ message << stderr
86
+ message << '--------------------------------------------------------------'
87
+ message << '</red>'
88
+ colorize(message)
89
+
90
+ $stderr.puts(message)
91
+ $stderr.flush
92
+ end
93
+
94
+ def repeat?
95
+ confirm(:do_you_want_repeat_command, false)
96
+ end
97
+
98
+ def show_title
99
+ if @with_timer
100
+ @timer = start_timer
101
+ else
102
+ $stdout.print(@title)
103
+ end
104
+ end
105
+
106
+ def start_timer
107
+ Thread.new do
108
+ counter = 0
109
+
110
+ loop {
111
+ hours, seconds = counter.divmod(3600)
112
+ minutes, seconds = seconds.divmod(60)
113
+
114
+ printf "[%02d:%02d:%02d] %s\r", hours, minutes, seconds, @title
115
+ counter += REFRESH_TIMER
116
+ sleep(REFRESH_TIMER)
117
+ }
118
+ end
119
+ end
120
+
121
+ def stop_timer
122
+ if @timer
123
+ @timer.kill
124
+
125
+ # Clean line
126
+ print ' ' * 100
127
+ print "\r"
128
+ end
129
+ end
130
+
131
+ def print_result(ok=true)
132
+ if ok
133
+ out = $stdout
134
+ message = '... OK'
135
+ else
136
+ out = $stderr
137
+ message = '... FAIL'
138
+ end
139
+
140
+ if @with_timer
141
+ out.puts("#{@title} #{message}")
142
+ else
143
+ out.print(message)
144
+ end
145
+
146
+ out.flush
147
+ end
148
+
149
+ def redirect_stream(stream, out)
150
+ Thread.new do
151
+ while (line = stream.gets)
152
+ out.puts(line)
153
+ end
154
+ end
155
+ end
156
+
157
+ end
158
+ end