about summary refs log tree commit diff
path: root/main/civisibility/utils/git.go
diff options
context:
space:
mode:
Diffstat (limited to 'main/civisibility/utils/git.go')
-rw-r--r--main/civisibility/utils/git.go104
1 files changed, 104 insertions, 0 deletions
diff --git a/main/civisibility/utils/git.go b/main/civisibility/utils/git.go
new file mode 100644
index 0000000..fb62a37
--- /dev/null
+++ b/main/civisibility/utils/git.go
@@ -0,0 +1,104 @@
+// Unless explicitly stated otherwise all files in this repository are licensed
+// under the Apache License Version 2.0.
+// This product includes software developed at Datadog (https://www.datadoghq.com/).
+// Copyright 2024 Datadog, Inc.
+
+package utils
+
+import (
+	"errors"
+	"os/exec"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// localGitData holds various pieces of information about the local Git repository,
+// including the source root, repository URL, branch, commit SHA, author and committer details, and commit message.
+type localGitData struct {
+	SourceRoot     string
+	RepositoryURL  string
+	Branch         string
+	CommitSha      string
+	AuthorDate     time.Time
+	AuthorName     string
+	AuthorEmail    string
+	CommitterDate  time.Time
+	CommitterName  string
+	CommitterEmail string
+	CommitMessage  string
+}
+
+// regexpSensitiveInfo is a regular expression used to match and filter out sensitive information from URLs.
+var regexpSensitiveInfo = regexp.MustCompile("(https?://|ssh?://)[^/]*@")
+
+// getLocalGitData retrieves information about the local Git repository from the current HEAD.
+// It gathers details such as the repository URL, current branch, latest commit SHA, author and committer details, and commit message.
+//
+// Returns:
+//
+//	A localGitData struct populated with the retrieved Git data.
+//	An error if any Git command fails or the retrieved data is incomplete.
+func getLocalGitData() (localGitData, error) {
+	gitData := localGitData{}
+
+	// Extract the absolute path to the Git directory
+	out, err := exec.Command("git", "rev-parse", "--absolute-git-dir").Output()
+	if err == nil {
+		gitData.SourceRoot = strings.ReplaceAll(strings.Trim(string(out), "\n"), ".git", "")
+	}
+
+	// Extract the repository URL
+	out, err = exec.Command("git", "ls-remote", "--get-url").Output()
+	if err == nil {
+		gitData.RepositoryURL = filterSensitiveInfo(strings.Trim(string(out), "\n"))
+	}
+
+	// Extract the current branch name
+	out, err = exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output()
+	if err == nil {
+		gitData.Branch = strings.Trim(string(out), "\n")
+	}
+
+	// Get commit details from the latest commit using git log (git log -1 --pretty='%H","%aI","%an","%ae","%cI","%cn","%ce","%B')
+	out, err = exec.Command("git", "log", "-1", "--pretty=%H\",\"%at\",\"%an\",\"%ae\",\"%ct\",\"%cn\",\"%ce\",\"%B").Output()
+	if err != nil {
+		return gitData, err
+	}
+
+	// Split the output into individual components
+	outArray := strings.Split(string(out), "\",\"")
+	if len(outArray) < 8 {
+		return gitData, errors.New("git log failed")
+	}
+
+	// Parse author and committer dates from Unix timestamp
+	authorUnixDate, _ := strconv.ParseInt(outArray[1], 10, 64)
+	committerUnixDate, _ := strconv.ParseInt(outArray[4], 10, 64)
+
+	// Populate the localGitData struct with the parsed information
+	gitData.CommitSha = outArray[0]
+	gitData.AuthorDate = time.Unix(authorUnixDate, 0)
+	gitData.AuthorName = outArray[2]
+	gitData.AuthorEmail = outArray[3]
+	gitData.CommitterDate = time.Unix(committerUnixDate, 0)
+	gitData.CommitterName = outArray[5]
+	gitData.CommitterEmail = outArray[6]
+	gitData.CommitMessage = strings.Trim(outArray[7], "\n")
+	return gitData, nil
+}
+
+// filterSensitiveInfo removes sensitive information from a given URL using a regular expression.
+// It replaces the user credentials part of the URL (if present) with an empty string.
+//
+// Parameters:
+//
+//	url - The URL string from which sensitive information should be filtered out.
+//
+// Returns:
+//
+//	The sanitized URL string with sensitive information removed.
+func filterSensitiveInfo(url string) string {
+	return string(regexpSensitiveInfo.ReplaceAll([]byte(url), []byte("$1"))[:])
+}