diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java index 3fc0eb482cc..ec6ffb74885 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java @@ -6,7 +6,6 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfoProvider; -import datadog.trace.api.git.PersonInfo; import datadog.trace.civisibility.ci.CIInfo; import datadog.trace.civisibility.ci.CIProviderInfo; import datadog.trace.civisibility.ci.CITagsProvider; @@ -127,23 +126,11 @@ static PullRequestInfo buildPullRequestInfo( // complete with CI vars if user didn't provide all information PullRequestInfo ciInfo = PullRequestInfo.merge(userInfo, ciProviderInfo.buildPullRequestInfo()); - if (Strings.isNotBlank(ciInfo.getGitCommitHead().getSha())) { + String headSha = ciInfo.getHeadCommit().getSha(); + if (Strings.isNotBlank(headSha)) { // if head sha present try to populate author, committer and message info through git client try { - gitRepoUnshallow.unshallow(true); - String headSha = ciInfo.getGitCommitHead().getSha(); - PersonInfo authorInfo = - new PersonInfo( - gitClient.getAuthorName(headSha), - gitClient.getAuthorEmail(headSha), - gitClient.getAuthorDate(headSha)); - PersonInfo committerInfo = - new PersonInfo( - gitClient.getCommitterName(headSha), - gitClient.getCommitterEmail(headSha), - gitClient.getCommitterDate(headSha)); - CommitInfo commitInfo = - new CommitInfo(headSha, authorInfo, committerInfo, gitClient.getFullMessage(headSha)); + CommitInfo commitInfo = gitClient.getCommitInfo(headSha, true); return PullRequestInfo.merge(ciInfo, new PullRequestInfo(null, null, commitInfo, null)); } catch (Exception ignored) { } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CITagsProvider.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CITagsProvider.java index a7d7bd0ccdc..c3d2aae75f5 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CITagsProvider.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CITagsProvider.java @@ -140,48 +140,47 @@ public CITagsBuilder withPullRequestBaseBranchSha(final PullRequestInfo pullRequ } public CITagsBuilder withGitCommitHeadSha(final PullRequestInfo pullRequestInfo) { - return putTagValue(Tags.GIT_COMMIT_HEAD_SHA, pullRequestInfo.getGitCommitHead().getSha()); + return putTagValue(Tags.GIT_COMMIT_HEAD_SHA, pullRequestInfo.getHeadCommit().getSha()); } public CITagsBuilder withGitCommitHeadAuthorName(final PullRequestInfo pullRequestInfo) { return putTagValue( - Tags.GIT_COMMIT_HEAD_AUTHOR_NAME, - pullRequestInfo.getGitCommitHead().getAuthor().getName()); + Tags.GIT_COMMIT_HEAD_AUTHOR_NAME, pullRequestInfo.getHeadCommit().getAuthor().getName()); } public CITagsBuilder withGitCommitHeadAuthorEmail(final PullRequestInfo pullRequestInfo) { return putTagValue( Tags.GIT_COMMIT_HEAD_AUTHOR_EMAIL, - pullRequestInfo.getGitCommitHead().getAuthor().getEmail()); + pullRequestInfo.getHeadCommit().getAuthor().getEmail()); } public CITagsBuilder withGitCommitHeadAuthorDate(final PullRequestInfo pullRequestInfo) { return putTagValue( Tags.GIT_COMMIT_HEAD_AUTHOR_DATE, - pullRequestInfo.getGitCommitHead().getAuthor().getIso8601Date()); + pullRequestInfo.getHeadCommit().getAuthor().getIso8601Date()); } public CITagsBuilder withGitCommitHeadCommitterName(final PullRequestInfo pullRequestInfo) { return putTagValue( Tags.GIT_COMMIT_HEAD_COMMITTER_NAME, - pullRequestInfo.getGitCommitHead().getCommitter().getName()); + pullRequestInfo.getHeadCommit().getCommitter().getName()); } public CITagsBuilder withGitCommitHeadCommitterEmail(final PullRequestInfo pullRequestInfo) { return putTagValue( Tags.GIT_COMMIT_HEAD_COMMITTER_EMAIL, - pullRequestInfo.getGitCommitHead().getCommitter().getEmail()); + pullRequestInfo.getHeadCommit().getCommitter().getEmail()); } public CITagsBuilder withGitCommitHeadCommitterDate(final PullRequestInfo pullRequestInfo) { return putTagValue( Tags.GIT_COMMIT_HEAD_COMMITTER_DATE, - pullRequestInfo.getGitCommitHead().getCommitter().getIso8601Date()); + pullRequestInfo.getHeadCommit().getCommitter().getIso8601Date()); } public CITagsBuilder withGitCommitHeadMessage(final PullRequestInfo pullRequestInfo) { return putTagValue( - Tags.GIT_COMMIT_HEAD_MESSAGE, pullRequestInfo.getGitCommitHead().getFullMessage()); + Tags.GIT_COMMIT_HEAD_MESSAGE, pullRequestInfo.getHeadCommit().getFullMessage()); } public CITagsBuilder withPullRequestNumber(final PullRequestInfo pullRequestInfo) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java index 0be6c3e0b70..7077ad17bbf 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java @@ -109,6 +109,7 @@ public PullRequestInfo buildPullRequestInfo() { String baseSha = null; String headSha = null; + String prNumber = null; Map pullRequest = (Map) eventJson.get("pull_request"); if (pullRequest != null) { @@ -121,9 +122,14 @@ public PullRequestInfo buildPullRequestInfo() { if (base != null) { baseSha = (String) base.get("sha"); } + + Double number = (Double) pullRequest.get("number"); + if (number != null) { + prNumber = String.valueOf(number.intValue()); + } } - return new PullRequestInfo(baseRef, baseSha, new CommitInfo(headSha), null); + return new PullRequestInfo(baseRef, baseSha, new CommitInfo(headSha), prNumber); } catch (Exception e) { LOGGER.warn("Error while parsing GitHub event", e); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/PullRequestInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/PullRequestInfo.java index f58151c08d9..75a18d3ebb2 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/PullRequestInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/PullRequestInfo.java @@ -12,17 +12,17 @@ public class PullRequestInfo { private final String pullRequestBaseBranch; private final String pullRequestBaseBranchSha; - @Nonnull private final CommitInfo gitCommitHead; + @Nonnull private final CommitInfo headCommit; private final String pullRequestNumber; public PullRequestInfo( String pullRequestBaseBranch, String pullRequestBaseBranchSha, - @Nonnull CommitInfo gitCommitHead, + @Nonnull CommitInfo headCommit, String pullRequestNumber) { this.pullRequestBaseBranch = pullRequestBaseBranch; this.pullRequestBaseBranchSha = pullRequestBaseBranchSha; - this.gitCommitHead = gitCommitHead; + this.headCommit = headCommit; this.pullRequestNumber = pullRequestNumber; } @@ -35,8 +35,8 @@ public String getPullRequestBaseBranchSha() { } @Nonnull - public CommitInfo getGitCommitHead() { - return gitCommitHead; + public CommitInfo getHeadCommit() { + return headCommit; } public String getPullRequestNumber() { @@ -46,14 +46,14 @@ public String getPullRequestNumber() { public boolean isEmpty() { return Strings.isBlank(pullRequestBaseBranch) && Strings.isBlank(pullRequestBaseBranchSha) - && gitCommitHead.isEmpty() + && headCommit.isEmpty() && Strings.isBlank(pullRequestNumber); } public boolean isComplete() { return Strings.isNotBlank(pullRequestBaseBranch) && Strings.isNotBlank(pullRequestBaseBranchSha) - && gitCommitHead.isComplete() + && headCommit.isComplete() && Strings.isNotBlank(pullRequestNumber); } @@ -72,7 +72,7 @@ public static PullRequestInfo merge(PullRequestInfo info, PullRequestInfo fallba Strings.isNotBlank(info.pullRequestBaseBranchSha) ? info.pullRequestBaseBranchSha : fallback.pullRequestBaseBranchSha, - CommitInfo.merge(info.gitCommitHead, fallback.gitCommitHead), + CommitInfo.merge(info.headCommit, fallback.headCommit), Strings.isNotBlank(info.pullRequestNumber) ? info.pullRequestNumber : fallback.pullRequestNumber); @@ -89,14 +89,14 @@ public boolean equals(Object o) { PullRequestInfo that = (PullRequestInfo) o; return Objects.equals(pullRequestBaseBranch, that.pullRequestBaseBranch) && Objects.equals(pullRequestBaseBranchSha, that.pullRequestBaseBranchSha) - && Objects.equals(gitCommitHead, that.gitCommitHead) + && Objects.equals(headCommit, that.headCommit) && Objects.equals(pullRequestNumber, that.pullRequestNumber); } @Override public int hashCode() { return Objects.hash( - pullRequestBaseBranch, pullRequestBaseBranchSha, gitCommitHead, pullRequestNumber); + pullRequestBaseBranch, pullRequestBaseBranchSha, headCommit, pullRequestNumber); } @Override @@ -108,8 +108,8 @@ public String toString() { + ", baseSHA='" + pullRequestBaseBranchSha + '\'' - + ", commitSHA='" - + gitCommitHead + + ", headCommit='" + + headCommit + '\'' + ", prNumber='" + pullRequestNumber diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java index 3a2855ada83..4382931defc 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java @@ -396,12 +396,12 @@ private Map>> getTestManagementTest return Collections.emptyMap(); } try { - if (Strings.isNotBlank(pullRequestInfo.getGitCommitHead().getSha()) - && Strings.isNotBlank(pullRequestInfo.getGitCommitHead().getFullMessage())) { + if (Strings.isNotBlank(pullRequestInfo.getHeadCommit().getSha()) + && Strings.isNotBlank(pullRequestInfo.getHeadCommit().getFullMessage())) { return configurationApi.getTestManagementTestsByModule( tracerEnvironment, - pullRequestInfo.getGitCommitHead().getSha(), - pullRequestInfo.getGitCommitHead().getFullMessage()); + pullRequestInfo.getHeadCommit().getSha(), + pullRequestInfo.getHeadCommit().getFullMessage()); } else { return configurationApi.getTestManagementTestsByModule( tracerEnvironment, tracerEnvironment.getSha(), tracerEnvironment.getCommitMessage()); @@ -421,7 +421,7 @@ private Diff getPullRequestDiff(boolean impactedTestsDetectionEnabled, String de try { if (repositoryRoot != null) { // ensure repo is not shallow before attempting to get git diff - gitRepoUnshallow.unshallow(false); + gitRepoUnshallow.unshallow(); String baseCommitSha = pullRequestInfo.getPullRequestBaseBranchSha(); if (baseCommitSha == null) { @@ -429,8 +429,7 @@ private Diff getPullRequestDiff(boolean impactedTestsDetectionEnabled, String de gitClient.getBaseCommitSha(pullRequestInfo.getPullRequestBaseBranch(), defaultBranch); } - Diff diff = - gitClient.getGitDiff(baseCommitSha, pullRequestInfo.getGitCommitHead().getSha()); + Diff diff = gitClient.getGitDiff(baseCommitSha, pullRequestInfo.getHeadCommit().getSha()); if (diff != null) { return diff; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/GitClientGitInfoBuilder.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/GitClientGitInfoBuilder.java index 7553cf40318..a12646a8f67 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/GitClientGitInfoBuilder.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/GitClientGitInfoBuilder.java @@ -6,7 +6,6 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.GitInfoBuilder; -import datadog.trace.api.git.PersonInfo; import datadog.trace.civisibility.git.tree.GitClient; import java.util.List; import javax.annotation.Nullable; @@ -39,20 +38,7 @@ public GitInfo build(@Nullable String repositoryPath) { List tags = gitClient.getTags(GitClient.HEAD); String tag = !tags.isEmpty() ? tags.iterator().next() : null; - String currentCommitSha = gitClient.getSha(GitClient.HEAD); - String fullMessage = gitClient.getFullMessage(GitClient.HEAD); - - String authorName = gitClient.getAuthorName(GitClient.HEAD); - String authorEmail = gitClient.getAuthorEmail(GitClient.HEAD); - String authorDate = gitClient.getAuthorDate(GitClient.HEAD); - PersonInfo author = new PersonInfo(authorName, authorEmail, authorDate); - - String committerName = gitClient.getCommitterName(GitClient.HEAD); - String committerEmail = gitClient.getCommitterEmail(GitClient.HEAD); - String committerDate = gitClient.getCommitterDate(GitClient.HEAD); - PersonInfo committer = new PersonInfo(committerName, committerEmail, committerDate); - - CommitInfo commitInfo = new CommitInfo(currentCommitSha, author, committer, fullMessage); + CommitInfo commitInfo = gitClient.getCommitInfo(GitClient.HEAD, false); return new GitInfo(remoteUrl, branch, tag, commitInfo); } catch (Exception e) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java index b427a26288a..140aa3999ab 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java @@ -1,5 +1,6 @@ package datadog.trace.civisibility.git.tree; +import datadog.trace.api.git.CommitInfo; import datadog.trace.civisibility.diff.LineDiff; import java.io.IOException; import java.nio.file.Path; @@ -16,7 +17,7 @@ public interface GitClient { boolean isShallow() throws IOException, TimeoutException, InterruptedException; - void unshallow(@Nullable String remoteCommitReference, boolean parentOnly) + void unshallow(@Nullable String remoteCommitReference) throws IOException, TimeoutException, InterruptedException; @Nullable @@ -40,28 +41,10 @@ void unshallow(@Nullable String remoteCommitReference, boolean parentOnly) @Nullable String getSha(String reference) throws IOException, TimeoutException, InterruptedException; - @Nullable - String getFullMessage(String commit) throws IOException, TimeoutException, InterruptedException; - - @Nullable - String getAuthorName(String commit) throws IOException, TimeoutException, InterruptedException; - - @Nullable - String getAuthorEmail(String commit) throws IOException, TimeoutException, InterruptedException; - - @Nullable - String getAuthorDate(String commit) throws IOException, TimeoutException, InterruptedException; - - @Nullable - String getCommitterName(String commit) throws IOException, TimeoutException, InterruptedException; - - @Nullable - String getCommitterEmail(String commit) + @Nonnull + CommitInfo getCommitInfo(String commit, boolean fetchIfNotPresent) throws IOException, TimeoutException, InterruptedException; - @Nullable - String getCommitterDate(String commit) throws IOException, TimeoutException, InterruptedException; - @Nonnull List getLatestCommits() throws IOException, TimeoutException, InterruptedException; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitDataUploaderImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitDataUploaderImpl.java index 4878f7cf8af..5cbc46a51c9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitDataUploaderImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitDataUploaderImpl.java @@ -91,7 +91,7 @@ private void uploadGitData() { LOGGER.debug("Starting git data upload, {}", gitClient); if (!config.isCiVisibilityGitUnshallowDefer()) { - gitRepoUnshallow.unshallow(false); + gitRepoUnshallow.unshallow(); } GitInfo gitInfo = gitInfoProvider.getGitInfo(repoRoot); @@ -112,7 +112,7 @@ private void uploadGitData() { return; } - if (config.isCiVisibilityGitUnshallowDefer() && gitRepoUnshallow.unshallow(false)) { + if (config.isCiVisibilityGitUnshallowDefer() && gitRepoUnshallow.unshallow()) { latestCommits = gitClient.getLatestCommits(); commitsToSkip = gitDataApi.searchCommits(remoteUrl, latestCommits); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitRepoUnshallow.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitRepoUnshallow.java index f9dc3f28750..489e2a4d377 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitRepoUnshallow.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitRepoUnshallow.java @@ -19,7 +19,7 @@ public GitRepoUnshallow(Config config, GitClient gitClient) { this.gitClient = gitClient; } - public synchronized boolean unshallow(boolean parentOnly) + public synchronized boolean unshallow() throws IOException, InterruptedException, TimeoutException { if (!config.isCiVisibilityGitUnshallowEnabled() || !gitClient.isShallow()) { return false; @@ -27,7 +27,7 @@ public synchronized boolean unshallow(boolean parentOnly) long unshallowStart = System.currentTimeMillis(); try { - gitClient.unshallow(GitClient.HEAD, parentOnly); + gitClient.unshallow(GitClient.HEAD); } catch (ShellCommandExecutor.ShellCommandFailedException e) { LOGGER.debug( "Could not unshallow using HEAD - assuming HEAD points to a local commit that does not exist in the remote repo", @@ -36,12 +36,12 @@ public synchronized boolean unshallow(boolean parentOnly) try { String upstreamBranch = gitClient.getUpstreamBranchSha(); - gitClient.unshallow(upstreamBranch, parentOnly); + gitClient.unshallow(upstreamBranch); } catch (ShellCommandExecutor.ShellCommandFailedException e) { LOGGER.debug( "Could not unshallow using upstream branch - assuming currently checked out local branch does not track any remote branch", e); - gitClient.unshallow(null, parentOnly); + gitClient.unshallow(null); } LOGGER.debug("Repository unshallowing took {} ms", System.currentTimeMillis() - unshallowStart); return true; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java index 52f959ae9a5..0a77fb72163 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java @@ -1,5 +1,6 @@ package datadog.trace.civisibility.git.tree; +import datadog.trace.api.git.CommitInfo; import datadog.trace.civisibility.diff.LineDiff; import java.nio.file.Path; import java.util.Collection; @@ -20,7 +21,7 @@ public boolean isShallow() { } @Override - public void unshallow(@Nullable String remoteCommitReference, boolean parentOnly) { + public void unshallow(@Nullable String remoteCommitReference) { // no op } @@ -66,46 +67,10 @@ public String getSha(String reference) { return null; } - @Nullable - @Override - public String getFullMessage(String commit) { - return null; - } - - @Nullable - @Override - public String getAuthorName(String commit) { - return null; - } - - @Nullable - @Override - public String getAuthorEmail(String commit) { - return null; - } - - @Nullable - @Override - public String getAuthorDate(String commit) { - return null; - } - - @Nullable - @Override - public String getCommitterName(String commit) { - return null; - } - - @Nullable - @Override - public String getCommitterEmail(String commit) { - return null; - } - - @Nullable + @Nonnull @Override - public String getCommitterDate(String commit) { - return null; + public CommitInfo getCommitInfo(String commit, boolean fetchIfNotPresent) { + return CommitInfo.NOOP; } @Nonnull diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java index 45a73449268..f353b05c0b9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java @@ -6,7 +6,9 @@ import datadog.trace.api.civisibility.telemetry.CiVisibilityDistributionMetric; import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector; import datadog.trace.api.civisibility.telemetry.tag.Command; +import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitUtils; +import datadog.trace.api.git.PersonInfo; import datadog.trace.civisibility.diff.LineDiff; import datadog.trace.civisibility.utils.ShellCommandExecutor; import datadog.trace.util.Strings; @@ -43,6 +45,7 @@ public class ShellGitClient implements GitClient { Arrays.asList("release/", "hotfix/"); private static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); private static final String ORIGIN = "origin"; + private static final Pattern COMMIT_INFO_SPLIT = Pattern.compile("\",\""); private final CiVisibilityMetricCollector metricCollector; private final String repoRoot; @@ -126,55 +129,41 @@ public String getUpstreamBranchSha() throws IOException, TimeoutException, Inter * * @param remoteCommitReference The commit to fetch from the remote repository, so local repo will * be updated with this commit and its ancestors. If {@code null}, everything will be fetched. - * @param parentOnly If only the parent commit should be unshallowed or the full {@code - * latestCommitsSince} * @throws IOException If an error was encountered while writing command input or reading output * @throws TimeoutException If timeout was reached while waiting for Git command to finish * @throws InterruptedException If current thread was interrupted while waiting for Git command to * finish */ @Override - public void unshallow(@Nullable String remoteCommitReference, boolean parentOnly) + public void unshallow(@Nullable String remoteCommitReference) throws IOException, TimeoutException, InterruptedException { executeCommand( Command.UNSHALLOW, () -> { - String remote = - commandExecutor - .executeCommand( - IOUtils::readFully, - "git", - "config", - "--default", - "origin", - "--get", - "clone.defaultRemoteName") - .trim(); + String remote = getRemoteName(); // refetch data from the server for the given period of time - String depth = - parentOnly ? "--deepen=1" : String.format("--shallow-since='%s'", latestCommitsSince); if (remoteCommitReference != null && GitUtils.isValidRef(remoteCommitReference)) { - String headSha = getSha(remoteCommitReference); + String commitSha = getSha(remoteCommitReference); commandExecutor.executeCommand( ShellCommandExecutor.OutputParser.IGNORE, "git", "fetch", - depth, "--update-shallow", "--filter=blob:none", "--recurse-submodules=no", + String.format("--shallow-since='%s'", latestCommitsSince), remote, - headSha); + commitSha); } else { commandExecutor.executeCommand( ShellCommandExecutor.OutputParser.IGNORE, "git", "fetch", - depth, "--update-shallow", "--filter=blob:none", "--recurse-submodules=no", + String.format("--shallow-since='%s'", latestCommitsSince), remote); } @@ -324,179 +313,108 @@ public String getSha(String reference) .trim()); } - /** - * Returns full message of the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return full message of the provided commit - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getFullMessage(String commit) + /** Checks whether the provided reference object is present or not. */ + private boolean isCommitPresent(String commitReference) throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; + if (GitUtils.isNotValidCommit(commitReference)) { + return false; } return executeCommand( Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%B", commit) - .trim()); - } - - /** - * Returns author name for the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return author name for the provided commit - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getAuthorName(String commit) - throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; - } - return executeCommand( - Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%an", commit) - .trim()); + () -> { + try { + commandExecutor.executeCommand( + ShellCommandExecutor.OutputParser.IGNORE, + "git", + "cat-file", + "-e", + commitReference + "^{commit}"); + return true; + } catch (ShellCommandExecutor.ShellCommandFailedException ignored) { + return false; + } + }); } - /** - * Returns author email for the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return author email for the provided commit - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getAuthorEmail(String commit) + /** Fetches provided commit object from the server. */ + private void fetchCommit(String remoteCommitReference) throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; + if (GitUtils.isNotValidCommit(remoteCommitReference)) { + return; } - return executeCommand( - Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%ae", commit) - .trim()); - } + executeCommand( + Command.FETCH_COMMIT, + () -> { + String remote = getRemoteName(); + commandExecutor.executeCommand( + ShellCommandExecutor.OutputParser.IGNORE, + "git", + "fetch", + "--filter=blob:none", + "--recurse-submodules=no", + "--no-write-fetch-head", + remote, + remoteCommitReference); - /** - * Returns author date in strict ISO 8601 format for the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return author date in strict ISO 8601 format - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getAuthorDate(String commit) - throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; - } - return executeCommand( - Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%aI", commit) - .trim()); + return (Void) null; + }); } /** - * Returns committer name for the provided commit + * Returns commit information for the provided commit * * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return committer name for the provided commit + * @param fetchIfNotPresent If the commit should be fetched from server if not present locally + * @return commit info (sha, author info, committer info, full message) * @throws IOException If an error was encountered while writing command input or reading output * @throws TimeoutException If timeout was reached while waiting for Git command to finish * @throws InterruptedException If current thread was interrupted while waiting for Git command to * finish */ - @Nullable + @Nonnull @Override - public String getCommitterName(String commit) - throws IOException, TimeoutException, InterruptedException { + public CommitInfo getCommitInfo(String commit, boolean fetchIfNotPresent) + throws IOException, InterruptedException, TimeoutException { if (GitUtils.isNotValidCommit(commit)) { - return null; + return CommitInfo.NOOP; } - return executeCommand( - Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%cn", commit) - .trim()); - } - - /** - * Returns committer email for the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return committer email for the provided commit - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getCommitterEmail(String commit) - throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; + if (fetchIfNotPresent) { + boolean isPresent = isCommitPresent(commit); + if (!isPresent) { + fetchCommit(commit); + } } return executeCommand( Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%ce", commit) - .trim()); - } + () -> { + String info = ""; + try { + info = + commandExecutor + .executeCommand( + IOUtils::readFully, + "git", + "show", + commit, + "-s", + "--format=%H\",\"%an\",\"%ae\",\"%aI\",\"%cn\",\"%ce\",\"%cI\",\"%B") + .trim(); + } catch (ShellCommandExecutor.ShellCommandFailedException e) { + LOGGER.error("Failed to fetch commit info", e); + return CommitInfo.NOOP; + } - /** - * Returns committer date in strict ISO 8601 format for the provided commit - * - * @param commit Commit SHA or reference (HEAD, branch name, etc) to check - * @return committer date in strict ISO 8601 format - * @throws IOException If an error was encountered while writing command input or reading output - * @throws TimeoutException If timeout was reached while waiting for Git command to finish - * @throws InterruptedException If current thread was interrupted while waiting for Git command to - * finish - */ - @Nullable - @Override - public String getCommitterDate(String commit) - throws IOException, TimeoutException, InterruptedException { - if (GitUtils.isNotValidCommit(commit)) { - return null; - } - return executeCommand( - Command.OTHER, - () -> - commandExecutor - .executeCommand(IOUtils::readFully, "git", "log", "-n", "1", "--format=%cI", commit) - .trim()); + String[] fields = COMMIT_INFO_SPLIT.split(info); + if (fields.length < 8) { + LOGGER.error("Could not parse commit info: {}", info); + return CommitInfo.NOOP; + } + return new CommitInfo( + fields[0], + new PersonInfo(fields[1], fields[2], fields[3]), + new PersonInfo(fields[4], fields[5], fields[6]), + fields[7]); + }); } /** diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityRepoServicesTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityRepoServicesTest.groovy index a683da60369..a3ddb6f4f1e 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityRepoServicesTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityRepoServicesTest.groovy @@ -51,7 +51,7 @@ class CiVisibilityRepoServicesTest extends Specification { def environment = Stub(CiEnvironment) environment.get(Constants.DDCI_PULL_REQUEST_TARGET_SHA) >> "targetSha" - environment.get(Constants.DDCI_PULL_REQUEST_SOURCE_SHA) >> expectedInfo.getGitCommitHead().getSha() + environment.get(Constants.DDCI_PULL_REQUEST_SOURCE_SHA) >> expectedInfo.getHeadCommit().getSha() def repoUnshallow = Stub(GitRepoUnshallow) def ciProviderInfo = Stub(CIProviderInfo) @@ -59,13 +59,7 @@ class CiVisibilityRepoServicesTest extends Specification { def gitClient = Stub(GitClient) gitClient.getMergeBase("targetSha", "sourceSha") >> expectedInfo.getPullRequestBaseBranchSha() - gitClient.getAuthorName("sourceSha") >> expectedInfo.getGitCommitHead().getAuthor().getName() - gitClient.getAuthorEmail("sourceSha") >> expectedInfo.getGitCommitHead().getAuthor().getEmail() - gitClient.getAuthorDate("sourceSha") >> expectedInfo.getGitCommitHead().getAuthor().getIso8601Date() - gitClient.getCommitterName("sourceSha") >> expectedInfo.getGitCommitHead().getCommitter().getName() - gitClient.getCommitterEmail("sourceSha") >> expectedInfo.getGitCommitHead().getCommitter().getEmail() - gitClient.getCommitterDate("sourceSha") >> expectedInfo.getGitCommitHead().getCommitter().getIso8601Date() - gitClient.getFullMessage("sourceSha") >> expectedInfo.getGitCommitHead().getFullMessage() + gitClient.getCommitInfo("sourceSha", true) >> expectedInfo.getHeadCommit() expect: CiVisibilityRepoServices.buildPullRequestInfo(config, environment, ciProviderInfo, gitClient, repoUnshallow) == expectedInfo diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy index 6ffdf46166e..0be0b908c7b 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy @@ -42,6 +42,7 @@ class GithubActionsInfoTest extends CITagsProviderTest { then: pullRequestInfo.getPullRequestBaseBranch() == "base-ref" pullRequestInfo.getPullRequestBaseBranchSha() == "52e0974c74d41160a03d59ddc73bb9f5adab054b" - pullRequestInfo.getGitCommitHead().getSha() == "df289512a51123083a8e6931dd6f57bb3883d4c4" + pullRequestInfo.getHeadCommit().getSha() == "df289512a51123083a8e6931dd6f57bb3883d4c4" + pullRequestInfo.getPullRequestNumber() == "1" } } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/tree/GitClientTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/tree/GitClientTest.groovy index ee3fed3b9d4..479c3ce922c 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/tree/GitClientTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/tree/GitClientTest.groovy @@ -3,6 +3,7 @@ package datadog.trace.civisibility.git.tree import static datadog.trace.civisibility.TestUtils.lines import datadog.communication.util.IOUtils +import datadog.trace.api.git.CommitInfo import datadog.trace.civisibility.git.GitObject import datadog.trace.civisibility.git.pack.V2PackGitInfoExtractor import datadog.trace.civisibility.telemetry.CiVisibilityMetricCollectorImpl @@ -70,7 +71,7 @@ class GitClientTest extends Specification { upstreamBranch == "98b944cc44f18bfb78e3021de2999cdcda8efdf6" } - def "test unshallow: sha-#remoteSha parentOnly-#parentOnly"() { + def "test unshallow: sha-#remoteSha"() { given: givenGitRepo("ci/git/shallow/git") @@ -84,20 +85,16 @@ class GitClientTest extends Specification { commits.size() == 1 when: - gitClient.unshallow(remoteSha, parentOnly) + gitClient.unshallow(remoteSha) shallow = gitClient.isShallow() commits = gitClient.getLatestCommits() then: - shallow == isShallow - commits.size() == numCommits + !shallow + commits.size() == 10 where: - remoteSha | parentOnly | isShallow | numCommits - GitClient.HEAD | false | false | 10 - null | false | false | 10 - GitClient.HEAD | true | true | 2 - null | true | true | 2 + remoteSha << [GitClient.HEAD, null] } def "test get git folder"() { @@ -160,91 +157,30 @@ class GitClientTest extends Specification { sha == "5b6f3a6dab5972d73a56dff737bd08d995255c08" } - def "test get full message"() { - given: - givenGitRepo() - - when: - def gitClient = givenGitClient() - def message = gitClient.getFullMessage(GitClient.HEAD) - - then: - message == "Adding Git information to test spans (#1242)\n\n" + - "* Initial basic GitInfo implementation.\r\n\r\n" + - "* Adds Author, Committer and Message git parser.\r\n\r\n" + - "* Changes based on the review." - } - - def "test get author name"() { + def "test get commit info with fetching"() { given: - givenGitRepo() - - when: - def gitClient = givenGitClient() - def authorName = gitClient.getAuthorName(GitClient.HEAD) - - then: - authorName == "Tony Redondo" - } - - def "test get author email"() { - given: - givenGitRepo() - - when: - def gitClient = givenGitClient() - def authorEmail = gitClient.getAuthorEmail(GitClient.HEAD) - - then: - authorEmail == "tony.redondo@datadoghq.com" - } - - def "test get author date"() { - given: - givenGitRepo() - - when: - def gitClient = givenGitClient() - def authorDate = gitClient.getAuthorDate(GitClient.HEAD) - - then: - authorDate == "2021-02-26T19:32:13+01:00" - } - - def "test get committer name"() { - given: - givenGitRepo() - - when: - def gitClient = givenGitClient() - def authorName = gitClient.getCommitterName(GitClient.HEAD) - - then: - authorName == "GitHub" - } - - def "test get committer email"() { - given: - givenGitRepo() + givenGitRepo("ci/git/shallow/git") when: + def commit = "f4377e97f10c2d58696192b170b2fef2a8464b04" def gitClient = givenGitClient() - def authorEmail = gitClient.getCommitterEmail(GitClient.HEAD) + def commitInfo = gitClient.getCommitInfo(commit, false) then: - authorEmail == "noreply@github.com" - } - - def "test get committer date"() { - given: - givenGitRepo() + commitInfo == CommitInfo.NOOP when: - def gitClient = givenGitClient() - def authorDate = gitClient.getCommitterDate(GitClient.HEAD) + commitInfo = gitClient.getCommitInfo(commit, true) then: - authorDate == "2021-02-26T19:32:13+01:00" + commitInfo.sha == commit + commitInfo.author.name == "sullis" + commitInfo.author.email == "github@seansullivan.com" + commitInfo.author.iso8601Date == "2023-05-30T07:07:35-07:00" + commitInfo.committer.name == "GitHub" + commitInfo.committer.email == "noreply@github.com" + commitInfo.committer.iso8601Date == "2023-05-30T07:07:35-07:00" + commitInfo.fullMessage == "brotli4j 1.12.0 (#1592)" } def "test get latest commits"() { diff --git a/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/Command.java b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/Command.java index 0413066d100..5ea133cb7e3 100644 --- a/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/Command.java +++ b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/Command.java @@ -13,6 +13,7 @@ public enum Command implements TagValue { PACK_OBJECTS, DIFF, BASE_COMMIT_SHA, + FETCH_COMMIT, OTHER; private final String s;