makit 0.0.167 → 0.0.169

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 (179) 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 +187 -187
  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/github_actions.rb +202 -0
  84. data/lib/makit/gitlab/pipeline.rb +857 -857
  85. data/lib/makit/gitlab/pipeline_service_impl.rb +1535 -1535
  86. data/lib/makit/gitlab_runner.rb +59 -59
  87. data/lib/makit/humanize.rb +218 -218
  88. data/lib/makit/indexer.rb +47 -47
  89. data/lib/makit/io/filesystem.rb +111 -111
  90. data/lib/makit/io/filesystem_service_impl.rb +337 -337
  91. data/lib/makit/lint.rb +212 -212
  92. data/lib/makit/logging/configuration.rb +309 -309
  93. data/lib/makit/logging/format_registry.rb +84 -84
  94. data/lib/makit/logging/formatters/base.rb +39 -39
  95. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  96. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  97. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  98. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  99. data/lib/makit/logging/log_request.rb +119 -119
  100. data/lib/makit/logging/logger.rb +199 -199
  101. data/lib/makit/logging/sinks/base.rb +91 -91
  102. data/lib/makit/logging/sinks/console.rb +72 -72
  103. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  104. data/lib/makit/logging/sinks/structured.rb +123 -123
  105. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  106. data/lib/makit/logging.rb +578 -578
  107. data/lib/makit/markdown.rb +75 -75
  108. data/lib/makit/mp/basic_object_mp.rb +17 -17
  109. data/lib/makit/mp/command_mp.rb +13 -13
  110. data/lib/makit/mp/command_request.mp.rb +17 -17
  111. data/lib/makit/mp/project_mp.rb +199 -199
  112. data/lib/makit/mp/string_mp.rb +205 -205
  113. data/lib/makit/nuget.rb +460 -454
  114. data/lib/makit/podman/podman.rb +458 -458
  115. data/lib/makit/podman/podman_service_impl.rb +1081 -1081
  116. data/lib/makit/port.rb +32 -32
  117. data/lib/makit/process.rb +377 -377
  118. data/lib/makit/protoc.rb +112 -112
  119. data/lib/makit/rake/cli.rb +196 -196
  120. data/lib/makit/rake/trace_controller.rb +174 -174
  121. data/lib/makit/rake.rb +81 -81
  122. data/lib/makit/ruby/cli.rb +185 -185
  123. data/lib/makit/ruby.rb +25 -25
  124. data/lib/makit/rubygems.rb +137 -137
  125. data/lib/makit/secrets/azure_key_vault.rb +322 -322
  126. data/lib/makit/secrets/azure_secrets.rb +221 -221
  127. data/lib/makit/secrets/local_secrets.rb +72 -72
  128. data/lib/makit/secrets/secrets_manager.rb +105 -105
  129. data/lib/makit/secrets.rb +96 -96
  130. data/lib/makit/serializer.rb +130 -130
  131. data/lib/makit/services/builder.rb +186 -186
  132. data/lib/makit/services/error_handler.rb +226 -226
  133. data/lib/makit/services/repository_manager.rb +367 -367
  134. data/lib/makit/services/validator.rb +112 -112
  135. data/lib/makit/setup/classlib.rb +101 -101
  136. data/lib/makit/setup/gem.rb +268 -268
  137. data/lib/makit/setup/pages.rb +11 -11
  138. data/lib/makit/setup/razorclasslib.rb +101 -101
  139. data/lib/makit/setup/runner.rb +54 -54
  140. data/lib/makit/setup.rb +5 -5
  141. data/lib/makit/show.rb +110 -110
  142. data/lib/makit/storage.rb +126 -126
  143. data/lib/makit/symbols.rb +175 -175
  144. data/lib/makit/task_info.rb +130 -130
  145. data/lib/makit/tasks/at_exit.rb +15 -15
  146. data/lib/makit/tasks/build.rb +22 -22
  147. data/lib/makit/tasks/bump.rb +7 -7
  148. data/lib/makit/tasks/clean.rb +13 -13
  149. data/lib/makit/tasks/configure.rb +10 -10
  150. data/lib/makit/tasks/format.rb +10 -10
  151. data/lib/makit/tasks/hook_manager.rb +443 -443
  152. data/lib/makit/tasks/info.rb +368 -368
  153. data/lib/makit/tasks/init.rb +49 -49
  154. data/lib/makit/tasks/integrate.rb +60 -60
  155. data/lib/makit/tasks/pull_incoming.rb +13 -13
  156. data/lib/makit/tasks/secrets.rb +7 -7
  157. data/lib/makit/tasks/setup.rb +16 -16
  158. data/lib/makit/tasks/sync.rb +14 -14
  159. data/lib/makit/tasks/tag.rb +27 -27
  160. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  161. data/lib/makit/tasks/test.rb +22 -22
  162. data/lib/makit/tasks/update.rb +21 -21
  163. data/lib/makit/tasks/version.rb +6 -6
  164. data/lib/makit/tasks.rb +24 -24
  165. data/lib/makit/test_cache.rb +239 -239
  166. data/lib/makit/tree.rb +37 -37
  167. data/lib/makit/v1/configuration/project_service_impl.rb +370 -370
  168. data/lib/makit/v1/git/git_repository_service_impl.rb +295 -295
  169. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  170. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  171. data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -572
  172. data/lib/makit/version.rb +661 -661
  173. data/lib/makit/version_util.rb +21 -21
  174. data/lib/makit/wix.rb +95 -95
  175. data/lib/makit/yaml.rb +29 -29
  176. data/lib/makit/zip.rb +17 -17
  177. data/lib/makit copy.rb +44 -44
  178. data/lib/makit.rb +121 -120
  179. 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"