rexer 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8deb1f0e6b437141c6bc838cf954ee5520cbc44d9aca368060c99a4e7ce17bf2
4
- data.tar.gz: cf110fb2a483dda81792c355e5fb8e83388bcf2b1a5ff177e764a16e423fb3ad
3
+ metadata.gz: 710e00ac5d2fecb5d7ce297cf9999431a7cc77d19bfd88616462496380a811d6
4
+ data.tar.gz: 40155d5be1545c861bff45842df72d27d0a87ea3c096920fefa012dd80b9d710
5
5
  SHA512:
6
- metadata.gz: 0e82d4c4bcda8901a8a44b1f9e3db8d4401f2e45781763f072fa6aea8eb75532cb3223d31b051fabee4f5afe4e53def13baa2df8d2c731aa7dee740c6548ac19
7
- data.tar.gz: 0cdd7fa7759a3e94376b2539bef039c8ee5525b7c0358e8f19ab1409f5ff7946adf692f432c9bd862cb917ff7ab5b1661f0605d98b25f32a1ef4df75ddaf86a9
6
+ metadata.gz: 032d42c1c5ee5536bf7d5395989273fc2ceaf5adbf3605dddb5ff2f7ea7a16ba8b185d4294e6e91d5dbcda8653101eb28412e322911833aec3ffc151b3b13684
7
+ data.tar.gz: db390096e17b01ed36780a65f689c0b5cc25e71b55395c420e5bedaacbc67d53072113ac6b50276fdca628281fe00defb97e15e5752080fe6e650970a5a35892
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.
@@ -120,6 +152,16 @@ plugin :redmica_s3, github: { repo: "redmica/redmica_s3" } do
120
152
  end
121
153
  ```
122
154
 
155
+ ### Configuring the command prefix
156
+
157
+ You can set a prefix for the commands such as `bundle install` that Rexer executes with the `REXER_COMMAND_PREFIX` environment variable.
158
+
159
+ ```
160
+ export REXER_COMMAND_PREFIX="docker compose exec -T app"
161
+ ```
162
+
163
+ In the above case, the `bin/rails redmine:plugins:migrate` command is executed as `docker compose exec -T app bin/rails redmine:plugins:migrate`.
164
+
123
165
  ## Developing
124
166
 
125
167
  ### Running tests
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
@@ -5,6 +5,7 @@ module Rexer
5
5
  def self.exit_on_failure? = true
6
6
 
7
7
  class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed output"
8
+ class_option :quiet, type: :boolean, aliases: "-q", desc: "Minimal output"
8
9
 
9
10
  desc "install [ENV]", "Install the definitions in .extensions.rb for the specified environment"
10
11
  def install(env = "default")
@@ -50,6 +51,15 @@ module Rexer
50
51
 
51
52
  def initialize_options
52
53
  ENV["VERBOSE"] = "1" if options[:verbose]
54
+
55
+ verbosity_level = if options[:verbose]
56
+ :debug
57
+ elsif options[:quiet]
58
+ :error
59
+ else
60
+ :info
61
+ end
62
+ Rexer.verbosity = Commands::Verbosity.new(verbosity_level)
53
63
  end
54
64
  end
55
65
  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,24 +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, "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
57
+
58
+ def cmd(*command)
59
+ [Rexer.config.command_prefix, *command].compact.join(" ")
60
+ end
47
61
  end
48
62
 
49
- class Installer < Base
50
- def install
63
+ class Install < Base
64
+ def call
51
65
  return if plugin_exists?
52
66
 
67
+ broadcast(:started, "Install #{name}")
68
+
53
69
  load_from_source
54
70
  run_bundle_install
55
71
  run_db_migrate
56
72
  hooks[:installed]&.call
73
+
74
+ broadcast(:completed)
57
75
  end
58
76
 
59
77
  private
@@ -65,18 +83,25 @@ module Rexer
65
83
  def run_bundle_install
66
84
  return unless plugin_dir.join("Gemfile").exist?
67
85
 
68
- _, error, status = Open3.capture3("bundle install")
69
- 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)
70
91
  end
71
92
  end
72
93
 
73
- class Uninstaller < Base
74
- def uninstall
94
+ class Uninstall < Base
95
+ def call
75
96
  return unless plugin_exists?
76
97
 
98
+ broadcast(:started, "Uninstall #{name}")
99
+
77
100
  reset_db_migration
78
101
  remove_plugin
79
102
  hooks[:uninstalled]&.call
103
+
104
+ broadcast(:completed)
80
105
  end
81
106
 
82
107
  private
@@ -90,12 +115,16 @@ module Rexer
90
115
  end
91
116
  end
92
117
 
93
- class Updater < Base
94
- def update
118
+ class Update < Base
119
+ def call
95
120
  return unless plugin_exists?
96
121
 
122
+ broadcast(:started, "Update #{name}")
123
+
97
124
  update_source
98
125
  run_db_migrate
126
+
127
+ broadcast(:completed)
99
128
  end
100
129
 
101
130
  private
@@ -105,12 +134,16 @@ module Rexer
105
134
  end
106
135
  end
107
136
 
108
- class SourceReloader < Base
109
- def reload
137
+ class ReloadSource < Base
138
+ def call
110
139
  return unless plugin_exists?
111
140
 
141
+ broadcast(:started, "Reload #{name} source")
142
+
112
143
  reload_source
113
144
  run_db_migrate
145
+
146
+ broadcast(:completed)
114
147
  end
115
148
 
116
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.4.1"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/rexer.rb CHANGED
@@ -6,6 +6,25 @@ module Rexer
6
6
  def self.definition_lock_file
7
7
  ".extensions.lock"
8
8
  end
9
+
10
+ Config = Data.define(
11
+ # The prefix of the command such as bundle install and bin/rails redmine:plugins:migrate.
12
+ #
13
+ # For example, if the command_prefix is set "docker compose exec -T app",
14
+ # then bundle install will be executed as follows:
15
+ #
16
+ # docker compose exec -T app bundle install
17
+ #
18
+ :command_prefix
19
+ )
20
+
21
+ class << self
22
+ attr_accessor :verbosity
23
+
24
+ def config
25
+ @config ||= Config.new(command_prefix: ENV["REXER_COMMAND_PREFIX"])
26
+ end
27
+ end
9
28
  end
10
29
 
11
30
  require "pathname"
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.4.1
4
+ version: 0.6.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-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -52,6 +52,34 @@ 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'
55
83
  description: Rexer is a tool for managing Redmine Extension (Plugin and Themes). It
56
84
  allows you to define extensions in a Ruby DSL and install, uninstall, update, and
57
85
  switch between different sets of the extensions.
@@ -69,6 +97,7 @@ files:
69
97
  - exe/rex
70
98
  - lib/rexer.rb
71
99
  - lib/rexer/cli.rb
100
+ - lib/rexer/commands.rb
72
101
  - lib/rexer/commands/envs.rb
73
102
  - lib/rexer/commands/install.rb
74
103
  - lib/rexer/commands/state.rb