makit 0.0.111 → 0.0.126

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/makit/cli/repository_commands.rb +1 -1
  3. data/lib/makit/commands/middleware/cache.rb +3 -3
  4. data/lib/makit/commands/middleware/command_logger.rb +33 -45
  5. data/lib/makit/commands/request.rb +63 -1
  6. data/lib/makit/commands/runner.rb +56 -5
  7. data/lib/makit/commands/strategies/base.rb +13 -2
  8. data/lib/makit/commands/strategies/synchronous.rb +11 -6
  9. data/lib/makit/commands.rb +8 -0
  10. data/lib/makit/configuration/gitlab_helper.rb +0 -2
  11. data/lib/makit/configuration/project.rb +48 -8
  12. data/lib/makit/configuration/step.rb +3 -3
  13. data/lib/makit/content/default_gitignore.txt +226 -0
  14. data/lib/makit/directories.rb +3 -4
  15. data/lib/makit/docs/files.rb +1 -1
  16. data/lib/makit/docs/rake.rb +1 -1
  17. data/lib/makit/dotnet/cli.rb +69 -65
  18. data/lib/makit/dotnet/project.rb +71 -7
  19. data/lib/makit/examples/runner.rb +2 -2
  20. data/lib/makit/logging/configuration.rb +9 -6
  21. data/lib/makit/logging/format_registry.rb +84 -84
  22. data/lib/makit/logging/formatters/console_formatter.rb +22 -9
  23. data/lib/makit/logging/log_request.rb +6 -2
  24. data/lib/makit/logging/logger.rb +45 -5
  25. data/lib/makit/logging/sinks/base.rb +91 -91
  26. data/lib/makit/logging/sinks/structured.rb +123 -129
  27. data/lib/makit/logging/sinks/unified_file_sink.rb +39 -46
  28. data/lib/makit/logging.rb +45 -1
  29. data/lib/makit/mp/project_mp.rb +6 -6
  30. data/lib/makit/mp/string_mp.rb +108 -265
  31. data/lib/makit/serializer.rb +14 -1
  32. data/lib/makit/services/builder.rb +5 -5
  33. data/lib/makit/services/repository_manager.rb +8 -6
  34. data/lib/makit/setup/classlib.rb +44 -7
  35. data/lib/makit/setup/gem.rb +268 -250
  36. data/lib/makit/setup/razorclasslib.rb +91 -0
  37. data/lib/makit/setup/runner.rb +36 -22
  38. data/lib/makit/setup.rb +5 -0
  39. data/lib/makit/symbols.rb +10 -1
  40. data/lib/makit/tasks/at_exit.rb +3 -1
  41. data/lib/makit/tasks/build.rb +16 -12
  42. data/lib/makit/tasks/clean.rb +2 -0
  43. data/lib/makit/tasks/configure.rb +10 -0
  44. data/lib/makit/tasks/format.rb +10 -0
  45. data/lib/makit/tasks/hook_manager.rb +160 -8
  46. data/lib/makit/tasks/init.rb +2 -0
  47. data/lib/makit/tasks/integrate.rb +17 -3
  48. data/lib/makit/tasks/pull_incoming.rb +6 -5
  49. data/lib/makit/tasks/setup.rb +10 -3
  50. data/lib/makit/tasks/sync.rb +13 -7
  51. data/lib/makit/tasks/tag.rb +16 -0
  52. data/lib/makit/tasks/task_monkey_patch.rb +58 -56
  53. data/lib/makit/tasks/test.rb +22 -0
  54. data/lib/makit/tasks/update.rb +18 -0
  55. data/lib/makit/tasks.rb +20 -5
  56. data/lib/makit/v1/makit.v1_pb.rb +1 -0
  57. data/lib/makit/version.rb +1 -1
  58. data/lib/makit/version_util.rb +21 -0
  59. data/lib/makit copy.rb +44 -0
  60. data/lib/makit.rb +31 -0
  61. metadata +118 -13
  62. data/lib/makit/command_runner.rb +0 -463
  63. data/lib/makit/commands/compatibility.rb +0 -365
  64. data/lib/makit/commands/middleware/unified_logger.rb +0 -243
  65. data/lib/makit/task_hooks.rb +0 -125
@@ -1,463 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "English"
4
- require "open3"
5
- require "socket"
6
- require "etc"
7
- require "logger"
8
- require_relative "mp/command_request.mp"
9
-
10
- # This module provides classes for the Makit gem.
11
- module Makit
12
- # This class provide methods running commands.
13
- #
14
- # @deprecated Use Commands::Runner instead. This class will be removed in a future version.
15
- # @see Commands::Runner for the modern command execution API
16
- class CommandRunner
17
- attr_accessor :show_output_on_success, :log_to_artifacts, :commands, :debug, :default_modified
18
-
19
- def initialize
20
- warn_deprecation("CommandRunner is deprecated. Use Commands::Runner instead.")
21
- @show_output_on_success = false
22
- @log_to_artifacts = false
23
- @commands = []
24
- @debug = false
25
- git_file_infos = Makit::Git::Repository.get_file_infos
26
- @default_modified = if git_file_infos.length.positive?
27
- git_file_infos.first.mtime # Makit::GIT_FILE_INFOS.first.mtime
28
- else
29
- Time.now
30
- end
31
- end
32
-
33
- # search command history for matching commands
34
- def search(query)
35
- results = []
36
- commands.each do |command|
37
- keywords = []
38
- keywords << command.name.downcase
39
- command.arguments.each do |argument|
40
- keywords << argument.downcase unless keywords.include?(argument.downcase)
41
- end
42
- # output is bytes, so convert to UTF 8 string
43
- # output_bytes = command.output.clone
44
- # output = command.output.clone.force_encoding('UTF-8')
45
- # error_bytes = command.error.clone
46
- # error = error_bytes.force_encoding('UTF-8')
47
- # output.split(" ").each {|word|
48
- # if(word.length > 3)
49
- # keywords << word.downcase unless keywords.include?(word.downcase)
50
- # end
51
- # }
52
- # error.split(" ").each { |word|
53
- # if(word.length > 3)
54
- # keywords << word.downcase unless keywords.include?(word.downcase)
55
- # end
56
- # }
57
- matchCount = 0
58
- terms = query.downcase.split
59
- terms.each do |term|
60
- matchCount += 1 if keywords.include?(term)
61
- end
62
- results << command if matchCount == terms.length
63
- end
64
- results
65
- end
66
-
67
- def get_cache_filename(command)
68
- int_hash = Digest::SHA256.hexdigest("#{command.name}.#{command.arguments.join(" ")}")
69
- hash_string = int_hash.to_s
70
- cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
71
- "/commands/cache/#{hash_string}.pb"
72
- # create the directory if it does not already exist
73
- FileUtils.mkdir_p(File.dirname(cache_filename))
74
- cache_filename
75
- end
76
-
77
- # @deprecated Use Commands::Runner with caching middleware instead
78
- def cache_run(command_request)
79
- warn_deprecation("CommandRunner#cache_run is deprecated. Use Commands::Runner with caching middleware instead.")
80
- cache_run(command_request, @default_modified)
81
- end
82
-
83
- # if there is a matching cached command result, that then the specified timestamp,
84
- # then return the cached result
85
- # otherwise run the command and save the result to a cache file
86
- # then return the result
87
- def cache_run(command_request, timestamp)
88
- raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
89
-
90
- cache_filename = get_cache_filename(command_request)
91
-
92
- # Check if timestamp is a valid Time object
93
- raise ArgumentError, "timestamp must be a Time object, got #{timestamp.class}" unless timestamp.is_a?(Time)
94
-
95
- if debug
96
- Makit::Logging.debug("Cache run debug info", {
97
- timestamp: Makit::Humanize.get_humanized_timestamp(timestamp),
98
- command: command_request.name,
99
- arguments: command_request.arguments.join(" "),
100
- cache_filename: cache_filename,
101
- })
102
- end
103
- # cache_filename = Makit::Directories::PROJECT_ARTIFACTS + "/commands/#{command_request.name}.#{command_request.arguments.join("_")}.#{timestamp.seconds}.pb"
104
- if File.exist?(cache_filename)
105
- cache_timestamp = File.mtime(cache_filename)
106
- Makit::Logging.debug("Cache timestamp", {
107
- cache_timestamp: Makit::Humanize.get_humanized_timestamp(cache_timestamp),
108
- }) if debug
109
- # puts "cache file date: #{File.mtime(cache_filename)}"
110
- if File.mtime(cache_filename) > timestamp
111
- Makit::Logging.info("Using cached command result", {
112
- command: command_request.name,
113
- arguments: command_request.arguments,
114
- cache_filename: cache_filename,
115
- cache_timestamp: Makit::Humanize.get_humanized_timestamp(cache_timestamp),
116
- })
117
-
118
- command = Makit::Serializer.open(cache_filename, Makit::V1::Command)
119
- show_cached_command(command)
120
- abort "cached command failed: #{command.name} #{command.arguments.join(" ")}" if command.exit_code != 0
121
- return command
122
- else
123
- Makit::Logging.debug("Cache file is older than timestamp", {
124
- cache_filename: cache_filename,
125
- timestamp: Makit::Humanize.get_humanized_timestamp(timestamp),
126
- }) if debug
127
- File.delete(cache_filename)
128
- end
129
- end
130
-
131
- command = run(command_request)
132
- # make sure the cache directory exists
133
- FileUtils.mkdir_p(File.dirname(cache_filename))
134
-
135
- Makit::Logging.info("Saving command to cache", {
136
- command: command.name,
137
- arguments: command.arguments,
138
- cache_filename: cache_filename,
139
- success: command.exit_code.zero?,
140
- })
141
-
142
- Makit::Serializer.save_as(cache_filename, command)
143
- commands.push(command)
144
- command
145
- end
146
-
147
- def show_command(command)
148
- if command.exit_code.zero?
149
- Makit::Logging.success("Command completed", {
150
- command: command.name,
151
- arguments: command.arguments,
152
- duration: command.duration&.seconds || 0,
153
- output: show_output_on_success ? command.output : nil,
154
- })
155
- else
156
- Makit::Logging.error("Command failed", {
157
- command: command.name,
158
- arguments: command.arguments,
159
- exit_code: command.exit_code,
160
- directory: command.directory,
161
- duration: command.duration&.seconds || 0,
162
- output: command.output.length.positive? ? command.output : nil,
163
- error: command.error.length.positive? ? command.error : nil,
164
- })
165
- end
166
- end
167
-
168
- def show_cached_command(command)
169
- if command.exit_code.zero?
170
- Makit::Logging.info("Cached command completed", {
171
- command: command.name,
172
- arguments: command.arguments,
173
- duration: command.duration&.seconds || 0,
174
- cached: true,
175
- output: show_output_on_success ? command.output : nil,
176
- })
177
- else
178
- Makit::Logging.warn("Cached command failed", {
179
- command: command.name,
180
- arguments: command.arguments,
181
- exit_code: command.exit_code,
182
- directory: command.directory,
183
- duration: command.duration&.seconds || 0,
184
- cached: true,
185
- output: command.output.length.positive? ? command.output : nil,
186
- error: command.error.length.positive? ? command.error : nil,
187
- })
188
- end
189
- end
190
-
191
- # Run a command and return a Makit::V1::Command.
192
- # @deprecated Use Commands::Runner#execute instead
193
- def run(command_request)
194
- warn_deprecation("CommandRunner#run is deprecated. Use Commands::Runner#execute instead.")
195
- raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
196
-
197
- # Log command start
198
- Makit::Logging.info("Starting command execution", {
199
- command: command_request.name,
200
- arguments: command_request.arguments,
201
- directory: command_request.directory,
202
- })
203
-
204
- command = execute(command_request)
205
-
206
- log_to_artifacts(command) if @log_to_artifacts
207
- show_command(command)
208
- exit 1 if (command.exit_code != 0) && command_request.exit_on_error
209
- commands.push(command)
210
- command
211
- end
212
-
213
- def log_to_artifacts(command)
214
- log_filename = get_cache_filename(command)
215
- Makit::Serializer.save_as(log_filename, command)
216
- end
217
-
218
- # Run a command and return a Makit::V1::Command.
219
- # @deprecated Use Commands::Runner#execute with exit_on_error: false instead
220
- def try(args)
221
- warn_deprecation("CommandRunner#try is deprecated. Use Commands::Runner#execute with exit_on_error: false instead.")
222
- request = parse_command_request(args)
223
- request.exit_on_error = false
224
- run(request)
225
- end
226
-
227
- def cache_try(command_request)
228
- cache_try(command_request, @default_modified)
229
- end
230
-
231
- def cache_try(command_request, timestamp)
232
- command_request.exit_on_error = false
233
- cache_run(command_request, timestamp)
234
- end
235
-
236
- # Show the output of a command and return a Makit::V1::Command.
237
- # @deprecated Use Commands::Runner#execute with show_output: true instead
238
- def show(args)
239
- warn_deprecation("CommandRunner#show is deprecated. Use Commands::Runner#execute with show_output: true instead.")
240
- request = parse_args(args)
241
- command = execute(request)
242
-
243
- # Log command execution with structured data
244
- if command.exit_code.zero?
245
- Makit::Logging.success("Command executed successfully", {
246
- command: command.name,
247
- arguments: command.arguments,
248
- duration: command.duration&.seconds || 0,
249
- output: command.output,
250
- })
251
- else
252
- Makit::Logging.error("Command execution failed", {
253
- command: command.name,
254
- arguments: command.arguments,
255
- exit_code: command.exit_code,
256
- duration: command.duration&.seconds || 0,
257
- output: command.output,
258
- error: command.error,
259
- })
260
- exit(command.exit_code) if command.exit_code != 0
261
- end
262
- command
263
- end
264
-
265
- # Parse and return a Makit::V1::CommandRequest.
266
- def parse_command_request(source)
267
- return Makit::V1::CommandRequest.new(source) if source.is_a? Hash
268
- return source if source.is_a? Makit::V1::CommandRequest
269
- return parse_args(source) if source.is_a? String
270
-
271
- raise "Invalid source" unless source.is_a? Makit::V1::CommandRequest
272
- end
273
-
274
- def parse_command_request_from_hash(hash)
275
- raise "Invalid hash" unless hash.is_a? Hash
276
-
277
- Makit::V1::CommandRequest.new(hash)
278
- end
279
-
280
- def parse_command_request_from_string(source)
281
- raise "Invalid source" unless source.is_a? String
282
-
283
- words = source.split
284
- {
285
- name: words.shift,
286
- arguments: words,
287
- exit_on_error: true,
288
- }
289
- end
290
-
291
- # Parse the command line arguments into a Makit::V1::CommandRequest.
292
- def parse_args(args)
293
- # raise "No command specified" if args.empty?
294
- if args.is_a? Makit::V1::CommandRequest
295
- args
296
- elsif args.is_a? String
297
- args = args.split
298
- hash = if args.length == 1
299
- {
300
- name: args[0],
301
- arguments: [],
302
- exit_on_error: true,
303
- }
304
- else
305
- {
306
- name: args.shift,
307
- arguments: args,
308
- exit_on_error: true,
309
- }
310
- end
311
- Makit::V1::CommandRequest.new(hash)
312
- else
313
- Makit::V1::CommandRequest.new(args)
314
- end
315
- end
316
-
317
- def get_path_name(name)
318
- # replace all characters that a not valid in a filename with an underscore
319
- name.gsub(/[^0-9a-z]/i, "_")
320
- end
321
-
322
- # Given a Makit::V1::CommandRequest, execute the command and return a Makit::V1::Command.
323
- def execute(args)
324
- command_request = parse_args(args)
325
- command_request.directory = Dir.pwd if command_request.directory.nil?
326
- command_request.directory = Dir.pwd if command_request.directory.empty?
327
- result = Makit::V1::Command.new(name: command_request.name)
328
- command_request.arguments.each do |arg|
329
- result.arguments.push(arg)
330
- end
331
- command = "#{command_request.name} #{command_request.arguments.join(" ")}"
332
- result.directory = command_request.directory
333
- start = Time.now
334
- filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
335
- File.join(Makit::Directories::LOG, "#{filename_friendly_timestamp}.log")
336
-
337
- # assign a directory variable to the current working directory, if not specified,
338
- # otherwise assign the specified directory
339
- command_request.directory = Dir.pwd if command_request.directory.nil?
340
- command_request.directory = Dir.pwd if command_request.directory.empty?
341
- raise "Invalid directory" unless Dir.exist?(command_request.directory)
342
-
343
- result.started_at = Google::Protobuf::Timestamp.new(seconds: start.to_i, nanos: start.nsec.to_i)
344
- ############# execute the command
345
- (output, error, exit_code) = execute_command(command, command_request.directory, command_request.timeout)
346
- result.output = output.dup.force_encoding("ASCII-8BIT")
347
- result.error = error.dup.force_encoding("ASCII-8BIT")
348
- result.exit_code = exit_code.nil? ? 0 : exit_code
349
-
350
- elapsed_time = Time.now - start
351
- seconds = elapsed_time.to_i
352
- nanos = ((elapsed_time - seconds) * 1_000_000_000).to_i
353
-
354
- result.duration = Google::Protobuf::Duration.new(seconds: seconds, nanos: nanos)
355
-
356
- result
357
- end
358
-
359
- # pure function to execute a command
360
- # returns (stdout, stderr, exit_code) or raise an exception
361
- def execute_command(command, directory, timeout)
362
- original_directory = Dir.pwd
363
- begin
364
- output = nil
365
- error = nil
366
- process_status = nil
367
- Dir.chdir(directory) do
368
- output, error, process_status = Open3.capture3(command)
369
- end
370
- [output, error, process_status.exitstatus]
371
- rescue StandardError => e
372
- # restore the original working directory
373
- Dir.chdir(original_directory)
374
- message_parts = []
375
- message_parts << "failed to execute #{command}"
376
- message_parts << "directory: #{directory}"
377
- message_parts << "timeout: #{timeout}" unless timeout.nil?
378
- message_parts << "error: #{e.message}"
379
- message = "#{message_parts.join("\n")}\n"
380
- ["", message, 1]
381
- # raise Makit::Error, message
382
- end
383
- end
384
-
385
- def execute_command_request(command_request)
386
- # if the command_request is not a Makit::V1::CommandRequest, raise an error
387
- raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
388
-
389
- args = command_request.arguments.map do |arg|
390
- arg
391
- end
392
- Makit::V1::Command.new({
393
- name: command_request.name,
394
- arguments: args,
395
- started_at: Google::Protobuf::Timestamp.new({ seconds: Time.now.to_i,
396
- nanos: Time.now.nsec }),
397
- })
398
-
399
- begin
400
- rescue StandardError
401
- end
402
- end
403
-
404
- def indent_string(input_string, indent_spaces)
405
- indentation = " " * indent_spaces
406
- input_string.lines.map { |line| indentation + line }.join
407
- end
408
-
409
- def self.get_command_summary(command)
410
- symbol = Makit::Symbols.warning
411
- symbol = Makit::Symbols.checkmark if !command.exit_code.nil? && command.exit_code.zero?
412
- symbol = Makit::Symbols.error if command.exit_code != 0
413
- summary = "#{symbol} #{command.name.colorize(:yellow)} #{command.arguments.join(" ")}"
414
-
415
- summary = summary.to_lines(80, command.name.length + 3) if summary.length > 80
416
-
417
- summary
418
- end
419
-
420
- def log_rake_commands
421
- dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
422
- FileUtils.mkdir_p(dir)
423
-
424
- # open a text file to write to
425
- File.open(File.join(dir, "rake.commands.txt"), "w") do |file|
426
- # rake_commands = commands.select { |command| command.name == "rake" }
427
- commands.each do |command|
428
- file.puts " #{Makit::CommandRunner.get_command_summary(command).strip_color_codes}"
429
- file.puts " start time: #{command.started_at}"
430
- file.puts command.output.strip_color_codes unless command.output.strip_color_codes.strip.empty?
431
- file.puts command.error.strip_color_codes unless command.error.strip_color_codes.strip.empty?
432
- file.puts " "
433
- end
434
- end
435
- end
436
-
437
- def log_slowest_commands
438
- dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
439
- FileUtils.mkdir_p(dir)
440
-
441
- # open a text file to write to
442
- File.open(File.join(dir, "slow.commands.txt"), "w") do |file|
443
- Makit::RUNNER.commands.sort_by do |command|
444
- (command.duration.seconds + (command.duration.nanos / 1_000_000_000.0))
445
- end.reverse.first(5).each do |command|
446
- # Convert to float representation
447
- command.duration.seconds + (command.duration.nanos / 1_000_000_000.0)
448
- # puts " #{command.name} took #{duration_in_float} seconds"
449
- file.puts " #{Makit::CommandRunner.get_command_summary(command).strip_color_codes} (#{command.duration.seconds} seconds)"
450
- end
451
- end
452
- end
453
-
454
- private
455
-
456
- # Helper method to emit deprecation warnings
457
- #
458
- # @param message [String] deprecation message
459
- def warn_deprecation(message)
460
- warn "[DEPRECATED] #{message} (called from #{caller(1, 1).first})"
461
- end
462
- end
463
- end