makit 0.0.143 → 0.0.145
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/lib/makit/cli/base.rb +17 -0
 - data/lib/makit/cli/generators/templates/ruby/gemspec.rb +1 -0
 - data/lib/makit/cli/main.rb +9 -0
 - data/lib/makit/cli/pipeline_commands.rb +311 -0
 - data/lib/makit/cli/strategy_commands.rb +2 -7
 - data/lib/makit/commands/result.rb +1 -1
 - data/lib/makit/configuration/dotnet_project.rb +9 -0
 - data/lib/makit/configuration/gitlab_helper.rb +4 -1
 - data/lib/makit/configuration/project.rb +362 -84
 - data/lib/makit/configuration/timeout.rb +1 -1
 - data/lib/makit/configuration.rb +5 -0
 - data/lib/makit/fileinfo.rb +8 -0
 - data/lib/makit/git/repository.rb +207 -31
 - data/lib/makit/git.rb +6 -0
 - data/lib/makit/gitlab/pipeline.rb +857 -0
 - data/lib/makit/gitlab/pipeline_service_impl.rb +1536 -0
 - data/lib/makit/humanize.rb +81 -0
 - data/lib/makit/io/filesystem.rb +111 -0
 - data/lib/makit/io/filesystem_service_impl.rb +337 -0
 - data/lib/makit/mp/string_mp.rb +15 -9
 - data/lib/makit/podman/podman.rb +458 -0
 - data/lib/makit/podman/podman_service_impl.rb +1081 -0
 - data/lib/makit/process.rb +214 -0
 - data/lib/makit/protoc.rb +6 -1
 - data/lib/makit/services/repository_manager.rb +268 -132
 - data/lib/makit/symbols.rb +5 -0
 - data/lib/makit/v1/configuration/project_service_impl.rb +371 -0
 - data/lib/makit/v1/git/git_repository_service_impl.rb +295 -0
 - data/lib/makit/v1/makit.v1_pb.rb +1 -1
 - data/lib/makit/v1/makit.v1_services_pb.rb +1 -1
 - data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -0
 - data/lib/makit/version.rb +1 -1
 - data/lib/makit.rb +68 -0
 - metadata +61 -36
 
    
        data/lib/makit/process.rb
    CHANGED
    
    | 
         @@ -159,5 +159,219 @@ module Makit 
     | 
|
| 
       159 
159 
     | 
    
         
             
                    results.split("\n").reject(&:empty?)
         
     | 
| 
       160 
160 
     | 
    
         
             
                  end
         
     | 
| 
       161 
161 
     | 
    
         
             
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                # Run a command in the background and track it with a PID file
         
     | 
| 
      
 164 
     | 
    
         
            +
                #
         
     | 
| 
      
 165 
     | 
    
         
            +
                # This method starts a process in the background and stores its PID in a file
         
     | 
| 
      
 166 
     | 
    
         
            +
                # for later management. It handles cross-platform differences in process spawning.
         
     | 
| 
      
 167 
     | 
    
         
            +
                #
         
     | 
| 
      
 168 
     | 
    
         
            +
                # @param command [String] The command to run in the background
         
     | 
| 
      
 169 
     | 
    
         
            +
                # @param pid_file [String] Path to the PID file to store the process ID
         
     | 
| 
      
 170 
     | 
    
         
            +
                # @param working_dir [String, nil] Working directory for the process (optional)
         
     | 
| 
      
 171 
     | 
    
         
            +
                # @param environment [Hash, nil] Environment variables to set (optional)
         
     | 
| 
      
 172 
     | 
    
         
            +
                # @return [Integer] The process ID of the started process
         
     | 
| 
      
 173 
     | 
    
         
            +
                # @raise [StandardError] If the process fails to start
         
     | 
| 
      
 174 
     | 
    
         
            +
                def self.run_background(command, pid_file, working_dir: nil, environment: {})
         
     | 
| 
      
 175 
     | 
    
         
            +
                  # Ensure the command is not nil or empty
         
     | 
| 
      
 176 
     | 
    
         
            +
                  raise ArgumentError, "Command cannot be nil or empty" if command.nil? || command.strip.empty?
         
     | 
| 
      
 177 
     | 
    
         
            +
                  raise ArgumentError, "PID file path cannot be nil or empty" if pid_file.nil? || pid_file.strip.empty?
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                  # Convert command to array for Process.spawn
         
     | 
| 
      
 180 
     | 
    
         
            +
                  cmd_array = if Makit::Environment.is_windows?
         
     | 
| 
      
 181 
     | 
    
         
            +
                      # Windows: Use cmd /c for complex commands
         
     | 
| 
      
 182 
     | 
    
         
            +
                      ["cmd", "/c", command]
         
     | 
| 
      
 183 
     | 
    
         
            +
                    else
         
     | 
| 
      
 184 
     | 
    
         
            +
                      # Unix-like: Use shell for command parsing
         
     | 
| 
      
 185 
     | 
    
         
            +
                      ["sh", "-c", command]
         
     | 
| 
      
 186 
     | 
    
         
            +
                    end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                  # Prepare spawn options
         
     | 
| 
      
 189 
     | 
    
         
            +
                  spawn_options = {}
         
     | 
| 
      
 190 
     | 
    
         
            +
                  spawn_options[:chdir] = working_dir if working_dir
         
     | 
| 
      
 191 
     | 
    
         
            +
                  spawn_options[:pgroup] = true unless Makit::Environment.is_windows?
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                  # Set environment variables
         
     | 
| 
      
 194 
     | 
    
         
            +
                  env = ENV.to_h.merge(environment)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  spawn_options[:unsetenv_others] = false
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 198 
     | 
    
         
            +
                    # Start the process
         
     | 
| 
      
 199 
     | 
    
         
            +
                    pid = Process.spawn(env, *cmd_array, spawn_options)
         
     | 
| 
      
 200 
     | 
    
         
            +
                    
         
     | 
| 
      
 201 
     | 
    
         
            +
                    # Write PID to file
         
     | 
| 
      
 202 
     | 
    
         
            +
                    File.write(pid_file, pid.to_s)
         
     | 
| 
      
 203 
     | 
    
         
            +
                    
         
     | 
| 
      
 204 
     | 
    
         
            +
                    # Give the process a moment to start
         
     | 
| 
      
 205 
     | 
    
         
            +
                    sleep(0.5)
         
     | 
| 
      
 206 
     | 
    
         
            +
                    
         
     | 
| 
      
 207 
     | 
    
         
            +
                    # Verify the process is still running
         
     | 
| 
      
 208 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 209 
     | 
    
         
            +
                      Process.getpgid(pid) if Makit::Environment.is_windows?
         
     | 
| 
      
 210 
     | 
    
         
            +
                      Process.getpgid(pid) unless Makit::Environment.is_windows?
         
     | 
| 
      
 211 
     | 
    
         
            +
                    rescue Errno::ESRCH
         
     | 
| 
      
 212 
     | 
    
         
            +
                      raise StandardError, "Process failed to start or exited immediately"
         
     | 
| 
      
 213 
     | 
    
         
            +
                    end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                    pid
         
     | 
| 
      
 216 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 217 
     | 
    
         
            +
                    # Clean up PID file if process failed to start
         
     | 
| 
      
 218 
     | 
    
         
            +
                    File.delete(pid_file) if File.exist?(pid_file)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    raise StandardError, "Failed to start background process: #{e.message}"
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
                end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                # Stop a background process using its PID file
         
     | 
| 
      
 224 
     | 
    
         
            +
                #
         
     | 
| 
      
 225 
     | 
    
         
            +
                # This method reads the PID from a file and terminates the process gracefully.
         
     | 
| 
      
 226 
     | 
    
         
            +
                # It handles cross-platform differences in process termination.
         
     | 
| 
      
 227 
     | 
    
         
            +
                #
         
     | 
| 
      
 228 
     | 
    
         
            +
                # @param pid_file [String] Path to the PID file containing the process ID
         
     | 
| 
      
 229 
     | 
    
         
            +
                # @param signal [String] Signal to send (default: "TERM" for graceful shutdown)
         
     | 
| 
      
 230 
     | 
    
         
            +
                # @return [Boolean] True if the process was stopped, false if it wasn't running
         
     | 
| 
      
 231 
     | 
    
         
            +
                def self.stop_background(pid_file, signal: "TERM")
         
     | 
| 
      
 232 
     | 
    
         
            +
                  return false unless File.exist?(pid_file)
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 235 
     | 
    
         
            +
                    pid = File.read(pid_file).strip.to_i
         
     | 
| 
      
 236 
     | 
    
         
            +
                    return false if pid <= 0
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    # Check if process is still running
         
     | 
| 
      
 239 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 240 
     | 
    
         
            +
                      if Makit::Environment.is_windows?
         
     | 
| 
      
 241 
     | 
    
         
            +
                        # Windows: Use taskkill
         
     | 
| 
      
 242 
     | 
    
         
            +
                        if signal == "TERM"
         
     | 
| 
      
 243 
     | 
    
         
            +
                          system("taskkill /PID #{pid} /F >nul 2>&1")
         
     | 
| 
      
 244 
     | 
    
         
            +
                        else
         
     | 
| 
      
 245 
     | 
    
         
            +
                          system("taskkill /PID #{pid} /F >nul 2>&1")
         
     | 
| 
      
 246 
     | 
    
         
            +
                        end
         
     | 
| 
      
 247 
     | 
    
         
            +
                      else
         
     | 
| 
      
 248 
     | 
    
         
            +
                        # Unix-like: Use kill with specified signal
         
     | 
| 
      
 249 
     | 
    
         
            +
                        Process.kill(signal, pid)
         
     | 
| 
      
 250 
     | 
    
         
            +
                      end
         
     | 
| 
      
 251 
     | 
    
         
            +
                      
         
     | 
| 
      
 252 
     | 
    
         
            +
                      # Wait a moment for the process to terminate
         
     | 
| 
      
 253 
     | 
    
         
            +
                      sleep(0.5)
         
     | 
| 
      
 254 
     | 
    
         
            +
                      
         
     | 
| 
      
 255 
     | 
    
         
            +
                      # Verify the process is gone
         
     | 
| 
      
 256 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 257 
     | 
    
         
            +
                        Process.getpgid(pid)
         
     | 
| 
      
 258 
     | 
    
         
            +
                        # Process still running, force kill if TERM didn't work
         
     | 
| 
      
 259 
     | 
    
         
            +
                        if signal == "TERM"
         
     | 
| 
      
 260 
     | 
    
         
            +
                          return stop_background(pid_file, signal: "KILL")
         
     | 
| 
      
 261 
     | 
    
         
            +
                        end
         
     | 
| 
      
 262 
     | 
    
         
            +
                        return false
         
     | 
| 
      
 263 
     | 
    
         
            +
                      rescue Errno::ESRCH
         
     | 
| 
      
 264 
     | 
    
         
            +
                        # Process is gone, success
         
     | 
| 
      
 265 
     | 
    
         
            +
                        true
         
     | 
| 
      
 266 
     | 
    
         
            +
                      end
         
     | 
| 
      
 267 
     | 
    
         
            +
                    rescue Errno::ESRCH, Errno::EPERM
         
     | 
| 
      
 268 
     | 
    
         
            +
                      # Process was not running or permission denied
         
     | 
| 
      
 269 
     | 
    
         
            +
                      false
         
     | 
| 
      
 270 
     | 
    
         
            +
                    end
         
     | 
| 
      
 271 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 272 
     | 
    
         
            +
                    # Log error but don't raise
         
     | 
| 
      
 273 
     | 
    
         
            +
                    puts "Error stopping background process: #{e.message}" if defined?(puts)
         
     | 
| 
      
 274 
     | 
    
         
            +
                    false
         
     | 
| 
      
 275 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 276 
     | 
    
         
            +
                    # Clean up PID file
         
     | 
| 
      
 277 
     | 
    
         
            +
                    File.delete(pid_file) if File.exist?(pid_file)
         
     | 
| 
      
 278 
     | 
    
         
            +
                  end
         
     | 
| 
      
 279 
     | 
    
         
            +
                end
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
                # Check if a background process is still running using its PID file
         
     | 
| 
      
 282 
     | 
    
         
            +
                #
         
     | 
| 
      
 283 
     | 
    
         
            +
                # @param pid_file [String] Path to the PID file containing the process ID
         
     | 
| 
      
 284 
     | 
    
         
            +
                # @return [Boolean] True if the process is running, false otherwise
         
     | 
| 
      
 285 
     | 
    
         
            +
                def self.background_running?(pid_file)
         
     | 
| 
      
 286 
     | 
    
         
            +
                  return false unless File.exist?(pid_file)
         
     | 
| 
      
 287 
     | 
    
         
            +
             
     | 
| 
      
 288 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 289 
     | 
    
         
            +
                    pid = File.read(pid_file).strip.to_i
         
     | 
| 
      
 290 
     | 
    
         
            +
                    return false if pid <= 0
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
                    # Check if process is still running
         
     | 
| 
      
 293 
     | 
    
         
            +
                    Process.getpgid(pid)
         
     | 
| 
      
 294 
     | 
    
         
            +
                    true
         
     | 
| 
      
 295 
     | 
    
         
            +
                  rescue Errno::ESRCH, Errno::EPERM
         
     | 
| 
      
 296 
     | 
    
         
            +
                    false
         
     | 
| 
      
 297 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 298 
     | 
    
         
            +
                    # Log error but return false
         
     | 
| 
      
 299 
     | 
    
         
            +
                    puts "Error checking background process: #{e.message}" if defined?(puts)
         
     | 
| 
      
 300 
     | 
    
         
            +
                    false
         
     | 
| 
      
 301 
     | 
    
         
            +
                  end
         
     | 
| 
      
 302 
     | 
    
         
            +
                end
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                # Get the PID of a background process from its PID file
         
     | 
| 
      
 305 
     | 
    
         
            +
                #
         
     | 
| 
      
 306 
     | 
    
         
            +
                # @param pid_file [String] Path to the PID file containing the process ID
         
     | 
| 
      
 307 
     | 
    
         
            +
                # @return [Integer, nil] The process ID, or nil if not found or invalid
         
     | 
| 
      
 308 
     | 
    
         
            +
                def self.get_background_pid(pid_file)
         
     | 
| 
      
 309 
     | 
    
         
            +
                  return nil unless File.exist?(pid_file)
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 312 
     | 
    
         
            +
                    pid = File.read(pid_file).strip.to_i
         
     | 
| 
      
 313 
     | 
    
         
            +
                    return nil if pid <= 0
         
     | 
| 
      
 314 
     | 
    
         
            +
                    pid
         
     | 
| 
      
 315 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 316 
     | 
    
         
            +
                    puts "Error reading PID file: #{e.message}" if defined?(puts)
         
     | 
| 
      
 317 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 318 
     | 
    
         
            +
                  end
         
     | 
| 
      
 319 
     | 
    
         
            +
                end
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                # Clean up stale PID files (processes that are no longer running)
         
     | 
| 
      
 322 
     | 
    
         
            +
                #
         
     | 
| 
      
 323 
     | 
    
         
            +
                # @param pid_files [Array<String>] Array of PID file paths to check
         
     | 
| 
      
 324 
     | 
    
         
            +
                # @return [Array<String>] Array of cleaned up PID file paths
         
     | 
| 
      
 325 
     | 
    
         
            +
                def self.cleanup_stale_pids(pid_files)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  cleaned = []
         
     | 
| 
      
 327 
     | 
    
         
            +
                  
         
     | 
| 
      
 328 
     | 
    
         
            +
                  pid_files.each do |pid_file|
         
     | 
| 
      
 329 
     | 
    
         
            +
                    next unless File.exist?(pid_file)
         
     | 
| 
      
 330 
     | 
    
         
            +
                    
         
     | 
| 
      
 331 
     | 
    
         
            +
                    unless background_running?(pid_file)
         
     | 
| 
      
 332 
     | 
    
         
            +
                      File.delete(pid_file)
         
     | 
| 
      
 333 
     | 
    
         
            +
                      cleaned << pid_file
         
     | 
| 
      
 334 
     | 
    
         
            +
                    end
         
     | 
| 
      
 335 
     | 
    
         
            +
                  end
         
     | 
| 
      
 336 
     | 
    
         
            +
                  
         
     | 
| 
      
 337 
     | 
    
         
            +
                  cleaned
         
     | 
| 
      
 338 
     | 
    
         
            +
                end
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
                # Health check for a service running on a specific port
         
     | 
| 
      
 341 
     | 
    
         
            +
                #
         
     | 
| 
      
 342 
     | 
    
         
            +
                # @param port [Integer] Port number to check
         
     | 
| 
      
 343 
     | 
    
         
            +
                # @param host [String] Host to check (default: "localhost")
         
     | 
| 
      
 344 
     | 
    
         
            +
                # @param timeout [Integer] Timeout in seconds (default: 5)
         
     | 
| 
      
 345 
     | 
    
         
            +
                # @return [Boolean] True if the service is responding, false otherwise
         
     | 
| 
      
 346 
     | 
    
         
            +
                def self.health_check_port(port, host: "localhost", timeout: 5)
         
     | 
| 
      
 347 
     | 
    
         
            +
                  require 'net/http'
         
     | 
| 
      
 348 
     | 
    
         
            +
                  require 'timeout'
         
     | 
| 
      
 349 
     | 
    
         
            +
                  
         
     | 
| 
      
 350 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 351 
     | 
    
         
            +
                    uri = URI("http://#{host}:#{port}")
         
     | 
| 
      
 352 
     | 
    
         
            +
                    Timeout.timeout(timeout) do
         
     | 
| 
      
 353 
     | 
    
         
            +
                      response = Net::HTTP.get_response(uri)
         
     | 
| 
      
 354 
     | 
    
         
            +
                      response.code.to_i < 500 # Consider 4xx as "responding" but 5xx as "unhealthy"
         
     | 
| 
      
 355 
     | 
    
         
            +
                    end
         
     | 
| 
      
 356 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 357 
     | 
    
         
            +
                    false
         
     | 
| 
      
 358 
     | 
    
         
            +
                  end
         
     | 
| 
      
 359 
     | 
    
         
            +
                end
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
                # Health check for multiple ports
         
     | 
| 
      
 362 
     | 
    
         
            +
                #
         
     | 
| 
      
 363 
     | 
    
         
            +
                # @param ports [Array<Integer>] Array of port numbers to check
         
     | 
| 
      
 364 
     | 
    
         
            +
                # @param host [String] Host to check (default: "localhost")
         
     | 
| 
      
 365 
     | 
    
         
            +
                # @param timeout [Integer] Timeout in seconds (default: 5)
         
     | 
| 
      
 366 
     | 
    
         
            +
                # @return [Hash] Hash with port numbers as keys and health status as values
         
     | 
| 
      
 367 
     | 
    
         
            +
                def self.health_check_ports(ports, host: "localhost", timeout: 5)
         
     | 
| 
      
 368 
     | 
    
         
            +
                  results = {}
         
     | 
| 
      
 369 
     | 
    
         
            +
                  
         
     | 
| 
      
 370 
     | 
    
         
            +
                  ports.each do |port|
         
     | 
| 
      
 371 
     | 
    
         
            +
                    results[port] = health_check_port(port, host: host, timeout: timeout)
         
     | 
| 
      
 372 
     | 
    
         
            +
                  end
         
     | 
| 
      
 373 
     | 
    
         
            +
                  
         
     | 
| 
      
 374 
     | 
    
         
            +
                  results
         
     | 
| 
      
 375 
     | 
    
         
            +
                end
         
     | 
| 
       162 
376 
     | 
    
         
             
              end
         
     | 
| 
       163 
377 
     | 
    
         
             
            end
         
     | 
    
        data/lib/makit/protoc.rb
    CHANGED
    
    | 
         @@ -98,7 +98,12 @@ module Makit 
     | 
|
| 
       98 
98 
     | 
    
         
             
                        FileUtils.mkdir_p(output_dir.to_s)
         
     | 
| 
       99 
99 
     | 
    
         
             
                        "protoc --csharp_out=#{output_dir} #{proto}".run
         
     | 
| 
       100 
100 
     | 
    
         
             
                      else
         
     | 
| 
       101 
     | 
    
         
            -
                         
     | 
| 
      
 101 
     | 
    
         
            +
                        # Use grpc_tools_ruby_protoc for Ruby to generate compatible code
         
     | 
| 
      
 102 
     | 
    
         
            +
                        if language == "ruby"
         
     | 
| 
      
 103 
     | 
    
         
            +
                          "grpc_tools_ruby_protoc --ruby_out=#{output_relative_path} --grpc_out=#{output_relative_path} #{proto}".run
         
     | 
| 
      
 104 
     | 
    
         
            +
                        else
         
     | 
| 
      
 105 
     | 
    
         
            +
                          "protoc --#{language}_out=#{output_relative_path} #{proto}".run
         
     | 
| 
      
 106 
     | 
    
         
            +
                        end
         
     | 
| 
       102 
107 
     | 
    
         
             
                      end
         
     | 
| 
       103 
108 
     | 
    
         
             
                    end
         
     | 
| 
       104 
109 
     | 
    
         
             
                  end
         
     |