makit 0.0.140 → 0.0.142

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.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -41
  3. data/exe/makit +5 -5
  4. data/lib/makit/apache.rb +28 -28
  5. data/lib/makit/auto.rb +48 -48
  6. data/lib/makit/cli/build_commands.rb +500 -500
  7. data/lib/makit/cli/generators/base_generator.rb +74 -74
  8. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  9. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  10. data/lib/makit/cli/generators/node_generator.rb +50 -50
  11. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  12. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  13. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  14. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  15. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  16. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
  17. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  18. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  19. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  20. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  21. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  22. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  23. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  24. data/lib/makit/cli/main.rb +69 -69
  25. data/lib/makit/cli/project_commands.rb +868 -868
  26. data/lib/makit/cli/repository_commands.rb +661 -661
  27. data/lib/makit/cli/strategy_commands.rb +203 -203
  28. data/lib/makit/cli/utility_commands.rb +521 -521
  29. data/lib/makit/commands/factory.rb +359 -359
  30. data/lib/makit/commands/middleware/base.rb +73 -73
  31. data/lib/makit/commands/middleware/cache.rb +248 -248
  32. data/lib/makit/commands/middleware/command_logger.rb +312 -312
  33. data/lib/makit/commands/middleware/validator.rb +269 -269
  34. data/lib/makit/commands/request.rb +316 -316
  35. data/lib/makit/commands/result.rb +323 -323
  36. data/lib/makit/commands/runner.rb +388 -385
  37. data/lib/makit/commands/strategies/base.rb +171 -171
  38. data/lib/makit/commands/strategies/child_process.rb +165 -165
  39. data/lib/makit/commands/strategies/factory.rb +136 -136
  40. data/lib/makit/commands/strategies/synchronous.rb +139 -139
  41. data/lib/makit/commands.rb +50 -50
  42. data/lib/makit/configuration/dotnet_project.rb +12 -12
  43. data/lib/makit/configuration/gitlab_helper.rb +58 -58
  44. data/lib/makit/configuration/project.rb +168 -168
  45. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  46. data/lib/makit/configuration/step.rb +34 -34
  47. data/lib/makit/configuration/timeout.rb +74 -74
  48. data/lib/makit/configuration.rb +15 -15
  49. data/lib/makit/content/default_gitignore.rb +7 -7
  50. data/lib/makit/content/default_gitignore.txt +225 -225
  51. data/lib/makit/content/default_rakefile.rb +13 -13
  52. data/lib/makit/content/gem_rakefile.rb +16 -16
  53. data/lib/makit/context.rb +1 -1
  54. data/lib/makit/data.rb +49 -49
  55. data/lib/makit/directories.rb +140 -140
  56. data/lib/makit/directory.rb +262 -262
  57. data/lib/makit/docs/files.rb +89 -89
  58. data/lib/makit/docs/rake.rb +102 -102
  59. data/lib/makit/dotnet/cli.rb +69 -69
  60. data/lib/makit/dotnet/project.rb +217 -217
  61. data/lib/makit/dotnet/solution.rb +38 -38
  62. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  63. data/lib/makit/dotnet/solution_console.rb +264 -264
  64. data/lib/makit/dotnet/solution_maui.rb +354 -354
  65. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  66. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  67. data/lib/makit/dotnet.rb +102 -102
  68. data/lib/makit/email.rb +90 -90
  69. data/lib/makit/environment.rb +142 -142
  70. data/lib/makit/examples/runner.rb +370 -370
  71. data/lib/makit/exceptions.rb +45 -45
  72. data/lib/makit/fileinfo.rb +24 -24
  73. data/lib/makit/files.rb +43 -43
  74. data/lib/makit/gems.rb +40 -40
  75. data/lib/makit/git/cli.rb +54 -54
  76. data/lib/makit/git/repository.rb +90 -90
  77. data/lib/makit/git.rb +98 -98
  78. data/lib/makit/gitlab_runner.rb +59 -59
  79. data/lib/makit/humanize.rb +137 -137
  80. data/lib/makit/indexer.rb +47 -47
  81. data/lib/makit/logging/configuration.rb +308 -308
  82. data/lib/makit/logging/format_registry.rb +84 -84
  83. data/lib/makit/logging/formatters/base.rb +39 -39
  84. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  85. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  86. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  87. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  88. data/lib/makit/logging/log_request.rb +119 -119
  89. data/lib/makit/logging/logger.rb +199 -199
  90. data/lib/makit/logging/sinks/base.rb +91 -91
  91. data/lib/makit/logging/sinks/console.rb +72 -72
  92. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  93. data/lib/makit/logging/sinks/structured.rb +123 -123
  94. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  95. data/lib/makit/logging.rb +565 -565
  96. data/lib/makit/markdown.rb +75 -75
  97. data/lib/makit/mp/basic_object_mp.rb +17 -17
  98. data/lib/makit/mp/command_mp.rb +13 -13
  99. data/lib/makit/mp/command_request.mp.rb +17 -17
  100. data/lib/makit/mp/project_mp.rb +199 -199
  101. data/lib/makit/mp/string_mp.rb +199 -191
  102. data/lib/makit/nuget.rb +74 -74
  103. data/lib/makit/port.rb +32 -32
  104. data/lib/makit/process.rb +163 -163
  105. data/lib/makit/protoc.rb +107 -107
  106. data/lib/makit/rake/cli.rb +196 -196
  107. data/lib/makit/rake/trace_controller.rb +173 -173
  108. data/lib/makit/rake.rb +80 -80
  109. data/lib/makit/ruby/cli.rb +185 -185
  110. data/lib/makit/ruby.rb +25 -25
  111. data/lib/makit/secrets.rb +51 -51
  112. data/lib/makit/serializer.rb +130 -130
  113. data/lib/makit/services/builder.rb +186 -186
  114. data/lib/makit/services/error_handler.rb +226 -226
  115. data/lib/makit/services/repository_manager.rb +231 -231
  116. data/lib/makit/services/validator.rb +112 -112
  117. data/lib/makit/setup/classlib.rb +101 -101
  118. data/lib/makit/setup/gem.rb +268 -268
  119. data/lib/makit/setup/razorclasslib.rb +101 -101
  120. data/lib/makit/setup/runner.rb +54 -54
  121. data/lib/makit/setup.rb +5 -5
  122. data/lib/makit/show.rb +110 -110
  123. data/lib/makit/storage.rb +126 -126
  124. data/lib/makit/symbols.rb +170 -170
  125. data/lib/makit/task_info.rb +130 -130
  126. data/lib/makit/tasks/at_exit.rb +15 -15
  127. data/lib/makit/tasks/build.rb +22 -22
  128. data/lib/makit/tasks/clean.rb +13 -13
  129. data/lib/makit/tasks/configure.rb +10 -10
  130. data/lib/makit/tasks/format.rb +10 -10
  131. data/lib/makit/tasks/hook_manager.rb +443 -443
  132. data/lib/makit/tasks/init.rb +49 -49
  133. data/lib/makit/tasks/integrate.rb +29 -29
  134. data/lib/makit/tasks/pull_incoming.rb +13 -13
  135. data/lib/makit/tasks/setup.rb +13 -13
  136. data/lib/makit/tasks/sync.rb +17 -17
  137. data/lib/makit/tasks/tag.rb +16 -16
  138. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  139. data/lib/makit/tasks/test.rb +22 -22
  140. data/lib/makit/tasks/update.rb +18 -18
  141. data/lib/makit/tasks.rb +20 -20
  142. data/lib/makit/test_cache.rb +239 -239
  143. data/lib/makit/tree.rb +37 -37
  144. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  145. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  146. data/lib/makit/version.rb +99 -99
  147. data/lib/makit/version_util.rb +21 -21
  148. data/lib/makit/wix.rb +95 -95
  149. data/lib/makit/yaml.rb +29 -29
  150. data/lib/makit/zip.rb +17 -17
  151. data/lib/makit copy.rb +44 -44
  152. data/lib/makit.rb +43 -42
  153. 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
@@ -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"