makit 0.0.164 → 0.0.166

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 (178) 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/azure/blob_storage.rb +257 -257
  7. data/lib/makit/azure/cli.rb +284 -284
  8. data/lib/makit/azure-pipelines.rb +139 -0
  9. data/lib/makit/cli/base.rb +17 -17
  10. data/lib/makit/cli/build_commands.rb +500 -500
  11. data/lib/makit/cli/generators/base_generator.rb +74 -74
  12. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  13. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  14. data/lib/makit/cli/generators/node_generator.rb +50 -50
  15. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  16. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  17. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  18. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  19. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  20. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +41 -41
  21. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  22. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  23. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  24. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  25. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  26. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  27. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  28. data/lib/makit/cli/main.rb +78 -78
  29. data/lib/makit/cli/pipeline_commands.rb +311 -311
  30. data/lib/makit/cli/project_commands.rb +868 -868
  31. data/lib/makit/cli/repository_commands.rb +661 -661
  32. data/lib/makit/cli/strategy_commands.rb +207 -207
  33. data/lib/makit/cli/utility_commands.rb +521 -521
  34. data/lib/makit/commands/factory.rb +359 -359
  35. data/lib/makit/commands/middleware/base.rb +73 -73
  36. data/lib/makit/commands/middleware/cache.rb +248 -248
  37. data/lib/makit/commands/middleware/command_logger.rb +312 -312
  38. data/lib/makit/commands/middleware/validator.rb +269 -269
  39. data/lib/makit/commands/request.rb +316 -316
  40. data/lib/makit/commands/result.rb +323 -323
  41. data/lib/makit/commands/runner.rb +386 -386
  42. data/lib/makit/commands/strategies/base.rb +171 -171
  43. data/lib/makit/commands/strategies/child_process.rb +162 -162
  44. data/lib/makit/commands/strategies/factory.rb +136 -136
  45. data/lib/makit/commands/strategies/synchronous.rb +139 -139
  46. data/lib/makit/commands.rb +50 -50
  47. data/lib/makit/configuration/dotnet_project.rb +48 -48
  48. data/lib/makit/configuration/gitlab_helper.rb +61 -61
  49. data/lib/makit/configuration/project.rb +292 -292
  50. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  51. data/lib/makit/configuration/step.rb +34 -34
  52. data/lib/makit/configuration/timeout.rb +74 -74
  53. data/lib/makit/configuration.rb +21 -21
  54. data/lib/makit/content/default_gitignore.rb +7 -7
  55. data/lib/makit/content/default_gitignore.txt +225 -225
  56. data/lib/makit/content/default_rakefile.rb +13 -13
  57. data/lib/makit/content/gem_rakefile.rb +16 -16
  58. data/lib/makit/context.rb +1 -1
  59. data/lib/makit/data.rb +49 -49
  60. data/lib/makit/directories.rb +170 -170
  61. data/lib/makit/directory.rb +262 -262
  62. data/lib/makit/docs/files.rb +89 -89
  63. data/lib/makit/docs/rake.rb +102 -102
  64. data/lib/makit/dotnet/cli.rb +224 -224
  65. data/lib/makit/dotnet/project.rb +217 -217
  66. data/lib/makit/dotnet/solution.rb +38 -38
  67. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  68. data/lib/makit/dotnet/solution_console.rb +264 -264
  69. data/lib/makit/dotnet/solution_maui.rb +354 -354
  70. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  71. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  72. data/lib/makit/dotnet.rb +110 -110
  73. data/lib/makit/email.rb +90 -90
  74. data/lib/makit/environment.rb +142 -142
  75. data/lib/makit/examples/runner.rb +370 -370
  76. data/lib/makit/exceptions.rb +45 -45
  77. data/lib/makit/fileinfo.rb +32 -32
  78. data/lib/makit/files.rb +43 -43
  79. data/lib/makit/gems.rb +49 -49
  80. data/lib/makit/git/cli.rb +103 -103
  81. data/lib/makit/git/repository.rb +100 -100
  82. data/lib/makit/git.rb +104 -104
  83. data/lib/makit/gitlab/pipeline.rb +857 -857
  84. data/lib/makit/gitlab/pipeline_service_impl.rb +1535 -1535
  85. data/lib/makit/gitlab_runner.rb +59 -59
  86. data/lib/makit/humanize.rb +218 -218
  87. data/lib/makit/indexer.rb +47 -47
  88. data/lib/makit/io/filesystem.rb +111 -111
  89. data/lib/makit/io/filesystem_service_impl.rb +337 -337
  90. data/lib/makit/lint.rb +212 -212
  91. data/lib/makit/logging/configuration.rb +309 -309
  92. data/lib/makit/logging/format_registry.rb +84 -84
  93. data/lib/makit/logging/formatters/base.rb +39 -39
  94. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  95. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  96. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  97. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  98. data/lib/makit/logging/log_request.rb +119 -119
  99. data/lib/makit/logging/logger.rb +199 -199
  100. data/lib/makit/logging/sinks/base.rb +91 -91
  101. data/lib/makit/logging/sinks/console.rb +72 -72
  102. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  103. data/lib/makit/logging/sinks/structured.rb +123 -123
  104. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  105. data/lib/makit/logging.rb +578 -578
  106. data/lib/makit/markdown.rb +75 -75
  107. data/lib/makit/mp/basic_object_mp.rb +17 -17
  108. data/lib/makit/mp/command_mp.rb +13 -13
  109. data/lib/makit/mp/command_request.mp.rb +17 -17
  110. data/lib/makit/mp/project_mp.rb +199 -199
  111. data/lib/makit/mp/string_mp.rb +205 -205
  112. data/lib/makit/nuget.rb +454 -454
  113. data/lib/makit/podman/podman.rb +458 -458
  114. data/lib/makit/podman/podman_service_impl.rb +1081 -1081
  115. data/lib/makit/port.rb +32 -32
  116. data/lib/makit/process.rb +377 -377
  117. data/lib/makit/protoc.rb +112 -112
  118. data/lib/makit/rake/cli.rb +196 -196
  119. data/lib/makit/rake/trace_controller.rb +174 -174
  120. data/lib/makit/rake.rb +81 -81
  121. data/lib/makit/ruby/cli.rb +185 -185
  122. data/lib/makit/ruby.rb +25 -25
  123. data/lib/makit/rubygems.rb +137 -137
  124. data/lib/makit/secrets/azure_key_vault.rb +322 -322
  125. data/lib/makit/secrets/azure_secrets.rb +221 -183
  126. data/lib/makit/secrets/local_secrets.rb +72 -72
  127. data/lib/makit/secrets/secrets_manager.rb +105 -105
  128. data/lib/makit/secrets.rb +96 -16
  129. data/lib/makit/serializer.rb +130 -130
  130. data/lib/makit/services/builder.rb +186 -186
  131. data/lib/makit/services/error_handler.rb +226 -226
  132. data/lib/makit/services/repository_manager.rb +367 -367
  133. data/lib/makit/services/validator.rb +112 -112
  134. data/lib/makit/setup/classlib.rb +101 -101
  135. data/lib/makit/setup/gem.rb +268 -268
  136. data/lib/makit/setup/pages.rb +11 -11
  137. data/lib/makit/setup/razorclasslib.rb +101 -101
  138. data/lib/makit/setup/runner.rb +54 -54
  139. data/lib/makit/setup.rb +5 -5
  140. data/lib/makit/show.rb +110 -110
  141. data/lib/makit/storage.rb +126 -126
  142. data/lib/makit/symbols.rb +175 -175
  143. data/lib/makit/task_info.rb +130 -130
  144. data/lib/makit/tasks/at_exit.rb +15 -15
  145. data/lib/makit/tasks/build.rb +22 -22
  146. data/lib/makit/tasks/bump.rb +7 -7
  147. data/lib/makit/tasks/clean.rb +13 -13
  148. data/lib/makit/tasks/configure.rb +10 -10
  149. data/lib/makit/tasks/format.rb +10 -10
  150. data/lib/makit/tasks/hook_manager.rb +443 -443
  151. data/lib/makit/tasks/info.rb +368 -368
  152. data/lib/makit/tasks/init.rb +49 -49
  153. data/lib/makit/tasks/integrate.rb +60 -60
  154. data/lib/makit/tasks/pull_incoming.rb +13 -13
  155. data/lib/makit/tasks/secrets.rb +7 -7
  156. data/lib/makit/tasks/setup.rb +16 -16
  157. data/lib/makit/tasks/sync.rb +14 -14
  158. data/lib/makit/tasks/tag.rb +27 -27
  159. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  160. data/lib/makit/tasks/test.rb +22 -22
  161. data/lib/makit/tasks/update.rb +21 -21
  162. data/lib/makit/tasks/version.rb +6 -6
  163. data/lib/makit/tasks.rb +24 -24
  164. data/lib/makit/test_cache.rb +239 -239
  165. data/lib/makit/tree.rb +37 -37
  166. data/lib/makit/v1/configuration/project_service_impl.rb +370 -370
  167. data/lib/makit/v1/git/git_repository_service_impl.rb +295 -295
  168. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  169. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  170. data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -572
  171. data/lib/makit/version.rb +661 -661
  172. data/lib/makit/version_util.rb +21 -21
  173. data/lib/makit/wix.rb +95 -95
  174. data/lib/makit/yaml.rb +29 -29
  175. data/lib/makit/zip.rb +17 -17
  176. data/lib/makit copy.rb +44 -44
  177. data/lib/makit.rb +120 -119
  178. metadata +3 -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"