rexer 0.4.1 → 0.6.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 +4 -4
- data/README.md +44 -2
- data/exe/rex +1 -1
- data/lib/rexer/cli.rb +10 -0
- data/lib/rexer/commands/install.rb +8 -6
- data/lib/rexer/commands/uninstall.rb +4 -2
- data/lib/rexer/commands/update.rb +4 -2
- data/lib/rexer/commands.rb +44 -0
- data/lib/rexer/extension/plugin.rb +45 -12
- data/lib/rexer/extension/theme.rb +28 -8
- data/lib/rexer/version.rb +1 -1
- data/lib/rexer.rb +19 -0
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 710e00ac5d2fecb5d7ce297cf9999431a7cc77d19bfd88616462496380a811d6
|
4
|
+
data.tar.gz: 40155d5be1545c861bff45842df72d27d0a87ea3c096920fefa012dd80b9d710
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
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::
|
51
|
+
call_action Extension::Theme::Install, _1
|
50
52
|
end
|
51
53
|
|
52
54
|
plugins.each do
|
53
|
-
Extension::Plugin::
|
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::
|
61
|
+
call_action Extension::Theme::Uninstall, _1
|
60
62
|
end
|
61
63
|
|
62
64
|
plugins.each do
|
63
|
-
Extension::Plugin::
|
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::
|
71
|
+
call_action Extension::Theme::ReloadSource, _1
|
70
72
|
end
|
71
73
|
|
72
74
|
plugins.each do
|
73
|
-
Extension::Plugin::
|
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::
|
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::
|
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::
|
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::
|
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
|
-
|
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
|
-
|
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
|
50
|
-
def
|
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
|
-
|
69
|
-
|
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
|
74
|
-
def
|
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
|
94
|
-
def
|
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
|
109
|
-
def
|
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
|
40
|
-
def
|
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
|
55
|
-
def
|
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
|
70
|
-
def
|
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
|
84
|
-
def
|
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
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
|
+
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-
|
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
|