makit 0.0.99 → 0.0.111
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.
- checksums.yaml +4 -4
- data/README.md +41 -0
- data/exe/makit +5 -0
- data/lib/makit/apache.rb +7 -11
- data/lib/makit/cli/build_commands.rb +500 -0
- data/lib/makit/cli/generators/base_generator.rb +74 -0
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -0
- data/lib/makit/cli/generators/generator_factory.rb +49 -0
- data/lib/makit/cli/generators/node_generator.rb +50 -0
- data/lib/makit/cli/generators/ruby_generator.rb +77 -0
- data/lib/makit/cli/generators/rust_generator.rb +50 -0
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -0
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -0
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -0
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +40 -0
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -0
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -0
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -0
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -0
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -0
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -0
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -0
- data/lib/makit/cli/main.rb +48 -19
- data/lib/makit/cli/project_commands.rb +868 -0
- data/lib/makit/cli/repository_commands.rb +661 -0
- data/lib/makit/cli/utility_commands.rb +521 -0
- data/lib/makit/command_runner.rb +187 -128
- data/lib/makit/commands/compatibility.rb +365 -0
- data/lib/makit/commands/factory.rb +359 -0
- data/lib/makit/commands/middleware/base.rb +73 -0
- data/lib/makit/commands/middleware/cache.rb +248 -0
- data/lib/makit/commands/middleware/command_logger.rb +323 -0
- data/lib/makit/commands/middleware/unified_logger.rb +243 -0
- data/lib/makit/commands/middleware/validator.rb +269 -0
- data/lib/makit/commands/request.rb +254 -0
- data/lib/makit/commands/result.rb +323 -0
- data/lib/makit/commands/runner.rb +317 -0
- data/lib/makit/commands/strategies/base.rb +160 -0
- data/lib/makit/commands/strategies/synchronous.rb +134 -0
- data/lib/makit/commands.rb +24 -3
- data/lib/makit/configuration/gitlab_helper.rb +60 -0
- data/lib/makit/configuration/project.rb +127 -0
- data/lib/makit/configuration/rakefile_helper.rb +43 -0
- data/lib/makit/configuration/step.rb +34 -0
- data/lib/makit/configuration.rb +14 -0
- data/lib/makit/content/default_gitignore.rb +4 -2
- data/lib/makit/content/default_rakefile.rb +4 -2
- data/lib/makit/content/gem_rakefile.rb +4 -2
- data/lib/makit/context.rb +1 -0
- data/lib/makit/data.rb +9 -10
- data/lib/makit/directories.rb +48 -52
- data/lib/makit/directory.rb +38 -52
- data/lib/makit/docs/files.rb +5 -10
- data/lib/makit/docs/rake.rb +16 -20
- data/lib/makit/dotnet/cli.rb +65 -0
- data/lib/makit/dotnet/project.rb +153 -0
- data/lib/makit/dotnet/solution.rb +38 -0
- data/lib/makit/dotnet/solution_classlib.rb +239 -0
- data/lib/makit/dotnet/solution_console.rb +264 -0
- data/lib/makit/dotnet/solution_maui.rb +354 -0
- data/lib/makit/dotnet/solution_wasm.rb +275 -0
- data/lib/makit/dotnet/solution_wpf.rb +304 -0
- data/lib/makit/dotnet.rb +54 -171
- data/lib/makit/email.rb +46 -17
- data/lib/makit/environment.rb +22 -19
- data/lib/makit/examples/runner.rb +370 -0
- data/lib/makit/exceptions.rb +45 -0
- data/lib/makit/fileinfo.rb +3 -5
- data/lib/makit/files.rb +12 -16
- data/lib/makit/gems.rb +40 -39
- data/lib/makit/git/cli.rb +54 -0
- data/lib/makit/git/repository.rb +90 -0
- data/lib/makit/git.rb +44 -91
- data/lib/makit/gitlab_runner.rb +0 -1
- data/lib/makit/humanize.rb +31 -23
- data/lib/makit/indexer.rb +15 -24
- data/lib/makit/logging/configuration.rb +305 -0
- data/lib/makit/logging/format_registry.rb +84 -0
- data/lib/makit/logging/formatters/base.rb +39 -0
- data/lib/makit/logging/formatters/console_formatter.rb +127 -0
- data/lib/makit/logging/formatters/json_formatter.rb +65 -0
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -0
- data/lib/makit/logging/formatters/text_formatter.rb +64 -0
- data/lib/makit/logging/log_request.rb +115 -0
- data/lib/makit/logging/logger.rb +159 -0
- data/lib/makit/logging/sinks/base.rb +91 -0
- data/lib/makit/logging/sinks/console.rb +72 -0
- data/lib/makit/logging/sinks/file_sink.rb +92 -0
- data/lib/makit/logging/sinks/structured.rb +129 -0
- data/lib/makit/logging/sinks/unified_file_sink.rb +303 -0
- data/lib/makit/logging.rb +452 -37
- data/lib/makit/markdown.rb +18 -18
- data/lib/makit/mp/basic_object_mp.rb +5 -4
- data/lib/makit/mp/command_mp.rb +5 -5
- data/lib/makit/mp/command_request.mp.rb +3 -2
- data/lib/makit/mp/project_mp.rb +85 -96
- data/lib/makit/mp/string_mp.rb +245 -73
- data/lib/makit/nuget.rb +27 -25
- data/lib/makit/port.rb +25 -27
- data/lib/makit/process.rb +127 -29
- data/lib/makit/protoc.rb +27 -24
- data/lib/makit/rake/cli.rb +196 -0
- data/lib/makit/rake.rb +6 -6
- data/lib/makit/ruby/cli.rb +185 -0
- data/lib/makit/ruby.rb +25 -0
- data/lib/makit/secrets.rb +18 -18
- data/lib/makit/serializer.rb +29 -27
- data/lib/makit/services/builder.rb +186 -0
- data/lib/makit/services/error_handler.rb +226 -0
- data/lib/makit/services/repository_manager.rb +229 -0
- data/lib/makit/services/validator.rb +112 -0
- data/lib/makit/setup/classlib.rb +53 -0
- data/lib/makit/setup/gem.rb +250 -0
- data/lib/makit/setup/runner.rb +40 -0
- data/lib/makit/show.rb +16 -16
- data/lib/makit/storage.rb +32 -37
- data/lib/makit/symbols.rb +12 -0
- data/lib/makit/task_hooks.rb +125 -0
- data/lib/makit/task_info.rb +63 -21
- data/lib/makit/tasks/at_exit.rb +13 -0
- data/lib/makit/tasks/build.rb +18 -0
- data/lib/makit/tasks/clean.rb +11 -0
- data/lib/makit/tasks/hook_manager.rb +239 -0
- data/lib/makit/tasks/init.rb +47 -0
- data/lib/makit/tasks/integrate.rb +15 -0
- data/lib/makit/tasks/pull_incoming.rb +12 -0
- data/lib/makit/tasks/setup.rb +6 -0
- data/lib/makit/tasks/sync.rb +11 -0
- data/lib/makit/tasks/task_monkey_patch.rb +79 -0
- data/lib/makit/tasks.rb +5 -150
- data/lib/makit/test_cache.rb +239 -0
- data/lib/makit/v1/makit.v1_pb.rb +34 -35
- data/lib/makit/v1/makit.v1_services_pb.rb +2 -0
- data/lib/makit/version.rb +1 -57
- data/lib/makit/wix.rb +23 -23
- data/lib/makit/yaml.rb +18 -6
- data/lib/makit.rb +2 -261
- metadata +109 -145
- data/lib/makit/cli/clean.rb +0 -14
- data/lib/makit/cli/clone.rb +0 -59
- data/lib/makit/cli/init.rb +0 -38
- data/lib/makit/cli/make.rb +0 -54
- data/lib/makit/cli/new.rb +0 -37
- data/lib/makit/cli/nuget_cache.rb +0 -38
- data/lib/makit/cli/pull.rb +0 -31
- data/lib/makit/cli/setup.rb +0 -71
- data/lib/makit/cli/work.rb +0 -21
- data/lib/makit/content/default_gitignore.txt +0 -222
    
        data/lib/makit/command_runner.rb
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "English"
         | 
| 2 4 | 
             
            require "open3"
         | 
| 3 5 | 
             
            require "socket"
         | 
| @@ -9,21 +11,23 @@ require_relative "mp/command_request.mp" | |
| 9 11 | 
             
            module Makit
         | 
| 10 12 | 
             
              # This class provide methods running commands.
         | 
| 11 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
         | 
| 12 16 | 
             
              class CommandRunner
         | 
| 13 | 
            -
                attr_accessor :show_output_on_success, :log_to_artifacts, :commands
         | 
| 14 | 
            -
                attr_accessor :debug, :default_modified
         | 
| 17 | 
            +
                attr_accessor :show_output_on_success, :log_to_artifacts, :commands, :debug, :default_modified
         | 
| 15 18 |  | 
| 16 19 | 
             
                def initialize
         | 
| 20 | 
            +
                  warn_deprecation("CommandRunner is deprecated. Use Commands::Runner instead.")
         | 
| 17 21 | 
             
                  @show_output_on_success = false
         | 
| 18 22 | 
             
                  @log_to_artifacts = false
         | 
| 19 23 | 
             
                  @commands = []
         | 
| 20 24 | 
             
                  @debug = false
         | 
| 21 | 
            -
                  git_file_infos = Makit::Git::get_file_infos
         | 
| 22 | 
            -
                  if  | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 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
         | 
| 27 31 | 
             
                end
         | 
| 28 32 |  | 
| 29 33 | 
             
                # search command history for matching commands
         | 
| @@ -32,41 +36,37 @@ module Makit | |
| 32 36 | 
             
                  commands.each do |command|
         | 
| 33 37 | 
             
                    keywords = []
         | 
| 34 38 | 
             
                    keywords << command.name.downcase
         | 
| 35 | 
            -
                    command.arguments.each  | 
| 39 | 
            +
                    command.arguments.each do |argument|
         | 
| 36 40 | 
             
                      keywords << argument.downcase unless keywords.include?(argument.downcase)
         | 
| 37 | 
            -
                     | 
| 41 | 
            +
                    end
         | 
| 38 42 | 
             
                    # output is bytes, so convert to UTF 8 string
         | 
| 39 | 
            -
                    #output_bytes = command.output.clone
         | 
| 40 | 
            -
                    #output = command.output.clone.force_encoding('UTF-8')
         | 
| 41 | 
            -
                    #error_bytes = command.error.clone
         | 
| 42 | 
            -
                    #error = error_bytes.force_encoding('UTF-8')
         | 
| 43 | 
            -
                    #output.split(" ").each {|word|
         | 
| 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|
         | 
| 44 48 | 
             
                    #  if(word.length > 3)
         | 
| 45 49 | 
             
                    #    keywords << word.downcase unless keywords.include?(word.downcase)
         | 
| 46 50 | 
             
                    #  end
         | 
| 47 | 
            -
                    #}
         | 
| 48 | 
            -
                    #error.split(" ").each { |word|
         | 
| 51 | 
            +
                    # }
         | 
| 52 | 
            +
                    # error.split(" ").each { |word|
         | 
| 49 53 | 
             
                    #  if(word.length > 3)
         | 
| 50 54 | 
             
                    #    keywords << word.downcase unless keywords.include?(word.downcase)
         | 
| 51 55 | 
             
                    #  end
         | 
| 52 | 
            -
                    #}
         | 
| 56 | 
            +
                    # }
         | 
| 53 57 | 
             
                    matchCount = 0
         | 
| 54 | 
            -
                    terms = query.downcase.split | 
| 55 | 
            -
                    terms.each  | 
| 56 | 
            -
                      if  | 
| 57 | 
            -
                        matchCount += 1
         | 
| 58 | 
            -
                      end
         | 
| 59 | 
            -
                    }
         | 
| 60 | 
            -
                    if (matchCount == terms.length)
         | 
| 61 | 
            -
                      results << command
         | 
| 58 | 
            +
                    terms = query.downcase.split
         | 
| 59 | 
            +
                    terms.each do |term|
         | 
| 60 | 
            +
                      matchCount += 1 if keywords.include?(term)
         | 
| 62 61 | 
             
                    end
         | 
| 62 | 
            +
                    results << command if matchCount == terms.length
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 | 
             
                  results
         | 
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 67 | 
             
                def get_cache_filename(command)
         | 
| 68 68 | 
             
                  int_hash = Digest::SHA256.hexdigest("#{command.name}.#{command.arguments.join(" ")}")
         | 
| 69 | 
            -
                  hash_string =  | 
| 69 | 
            +
                  hash_string = int_hash.to_s
         | 
| 70 70 | 
             
                  cache_filename = Makit::Directories::PROJECT_ARTIFACTS +
         | 
| 71 71 | 
             
                                   "/commands/cache/#{hash_string}.pb"
         | 
| 72 72 | 
             
                  # create the directory if it does not already exist
         | 
| @@ -74,7 +74,9 @@ module Makit | |
| 74 74 | 
             
                  cache_filename
         | 
| 75 75 | 
             
                end
         | 
| 76 76 |  | 
| 77 | 
            +
                # @deprecated Use Commands::Runner with caching middleware instead
         | 
| 77 78 | 
             
                def cache_run(command_request)
         | 
| 79 | 
            +
                  warn_deprecation("CommandRunner#cache_run is deprecated. Use Commands::Runner with caching middleware instead.")
         | 
| 78 80 | 
             
                  cache_run(command_request, @default_modified)
         | 
| 79 81 | 
             
                end
         | 
| 80 82 |  | 
| @@ -84,38 +86,44 @@ module Makit | |
| 84 86 | 
             
                # then return the result
         | 
| 85 87 | 
             
                def cache_run(command_request, timestamp)
         | 
| 86 88 | 
             
                  raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
         | 
| 89 | 
            +
             | 
| 87 90 | 
             
                  cache_filename = get_cache_filename(command_request)
         | 
| 88 91 |  | 
| 89 92 | 
             
                  # Check if timestamp is a valid Time object
         | 
| 90 | 
            -
                  unless timestamp.is_a?(Time)
         | 
| 91 | 
            -
                    raise ArgumentError, "timestamp must be a Time object, got #{timestamp.class}"
         | 
| 92 | 
            -
                  end
         | 
| 93 | 
            +
                  raise ArgumentError, "timestamp must be a Time object, got #{timestamp.class}" unless timestamp.is_a?(Time)
         | 
| 93 94 |  | 
| 94 95 | 
             
                  if debug
         | 
| 95 | 
            -
                     | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 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 | 
            +
                    })
         | 
| 99 102 | 
             
                  end
         | 
| 100 | 
            -
                  #cache_filename = Makit::Directories::PROJECT_ARTIFACTS + "/commands/#{command_request.name}.#{command_request.arguments.join("_")}.#{timestamp.seconds}.pb"
         | 
| 103 | 
            +
                  # cache_filename = Makit::Directories::PROJECT_ARTIFACTS + "/commands/#{command_request.name}.#{command_request.arguments.join("_")}.#{timestamp.seconds}.pb"
         | 
| 101 104 | 
             
                  if File.exist?(cache_filename)
         | 
| 102 105 | 
             
                    cache_timestamp = File.mtime(cache_filename)
         | 
| 103 | 
            -
                     | 
| 104 | 
            -
                       | 
| 105 | 
            -
                     | 
| 106 | 
            -
                    #puts "cache file date: #{File.mtime(cache_filename)}"
         | 
| 107 | 
            -
                    if  | 
| 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 | 
            +
                      })
         | 
| 108 117 |  | 
| 109 | 
            -
                      #puts "  found cached command (newer than #{timestamp})".colorize(:grey)
         | 
| 110 | 
            -
                      #puts "  cache_filename: #{cache_filename}"
         | 
| 111 118 | 
             
                      command = Makit::Serializer.open(cache_filename, Makit::V1::Command)
         | 
| 112 119 | 
             
                      show_cached_command(command)
         | 
| 113 | 
            -
                      if command.exit_code != 0
         | 
| 114 | 
            -
                        abort "cached command failed: #{command.name} #{command.arguments.join(" ")}"
         | 
| 115 | 
            -
                      end
         | 
| 120 | 
            +
                      abort "cached command failed: #{command.name} #{command.arguments.join(" ")}" if command.exit_code != 0
         | 
| 116 121 | 
             
                      return command
         | 
| 117 122 | 
             
                    else
         | 
| 118 | 
            -
                       | 
| 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
         | 
| 119 127 | 
             
                      File.delete(cache_filename)
         | 
| 120 128 | 
             
                    end
         | 
| 121 129 | 
             
                  end
         | 
| @@ -123,52 +131,81 @@ module Makit | |
| 123 131 | 
             
                  command = run(command_request)
         | 
| 124 132 | 
             
                  # make sure the cache directory exists
         | 
| 125 133 | 
             
                  FileUtils.mkdir_p(File.dirname(cache_filename))
         | 
| 126 | 
            -
             | 
| 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 | 
            +
             | 
| 127 142 | 
             
                  Makit::Serializer.save_as(cache_filename, command)
         | 
| 128 143 | 
             
                  commands.push(command)
         | 
| 129 144 | 
             
                  command
         | 
| 130 145 | 
             
                end
         | 
| 131 146 |  | 
| 132 147 | 
             
                def show_command(command)
         | 
| 133 | 
            -
                  if command.exit_code | 
| 134 | 
            -
                     | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
                     | 
| 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 | 
            +
                    })
         | 
| 140 155 | 
             
                  else
         | 
| 141 | 
            -
                     | 
| 142 | 
            -
             | 
| 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 | 
            +
                    })
         | 
| 143 165 | 
             
                  end
         | 
| 144 166 | 
             
                end
         | 
| 145 167 |  | 
| 146 168 | 
             
                def show_cached_command(command)
         | 
| 147 | 
            -
                  if command.exit_code | 
| 148 | 
            -
                     | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 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 | 
            +
                    })
         | 
| 154 177 | 
             
                  else
         | 
| 155 | 
            -
                     | 
| 156 | 
            -
             | 
| 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 | 
            +
                    })
         | 
| 157 188 | 
             
                  end
         | 
| 158 189 | 
             
                end
         | 
| 159 190 |  | 
| 160 191 | 
             
                # Run a command and return a Makit::V1::Command.
         | 
| 192 | 
            +
                # @deprecated Use Commands::Runner#execute instead
         | 
| 161 193 | 
             
                def run(command_request)
         | 
| 194 | 
            +
                  warn_deprecation("CommandRunner#run is deprecated. Use Commands::Runner#execute instead.")
         | 
| 162 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 | 
            +
             | 
| 163 204 | 
             
                  command = execute(command_request)
         | 
| 164 | 
            -
                  show_output = true
         | 
| 165 | 
            -
                  exit_on_error = true
         | 
| 166 205 |  | 
| 167 206 | 
             
                  log_to_artifacts(command) if @log_to_artifacts
         | 
| 168 207 | 
             
                  show_command(command)
         | 
| 169 | 
            -
                  if command.exit_code != 0
         | 
| 170 | 
            -
                    exit 1 if command_request.exit_on_error
         | 
| 171 | 
            -
                  end
         | 
| 208 | 
            +
                  exit 1 if (command.exit_code != 0) && command_request.exit_on_error
         | 
| 172 209 | 
             
                  commands.push(command)
         | 
| 173 210 | 
             
                  command
         | 
| 174 211 | 
             
                end
         | 
| @@ -179,7 +216,9 @@ module Makit | |
| 179 216 | 
             
                end
         | 
| 180 217 |  | 
| 181 218 | 
             
                # Run a command and return a Makit::V1::Command.
         | 
| 219 | 
            +
                # @deprecated Use Commands::Runner#execute with exit_on_error: false instead
         | 
| 182 220 | 
             
                def try(args)
         | 
| 221 | 
            +
                  warn_deprecation("CommandRunner#try is deprecated. Use Commands::Runner#execute with exit_on_error: false instead.")
         | 
| 183 222 | 
             
                  request = parse_command_request(args)
         | 
| 184 223 | 
             
                  request.exit_on_error = false
         | 
| 185 224 | 
             
                  run(request)
         | 
| @@ -195,16 +234,31 @@ module Makit | |
| 195 234 | 
             
                end
         | 
| 196 235 |  | 
| 197 236 | 
             
                # Show the output of a command and return a Makit::V1::Command.
         | 
| 237 | 
            +
                # @deprecated Use Commands::Runner#execute with show_output: true instead
         | 
| 198 238 | 
             
                def show(args)
         | 
| 239 | 
            +
                  warn_deprecation("CommandRunner#show is deprecated. Use Commands::Runner#execute with show_output: true instead.")
         | 
| 199 240 | 
             
                  request = parse_args(args)
         | 
| 200 241 | 
             
                  command = execute(request)
         | 
| 201 242 |  | 
| 202 | 
            -
                   | 
| 203 | 
            -
                   | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 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
         | 
| 208 262 | 
             
                  command
         | 
| 209 263 | 
             
                end
         | 
| 210 264 |  | 
| @@ -212,22 +266,22 @@ module Makit | |
| 212 266 | 
             
                def parse_command_request(source)
         | 
| 213 267 | 
             
                  return Makit::V1::CommandRequest.new(source) if source.is_a? Hash
         | 
| 214 268 | 
             
                  return source if source.is_a? Makit::V1::CommandRequest
         | 
| 215 | 
            -
                  if source.is_a? String
         | 
| 216 | 
            -
                    return parse_args(source)
         | 
| 217 | 
            -
                  end
         | 
| 269 | 
            +
                  return parse_args(source) if source.is_a? String
         | 
| 218 270 |  | 
| 219 271 | 
             
                  raise "Invalid source" unless source.is_a? Makit::V1::CommandRequest
         | 
| 220 272 | 
             
                end
         | 
| 221 273 |  | 
| 222 274 | 
             
                def parse_command_request_from_hash(hash)
         | 
| 223 275 | 
             
                  raise "Invalid hash" unless hash.is_a? Hash
         | 
| 276 | 
            +
             | 
| 224 277 | 
             
                  Makit::V1::CommandRequest.new(hash)
         | 
| 225 278 | 
             
                end
         | 
| 226 279 |  | 
| 227 280 | 
             
                def parse_command_request_from_string(source)
         | 
| 228 281 | 
             
                  raise "Invalid source" unless source.is_a? String
         | 
| 229 | 
            -
             | 
| 230 | 
            -
                   | 
| 282 | 
            +
             | 
| 283 | 
            +
                  words = source.split
         | 
| 284 | 
            +
                  {
         | 
| 231 285 | 
             
                    name: words.shift,
         | 
| 232 286 | 
             
                    arguments: words,
         | 
| 233 287 | 
             
                    exit_on_error: true,
         | 
| @@ -236,31 +290,27 @@ module Makit | |
| 236 290 |  | 
| 237 291 | 
             
                # Parse the command line arguments into a Makit::V1::CommandRequest.
         | 
| 238 292 | 
             
                def parse_args(args)
         | 
| 239 | 
            -
                  #raise "No command specified" if args.empty?
         | 
| 293 | 
            +
                  # raise "No command specified" if args.empty?
         | 
| 240 294 | 
             
                  if args.is_a? Makit::V1::CommandRequest
         | 
| 241 295 | 
             
                    args
         | 
| 242 | 
            -
                   | 
| 243 | 
            -
                     | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
                        hash = {
         | 
| 296 | 
            +
                  elsif args.is_a? String
         | 
| 297 | 
            +
                    args = args.split
         | 
| 298 | 
            +
                    hash = if args.length == 1
         | 
| 299 | 
            +
                        {
         | 
| 247 300 | 
             
                          name: args[0],
         | 
| 248 301 | 
             
                          arguments: [],
         | 
| 249 302 | 
             
                          exit_on_error: true,
         | 
| 250 303 | 
             
                        }
         | 
| 251 | 
            -
                        Makit::V1::CommandRequest.new(hash)
         | 
| 252 304 | 
             
                      else
         | 
| 253 | 
            -
                         | 
| 305 | 
            +
                        {
         | 
| 254 306 | 
             
                          name: args.shift,
         | 
| 255 307 | 
             
                          arguments: args,
         | 
| 256 308 | 
             
                          exit_on_error: true,
         | 
| 257 309 | 
             
                        }
         | 
| 258 | 
            -
             | 
| 259 | 
            -
                        Makit::V1::CommandRequest.new(hash)
         | 
| 260 310 | 
             
                      end
         | 
| 261 | 
            -
                     | 
| 262 | 
            -
             | 
| 263 | 
            -
                     | 
| 311 | 
            +
                    Makit::V1::CommandRequest.new(hash)
         | 
| 312 | 
            +
                  else
         | 
| 313 | 
            +
                    Makit::V1::CommandRequest.new(args)
         | 
| 264 314 | 
             
                  end
         | 
| 265 315 | 
             
                end
         | 
| 266 316 |  | 
| @@ -273,7 +323,7 @@ module Makit | |
| 273 323 | 
             
                def execute(args)
         | 
| 274 324 | 
             
                  command_request = parse_args(args)
         | 
| 275 325 | 
             
                  command_request.directory = Dir.pwd if command_request.directory.nil?
         | 
| 276 | 
            -
                  command_request.directory = Dir.pwd if command_request.directory. | 
| 326 | 
            +
                  command_request.directory = Dir.pwd if command_request.directory.empty?
         | 
| 277 327 | 
             
                  result = Makit::V1::Command.new(name: command_request.name)
         | 
| 278 328 | 
             
                  command_request.arguments.each do |arg|
         | 
| 279 329 | 
             
                    result.arguments.push(arg)
         | 
| @@ -282,19 +332,19 @@ module Makit | |
| 282 332 | 
             
                  result.directory = command_request.directory
         | 
| 283 333 | 
             
                  start = Time.now
         | 
| 284 334 | 
             
                  filename_friendly_timestamp = Time.now.strftime("%Y.%m.%d_%H%M%S")
         | 
| 285 | 
            -
                   | 
| 335 | 
            +
                  File.join(Makit::Directories::LOG, "#{filename_friendly_timestamp}.log")
         | 
| 286 336 |  | 
| 287 337 | 
             
                  # assign a directory variable to the current working directory, if not specified,
         | 
| 288 338 | 
             
                  # otherwise assign the specified directory
         | 
| 289 339 | 
             
                  command_request.directory = Dir.pwd if command_request.directory.nil?
         | 
| 290 | 
            -
                  command_request.directory = Dir.pwd if command_request.directory. | 
| 340 | 
            +
                  command_request.directory = Dir.pwd if command_request.directory.empty?
         | 
| 291 341 | 
             
                  raise "Invalid directory" unless Dir.exist?(command_request.directory)
         | 
| 292 342 |  | 
| 293 343 | 
             
                  result.started_at = Google::Protobuf::Timestamp.new(seconds: start.to_i, nanos: start.nsec.to_i)
         | 
| 294 344 | 
             
                  ############# execute the command
         | 
| 295 345 | 
             
                  (output, error, exit_code) = execute_command(command, command_request.directory, command_request.timeout)
         | 
| 296 | 
            -
                  result.output = output.force_encoding("ASCII-8BIT")
         | 
| 297 | 
            -
                  result.error = error.force_encoding("ASCII-8BIT")
         | 
| 346 | 
            +
                  result.output = output.dup.force_encoding("ASCII-8BIT")
         | 
| 347 | 
            +
                  result.error = error.dup.force_encoding("ASCII-8BIT")
         | 
| 298 348 | 
             
                  result.exit_code = exit_code.nil? ? 0 : exit_code
         | 
| 299 349 |  | 
| 300 350 | 
             
                  elapsed_time = Time.now - start
         | 
| @@ -317,8 +367,8 @@ module Makit | |
| 317 367 | 
             
                    Dir.chdir(directory) do
         | 
| 318 368 | 
             
                      output, error, process_status = Open3.capture3(command)
         | 
| 319 369 | 
             
                    end
         | 
| 320 | 
            -
                     | 
| 321 | 
            -
                  rescue => e
         | 
| 370 | 
            +
                    [output, error, process_status.exitstatus]
         | 
| 371 | 
            +
                  rescue StandardError => e
         | 
| 322 372 | 
             
                    # restore the original working directory
         | 
| 323 373 | 
             
                    Dir.chdir(original_directory)
         | 
| 324 374 | 
             
                    message_parts = []
         | 
| @@ -326,9 +376,9 @@ module Makit | |
| 326 376 | 
             
                    message_parts << "directory: #{directory}"
         | 
| 327 377 | 
             
                    message_parts << "timeout: #{timeout}" unless timeout.nil?
         | 
| 328 378 | 
             
                    message_parts << "error: #{e.message}"
         | 
| 329 | 
            -
                    message = message_parts.join("\n") | 
| 330 | 
            -
                     | 
| 331 | 
            -
                    #raise Makit::Error, message
         | 
| 379 | 
            +
                    message = "#{message_parts.join("\n")}\n"
         | 
| 380 | 
            +
                    ["", message, 1]
         | 
| 381 | 
            +
                    # raise Makit::Error, message
         | 
| 332 382 | 
             
                  end
         | 
| 333 383 | 
             
                end
         | 
| 334 384 |  | 
| @@ -336,18 +386,18 @@ module Makit | |
| 336 386 | 
             
                  # if the command_request is not a Makit::V1::CommandRequest, raise an error
         | 
| 337 387 | 
             
                  raise "Invalid command_request" unless command_request.is_a? Makit::V1::CommandRequest
         | 
| 338 388 |  | 
| 339 | 
            -
                  args =  | 
| 340 | 
            -
             | 
| 341 | 
            -
                    args.push(arg)
         | 
| 389 | 
            +
                  args = command_request.arguments.map do |arg|
         | 
| 390 | 
            +
                    arg
         | 
| 342 391 | 
             
                  end
         | 
| 343 | 
            -
                   | 
| 344 | 
            -
             | 
| 345 | 
            -
             | 
| 346 | 
            -
             | 
| 347 | 
            -
             | 
| 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 | 
            +
                                         })
         | 
| 348 398 |  | 
| 349 399 | 
             
                  begin
         | 
| 350 | 
            -
                  rescue  | 
| 400 | 
            +
                  rescue StandardError
         | 
| 351 401 | 
             
                  end
         | 
| 352 402 | 
             
                end
         | 
| 353 403 |  | 
| @@ -362,25 +412,23 @@ module Makit | |
| 362 412 | 
             
                  symbol = Makit::Symbols.error if command.exit_code != 0
         | 
| 363 413 | 
             
                  summary = "#{symbol} #{command.name.colorize(:yellow)} #{command.arguments.join(" ")}"
         | 
| 364 414 |  | 
| 365 | 
            -
                  if summary.length > 80
         | 
| 366 | 
            -
                    summary = summary.to_lines(80, command.name.length + 3)
         | 
| 367 | 
            -
                  end
         | 
| 415 | 
            +
                  summary = summary.to_lines(80, command.name.length + 3) if summary.length > 80
         | 
| 368 416 |  | 
| 369 417 | 
             
                  summary
         | 
| 370 418 | 
             
                end
         | 
| 371 419 |  | 
| 372 420 | 
             
                def log_rake_commands
         | 
| 373 421 | 
             
                  dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
         | 
| 374 | 
            -
                  FileUtils.mkdir_p(dir) | 
| 422 | 
            +
                  FileUtils.mkdir_p(dir)
         | 
| 375 423 |  | 
| 376 424 | 
             
                  # open a text file to write to
         | 
| 377 425 | 
             
                  File.open(File.join(dir, "rake.commands.txt"), "w") do |file|
         | 
| 378 | 
            -
                    #rake_commands = commands.select { |command| command.name == "rake" }
         | 
| 426 | 
            +
                    # rake_commands = commands.select { |command| command.name == "rake" }
         | 
| 379 427 | 
             
                    commands.each do |command|
         | 
| 380 | 
            -
                      file.puts "  | 
| 428 | 
            +
                      file.puts " #{Makit::CommandRunner.get_command_summary(command).strip_color_codes}"
         | 
| 381 429 | 
             
                      file.puts "   start time: #{command.started_at}"
         | 
| 382 | 
            -
                      file.puts command.output.strip_color_codes unless command.output.strip_color_codes.strip. | 
| 383 | 
            -
                      file.puts command.error.strip_color_codes unless command.error.strip_color_codes.strip. | 
| 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?
         | 
| 384 432 | 
             
                      file.puts " "
         | 
| 385 433 | 
             
                    end
         | 
| 386 434 | 
             
                  end
         | 
| @@ -388,17 +436,28 @@ module Makit | |
| 388 436 |  | 
| 389 437 | 
             
                def log_slowest_commands
         | 
| 390 438 | 
             
                  dir = File.join(Makit::Directories::PROJECT_ARTIFACTS, "commands")
         | 
| 391 | 
            -
                  FileUtils.mkdir_p(dir) | 
| 439 | 
            +
                  FileUtils.mkdir_p(dir)
         | 
| 392 440 |  | 
| 393 441 | 
             
                  # open a text file to write to
         | 
| 394 442 | 
             
                  File.open(File.join(dir, "slow.commands.txt"), "w") do |file|
         | 
| 395 | 
            -
                    Makit::RUNNER.commands.sort_by  | 
| 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|
         | 
| 396 446 | 
             
                      # Convert to float representation
         | 
| 397 | 
            -
                       | 
| 398 | 
            -
                      #puts "  #{command.name} took #{duration_in_float} seconds"
         | 
| 399 | 
            -
                      file.puts "  | 
| 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)"
         | 
| 400 450 | 
             
                    end
         | 
| 401 451 | 
             
                  end
         | 
| 402 452 | 
             
                end
         | 
| 403 | 
            -
             | 
| 404 | 
            -
             | 
| 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
         |