makit 0.0.111 → 0.0.112

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 (140) 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/cli/build_commands.rb +500 -500
  6. data/lib/makit/cli/generators/base_generator.rb +74 -74
  7. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  8. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  9. data/lib/makit/cli/generators/node_generator.rb +50 -50
  10. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  11. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  12. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  13. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  14. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  15. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -40
  16. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  17. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  18. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  19. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  20. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  21. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  22. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  23. data/lib/makit/cli/main.rb +62 -62
  24. data/lib/makit/cli/project_commands.rb +868 -868
  25. data/lib/makit/cli/repository_commands.rb +661 -661
  26. data/lib/makit/cli/utility_commands.rb +521 -521
  27. data/lib/makit/commands/factory.rb +359 -359
  28. data/lib/makit/commands/middleware/base.rb +73 -73
  29. data/lib/makit/commands/middleware/cache.rb +248 -248
  30. data/lib/makit/commands/middleware/command_logger.rb +320 -323
  31. data/lib/makit/commands/middleware/unified_logger.rb +243 -243
  32. data/lib/makit/commands/middleware/validator.rb +269 -269
  33. data/lib/makit/commands/request.rb +254 -254
  34. data/lib/makit/commands/result.rb +323 -323
  35. data/lib/makit/commands/runner.rb +337 -317
  36. data/lib/makit/commands/strategies/base.rb +160 -160
  37. data/lib/makit/commands/strategies/synchronous.rb +134 -134
  38. data/lib/makit/commands.rb +51 -42
  39. data/lib/makit/configuration/gitlab_helper.rb +60 -60
  40. data/lib/makit/configuration/project.rb +127 -127
  41. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  42. data/lib/makit/configuration/step.rb +34 -34
  43. data/lib/makit/configuration.rb +14 -14
  44. data/lib/makit/content/default_gitignore.rb +7 -7
  45. data/lib/makit/content/default_rakefile.rb +13 -13
  46. data/lib/makit/content/gem_rakefile.rb +16 -16
  47. data/lib/makit/context.rb +1 -1
  48. data/lib/makit/data.rb +49 -49
  49. data/lib/makit/directories.rb +141 -141
  50. data/lib/makit/directory.rb +262 -262
  51. data/lib/makit/docs/files.rb +89 -89
  52. data/lib/makit/docs/rake.rb +102 -102
  53. data/lib/makit/dotnet/project.rb +153 -153
  54. data/lib/makit/dotnet/solution.rb +38 -38
  55. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  56. data/lib/makit/dotnet/solution_console.rb +264 -264
  57. data/lib/makit/dotnet/solution_maui.rb +354 -354
  58. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  59. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  60. data/lib/makit/dotnet.rb +102 -102
  61. data/lib/makit/email.rb +90 -90
  62. data/lib/makit/environment.rb +142 -142
  63. data/lib/makit/examples/runner.rb +370 -370
  64. data/lib/makit/exceptions.rb +45 -45
  65. data/lib/makit/fileinfo.rb +24 -24
  66. data/lib/makit/files.rb +43 -43
  67. data/lib/makit/gems.rb +40 -40
  68. data/lib/makit/git/cli.rb +54 -54
  69. data/lib/makit/git/repository.rb +90 -90
  70. data/lib/makit/git.rb +98 -98
  71. data/lib/makit/gitlab_runner.rb +59 -59
  72. data/lib/makit/humanize.rb +137 -137
  73. data/lib/makit/indexer.rb +47 -47
  74. data/lib/makit/logging/configuration.rb +305 -305
  75. data/lib/makit/logging/formatters/base.rb +39 -39
  76. data/lib/makit/logging/formatters/console_formatter.rb +140 -127
  77. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  78. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  79. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  80. data/lib/makit/logging/log_request.rb +115 -115
  81. data/lib/makit/logging/logger.rb +163 -159
  82. data/lib/makit/logging/sinks/console.rb +72 -72
  83. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  84. data/lib/makit/logging/sinks/unified_file_sink.rb +303 -303
  85. data/lib/makit/logging.rb +530 -521
  86. data/lib/makit/markdown.rb +75 -75
  87. data/lib/makit/mp/basic_object_mp.rb +17 -17
  88. data/lib/makit/mp/command_mp.rb +13 -13
  89. data/lib/makit/mp/command_request.mp.rb +17 -17
  90. data/lib/makit/mp/project_mp.rb +199 -199
  91. data/lib/makit/mp/string_mp.rb +193 -348
  92. data/lib/makit/nuget.rb +74 -74
  93. data/lib/makit/port.rb +32 -32
  94. data/lib/makit/process.rb +163 -163
  95. data/lib/makit/protoc.rb +107 -107
  96. data/lib/makit/rake/cli.rb +196 -196
  97. data/lib/makit/rake.rb +25 -25
  98. data/lib/makit/ruby/cli.rb +185 -185
  99. data/lib/makit/ruby.rb +25 -25
  100. data/lib/makit/secrets.rb +51 -51
  101. data/lib/makit/serializer.rb +130 -117
  102. data/lib/makit/services/builder.rb +186 -186
  103. data/lib/makit/services/error_handler.rb +226 -226
  104. data/lib/makit/services/repository_manager.rb +229 -229
  105. data/lib/makit/services/validator.rb +112 -112
  106. data/lib/makit/setup/classlib.rb +53 -53
  107. data/lib/makit/setup/gem.rb +30 -17
  108. data/lib/makit/setup/runner.rb +45 -40
  109. data/lib/makit/setup.rb +5 -0
  110. data/lib/makit/show.rb +110 -110
  111. data/lib/makit/storage.rb +126 -126
  112. data/lib/makit/symbols.rb +170 -161
  113. data/lib/makit/task_info.rb +128 -128
  114. data/lib/makit/tasks/at_exit.rb +13 -13
  115. data/lib/makit/tasks/build.rb +19 -18
  116. data/lib/makit/tasks/clean.rb +11 -11
  117. data/lib/makit/tasks/hook_manager.rb +393 -239
  118. data/lib/makit/tasks/init.rb +47 -47
  119. data/lib/makit/tasks/integrate.rb +17 -15
  120. data/lib/makit/tasks/pull_incoming.rb +11 -12
  121. data/lib/makit/tasks/setup.rb +6 -6
  122. data/lib/makit/tasks/sync.rb +12 -11
  123. data/lib/makit/tasks/tag.rb +15 -0
  124. data/lib/makit/tasks/task_monkey_patch.rb +79 -79
  125. data/lib/makit/tasks.rb +10 -0
  126. data/lib/makit/test_cache.rb +239 -239
  127. data/lib/makit/tree.rb +37 -37
  128. data/lib/makit/v1/makit.v1_pb.rb +34 -34
  129. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  130. data/lib/makit/version.rb +5 -5
  131. data/lib/makit/version_util.rb +21 -0
  132. data/lib/makit/wix.rb +95 -95
  133. data/lib/makit/yaml.rb +29 -29
  134. data/lib/makit/zip.rb +17 -17
  135. data/lib/makit copy.rb +44 -0
  136. data/lib/makit.rb +40 -8
  137. metadata +50 -7
  138. data/lib/makit/command_runner.rb +0 -463
  139. data/lib/makit/commands/compatibility.rb +0 -365
  140. data/lib/makit/task_hooks.rb +0 -125
@@ -1,11 +1,11 @@
1
- require "rake/clean"
2
- require_relative "../git/repository"
3
- require_relative "../commands/runner"
4
-
5
- CLEAN.include("artifacts/**/*")
6
-
7
- task :clean do
8
- if Makit::Git::Repository.git_repo?
9
- Makit::Commands::Runner.default.execute(Makit::Commands::Request.from_string("git clean -dXf"))
10
- end
11
- end
1
+ require "rake/clean"
2
+ require_relative "../git/repository"
3
+ require_relative "../commands/runner"
4
+
5
+ CLEAN.include("artifacts/**/*")
6
+
7
+ task :clean do
8
+ if Makit::Git::Repository.git_repo?
9
+ Makit::Commands::Runner.default.execute(Makit::Commands::Request.from_string("git clean -dXf"))
10
+ end
11
+ end
@@ -1,239 +1,393 @@
1
- # frozen_string_literal: true
2
-
3
- require "set"
4
- require "colorize"
5
-
6
- # Task hooks system for Makit
7
- #
8
- # This module provides a comprehensive hook system for Rake tasks, allowing
9
- # developers to add pre and post execution hooks globally or for specific tasks.
10
- # It uses monkey patching to intercept all task invocations and execute hooks
11
- # at the appropriate times.
12
- #
13
- # @example Global hooks
14
- # Makit::Tasks::HookManager.add_pre_hook do |task_name|
15
- # Makit::Logging.info("Starting task: #{task_name}")
16
- # end
17
- #
18
- # Makit::Tasks::HookManager.add_post_hook do |task_name, duration, result, error|
19
- # if error
20
- # Makit::Logging.error("Task failed: #{task_name}")
21
- # else
22
- # Makit::Logging.success("Task completed: #{task_name}")
23
- # end
24
- # end
25
- #
26
- # @example Task-specific hooks
27
- # Makit::Tasks::HookManager.add_pre_hook_for(:build) do |task_name|
28
- # Makit::Logging.info("Building project...")
29
- # end
30
- #
31
- # Makit::Tasks::HookManager.add_post_hook_for(:test) do |task_name, duration, result, error|
32
- # Makit::Logging.info("Test execution took #{duration.round(2)}s")
33
- # end
34
- module Makit
35
- module Tasks
36
- class HookManager
37
- @pre_hooks = []
38
- @post_hooks = []
39
- @task_specific_pre_hooks = {}
40
- @task_specific_post_hooks = {}
41
- @excluded_tasks = Set.new
42
- @logged_tasks = Set.new
43
-
44
- class << self
45
- # @return [Array<Proc>] Global pre-task hooks
46
- attr_reader :pre_hooks
47
-
48
- # @return [Array<Proc>] Global post-task hooks
49
- attr_reader :post_hooks
50
-
51
- # @return [Hash<String, Array<Proc>>] Task-specific pre-task hooks
52
- attr_reader :task_specific_pre_hooks
53
-
54
- # @return [Hash<String, Array<Proc>>] Task-specific post-task hooks
55
- attr_reader :task_specific_post_hooks
56
-
57
- # @return [Set<String>] Tasks excluded from hook execution
58
- attr_reader :excluded_tasks
59
-
60
- # Add a global pre-task hook
61
- #
62
- # The hook will be executed before every task runs.
63
- #
64
- # @yield [task_name] the name of the task being executed
65
- # @yieldparam task_name [String] the name of the task
66
- # @return [void]
67
- def add_pre_hook(&block)
68
- @pre_hooks << block
69
- end
70
-
71
- # Add a global post-task hook
72
- #
73
- # The hook will be executed after every task completes (success or failure).
74
- #
75
- # @yield [task_name, duration, result, error] hook parameters
76
- # @yieldparam task_name [String] the name of the task
77
- # @yieldparam duration [Float] execution duration in seconds
78
- # @yieldparam result [Object, nil] the result of the task execution
79
- # @yieldparam error [Exception, nil] any error that occurred during execution
80
- # @return [void]
81
- def add_post_hook(&block)
82
- @post_hooks << block
83
- end
84
-
85
- # Add a pre-task hook for a specific task
86
- #
87
- # The hook will only be executed before the specified task runs.
88
- #
89
- # @param task_name [String, Symbol] the name of the task
90
- # @yield [task_name] the name of the task being executed
91
- # @yieldparam task_name [String] the name of the task
92
- # @return [void]
93
- def add_pre_hook_for(task_name, &block)
94
- @task_specific_pre_hooks[task_name.to_s] ||= []
95
- @task_specific_pre_hooks[task_name.to_s] << block
96
- end
97
-
98
- # Add a post-task hook for a specific task
99
- #
100
- # The hook will only be executed after the specified task completes.
101
- #
102
- # @param task_name [String, Symbol] the name of the task
103
- # @yield [task_name, duration, result, error] hook parameters
104
- # @yieldparam task_name [String] the name of the task
105
- # @yieldparam duration [Float] execution duration in seconds
106
- # @yieldparam result [Object, nil] the result of the task execution
107
- # @yieldparam error [Exception, nil] any error that occurred during execution
108
- # @return [void]
109
- def add_post_hook_for(task_name, &block)
110
- @task_specific_post_hooks[task_name.to_s] ||= []
111
- @task_specific_post_hooks[task_name.to_s] << block
112
- end
113
-
114
- # Execute all pre-task hooks for a given task
115
- #
116
- # @param task_name [String] the name of the task
117
- # @return [void]
118
- def execute_pre_hooks(task_name)
119
- return if excluded?(task_name)
120
-
121
- # Execute global pre-hooks
122
- @pre_hooks.each { |hook| hook.call(task_name) }
123
-
124
- # Execute task-specific pre-hooks
125
- task_hooks = @task_specific_pre_hooks[task_name.to_s] || []
126
- task_hooks.each { |hook| hook.call(task_name) }
127
- end
128
-
129
- # Execute all post-task hooks for a given task
130
- #
131
- # @param task_name [String] the name of the task
132
- # @param duration [Float] execution duration in seconds
133
- # @param result [Object, nil] the result of the task execution
134
- # @param error [Exception, nil] any error that occurred during execution
135
- # @return [void]
136
- def execute_post_hooks(task_name, duration, result, error)
137
- return if excluded?(task_name)
138
-
139
- # Execute global post-hooks
140
- @post_hooks.each { |hook| hook.call(task_name, duration, result, error) }
141
-
142
- # Execute task-specific post-hooks
143
- task_hooks = @task_specific_post_hooks[task_name.to_s] || []
144
- task_hooks.each { |hook| hook.call(task_name, duration, result, error) }
145
- end
146
-
147
- # Clear all hooks
148
- #
149
- # @return [void]
150
- def clear_all_hooks
151
- @pre_hooks.clear
152
- @post_hooks.clear
153
- @task_specific_pre_hooks.clear
154
- @task_specific_post_hooks.clear
155
- end
156
-
157
- # Exclude a task from hook execution
158
- #
159
- # @param task_name [String, Symbol] the name of the task to exclude
160
- # @return [void]
161
- def exclude_task(task_name)
162
- @excluded_tasks.add(task_name.to_s)
163
- end
164
-
165
- # Include a task in hook execution (remove from exclusions)
166
- #
167
- # @param task_name [String, Symbol] the name of the task to include
168
- # @return [void]
169
- def include_task(task_name)
170
- @excluded_tasks.delete(task_name.to_s)
171
- end
172
-
173
- # Check if a task is excluded from hook execution
174
- #
175
- # @param task_name [String, Symbol] the name of the task to check
176
- # @return [Boolean] true if the task is excluded
177
- def excluded?(task_name)
178
- @excluded_tasks.include?(task_name.to_s)
179
- end
180
-
181
- # Get statistics about registered hooks
182
- #
183
- # @return [Hash] hook statistics
184
- def stats
185
- {
186
- global_pre_hooks: @pre_hooks.size,
187
- global_post_hooks: @post_hooks.size,
188
- task_specific_pre_hooks: @task_specific_pre_hooks.values.flatten.size,
189
- task_specific_post_hooks: @task_specific_post_hooks.values.flatten.size,
190
- tasks_with_pre_hooks: @task_specific_pre_hooks.keys,
191
- tasks_with_post_hooks: @task_specific_post_hooks.keys,
192
- }
193
- end
194
-
195
- # Setup default task hooks
196
- #
197
- # This method sets up the default task hooks that provide basic
198
- # task execution feedback. It should be called during initialization.
199
- #
200
- # @return [void]
201
- def setup_default_hooks
202
- # Only setup if no hooks are already registered
203
- return unless @pre_hooks.empty? && @post_hooks.empty?
204
-
205
- # Exclude the init task from hooks to prevent duplication
206
- exclude_task(:init)
207
- exclude_task(:default)
208
-
209
- # Default pre-task hook: log task start to default logger
210
- add_pre_hook do |task_name|
211
- log_task_start(task_name)
212
- end
213
-
214
- # Default post-task hook: log task completion
215
- add_post_hook do |task_name, duration, result, error|
216
- log_task_completion(task_name, duration, result, error)
217
- end
218
- end
219
-
220
- def log_task_start(task_name)
221
- #return if @logged_tasks.include?(task_name)
222
- #@logged_tasks.add(task_name)
223
- #Makit::Logging.info("#{task_name}".colorize(:white).bold)
224
- end
225
-
226
- def log_task_completion(task_name, duration, result, error)
227
- #Makit::Logging.info("#{task_name}".colorize(:white).bold)
228
- #Makit::Logging.info("Task completed".colorize(:green).bold)
229
- #Makit::Logging.info("Duration: #{duration.round(2)}s".colorize(:green).bold)
230
- # Makit::Logging.info("Result: #{result}".colorize(:green).bold)
231
- #Makit::Logging.info("Error: #{error}".colorize(:red).bold)
232
- end
233
- end
234
- end
235
- end
236
- end
237
-
238
- # Setup default hooks when the module is loaded
239
- Makit::Tasks::HookManager.setup_default_hooks
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "colorize"
5
+ require "fileutils"
6
+
7
+ # Task hooks system for Makit
8
+ #
9
+ # This module provides a comprehensive hook system for Rake tasks, allowing
10
+ # developers to add pre and post execution hooks globally or for specific tasks.
11
+ # It uses monkey patching to intercept all task invocations and execute hooks
12
+ # at the appropriate times.
13
+ #
14
+ # @example Global hooks
15
+ # Makit::Tasks::HookManager.add_pre_hook do |task_name|
16
+ # Makit::Logging.info("Starting task: #{task_name}")
17
+ # end
18
+ #
19
+ # Makit::Tasks::HookManager.add_post_hook do |task_name, duration, result, error|
20
+ # if error
21
+ # Makit::Logging.error("Task failed: #{task_name}")
22
+ # else
23
+ # Makit::Logging.success("Task completed: #{task_name}")
24
+ # end
25
+ # end
26
+ #
27
+ # @example Task-specific hooks
28
+ # Makit::Tasks::HookManager.add_pre_hook_for(:build) do |task_name|
29
+ # Makit::Logging.info("Building project...")
30
+ # end
31
+ #
32
+ # Makit::Tasks::HookManager.add_post_hook_for(:test) do |task_name, duration, result, error|
33
+ # Makit::Logging.info("Test execution took #{duration.round(2)}s")
34
+ # end
35
+ module Makit
36
+ module Tasks
37
+ class HookManager
38
+ @pre_hooks = []
39
+ @post_hooks = []
40
+ @task_specific_pre_hooks = {}
41
+ @task_specific_post_hooks = {}
42
+ @excluded_tasks = Set.new
43
+ @logged_tasks = Set.new
44
+
45
+ # Timing functionality
46
+ @timing_enabled = false
47
+ @task_stack = []
48
+ @performance_log = "artifacts/task_performance.log"
49
+ @hooks_installed = false
50
+
51
+ class << self
52
+ # @return [Array<Proc>] Global pre-task hooks
53
+ attr_reader :pre_hooks
54
+
55
+ # @return [Array<Proc>] Global post-task hooks
56
+ attr_reader :post_hooks
57
+
58
+ # @return [Hash<String, Array<Proc>>] Task-specific pre-task hooks
59
+ attr_reader :task_specific_pre_hooks
60
+
61
+ # @return [Hash<String, Array<Proc>>] Task-specific post-task hooks
62
+ attr_reader :task_specific_post_hooks
63
+
64
+ # @return [Set<String>] Tasks excluded from hook execution
65
+ attr_reader :excluded_tasks
66
+
67
+ # @return [Boolean] Whether timing is enabled
68
+ attr_reader :timing_enabled
69
+
70
+ # @return [Array<Hash>] Stack of currently executing tasks
71
+ attr_reader :task_stack
72
+
73
+ # @return [String] Path to performance log file
74
+ attr_reader :performance_log
75
+
76
+ # Add a global pre-task hook
77
+ #
78
+ # The hook will be executed before every task runs.
79
+ #
80
+ # @yield [task_name] the name of the task being executed
81
+ # @yieldparam task_name [String] the name of the task
82
+ # @return [void]
83
+ def add_pre_hook(&block)
84
+ @pre_hooks << block
85
+ end
86
+
87
+ # Add a global post-task hook
88
+ #
89
+ # The hook will be executed after every task completes (success or failure).
90
+ #
91
+ # @yield [task_name, duration, result, error] hook parameters
92
+ # @yieldparam task_name [String] the name of the task
93
+ # @yieldparam duration [Float] execution duration in seconds
94
+ # @yieldparam result [Object, nil] the result of the task execution
95
+ # @yieldparam error [Exception, nil] any error that occurred during execution
96
+ # @return [void]
97
+ def add_post_hook(&block)
98
+ @post_hooks << block
99
+ end
100
+
101
+ # Add a pre-task hook for a specific task
102
+ #
103
+ # The hook will only be executed before the specified task runs.
104
+ #
105
+ # @param task_name [String, Symbol] the name of the task
106
+ # @yield [task_name] the name of the task being executed
107
+ # @yieldparam task_name [String] the name of the task
108
+ # @return [void]
109
+ def add_pre_hook_for(task_name, &block)
110
+ @task_specific_pre_hooks[task_name.to_s] ||= []
111
+ @task_specific_pre_hooks[task_name.to_s] << block
112
+ end
113
+
114
+ # Add a post-task hook for a specific task
115
+ #
116
+ # The hook will only be executed after the specified task completes.
117
+ #
118
+ # @param task_name [String, Symbol] the name of the task
119
+ # @yield [task_name, duration, result, error] hook parameters
120
+ # @yieldparam task_name [String] the name of the task
121
+ # @yieldparam duration [Float] execution duration in seconds
122
+ # @yieldparam result [Object, nil] the result of the task execution
123
+ # @yieldparam error [Exception, nil] any error that occurred during execution
124
+ # @return [void]
125
+ def add_post_hook_for(task_name, &block)
126
+ @task_specific_post_hooks[task_name.to_s] ||= []
127
+ @task_specific_post_hooks[task_name.to_s] << block
128
+ end
129
+
130
+ # Execute all pre-task hooks for a given task
131
+ #
132
+ # @param task_name [String] the name of the task
133
+ # @return [void]
134
+ def execute_pre_hooks(task_name)
135
+ return if excluded?(task_name)
136
+
137
+ # Track timing if enabled
138
+ if timing_enabled?
139
+ @task_stack.push({
140
+ name: task_name,
141
+ start_time: Time.now,
142
+ level: @task_stack.length,
143
+ })
144
+ end
145
+
146
+ # Execute global pre-hooks
147
+ @pre_hooks.each { |hook| hook.call(task_name) }
148
+
149
+ # Execute task-specific pre-hooks
150
+ task_hooks = @task_specific_pre_hooks[task_name.to_s] || []
151
+ task_hooks.each { |hook| hook.call(task_name) }
152
+ end
153
+
154
+ # Execute all post-task hooks for a given task
155
+ #
156
+ # @param task_name [String] the name of the task
157
+ # @param duration [Float] execution duration in seconds
158
+ # @param result [Object, nil] the result of the task execution
159
+ # @param error [Exception, nil] any error that occurred during execution
160
+ # @return [void]
161
+ def execute_post_hooks(task_name, duration, result, error)
162
+ return if excluded?(task_name)
163
+
164
+ # Handle timing if enabled
165
+ if timing_enabled?
166
+ task_info = @task_stack.pop
167
+ if task_info && task_info[:name] == task_name
168
+ # Log performance for tasks that took longer than 0.1 seconds
169
+ log_task_performance(task_name, duration, task_info[:level]) if duration > 0.1
170
+ end
171
+
172
+ # Log task failure if there was an error
173
+ if error
174
+ log_task_failure(task_name, duration, error, task_info&.dig(:level) || 0)
175
+ end
176
+ end
177
+
178
+ # Execute global post-hooks
179
+ @post_hooks.each { |hook| hook.call(task_name, duration, result, error) }
180
+
181
+ # Execute task-specific post-hooks
182
+ task_hooks = @task_specific_post_hooks[task_name.to_s] || []
183
+ task_hooks.each { |hook| hook.call(task_name, duration, result, error) }
184
+ end
185
+
186
+ # Clear all hooks
187
+ #
188
+ # @return [void]
189
+ def clear_all_hooks
190
+ @pre_hooks.clear
191
+ @post_hooks.clear
192
+ @task_specific_pre_hooks.clear
193
+ @task_specific_post_hooks.clear
194
+ end
195
+
196
+ # Exclude a task from hook execution
197
+ #
198
+ # @param task_name [String, Symbol] the name of the task to exclude
199
+ # @return [void]
200
+ def exclude_task(task_name)
201
+ @excluded_tasks.add(task_name.to_s)
202
+ end
203
+
204
+ # Include a task in hook execution (remove from exclusions)
205
+ #
206
+ # @param task_name [String, Symbol] the name of the task to include
207
+ # @return [void]
208
+ def include_task(task_name)
209
+ @excluded_tasks.delete(task_name.to_s)
210
+ end
211
+
212
+ # Check if a task is excluded from hook execution
213
+ #
214
+ # @param task_name [String, Symbol] the name of the task to check
215
+ # @return [Boolean] true if the task is excluded
216
+ def excluded?(task_name)
217
+ @excluded_tasks.include?(task_name.to_s)
218
+ end
219
+
220
+ # Get statistics about registered hooks
221
+ #
222
+ # @return [Hash] hook statistics
223
+ def stats
224
+ {
225
+ global_pre_hooks: @pre_hooks.size,
226
+ global_post_hooks: @post_hooks.size,
227
+ task_specific_pre_hooks: @task_specific_pre_hooks.values.flatten.size,
228
+ task_specific_post_hooks: @task_specific_post_hooks.values.flatten.size,
229
+ tasks_with_pre_hooks: @task_specific_pre_hooks.keys,
230
+ tasks_with_post_hooks: @task_specific_post_hooks.keys,
231
+ timing_enabled: @timing_enabled,
232
+ task_stack_depth: @task_stack.size,
233
+ }
234
+ end
235
+
236
+ # Enable task timing and performance logging
237
+ #
238
+ # @return [void]
239
+ def enable_timing!
240
+ @timing_enabled = true
241
+ puts "🔧 Task timing enabled".colorize(:grey) if defined?(String.instance_method(:colorize))
242
+ end
243
+
244
+ # Disable task timing and performance logging
245
+ #
246
+ # @return [void]
247
+ def disable_timing!
248
+ @timing_enabled = false
249
+ end
250
+
251
+ # Check if timing is enabled
252
+ #
253
+ # @return [Boolean] true if timing is enabled
254
+ def timing_enabled?
255
+ @timing_enabled == true
256
+ end
257
+
258
+ # Clear performance logs
259
+ #
260
+ # @return [void]
261
+ def clear_performance_logs
262
+ FileUtils.rm_f(@performance_log)
263
+ FileUtils.rm_f("artifacts/task_failures.log")
264
+ end
265
+
266
+ # Setup task hooks by monkey patching Rake::Task
267
+ #
268
+ # This method patches the Rake::Task#execute method to automatically
269
+ # call pre and post hooks for all task executions.
270
+ #
271
+ # @return [void]
272
+ def setup!
273
+ return if @hooks_installed
274
+
275
+ Rake::Task.class_eval do
276
+ alias_method :makit_original_execute, :execute
277
+
278
+ def execute(args = nil)
279
+ start_time = Time.now
280
+ error = nil
281
+ result = nil
282
+
283
+ begin
284
+ # Execute pre-hooks
285
+ Makit::Tasks::HookManager.execute_pre_hooks(name)
286
+
287
+ # Execute the original task
288
+ result = makit_original_execute(args)
289
+ rescue StandardError => e
290
+ error = e
291
+ raise
292
+ ensure
293
+ # Calculate duration
294
+ duration = Time.now - start_time
295
+
296
+ # Execute post-hooks
297
+ Makit::Tasks::HookManager.execute_post_hooks(name, duration, result, error)
298
+ end
299
+
300
+ result
301
+ end
302
+ end
303
+
304
+ @hooks_installed = true
305
+ end
306
+
307
+ # Setup default task hooks
308
+ #
309
+ # This method sets up the default task hooks that provide basic
310
+ # task execution feedback. It should be called during initialization.
311
+ #
312
+ # @return [void]
313
+ def setup_default_hooks
314
+ # Setup the monkey patching first
315
+ setup!
316
+
317
+ # Only setup default hooks if no hooks are already registered
318
+ return unless @pre_hooks.empty? && @post_hooks.empty?
319
+
320
+ # Exclude the init task from hooks to prevent duplication
321
+ exclude_task(:init)
322
+ exclude_task(:default)
323
+
324
+ # Default pre-task hook: log task start to default logger
325
+ add_pre_hook do |task_name|
326
+ log_task_start(task_name)
327
+ end
328
+
329
+ # Default post-task hook: log task completion
330
+ add_post_hook do |task_name, duration, result, error|
331
+ log_task_completion(task_name, duration, result, error)
332
+ end
333
+ end
334
+
335
+ def log_task_start(task_name)
336
+ #return if @logged_tasks.include?(task_name)
337
+ #@logged_tasks.add(task_name)
338
+ #Makit::Logging.info("#{task_name}".colorize(:white).bold)
339
+ end
340
+
341
+ def log_task_completion(task_name, duration, result, error)
342
+ #Makit::Logging.info("#{task_name}".colorize(:white).bold)
343
+ #Makit::Logging.info("Task completed".colorize(:green).bold)
344
+ #Makit::Logging.info("Duration: #{duration.round(2)}s".colorize(:green).bold)
345
+ # Makit::Logging.info("Result: #{result}".colorize(:green).bold)
346
+ #Makit::Logging.info("Error: #{error}".colorize(:red).bold)
347
+ end
348
+
349
+ private
350
+
351
+ # Log task performance to file
352
+ #
353
+ # @param name [String] task name
354
+ # @param duration [Float] execution duration
355
+ # @param level [Integer] nesting level
356
+ # @return [void]
357
+ def log_task_performance(name, duration, level)
358
+ return if ENV["CI"] == "true" && duration < 1.0
359
+
360
+ FileUtils.mkdir_p("artifacts")
361
+ File.open(@performance_log, "a") do |f|
362
+ f.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")},#{name},#{duration.round(4)},#{level}"
363
+ end
364
+ rescue StandardError
365
+ # Silently fail performance logging to not interrupt tasks
366
+ end
367
+
368
+ # Log task failure to file
369
+ #
370
+ # @param name [String] task name
371
+ # @param duration [Float] execution duration
372
+ # @param error [Exception] the error that occurred
373
+ # @param level [Integer] nesting level
374
+ # @return [void]
375
+ def log_task_failure(name, duration, error, level)
376
+ failure_log = "artifacts/task_failures.log"
377
+ FileUtils.mkdir_p("artifacts")
378
+
379
+ File.open(failure_log, "a") do |f|
380
+ timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S")
381
+ message = error.message.gsub(",", ";")
382
+ f.puts "#{timestamp},#{name},#{duration.round(4)},#{error.class.name},#{message}"
383
+ end
384
+ rescue StandardError
385
+ # Silently fail error logging
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end
391
+
392
+ # Setup default hooks when the module is loaded
393
+ Makit::Tasks::HookManager.setup_default_hooks