rexer 0.5.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bb969edc94e8ed8a471a4de3b393768e471b75f4b200637235cc05d247e15f5
4
- data.tar.gz: 93655f0b69f0f02f91920f9f09f56339f71caefe68e8be78eb276e9cbeaaebba
3
+ metadata.gz: 9c8c8383d931ce1824f0b3dff3b835d16b242803e3991f1ab9ff3b60df396ecc
4
+ data.tar.gz: 03270c384dfe36f34ee418a48847d671e470bb49f1699c69944a3f38326bdf37
5
5
  SHA512:
6
- metadata.gz: e69305a1d92ba1445eada1931379b590b6186cc09dffa12e3598d4a3b8a94c862f868828e21b7e19910280bef08dd13a5f42c74d28a4134d109fd64a3178c931
7
- data.tar.gz: 8508080c6d1a030b8ca1de6d2bb16cf547014dbe9a777b4b838cb6e7d40e8d773977519462f8fb5f547cf354d0d912f8b93cab8571552f3edd5423ad1250a4ce
6
+ metadata.gz: f06dd899a19bb55eab11bd5891b40ab1135cf5b2f4ee001b744bd2e2421a543470b960d6a7ea369efc9c96c98c1784eb1ff37a35445d1270ee5699c9a012ebb1
7
+ data.tar.gz: cb0652c4d01e86e99f2c727c29ebc276d988e5f174ec0be980df977ad8fdf0118234decec87143ba5da57b9b575466d1edf77bc6eec7cc0eef723bf1fdb2c408
data/README.md CHANGED
@@ -64,7 +64,24 @@ Commands:
64
64
  rex version # Show Rexer version
65
65
  ```
66
66
 
67
- ### Defining environments and extensions for the environment
67
+ #### rex install [ENV]
68
+
69
+ Installs extensions in the specified ENV environment and makes them available for use. Specifically, it does the following:
70
+
71
+ If the specified ENV is NOT currently installed, it adds all extensions in the ENV environment in `.extensions.rb`.
72
+
73
+ If the specified ENV is currently installed, it compares the current `.extensions.lock` with `.extensions.rb` and does the following:
74
+ * Installs additional extensions (the `installed` hook is executed).
75
+ * Uninstalls deleted extensions (the `uninstalled` hook is executed).
76
+ * Re-fetches extensions whose source settings has changed (for example, the `branch` or `tag` has changed) and runs the database migration if necessary.
77
+
78
+ #### rex update
79
+
80
+ Loads `.extensions.lock` and updates the currently installed extensions to the latest version. `.extensions.rb` is NOT referenced in this command.
81
+
82
+ ### Defining for each environment and extension
83
+
84
+ You can define an environment and extensions for each environment using the `env ... do - end` block.
68
85
 
69
86
  ```ruby
70
87
  theme :bleuclair, github: { repo: "farend/redmine_theme_farend_bleuclair" }
@@ -76,7 +93,14 @@ env :stable do
76
93
  end
77
94
  ```
78
95
 
79
- In above example, the `bleuclair` theme and the `redmine_issues_panel` plugin are defined for the `default` environment. The `bleuclair` theme and the `redmine_issues_panel` plugin are defined for the `stable` environment.
96
+ Definitions other than `env ... do - end` are implicitly defined as `env :default do - end`. Therefore, the above is resolved as follows:
97
+
98
+ * default env
99
+ * bleuclair (master)
100
+ * redmine_issues_panel (master)
101
+ * stable env
102
+ * bleuclair (support-propshaft)
103
+ * redmine_issues_panel (v1.0.2)
80
104
 
81
105
  If you want to install extensions for the `default` environment, run the following command.
82
106
 
@@ -102,6 +126,14 @@ rex install stable
102
126
 
103
127
  The above command uninstalls the extensions for the currently installed environment and installs the extensions for the `stable` environment.
104
128
 
129
+ In addition, you can define as many environments as you like, and list the defined environments with the `rex envs` command.
130
+
131
+ ```
132
+ $ rex envs
133
+ default
134
+ stable
135
+ ```
136
+
105
137
  ### Defining hooks
106
138
 
107
139
  You can define hooks for each extension.
data/exe/rex CHANGED
@@ -5,7 +5,7 @@ require "rexer"
5
5
  begin
6
6
  Rexer::Cli.start(ARGV)
7
7
  rescue => e
8
- puts "ERROR (#{e.class}): #{e.message}"
8
+ puts "\e[31mERROR (#{e.class}): #{e.message}\e[0m"
9
9
  puts e.backtrace if ENV["VERBOSE"]
10
10
  exit 1
11
11
  end
data/lib/rexer/cli.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  require "thor"
2
+ require "dotenv"
3
+ require "erb"
2
4
 
3
5
  module Rexer
4
6
  class Cli < Thor
5
7
  def self.exit_on_failure? = true
6
8
 
7
9
  class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed output"
10
+ class_option :quiet, type: :boolean, aliases: "-q", desc: "Minimal output"
8
11
 
9
12
  desc "install [ENV]", "Install the definitions in .extensions.rb for the specified environment"
10
13
  def install(env = "default")
@@ -43,6 +46,7 @@ module Rexer
43
46
 
44
47
  def initialize(*)
45
48
  super
49
+ Dotenv.load
46
50
  initialize_options
47
51
  end
48
52
 
@@ -50,6 +54,15 @@ module Rexer
50
54
 
51
55
  def initialize_options
52
56
  ENV["VERBOSE"] = "1" if options[:verbose]
57
+
58
+ verbosity_level = if options[:verbose]
59
+ :debug
60
+ elsif options[:quiet]
61
+ :error
62
+ else
63
+ :info
64
+ end
65
+ Rexer.verbosity = Commands::Verbosity.new(verbosity_level)
53
66
  end
54
67
  end
55
68
  end
@@ -1,6 +1,8 @@
1
1
  module Rexer
2
2
  module Commands
3
3
  class Install
4
+ include ActionCallable
5
+
4
6
  def call(env)
5
7
  definition = load_definition(env)
6
8
  lock_definition = load_lock_definition
@@ -46,31 +48,31 @@ module Rexer
46
48
 
47
49
  def install(themes, plugins)
48
50
  themes.each do
49
- Extension::Theme::Installer.new(_1).install
51
+ call_action Extension::Theme::Install, _1
50
52
  end
51
53
 
52
54
  plugins.each do
53
- Extension::Plugin::Installer.new(_1).install
55
+ call_action Extension::Plugin::Install, _1
54
56
  end
55
57
  end
56
58
 
57
59
  def uninstall(themes, plugins)
58
60
  themes.each do
59
- Extension::Theme::Uninstaller.new(_1).uninstall
61
+ call_action Extension::Theme::Uninstall, _1
60
62
  end
61
63
 
62
64
  plugins.each do
63
- Extension::Plugin::Uninstaller.new(_1).uninstall
65
+ call_action Extension::Plugin::Uninstall, _1
64
66
  end
65
67
  end
66
68
 
67
69
  def reload_source(themes, plugins)
68
70
  themes.each do
69
- Extension::Theme::SourceReloader.new(_1).reload
71
+ call_action Extension::Theme::ReloadSource, _1
70
72
  end
71
73
 
72
74
  plugins.each do
73
- Extension::Plugin::SourceReloader.new(_1).reload
75
+ call_action Extension::Plugin::ReloadSource, _1
74
76
  end
75
77
  end
76
78
 
@@ -1,6 +1,8 @@
1
1
  module Rexer
2
2
  module Commands
3
3
  class Uninstall
4
+ include ActionCallable
5
+
4
6
  def initialize
5
7
  @lock_definition = Definition::Lock.load_data
6
8
  end
@@ -20,13 +22,13 @@ module Rexer
20
22
 
21
23
  def uninstall_plugins
22
24
  lock_definition.plugins.each do
23
- Extension::Plugin::Uninstaller.new(_1).uninstall
25
+ call_action Extension::Plugin::Uninstall, _1
24
26
  end
25
27
  end
26
28
 
27
29
  def uninstall_themes
28
30
  lock_definition.themes.each do
29
- Extension::Theme::Uninstaller.new(_1).uninstall
31
+ call_action Extension::Theme::Uninstall, _1
30
32
  end
31
33
  end
32
34
 
@@ -1,6 +1,8 @@
1
1
  module Rexer
2
2
  module Commands
3
3
  class Update
4
+ include ActionCallable
5
+
4
6
  def initialize
5
7
  @lock_definition = Definition::Lock.load_data
6
8
  end
@@ -18,13 +20,13 @@ module Rexer
18
20
 
19
21
  def update_plugins
20
22
  lock_definition.plugins.each do
21
- Extension::Plugin::Updater.new(_1).update
23
+ call_action Extension::Plugin::Update, _1
22
24
  end
23
25
  end
24
26
 
25
27
  def update_themes
26
28
  lock_definition.themes.each do
27
- Extension::Theme::Updater.new(_1).update
29
+ call_action Extension::Theme::Update, _1
28
30
  end
29
31
  end
30
32
 
@@ -0,0 +1,44 @@
1
+ require "paint"
2
+
3
+ module Rexer
4
+ module Commands
5
+ module ActionCallable
6
+ def call_action(action_class, *init_args)
7
+ progress_notifier = ProgressNotifier.new
8
+
9
+ action = action_class.new(*init_args)
10
+ action.subscribe(progress_notifier).call
11
+ end
12
+ end
13
+
14
+ class Verbosity < Data.define(:current_level)
15
+ LEVELS = %i[error info debug].freeze
16
+
17
+ LEVELS.each do |level|
18
+ define_method(:"#{level}?") { level == current_level }
19
+ end
20
+
21
+ def on?(level)
22
+ LEVELS.index(current_level) >= LEVELS.index(level)
23
+ end
24
+
25
+ def on(level, &block)
26
+ on?(level) ? block.call : nil
27
+ end
28
+ end
29
+
30
+ class ProgressNotifier
31
+ def started(process_title)
32
+ Rexer.verbosity.on(:info) { print "#{process_title} ... " }
33
+ end
34
+
35
+ def completed
36
+ Rexer.verbosity.on(:info) { puts Paint["done", :green] }
37
+ end
38
+
39
+ def processing(process_title)
40
+ Rexer.verbosity.on(:debug) { puts Paint[process_title, :gray] }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,4 +1,5 @@
1
1
  require "open3"
2
+ require "wisper"
2
3
 
3
4
  module Rexer
4
5
  module Extension
@@ -8,6 +9,8 @@ module Rexer
8
9
  end
9
10
 
10
11
  class Base
12
+ include Wisper::Publisher
13
+
11
14
  def initialize(definition)
12
15
  @definition = definition
13
16
  @name = definition.name
@@ -36,28 +39,39 @@ module Rexer
36
39
  return unless needs_db_migration?
37
40
 
38
41
  envs = {"NAME" => name.to_s}.merge(extra_envs)
39
- _, error, status = Open3.capture3(envs, cmd_with_prefix("bin/rails redmine:plugins:migrate"))
42
+ cmds = cmd("bundle", "exec", "rake", Rexer.verbosity.debug? ? nil : "-q", "redmine:plugins:migrate")
43
+
44
+ broadcast(:processing, "Execute #{cmds} with #{envs}")
40
45
 
41
- raise error unless status.success?
46
+ if Rexer.verbosity.debug?
47
+ system(envs, cmds, exception: true)
48
+ else
49
+ _, error, status = Open3.capture3(envs, cmds)
50
+ raise error unless status.success?
51
+ end
42
52
  end
43
53
 
44
54
  def source
45
55
  @source ||= Source.from_definition(definition.source)
46
56
  end
47
57
 
48
- def cmd_with_prefix(command)
49
- [Rexer.config.command_prefix, command].compact.join(" ")
58
+ def cmd(*command)
59
+ [Rexer.config.command_prefix, *command].compact.join(" ")
50
60
  end
51
61
  end
52
62
 
53
- class Installer < Base
54
- def install
63
+ class Install < Base
64
+ def call
55
65
  return if plugin_exists?
56
66
 
67
+ broadcast(:started, "Install #{name}")
68
+
57
69
  load_from_source
58
70
  run_bundle_install
59
71
  run_db_migrate
60
72
  hooks[:installed]&.call
73
+
74
+ broadcast(:completed)
61
75
  end
62
76
 
63
77
  private
@@ -69,18 +83,25 @@ module Rexer
69
83
  def run_bundle_install
70
84
  return unless plugin_dir.join("Gemfile").exist?
71
85
 
72
- _, error, status = Open3.capture3(cmd_with_prefix("bundle install"))
73
- raise error unless status.success?
86
+ cmds = cmd("bundle", "install", Rexer.verbosity.debug? ? nil : "--quiet")
87
+
88
+ broadcast(:processing, "Execute #{cmds}")
89
+
90
+ system(cmds, exception: true)
74
91
  end
75
92
  end
76
93
 
77
- class Uninstaller < Base
78
- def uninstall
94
+ class Uninstall < Base
95
+ def call
79
96
  return unless plugin_exists?
80
97
 
98
+ broadcast(:started, "Uninstall #{name}")
99
+
81
100
  reset_db_migration
82
101
  remove_plugin
83
102
  hooks[:uninstalled]&.call
103
+
104
+ broadcast(:completed)
84
105
  end
85
106
 
86
107
  private
@@ -94,12 +115,16 @@ module Rexer
94
115
  end
95
116
  end
96
117
 
97
- class Updater < Base
98
- def update
118
+ class Update < Base
119
+ def call
99
120
  return unless plugin_exists?
100
121
 
122
+ broadcast(:started, "Update #{name}")
123
+
101
124
  update_source
102
125
  run_db_migrate
126
+
127
+ broadcast(:completed)
103
128
  end
104
129
 
105
130
  private
@@ -109,12 +134,16 @@ module Rexer
109
134
  end
110
135
  end
111
136
 
112
- class SourceReloader < Base
113
- def reload
137
+ class ReloadSource < Base
138
+ def call
114
139
  return unless plugin_exists?
115
140
 
141
+ broadcast(:started, "Reload #{name} source")
142
+
116
143
  reload_source
117
144
  run_db_migrate
145
+
146
+ broadcast(:completed)
118
147
  end
119
148
 
120
149
  private
@@ -1,3 +1,5 @@
1
+ require "wisper"
2
+
1
3
  module Rexer
2
4
  module Extension
3
5
  module Theme
@@ -13,6 +15,8 @@ module Rexer
13
15
  end
14
16
 
15
17
  class Base
18
+ include Wisper::Publisher
19
+
16
20
  def initialize(definition)
17
21
  @definition = definition
18
22
  @name = definition.name
@@ -36,12 +40,16 @@ module Rexer
36
40
  end
37
41
  end
38
42
 
39
- class Installer < Base
40
- def install
43
+ class Install < Base
44
+ def call
41
45
  return if theme_exists?
42
46
 
47
+ broadcast(:started, "Install #{name}")
48
+
43
49
  load_from_source
44
50
  hooks[:installed]&.call
51
+
52
+ broadcast(:completed)
45
53
  end
46
54
 
47
55
  private
@@ -51,12 +59,16 @@ module Rexer
51
59
  end
52
60
  end
53
61
 
54
- class Uninstaller < Base
55
- def uninstall
62
+ class Uninstall < Base
63
+ def call
56
64
  return unless theme_exists?
57
65
 
66
+ broadcast(:started, "Uninstall #{name}")
67
+
58
68
  remove_theme
59
69
  hooks[:uninstalled]&.call
70
+
71
+ broadcast(:completed)
60
72
  end
61
73
 
62
74
  private
@@ -66,11 +78,15 @@ module Rexer
66
78
  end
67
79
  end
68
80
 
69
- class Updater < Base
70
- def update
81
+ class Update < Base
82
+ def call
71
83
  return unless theme_exists?
72
84
 
85
+ broadcast(:started, "Update #{name}")
86
+
73
87
  update_source
88
+
89
+ broadcast(:completed)
74
90
  end
75
91
 
76
92
  private
@@ -80,11 +96,15 @@ module Rexer
80
96
  end
81
97
  end
82
98
 
83
- class SourceReloader < Base
84
- def reload
99
+ class ReloadSource < Base
100
+ def call
85
101
  return unless theme_exists?
86
102
 
103
+ broadcast(:started, "Reload #{name} source")
104
+
87
105
  reload_source
106
+
107
+ broadcast(:completed)
88
108
  end
89
109
 
90
110
  private
data/lib/rexer/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rexer
2
- VERSION = "0.5.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/lib/rexer.rb CHANGED
@@ -18,8 +18,12 @@ module Rexer
18
18
  :command_prefix
19
19
  )
20
20
 
21
- def self.config
22
- @config ||= Config.new(command_prefix: ENV["REXER_COMMAND_PREFIX"])
21
+ class << self
22
+ attr_accessor :verbosity
23
+
24
+ def config
25
+ @config ||= Config.new(command_prefix: ENV["REXER_COMMAND_PREFIX"])
26
+ end
23
27
  end
24
28
  end
25
29
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rexer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuya Hidaka
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-17 00:00:00.000000000 Z
11
+ date: 2024-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -52,6 +52,48 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: wisper
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: paint
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.3'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: dotenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.1'
55
97
  description: Rexer is a tool for managing Redmine Extension (Plugin and Themes). It
56
98
  allows you to define extensions in a Ruby DSL and install, uninstall, update, and
57
99
  switch between different sets of the extensions.
@@ -69,6 +111,7 @@ files:
69
111
  - exe/rex
70
112
  - lib/rexer.rb
71
113
  - lib/rexer/cli.rb
114
+ - lib/rexer/commands.rb
72
115
  - lib/rexer/commands/envs.rb
73
116
  - lib/rexer/commands/install.rb
74
117
  - lib/rexer/commands/state.rb