lib/datadog/ci/git/local_repository.rb in datadog-ci-1.2.0 vs lib/datadog/ci/git/local_repository.rb in datadog-ci-1.3.0
- old
+ new
@@ -1,16 +1,29 @@
# frozen_string_literal: true
require "open3"
require "pathname"
+require_relative "../ext/telemetry"
+require_relative "telemetry"
require_relative "user"
module Datadog
module CI
module Git
module LocalRepository
+ class GitCommandExecutionError < StandardError
+ attr_reader :output, :command, :status
+ def initialize(message, output:, command:, status:)
+ super(message)
+
+ @output = output
+ @command = command
+ @status = status
+ end
+ end
+
COMMAND_RETRY_COUNT = 3
def self.root
return @root if defined?(@root)
@@ -46,13 +59,22 @@
def self.current_folder_name
File.basename(root)
end
def self.git_repository_url
- exec_git_command("git ls-remote --get-url")
+ Telemetry.git_command(Ext::Telemetry::Command::GET_REPOSITORY)
+ res = nil
+
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ res = exec_git_command("git ls-remote --get-url")
+ end
+
+ Telemetry.git_command_ms(Ext::Telemetry::Command::GET_REPOSITORY, duration_ms)
+ res
rescue => e
log_failure(e, "git repository url")
+ telemetry_track_error(e, Ext::Telemetry::Command::GET_REPOSITORY)
nil
end
def self.git_root
exec_git_command("git rev-parse --show-toplevel")
@@ -67,13 +89,22 @@
log_failure(e, "git commit sha")
nil
end
def self.git_branch
- exec_git_command("git rev-parse --abbrev-ref HEAD")
+ Telemetry.git_command(Ext::Telemetry::Command::GET_BRANCH)
+ res = nil
+
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ res = exec_git_command("git rev-parse --abbrev-ref HEAD")
+ end
+
+ Telemetry.git_command_ms(Ext::Telemetry::Command::GET_BRANCH, duration_ms)
+ res
rescue => e
log_failure(e, "git branch")
+ telemetry_track_error(e, Ext::Telemetry::Command::GET_BRANCH)
nil
end
def self.git_tag
exec_git_command("git tag --points-at HEAD")
@@ -114,33 +145,53 @@
[nil_user, nil_user]
end
# returns maximum of 1000 latest commits in the last month
def self.git_commits
- output = exec_git_command("git log --format=%H -n 1000 --since=\"1 month ago\"")
+ Telemetry.git_command(Ext::Telemetry::Command::GET_LOCAL_COMMITS)
+
+ output = nil
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ output = exec_git_command("git log --format=%H -n 1000 --since=\"1 month ago\"")
+ end
+
+ Telemetry.git_command_ms(Ext::Telemetry::Command::GET_LOCAL_COMMITS, duration_ms)
+
return [] if output.nil?
+ # @type var output: String
output.split("\n")
rescue => e
log_failure(e, "git commits")
+ telemetry_track_error(e, Ext::Telemetry::Command::GET_LOCAL_COMMITS)
[]
end
def self.git_commits_rev_list(included_commits:, excluded_commits:)
+ Telemetry.git_command(Ext::Telemetry::Command::GET_OBJECTS)
included_commits = filter_invalid_commits(included_commits).join(" ")
excluded_commits = filter_invalid_commits(excluded_commits).map! { |sha| "^#{sha}" }.join(" ")
- exec_git_command(
- "git rev-list " \
- "--objects " \
- "--no-object-names " \
- "--filter=blob:none " \
- "--since=\"1 month ago\" " \
- "#{excluded_commits} #{included_commits}"
- )
+ res = nil
+
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ res = exec_git_command(
+ "git rev-list " \
+ "--objects " \
+ "--no-object-names " \
+ "--filter=blob:none " \
+ "--since=\"1 month ago\" " \
+ "#{excluded_commits} #{included_commits}"
+ )
+ end
+
+ Telemetry.git_command_ms(Ext::Telemetry::Command::GET_OBJECTS, duration_ms)
+
+ res
rescue => e
log_failure(e, "git commits rev list")
+ telemetry_track_error(e, Ext::Telemetry::Command::GET_OBJECTS)
nil
end
def self.git_generate_packfiles(included_commits:, excluded_commits:, path:)
return nil unless File.exist?(path)
@@ -148,39 +199,63 @@
commit_tree = git_commits_rev_list(included_commits: included_commits, excluded_commits: excluded_commits)
return nil if commit_tree.nil?
basename = SecureRandom.hex(4)
- exec_git_command(
- "git pack-objects --compression=9 --max-pack-size=3m #{path}/#{basename}",
- stdin: commit_tree
- )
+ Telemetry.git_command(Ext::Telemetry::Command::PACK_OBJECTS)
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ exec_git_command(
+ "git pack-objects --compression=9 --max-pack-size=3m #{path}/#{basename}",
+ stdin: commit_tree
+ )
+ end
+ Telemetry.git_command_ms(Ext::Telemetry::Command::PACK_OBJECTS, duration_ms)
+
basename
rescue => e
log_failure(e, "git generate packfiles")
+ telemetry_track_error(e, Ext::Telemetry::Command::PACK_OBJECTS)
nil
end
def self.git_shallow_clone?
- exec_git_command("git rev-parse --is-shallow-repository") == "true"
+ Telemetry.git_command(Ext::Telemetry::Command::CHECK_SHALLOW)
+ res = false
+
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ res = exec_git_command("git rev-parse --is-shallow-repository") == "true"
+ end
+ Telemetry.git_command_ms(Ext::Telemetry::Command::CHECK_SHALLOW, duration_ms)
+
+ res
rescue => e
log_failure(e, "git shallow clone")
+ telemetry_track_error(e, Ext::Telemetry::Command::CHECK_SHALLOW)
false
end
def self.git_unshallow
- exec_git_command(
- "git fetch " \
- "--shallow-since=\"1 month ago\" " \
- "--update-shallow " \
- "--filter=\"blob:none\" " \
- "--recurse-submodules=no " \
- "$(git config --default origin --get clone.defaultRemoteName) $(git rev-parse HEAD)"
- )
+ Telemetry.git_command(Ext::Telemetry::Command::UNSHALLOW)
+ res = nil
+
+ duration_ms = Core::Utils::Time.measure(:float_millisecond) do
+ res = exec_git_command(
+ "git fetch " \
+ "--shallow-since=\"1 month ago\" " \
+ "--update-shallow " \
+ "--filter=\"blob:none\" " \
+ "--recurse-submodules=no " \
+ "$(git config --default origin --get clone.defaultRemoteName) $(git rev-parse HEAD)"
+ )
+ end
+ Telemetry.git_command_ms(Ext::Telemetry::Command::UNSHALLOW, duration_ms)
+
+ res
rescue => e
log_failure(e, "git unshallow")
+ telemetry_track_error(e, Ext::Telemetry::Command::UNSHALLOW)
nil
end
# makes .exec_git_command private to make sure that this method
# is not called from outside of this module with insecure parameters
@@ -207,11 +282,16 @@
retry_count -= 1
end
end
if status.nil? || !status.success?
- raise "Failed to run git command [#{cmd}] with input [#{stdin}] and output [#{out}]"
+ raise GitCommandExecutionError.new(
+ "Failed to run git command [#{cmd}] with input [#{stdin}] and output [#{out}]",
+ output: out,
+ command: cmd,
+ status: status
+ )
end
# Sometimes Encoding.default_external is somehow set to US-ASCII which breaks
# commit messages with UTF-8 characters like emojis
# We force output's encoding to be UTF-8 in this case
@@ -228,9 +308,20 @@
def log_failure(e, action)
Datadog.logger.debug(
"Unable to perform #{action}: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
)
+ end
+
+ def telemetry_track_error(e, command)
+ case e
+ when Errno::ENOENT
+ Telemetry.git_command_errors(command, executable_missing: true)
+ when GitCommandExecutionError
+ Telemetry.git_command_errors(command, exit_code: e.status&.to_i)
+ else
+ Telemetry.git_command_errors(command, exit_code: -9000)
+ end
end
end
end
end
end