makit 0.0.140 → 0.0.141
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 +41 -41
- data/exe/makit +5 -5
- data/lib/makit/apache.rb +28 -28
- data/lib/makit/auto.rb +48 -48
- data/lib/makit/cli/build_commands.rb +500 -500
- data/lib/makit/cli/generators/base_generator.rb +74 -74
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
- data/lib/makit/cli/generators/generator_factory.rb +49 -49
- data/lib/makit/cli/generators/node_generator.rb +50 -50
- data/lib/makit/cli/generators/ruby_generator.rb +77 -77
- data/lib/makit/cli/generators/rust_generator.rb +50 -50
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
- data/lib/makit/cli/main.rb +69 -69
- data/lib/makit/cli/project_commands.rb +868 -868
- data/lib/makit/cli/repository_commands.rb +661 -661
- data/lib/makit/cli/strategy_commands.rb +203 -203
- data/lib/makit/cli/utility_commands.rb +521 -521
- data/lib/makit/commands/factory.rb +359 -359
- data/lib/makit/commands/middleware/base.rb +73 -73
- data/lib/makit/commands/middleware/cache.rb +248 -248
- data/lib/makit/commands/middleware/command_logger.rb +312 -312
- data/lib/makit/commands/middleware/validator.rb +269 -269
- data/lib/makit/commands/request.rb +316 -316
- data/lib/makit/commands/result.rb +323 -323
- data/lib/makit/commands/runner.rb +388 -385
- data/lib/makit/commands/strategies/base.rb +171 -171
- data/lib/makit/commands/strategies/child_process.rb +165 -165
- data/lib/makit/commands/strategies/factory.rb +136 -136
- data/lib/makit/commands/strategies/synchronous.rb +139 -139
- data/lib/makit/commands.rb +50 -50
- data/lib/makit/configuration/dotnet_project.rb +12 -12
- data/lib/makit/configuration/gitlab_helper.rb +58 -58
- data/lib/makit/configuration/project.rb +168 -168
- data/lib/makit/configuration/rakefile_helper.rb +43 -43
- data/lib/makit/configuration/step.rb +34 -34
- data/lib/makit/configuration/timeout.rb +74 -74
- data/lib/makit/configuration.rb +15 -15
- data/lib/makit/content/default_gitignore.rb +7 -7
- data/lib/makit/content/default_gitignore.txt +225 -225
- data/lib/makit/content/default_rakefile.rb +13 -13
- data/lib/makit/content/gem_rakefile.rb +16 -16
- data/lib/makit/context.rb +1 -1
- data/lib/makit/data.rb +49 -49
- data/lib/makit/directories.rb +140 -140
- data/lib/makit/directory.rb +262 -262
- data/lib/makit/docs/files.rb +89 -89
- data/lib/makit/docs/rake.rb +102 -102
- data/lib/makit/dotnet/cli.rb +69 -69
- data/lib/makit/dotnet/project.rb +217 -217
- data/lib/makit/dotnet/solution.rb +38 -38
- data/lib/makit/dotnet/solution_classlib.rb +239 -239
- data/lib/makit/dotnet/solution_console.rb +264 -264
- data/lib/makit/dotnet/solution_maui.rb +354 -354
- data/lib/makit/dotnet/solution_wasm.rb +275 -275
- data/lib/makit/dotnet/solution_wpf.rb +304 -304
- data/lib/makit/dotnet.rb +102 -102
- data/lib/makit/email.rb +90 -90
- data/lib/makit/environment.rb +142 -142
- data/lib/makit/examples/runner.rb +370 -370
- data/lib/makit/exceptions.rb +45 -45
- data/lib/makit/fileinfo.rb +24 -24
- data/lib/makit/files.rb +43 -43
- data/lib/makit/gems.rb +40 -40
- data/lib/makit/git/cli.rb +54 -54
- data/lib/makit/git/repository.rb +90 -90
- data/lib/makit/git.rb +98 -98
- data/lib/makit/gitlab_runner.rb +59 -59
- data/lib/makit/humanize.rb +137 -137
- data/lib/makit/indexer.rb +47 -47
- data/lib/makit/logging/configuration.rb +308 -308
- data/lib/makit/logging/format_registry.rb +84 -84
- data/lib/makit/logging/formatters/base.rb +39 -39
- data/lib/makit/logging/formatters/console_formatter.rb +140 -140
- data/lib/makit/logging/formatters/json_formatter.rb +65 -65
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
- data/lib/makit/logging/formatters/text_formatter.rb +64 -64
- data/lib/makit/logging/log_request.rb +119 -119
- data/lib/makit/logging/logger.rb +199 -199
- data/lib/makit/logging/sinks/base.rb +91 -91
- data/lib/makit/logging/sinks/console.rb +72 -72
- data/lib/makit/logging/sinks/file_sink.rb +92 -92
- data/lib/makit/logging/sinks/structured.rb +123 -123
- data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
- data/lib/makit/logging.rb +565 -565
- data/lib/makit/markdown.rb +75 -75
- data/lib/makit/mp/basic_object_mp.rb +17 -17
- data/lib/makit/mp/command_mp.rb +13 -13
- data/lib/makit/mp/command_request.mp.rb +17 -17
- data/lib/makit/mp/project_mp.rb +199 -199
- data/lib/makit/mp/string_mp.rb +199 -191
- data/lib/makit/nuget.rb +74 -74
- data/lib/makit/port.rb +32 -32
- data/lib/makit/process.rb +163 -163
- data/lib/makit/protoc.rb +107 -107
- data/lib/makit/rake/cli.rb +196 -196
- data/lib/makit/rake/trace_controller.rb +173 -173
- data/lib/makit/rake.rb +80 -80
- data/lib/makit/ruby/cli.rb +185 -185
- data/lib/makit/ruby.rb +25 -25
- data/lib/makit/secrets.rb +51 -51
- data/lib/makit/serializer.rb +130 -130
- data/lib/makit/services/builder.rb +186 -186
- data/lib/makit/services/error_handler.rb +226 -226
- data/lib/makit/services/repository_manager.rb +231 -231
- data/lib/makit/services/validator.rb +112 -112
- data/lib/makit/setup/classlib.rb +101 -101
- data/lib/makit/setup/gem.rb +268 -268
- data/lib/makit/setup/razorclasslib.rb +101 -101
- data/lib/makit/setup/runner.rb +54 -54
- data/lib/makit/setup.rb +5 -5
- data/lib/makit/show.rb +110 -110
- data/lib/makit/storage.rb +126 -126
- data/lib/makit/symbols.rb +170 -170
- data/lib/makit/task_info.rb +130 -130
- data/lib/makit/tasks/at_exit.rb +15 -15
- data/lib/makit/tasks/build.rb +22 -22
- data/lib/makit/tasks/clean.rb +13 -13
- data/lib/makit/tasks/configure.rb +10 -10
- data/lib/makit/tasks/format.rb +10 -10
- data/lib/makit/tasks/hook_manager.rb +443 -443
- data/lib/makit/tasks/init.rb +49 -49
- data/lib/makit/tasks/integrate.rb +29 -29
- data/lib/makit/tasks/pull_incoming.rb +13 -13
- data/lib/makit/tasks/setup.rb +13 -13
- data/lib/makit/tasks/sync.rb +17 -17
- data/lib/makit/tasks/tag.rb +16 -16
- data/lib/makit/tasks/task_monkey_patch.rb +81 -81
- data/lib/makit/tasks/test.rb +22 -22
- data/lib/makit/tasks/update.rb +18 -18
- data/lib/makit/tasks.rb +20 -20
- data/lib/makit/test_cache.rb +239 -239
- data/lib/makit/tree.rb +37 -37
- data/lib/makit/v1/makit.v1_pb.rb +35 -35
- data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
- data/lib/makit/version.rb +99 -99
- data/lib/makit/version_util.rb +21 -21
- data/lib/makit/wix.rb +95 -95
- data/lib/makit/yaml.rb +29 -29
- data/lib/makit/zip.rb +17 -17
- data/lib/makit copy.rb +44 -44
- data/lib/makit.rb +42 -42
- metadata +2 -2
@@ -1,136 +1,136 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base"
|
4
|
-
require_relative "synchronous"
|
5
|
-
|
6
|
-
module Makit
|
7
|
-
module Commands
|
8
|
-
module Strategies
|
9
|
-
# Factory for creating command execution strategies with fallback support
|
10
|
-
#
|
11
|
-
# This factory allows easy switching between different execution strategies
|
12
|
-
# (ChildProcess, Open3, etc.) with automatic fallback to Open3 if the
|
13
|
-
# preferred strategy fails to load or execute.
|
14
|
-
#
|
15
|
-
# @example Using environment variable to control strategy
|
16
|
-
# # Use ChildProcess (default)
|
17
|
-
# MAKIT_STRATEGY=childprocess rake
|
18
|
-
#
|
19
|
-
# # Force Open3 usage
|
20
|
-
# MAKIT_STRATEGY=open3 rake
|
21
|
-
#
|
22
|
-
# # Auto-detect (try ChildProcess, fallback to Open3)
|
23
|
-
# MAKIT_STRATEGY=auto rake
|
24
|
-
class Factory
|
25
|
-
# Available strategy types
|
26
|
-
STRATEGIES = {
|
27
|
-
'childprocess' => 'ChildProcess',
|
28
|
-
'open3' => 'Synchronous',
|
29
|
-
'auto' => 'AutoDetect'
|
30
|
-
}.freeze
|
31
|
-
|
32
|
-
# Get the configured strategy instance
|
33
|
-
#
|
34
|
-
# @param options [Hash] strategy options
|
35
|
-
# @return [Strategies::Base] configured strategy instance
|
36
|
-
def self.create(options = {})
|
37
|
-
strategy_type = determine_strategy_type
|
38
|
-
|
39
|
-
begin
|
40
|
-
case strategy_type
|
41
|
-
when 'childprocess'
|
42
|
-
create_childprocess_strategy(options)
|
43
|
-
when 'open3'
|
44
|
-
create_open3_strategy(options)
|
45
|
-
when 'auto'
|
46
|
-
create_auto_detect_strategy(options)
|
47
|
-
else
|
48
|
-
Makit::Logging.warn("Unknown strategy '#{strategy_type}', falling back to Open3") if defined?(Makit::Logging)
|
49
|
-
create_open3_strategy(options)
|
50
|
-
end
|
51
|
-
rescue => e
|
52
|
-
# Ultimate fallback - create basic synchronous strategy
|
53
|
-
Makit::Logging.warn("Failed to create strategy: #{e.message}") if defined?(Makit::Logging)
|
54
|
-
Synchronous.new
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Get the current strategy type from environment or default
|
59
|
-
#
|
60
|
-
# @return [String] strategy type
|
61
|
-
def self.determine_strategy_type
|
62
|
-
env_strategy = ENV['MAKIT_STRATEGY']&.downcase
|
63
|
-
|
64
|
-
if env_strategy && STRATEGIES.key?(env_strategy)
|
65
|
-
env_strategy
|
66
|
-
else
|
67
|
-
'auto' # Default to auto-detect
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Create ChildProcess strategy with fallback
|
72
|
-
#
|
73
|
-
# @param options [Hash] strategy options
|
74
|
-
# @return [Strategies::Base] strategy instance
|
75
|
-
def self.create_childprocess_strategy(options)
|
76
|
-
begin
|
77
|
-
require_relative 'child_process'
|
78
|
-
ChildProcess.new(**options)
|
79
|
-
rescue LoadError, StandardError => e
|
80
|
-
Makit::Logging.warn("Failed to load ChildProcess strategy: #{e.message}")
|
81
|
-
Makit::Logging.info("Falling back to Open3 strategy")
|
82
|
-
create_open3_strategy(options)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Create Open3 strategy
|
87
|
-
#
|
88
|
-
# @param options [Hash] strategy options
|
89
|
-
# @return [Strategies::Base] strategy instance
|
90
|
-
def self.create_open3_strategy(options)
|
91
|
-
Synchronous.new(**options)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Create auto-detect strategy that tries ChildProcess first
|
95
|
-
#
|
96
|
-
# @param options [Hash] strategy options
|
97
|
-
# @return [Strategies::Base] strategy instance
|
98
|
-
def self.create_auto_detect_strategy(options)
|
99
|
-
# Always use Open3 for now to avoid circular dependency issues
|
100
|
-
begin
|
101
|
-
Makit::Logging.debug("Using Open3 strategy") if defined?(Makit::Logging)
|
102
|
-
Synchronous.new(**options)
|
103
|
-
rescue => e
|
104
|
-
# Fallback to basic strategy if there are any issues
|
105
|
-
Makit::Logging.warn("Failed to create Open3 strategy: #{e.message}") if defined?(Makit::Logging)
|
106
|
-
Synchronous.new
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Get information about available strategies
|
111
|
-
#
|
112
|
-
# @return [Hash] strategy information
|
113
|
-
def self.strategy_info
|
114
|
-
{
|
115
|
-
current: determine_strategy_type,
|
116
|
-
available: STRATEGIES.keys,
|
117
|
-
childprocess_available: childprocess_available?,
|
118
|
-
open3_available: true # Always available
|
119
|
-
}
|
120
|
-
end
|
121
|
-
|
122
|
-
# Check if ChildProcess strategy is available
|
123
|
-
#
|
124
|
-
# @return [Boolean] true if ChildProcess can be loaded
|
125
|
-
def self.childprocess_available?
|
126
|
-
begin
|
127
|
-
require 'childprocess'
|
128
|
-
true
|
129
|
-
rescue LoadError
|
130
|
-
false
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
require_relative "synchronous"
|
5
|
+
|
6
|
+
module Makit
|
7
|
+
module Commands
|
8
|
+
module Strategies
|
9
|
+
# Factory for creating command execution strategies with fallback support
|
10
|
+
#
|
11
|
+
# This factory allows easy switching between different execution strategies
|
12
|
+
# (ChildProcess, Open3, etc.) with automatic fallback to Open3 if the
|
13
|
+
# preferred strategy fails to load or execute.
|
14
|
+
#
|
15
|
+
# @example Using environment variable to control strategy
|
16
|
+
# # Use ChildProcess (default)
|
17
|
+
# MAKIT_STRATEGY=childprocess rake
|
18
|
+
#
|
19
|
+
# # Force Open3 usage
|
20
|
+
# MAKIT_STRATEGY=open3 rake
|
21
|
+
#
|
22
|
+
# # Auto-detect (try ChildProcess, fallback to Open3)
|
23
|
+
# MAKIT_STRATEGY=auto rake
|
24
|
+
class Factory
|
25
|
+
# Available strategy types
|
26
|
+
STRATEGIES = {
|
27
|
+
'childprocess' => 'ChildProcess',
|
28
|
+
'open3' => 'Synchronous',
|
29
|
+
'auto' => 'AutoDetect'
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
# Get the configured strategy instance
|
33
|
+
#
|
34
|
+
# @param options [Hash] strategy options
|
35
|
+
# @return [Strategies::Base] configured strategy instance
|
36
|
+
def self.create(options = {})
|
37
|
+
strategy_type = determine_strategy_type
|
38
|
+
|
39
|
+
begin
|
40
|
+
case strategy_type
|
41
|
+
when 'childprocess'
|
42
|
+
create_childprocess_strategy(options)
|
43
|
+
when 'open3'
|
44
|
+
create_open3_strategy(options)
|
45
|
+
when 'auto'
|
46
|
+
create_auto_detect_strategy(options)
|
47
|
+
else
|
48
|
+
Makit::Logging.warn("Unknown strategy '#{strategy_type}', falling back to Open3") if defined?(Makit::Logging)
|
49
|
+
create_open3_strategy(options)
|
50
|
+
end
|
51
|
+
rescue => e
|
52
|
+
# Ultimate fallback - create basic synchronous strategy
|
53
|
+
Makit::Logging.warn("Failed to create strategy: #{e.message}") if defined?(Makit::Logging)
|
54
|
+
Synchronous.new
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get the current strategy type from environment or default
|
59
|
+
#
|
60
|
+
# @return [String] strategy type
|
61
|
+
def self.determine_strategy_type
|
62
|
+
env_strategy = ENV['MAKIT_STRATEGY']&.downcase
|
63
|
+
|
64
|
+
if env_strategy && STRATEGIES.key?(env_strategy)
|
65
|
+
env_strategy
|
66
|
+
else
|
67
|
+
'auto' # Default to auto-detect
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Create ChildProcess strategy with fallback
|
72
|
+
#
|
73
|
+
# @param options [Hash] strategy options
|
74
|
+
# @return [Strategies::Base] strategy instance
|
75
|
+
def self.create_childprocess_strategy(options)
|
76
|
+
begin
|
77
|
+
require_relative 'child_process'
|
78
|
+
ChildProcess.new(**options)
|
79
|
+
rescue LoadError, StandardError => e
|
80
|
+
Makit::Logging.warn("Failed to load ChildProcess strategy: #{e.message}")
|
81
|
+
Makit::Logging.info("Falling back to Open3 strategy")
|
82
|
+
create_open3_strategy(options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Create Open3 strategy
|
87
|
+
#
|
88
|
+
# @param options [Hash] strategy options
|
89
|
+
# @return [Strategies::Base] strategy instance
|
90
|
+
def self.create_open3_strategy(options)
|
91
|
+
Synchronous.new(**options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Create auto-detect strategy that tries ChildProcess first
|
95
|
+
#
|
96
|
+
# @param options [Hash] strategy options
|
97
|
+
# @return [Strategies::Base] strategy instance
|
98
|
+
def self.create_auto_detect_strategy(options)
|
99
|
+
# Always use Open3 for now to avoid circular dependency issues
|
100
|
+
begin
|
101
|
+
Makit::Logging.debug("Using Open3 strategy") if defined?(Makit::Logging)
|
102
|
+
Synchronous.new(**options)
|
103
|
+
rescue => e
|
104
|
+
# Fallback to basic strategy if there are any issues
|
105
|
+
Makit::Logging.warn("Failed to create Open3 strategy: #{e.message}") if defined?(Makit::Logging)
|
106
|
+
Synchronous.new
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Get information about available strategies
|
111
|
+
#
|
112
|
+
# @return [Hash] strategy information
|
113
|
+
def self.strategy_info
|
114
|
+
{
|
115
|
+
current: determine_strategy_type,
|
116
|
+
available: STRATEGIES.keys,
|
117
|
+
childprocess_available: childprocess_available?,
|
118
|
+
open3_available: true # Always available
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
# Check if ChildProcess strategy is available
|
123
|
+
#
|
124
|
+
# @return [Boolean] true if ChildProcess can be loaded
|
125
|
+
def self.childprocess_available?
|
126
|
+
begin
|
127
|
+
require 'childprocess'
|
128
|
+
true
|
129
|
+
rescue LoadError
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,139 +1,139 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base"
|
4
|
-
require_relative "../result"
|
5
|
-
|
6
|
-
module Makit
|
7
|
-
module Commands
|
8
|
-
module Strategies
|
9
|
-
# Synchronous command execution strategy.
|
10
|
-
#
|
11
|
-
# This strategy executes commands one at a time, blocking until each
|
12
|
-
# command completes. This is the simplest and most reliable execution
|
13
|
-
# pattern, suitable for most use cases.
|
14
|
-
#
|
15
|
-
# @example Using synchronous execution
|
16
|
-
# strategy = Synchronous.new
|
17
|
-
# request = Request.new(command: "echo", arguments: ["hello"])
|
18
|
-
# result = strategy.execute(request)
|
19
|
-
# puts result.stdout # "hello"
|
20
|
-
class Synchronous < Base
|
21
|
-
# Initialize synchronous execution strategy.
|
22
|
-
#
|
23
|
-
# @param options [Hash] strategy configuration
|
24
|
-
# @option options [Boolean] :validate_commands (true) whether to validate commands exist
|
25
|
-
# @option options [Integer] :max_output_size (1048576) maximum output size in bytes
|
26
|
-
def initialize(**options)
|
27
|
-
@validate_commands = false # Always disable validation to avoid path issues
|
28
|
-
@max_output_size = options.fetch(:max_output_size, 1024 * 1024) # 1MB default
|
29
|
-
end
|
30
|
-
|
31
|
-
# Execute a single command request synchronously.
|
32
|
-
#
|
33
|
-
# @param request [Request] the command request to execute
|
34
|
-
# @return [Result] execution result
|
35
|
-
def execute(request)
|
36
|
-
# Skip command validation for basic commands like echo on Windows
|
37
|
-
# This is a simplified approach for demonstration purposes
|
38
|
-
if @validate_commands && !basic_command?(request.command) && !command_available?(request.command)
|
39
|
-
# For dotnet commands, try to execute anyway as validation might be unreliable
|
40
|
-
if request.command == "dotnet"
|
41
|
-
Makit::Logging.debug("Skipping validation for dotnet command due to potential path issues")
|
42
|
-
else
|
43
|
-
return Result.failure(
|
44
|
-
command: request.to_shell_command,
|
45
|
-
error: "Command not found: #{request.command}",
|
46
|
-
)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Execute using Open3 for cross-platform support
|
51
|
-
result = execute_with_open3(request)
|
52
|
-
|
53
|
-
# Truncate output if too large
|
54
|
-
if result.stdout.bytesize > @max_output_size
|
55
|
-
original_size = result.stdout.bytesize
|
56
|
-
truncated_stdout = result.stdout.byteslice(0, @max_output_size)
|
57
|
-
result.instance_variable_set(:@stdout, "#{truncated_stdout}\n[OUTPUT TRUNCATED]")
|
58
|
-
result.add_metadata(:output_truncated, true)
|
59
|
-
result.add_metadata(:original_stdout_size, original_size)
|
60
|
-
end
|
61
|
-
|
62
|
-
if result.stderr.bytesize > @max_output_size
|
63
|
-
original_size = result.stderr.bytesize
|
64
|
-
truncated_stderr = result.stderr.byteslice(0, @max_output_size)
|
65
|
-
result.instance_variable_set(:@stderr, "#{truncated_stderr}\n[ERROR OUTPUT TRUNCATED]")
|
66
|
-
result.add_metadata(:stderr_truncated, true)
|
67
|
-
result.add_metadata(:original_stderr_size, original_size)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Add strategy metadata
|
71
|
-
result.add_metadata(:execution_strategy, "synchronous")
|
72
|
-
result.add_metadata(:validated_command, @validate_commands)
|
73
|
-
|
74
|
-
result
|
75
|
-
end
|
76
|
-
|
77
|
-
# Execute multiple requests sequentially.
|
78
|
-
#
|
79
|
-
# @param requests [Array<Request>] requests to execute
|
80
|
-
# @return [Array<Result>] execution results in same order
|
81
|
-
def execute_batch(requests)
|
82
|
-
results = []
|
83
|
-
|
84
|
-
requests.each_with_index do |request, index|
|
85
|
-
result = execute(request)
|
86
|
-
result.add_metadata(:batch_index, index)
|
87
|
-
result.add_metadata(:batch_size, requests.size)
|
88
|
-
results << result
|
89
|
-
|
90
|
-
# Stop on first failure if configured
|
91
|
-
break if result.failure? && fail_fast?
|
92
|
-
end
|
93
|
-
|
94
|
-
results
|
95
|
-
end
|
96
|
-
|
97
|
-
# Check if strategy supports the given request.
|
98
|
-
#
|
99
|
-
# Synchronous strategy supports all requests.
|
100
|
-
#
|
101
|
-
# @param request [Request] the command request
|
102
|
-
# @return [Boolean] always true
|
103
|
-
def supports?(_request)
|
104
|
-
true
|
105
|
-
end
|
106
|
-
|
107
|
-
# Get strategy configuration.
|
108
|
-
#
|
109
|
-
# @return [Hash] strategy configuration
|
110
|
-
def config
|
111
|
-
{
|
112
|
-
name: "synchronous",
|
113
|
-
validate_commands: @validate_commands,
|
114
|
-
max_output_size: @max_output_size,
|
115
|
-
fail_fast: fail_fast?,
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
# Check if command is a basic system command that should always be available.
|
122
|
-
#
|
123
|
-
# @param command [String] command name
|
124
|
-
# @return [Boolean] true if it's a basic command
|
125
|
-
def basic_command?(command)
|
126
|
-
%w[echo ruby bundle rake git dotnet].include?(command)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Check if execution should stop on first failure.
|
130
|
-
#
|
131
|
-
# @return [Boolean] whether to fail fast
|
132
|
-
def fail_fast?
|
133
|
-
# Could be configurable in the future
|
134
|
-
false
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
require_relative "../result"
|
5
|
+
|
6
|
+
module Makit
|
7
|
+
module Commands
|
8
|
+
module Strategies
|
9
|
+
# Synchronous command execution strategy.
|
10
|
+
#
|
11
|
+
# This strategy executes commands one at a time, blocking until each
|
12
|
+
# command completes. This is the simplest and most reliable execution
|
13
|
+
# pattern, suitable for most use cases.
|
14
|
+
#
|
15
|
+
# @example Using synchronous execution
|
16
|
+
# strategy = Synchronous.new
|
17
|
+
# request = Request.new(command: "echo", arguments: ["hello"])
|
18
|
+
# result = strategy.execute(request)
|
19
|
+
# puts result.stdout # "hello"
|
20
|
+
class Synchronous < Base
|
21
|
+
# Initialize synchronous execution strategy.
|
22
|
+
#
|
23
|
+
# @param options [Hash] strategy configuration
|
24
|
+
# @option options [Boolean] :validate_commands (true) whether to validate commands exist
|
25
|
+
# @option options [Integer] :max_output_size (1048576) maximum output size in bytes
|
26
|
+
def initialize(**options)
|
27
|
+
@validate_commands = false # Always disable validation to avoid path issues
|
28
|
+
@max_output_size = options.fetch(:max_output_size, 1024 * 1024) # 1MB default
|
29
|
+
end
|
30
|
+
|
31
|
+
# Execute a single command request synchronously.
|
32
|
+
#
|
33
|
+
# @param request [Request] the command request to execute
|
34
|
+
# @return [Result] execution result
|
35
|
+
def execute(request)
|
36
|
+
# Skip command validation for basic commands like echo on Windows
|
37
|
+
# This is a simplified approach for demonstration purposes
|
38
|
+
if @validate_commands && !basic_command?(request.command) && !command_available?(request.command)
|
39
|
+
# For dotnet commands, try to execute anyway as validation might be unreliable
|
40
|
+
if request.command == "dotnet"
|
41
|
+
Makit::Logging.debug("Skipping validation for dotnet command due to potential path issues")
|
42
|
+
else
|
43
|
+
return Result.failure(
|
44
|
+
command: request.to_shell_command,
|
45
|
+
error: "Command not found: #{request.command}",
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Execute using Open3 for cross-platform support
|
51
|
+
result = execute_with_open3(request)
|
52
|
+
|
53
|
+
# Truncate output if too large
|
54
|
+
if result.stdout.bytesize > @max_output_size
|
55
|
+
original_size = result.stdout.bytesize
|
56
|
+
truncated_stdout = result.stdout.byteslice(0, @max_output_size)
|
57
|
+
result.instance_variable_set(:@stdout, "#{truncated_stdout}\n[OUTPUT TRUNCATED]")
|
58
|
+
result.add_metadata(:output_truncated, true)
|
59
|
+
result.add_metadata(:original_stdout_size, original_size)
|
60
|
+
end
|
61
|
+
|
62
|
+
if result.stderr.bytesize > @max_output_size
|
63
|
+
original_size = result.stderr.bytesize
|
64
|
+
truncated_stderr = result.stderr.byteslice(0, @max_output_size)
|
65
|
+
result.instance_variable_set(:@stderr, "#{truncated_stderr}\n[ERROR OUTPUT TRUNCATED]")
|
66
|
+
result.add_metadata(:stderr_truncated, true)
|
67
|
+
result.add_metadata(:original_stderr_size, original_size)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Add strategy metadata
|
71
|
+
result.add_metadata(:execution_strategy, "synchronous")
|
72
|
+
result.add_metadata(:validated_command, @validate_commands)
|
73
|
+
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
# Execute multiple requests sequentially.
|
78
|
+
#
|
79
|
+
# @param requests [Array<Request>] requests to execute
|
80
|
+
# @return [Array<Result>] execution results in same order
|
81
|
+
def execute_batch(requests)
|
82
|
+
results = []
|
83
|
+
|
84
|
+
requests.each_with_index do |request, index|
|
85
|
+
result = execute(request)
|
86
|
+
result.add_metadata(:batch_index, index)
|
87
|
+
result.add_metadata(:batch_size, requests.size)
|
88
|
+
results << result
|
89
|
+
|
90
|
+
# Stop on first failure if configured
|
91
|
+
break if result.failure? && fail_fast?
|
92
|
+
end
|
93
|
+
|
94
|
+
results
|
95
|
+
end
|
96
|
+
|
97
|
+
# Check if strategy supports the given request.
|
98
|
+
#
|
99
|
+
# Synchronous strategy supports all requests.
|
100
|
+
#
|
101
|
+
# @param request [Request] the command request
|
102
|
+
# @return [Boolean] always true
|
103
|
+
def supports?(_request)
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
# Get strategy configuration.
|
108
|
+
#
|
109
|
+
# @return [Hash] strategy configuration
|
110
|
+
def config
|
111
|
+
{
|
112
|
+
name: "synchronous",
|
113
|
+
validate_commands: @validate_commands,
|
114
|
+
max_output_size: @max_output_size,
|
115
|
+
fail_fast: fail_fast?,
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
# Check if command is a basic system command that should always be available.
|
122
|
+
#
|
123
|
+
# @param command [String] command name
|
124
|
+
# @return [Boolean] true if it's a basic command
|
125
|
+
def basic_command?(command)
|
126
|
+
%w[echo ruby bundle rake git dotnet].include?(command)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if execution should stop on first failure.
|
130
|
+
#
|
131
|
+
# @return [Boolean] whether to fail fast
|
132
|
+
def fail_fast?
|
133
|
+
# Could be configurable in the future
|
134
|
+
false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/makit/commands.rb
CHANGED
@@ -1,50 +1,50 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "English"
|
4
|
-
require "open3"
|
5
|
-
require "socket"
|
6
|
-
require "etc"
|
7
|
-
require "logger"
|
8
|
-
|
9
|
-
# This module provides classes for the Makit gem.
|
10
|
-
module Makit
|
11
|
-
# Commands module provides a modern, flexible command execution framework
|
12
|
-
# with middleware support, validation, caching, and structured logging.
|
13
|
-
module Commands
|
14
|
-
# Custom exception for security-related command validation failures
|
15
|
-
class SecurityError < StandardError; end
|
16
|
-
|
17
|
-
# Custom exception for command execution failures
|
18
|
-
class ExecutionError < StandardError
|
19
|
-
attr_reader :exit_code, :stderr
|
20
|
-
|
21
|
-
def initialize(message, exit_code: nil, stderr: nil)
|
22
|
-
@exit_code = exit_code
|
23
|
-
@stderr = stderr
|
24
|
-
super(message)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# This class provide methods running commands.
|
30
|
-
#
|
31
|
-
class LegacyCommands < Array
|
32
|
-
# Generate the commands based on the current directory.
|
33
|
-
def auto_generate
|
34
|
-
self << Makit::V1::CommandRequest.new(name: "bundle", arguments: ["install"]) if File.exist?("Gemfile")
|
35
|
-
self << Makit::V1::CommandRequest.new(name: "bundle", arguments: %w[exec rake]) if File.exist?("Rakefile")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Load command system components (load existing components only)
|
41
|
-
require_relative "commands/result"
|
42
|
-
require_relative "commands/request"
|
43
|
-
require_relative "commands/runner"
|
44
|
-
require_relative "commands/factory"
|
45
|
-
require_relative "commands/middleware/validator"
|
46
|
-
require_relative "commands/middleware/cache"
|
47
|
-
require_relative "commands/middleware/command_logger"
|
48
|
-
require_relative "commands/middleware/base"
|
49
|
-
require_relative "commands/strategies/base"
|
50
|
-
require_relative "commands/strategies/synchronous"
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "English"
|
4
|
+
require "open3"
|
5
|
+
require "socket"
|
6
|
+
require "etc"
|
7
|
+
require "logger"
|
8
|
+
|
9
|
+
# This module provides classes for the Makit gem.
|
10
|
+
module Makit
|
11
|
+
# Commands module provides a modern, flexible command execution framework
|
12
|
+
# with middleware support, validation, caching, and structured logging.
|
13
|
+
module Commands
|
14
|
+
# Custom exception for security-related command validation failures
|
15
|
+
class SecurityError < StandardError; end
|
16
|
+
|
17
|
+
# Custom exception for command execution failures
|
18
|
+
class ExecutionError < StandardError
|
19
|
+
attr_reader :exit_code, :stderr
|
20
|
+
|
21
|
+
def initialize(message, exit_code: nil, stderr: nil)
|
22
|
+
@exit_code = exit_code
|
23
|
+
@stderr = stderr
|
24
|
+
super(message)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# This class provide methods running commands.
|
30
|
+
#
|
31
|
+
class LegacyCommands < Array
|
32
|
+
# Generate the commands based on the current directory.
|
33
|
+
def auto_generate
|
34
|
+
self << Makit::V1::CommandRequest.new(name: "bundle", arguments: ["install"]) if File.exist?("Gemfile")
|
35
|
+
self << Makit::V1::CommandRequest.new(name: "bundle", arguments: %w[exec rake]) if File.exist?("Rakefile")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Load command system components (load existing components only)
|
41
|
+
require_relative "commands/result"
|
42
|
+
require_relative "commands/request"
|
43
|
+
require_relative "commands/runner"
|
44
|
+
require_relative "commands/factory"
|
45
|
+
require_relative "commands/middleware/validator"
|
46
|
+
require_relative "commands/middleware/cache"
|
47
|
+
require_relative "commands/middleware/command_logger"
|
48
|
+
require_relative "commands/middleware/base"
|
49
|
+
require_relative "commands/strategies/base"
|
50
|
+
require_relative "commands/strategies/synchronous"
|