Module: Datadog::CI::Git::CLI
- Defined in:
- lib/datadog/ci/git/cli.rb
Defined Under Namespace
Classes: GitCommandExecutionError
Constant Summary collapse
- UNSHALLOW_TIMEOUT =
Timeout constants for git commands (in seconds) These values were set based on internal telemetry
500- LONG_TIMEOUT =
30- SHORT_TIMEOUT =
3
Class Method Summary collapse
-
.exec_git_command(cmd, stdin: nil, timeout: SHORT_TIMEOUT) ⇒ String?
Execute a git command with optional stdin input and timeout.
-
.find_git_directory(start_dir) ⇒ String
Traverses up from the given directory to find the nearest .git folder or file.
-
.safe_directory ⇒ String
Returns the directory to use for git’s safe.directory config.
Class Method Details
.exec_git_command(cmd, stdin: nil, timeout: SHORT_TIMEOUT) ⇒ String?
Execute a git command with optional stdin input and timeout
All git commands are executed with the ‘-c safe.directory` option to handle cases where the repository is owned by a different user (common in CI environments with containerized builds).
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/datadog/ci/git/cli.rb', line 37 def self.exec_git_command(cmd, stdin: nil, timeout: SHORT_TIMEOUT) # @type var out: String # @type var status: Process::Status? out, status = Utils::Command.exec_command( ["git", "-c", "safe.directory=#{safe_directory}"] + cmd, stdin_data: stdin, timeout: timeout ) if status.nil? || !status.success? # Convert command to string representation for error message cmd_str = cmd.join(" ") raise GitCommandExecutionError.new( "Failed to run git command [#{cmd_str}] with input [#{stdin}] and output [#{out}]. Status: #{status}", output: out, command: cmd_str, status: status ) end return nil if out.empty? out end |
.find_git_directory(start_dir) ⇒ String
Traverses up from the given directory to find the nearest .git folder or file. Returns the repository root (parent of .git) if found, otherwise the original directory.
Note: .git can be either a directory (regular repos) or a file (worktrees/submodules). In worktrees and submodules, .git is a file containing a pointer to the actual git directory.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/datadog/ci/git/cli.rb', line 86 def self.find_git_directory(start_dir) Datadog.logger.debug { "Searching for .git starting from: #{start_dir}" } current_dir = File.(start_dir) loop do git_path = File.join(current_dir, ".git") # Check for both directory (.git in regular repos) and file (.git in worktrees/submodules) if File.exist?(git_path) Datadog.logger.debug { "Found .git at: #{git_path} (#{File.directory?(git_path) ? "directory" : "file"})" } return current_dir end parent_dir = File.dirname(current_dir) # Reached the root directory break if parent_dir == current_dir current_dir = parent_dir end # Fallback to original directory if no .git found Datadog.logger.debug { "No .git found, using fallback: #{start_dir}" } start_dir end |
.safe_directory ⇒ String
Returns the directory to use for git’s safe.directory config. This is cached to avoid repeated filesystem lookups.
Traverses up from current directory to find the nearest .git folder and returns its parent (the repository root). Falls back to current working directory if no .git folder is found.
70 71 72 73 74 75 76 |
# File 'lib/datadog/ci/git/cli.rb', line 70 def self.safe_directory return @safe_directory if defined?(@safe_directory) @safe_directory = find_git_directory(Dir.pwd) Datadog.logger.debug { "Git safe.directory configured to: #{@safe_directory}" } @safe_directory end |