Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GetCommits API #110

Merged
merged 8 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 50 additions & 17 deletions vcsclient/azurerepos.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,33 +326,66 @@ func (client *AzureReposClient) GetPullRequestByID(ctx context.Context, owner, r

// GetLatestCommit on Azure Repos
func (client *AzureReposClient) GetLatestCommit(ctx context.Context, _, repository, branch string) (CommitInfo, error) {
azureReposGitClient, err := client.buildAzureReposClient(ctx)
commitsInfo, err := client.GetCommits(ctx, "", repository, branch)
if err != nil {
return CommitInfo{}, err
}
latestCommitInfo := CommitInfo{}

var latestCommit CommitInfo
if len(commitsInfo) > 0 {
latestCommit = commitsInfo[0]
}
return latestCommit, nil
}

// GetCommits on Azure Repos
func (client *AzureReposClient) GetCommits(ctx context.Context, _, repository, branch string) ([]CommitInfo, error) {
azureReposGitClient, err := client.buildAzureReposClient(ctx)
if err != nil {
return nil, err
}
commits, err := azureReposGitClient.GetCommits(ctx, git.GetCommitsArgs{
RepositoryId: &repository,
Project: &client.vcsInfo.Project,
SearchCriteria: &git.GitQueryCommitsCriteria{ItemVersion: &git.GitVersionDescriptor{Version: &branch, VersionType: &git.GitVersionTypeValues.Branch}},
})
if err != nil {
return latestCommitInfo, err
}
if len(*commits) > 0 {
// The latest commit is the first in the list
latestCommit := (*commits)[0]
latestCommitInfo = CommitInfo{
Hash: vcsutils.DefaultIfNotNil(latestCommit.CommitId),
AuthorName: vcsutils.DefaultIfNotNil(latestCommit.Author.Name),
CommitterName: vcsutils.DefaultIfNotNil(latestCommit.Committer.Name),
Url: vcsutils.DefaultIfNotNil(latestCommit.Url),
Timestamp: latestCommit.Committer.Date.Time.Unix(),
Message: vcsutils.DefaultIfNotNil(latestCommit.Comment),
ParentHashes: vcsutils.DefaultIfNotNil(latestCommit.Parents),
}
return nil, err
}
if commits == nil {
return nil, fmt.Errorf("could not retrieve commits for <%s/%s>", repository, branch)
}

var commitsInfo []CommitInfo
for _, commit := range *commits {
commitInfo := mapAzureReposCommitsToCommitInfo(commit)
commitsInfo = append(commitsInfo, commitInfo)
}
return commitsInfo, nil
}

func mapAzureReposCommitsToCommitInfo(commit git.GitCommitRef) CommitInfo {
var authorName, authorEmail string
if commit.Author != nil {
authorName = vcsutils.DefaultIfNotNil(commit.Author.Name)
authorEmail = vcsutils.DefaultIfNotNil(commit.Author.Email)
}
var committerName string
var timestamp int64
if commit.Committer != nil {
committerName = vcsutils.DefaultIfNotNil(commit.Committer.Name)
timestamp = vcsutils.DefaultIfNotNil(commit.Committer.Date).Time.Unix()
}
return CommitInfo{
Hash: vcsutils.DefaultIfNotNil(commit.CommitId),
AuthorName: authorName,
CommitterName: committerName,
Url: vcsutils.DefaultIfNotNil(commit.Url),
Timestamp: timestamp,
Message: vcsutils.DefaultIfNotNil(commit.Comment),
ParentHashes: vcsutils.DefaultIfNotNil(commit.Parents),
AuthorEmail: authorEmail,
}
return latestCommitInfo, nil
}

func getUnsupportedInAzureError(functionName string) error {
Expand Down
47 changes: 46 additions & 1 deletion vcsclient/azurerepos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func TestAzureRepos_TestGetLatestCommit(t *testing.T) {
response, err := os.ReadFile(filepath.Join("testdata", "azurerepos", "commits.json"))
assert.NoError(t, err)

client, cleanUp := createServerAndClient(t, vcsutils.AzureRepos, true, response, "getLatestCommit", createAzureReposHandler)
client, cleanUp := createServerAndClient(t, vcsutils.AzureRepos, true, response, "getCommits", createAzureReposHandler)
defer cleanUp()

commit, err := client.GetLatestCommit(ctx, "", repo1, branch1)
Expand All @@ -351,6 +351,7 @@ func TestAzureRepos_TestGetLatestCommit(t *testing.T) {
Url: "https://dev.azure.com/testuser/0b8072c4-ad86-4edb-a8f2-06dbc07e3e2d/_apis/git/repositories/94c1dba8-d9d9-4600-94b4-1a51acb43220/commits/86d6919952702f9ab03bc95b45687f145a663de0",
Timestamp: 1667812601,
Message: "Updated package.json",
AuthorEmail: "testuser@jfrog.com",
})
assert.NoError(t, err)

Expand All @@ -360,6 +361,50 @@ func TestAzureRepos_TestGetLatestCommit(t *testing.T) {
assert.Error(t, err)
}

func TestAzureRepos_TestGetCommits(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "azurerepos", "commits.json"))
assert.NoError(t, err)

client, cleanUp := createServerAndClient(t, vcsutils.AzureRepos, true, response, "getCommits", createAzureReposHandler)
defer cleanUp()

commits, err := client.GetCommits(ctx, "", repo1, branch1)
assert.Equal(t, CommitInfo{
Hash: "86d6919952702f9ab03bc95b45687f145a663de0",
AuthorName: "Test User",
CommitterName: "Test User",
Url: "https://dev.azure.com/testuser/0b8072c4-ad86-4edb-a8f2-06dbc07e3e2d/_apis/git/repositories/94c1dba8-d9d9-4600-94b4-1a51acb43220/commits/86d6919952702f9ab03bc95b45687f145a663de0",
Timestamp: 1667812601,
Message: "Updated package.json",
AuthorEmail: "testuser@jfrog.com",
}, commits[0])
assert.Equal(t, CommitInfo{
Hash: "4aa8367809020c4e97af29e2b57f7528d5d27702",
AuthorName: "Test User",
CommitterName: "Test User",
Url: "https://dev.azure.com/testuser/0b8072c4-ad86-4edb-a8f2-06dbc07e3e2d/_apis/git/repositories/94c1dba8-d9d9-4600-94b4-1a51acb43220/commits/4aa8367809020c4e97af29e2b57f7528d5d27702",
Timestamp: 1667201343,
Message: "Set up CI with Azure Pipelines",
AuthorEmail: "testuser@jfrog.com",
}, commits[1])
assert.Equal(t, CommitInfo{
Hash: "3779104c35804e15b6fdf4fee303e717cd6c1352",
AuthorName: "Test User",
CommitterName: "Test User",
Url: "https://dev.azure.com/testuser/0b8072c4-ad86-4edb-a8f2-06dbc07e3e2d/_apis/git/repositories/94c1dba8-d9d9-4600-94b4-1a51acb43220/commits/3779104c35804e15b6fdf4fee303e717cd6c1352",
Timestamp: 1667201200,
Message: "first commit",
AuthorEmail: "testuser@jfrog.com",
}, commits[2])
assert.NoError(t, err)

badClient, cleanUp := createBadAzureReposClient(t, []byte{})
defer cleanUp()
_, err = badClient.GetCommits(ctx, "", repo1, branch1)
assert.Error(t, err)
}

func TestAzureReposClient_AddSshKeyToRepository(t *testing.T) {
ctx := context.Background()
client, cleanUp := createServerAndClient(t, vcsutils.AzureRepos, true, "", "getLatestCommit", createAzureReposHandler)
Expand Down
5 changes: 5 additions & 0 deletions vcsclient/bitbucketcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,11 @@ func (client *BitbucketCloudClient) GetLatestCommit(ctx context.Context, owner,
return CommitInfo{}, nil
}

// GetCommits on Bitbucket Cloud
func (client *BitbucketCloudClient) GetCommits(_ context.Context, _, _, _ string) ([]CommitInfo, error) {
return nil, errBitbucketGetCommitsNotSupported
}

// GetRepositoryInfo on Bitbucket cloud
func (client *BitbucketCloudClient) GetRepositoryInfo(ctx context.Context, owner, repository string) (RepositoryInfo, error) {
if err := validateParametersNotBlank(map[string]string{"owner": owner, "repository": repository}); err != nil {
Expand Down
15 changes: 15 additions & 0 deletions vcsclient/bitbucketcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,21 @@ func TestBitbucketCloud_GetLatestCommit(t *testing.T) {
}, result)
}

func TestBitbucketCloud_GetCommits(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketcloud", "commit_list_response.json"))
assert.NoError(t, err)

client, cleanUp := createServerAndClient(t, vcsutils.BitbucketCloud, true, response,
fmt.Sprintf("/repositories/%s/%s/commits/%s?pagelen=1", owner, repo1, "master"), createBitbucketCloudHandler)
defer cleanUp()

result, err := client.GetCommits(ctx, owner, repo1, "master")
assert.Error(t, err)
assert.Equal(t, errBitbucketGetCommitsNotSupported.Error(), err.Error())
assert.Nil(t, result)
}

func TestBitbucketCloud_GetLatestCommitNotFound(t *testing.T) {
ctx := context.Background()
response := []byte(`<!DOCTYPE html><html lang="en"></html>`)
Expand Down
1 change: 1 addition & 0 deletions vcsclient/bitbucketcommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var (
errLabelsNotSupported = errors.New("labels are not supported on Bitbucket")
errBitbucketCodeScanningNotSupported = errors.New("code scanning is not supported on Bitbucket")
errBitbucketDownloadFileFromRepoNotSupported = errors.New("download file from repo is currently not supported on Bitbucket")
errBitbucketGetCommitsNotSupported = errors.New("get commits is currently not supported on Bitbucket")
errBitbucketGetRepoEnvironmentInfoNotSupported = errors.New("get repository environment info is currently not supported on Bitbucket")
)

Expand Down
32 changes: 24 additions & 8 deletions vcsclient/bitbucketserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,34 +476,49 @@ type projectsResponse struct {

// GetLatestCommit on Bitbucket server
func (client *BitbucketServerClient) GetLatestCommit(ctx context.Context, owner, repository, branch string) (CommitInfo, error) {
commits, err := client.GetCommits(ctx, owner, repository, branch)
if err != nil {
return CommitInfo{}, err
}

latestCommit := CommitInfo{}
if len(commits) > 0 {
latestCommit = commits[0]
}
return latestCommit, nil
}

// GetCommits on Bitbucket server
func (client *BitbucketServerClient) GetCommits(ctx context.Context, owner, repository, branch string) ([]CommitInfo, error) {
err := validateParametersNotBlank(map[string]string{
"owner": owner,
"repository": repository,
"branch": branch,
})
if err != nil {
return CommitInfo{}, err
return nil, err
}

options := map[string]interface{}{
"limit": 1,
"limit": vcsutils.NumberOfCommitsToFetch,
"until": branch,
}
bitbucketClient := client.buildBitbucketClient(ctx)

apiResponse, err := bitbucketClient.GetCommits(owner, repository, options)
if err != nil {
return CommitInfo{}, err
return nil, err
}
commits, err := bitbucketv1.GetCommitsResponse(apiResponse)
if err != nil {
return CommitInfo{}, err
return nil, err
}
if len(commits) > 0 {
latestCommit := commits[0]
return client.mapBitbucketServerCommitToCommitInfo(latestCommit, owner, repository), nil
var commitsInfo []CommitInfo
for _, commit := range commits {
commitInfo := client.mapBitbucketServerCommitToCommitInfo(commit, owner, repository)
commitsInfo = append(commitsInfo, commitInfo)
}
return CommitInfo{}, nil
return commitsInfo, nil
}

// GetRepositoryInfo on Bitbucket server
Expand Down Expand Up @@ -705,6 +720,7 @@ func (client *BitbucketServerClient) mapBitbucketServerCommitToCommitInfo(commit
Timestamp: commit.CommitterTimestamp,
Message: commit.Message,
ParentHashes: parents,
AuthorEmail: commit.Author.EmailAddress,
}
}

Expand Down
49 changes: 46 additions & 3 deletions vcsclient/bitbucketserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func TestBitbucketServer_GetLatestCommit(t *testing.T) {
// limit=1 appears twice because it is added twice by: github.com/gfleury/go-bitbucket-v1@v0.0.0-20210826163055-dff2223adeac/default_api.go:3848
client, serverUrl, cleanUp := createServerWithUrlAndClientReturningStatus(t, vcsutils.BitbucketServer, false,
response,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=1&limit=1&until=master", owner, repo1),
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=50&limit=50&until=master", owner, repo1),
http.StatusOK, createBitbucketServerHandler)
defer cleanUp()

Expand All @@ -324,12 +324,54 @@ func TestBitbucketServer_GetLatestCommit(t *testing.T) {
Timestamp: 1548720847610,
Message: "More work on feature 1",
ParentHashes: []string{"abcdef0123abcdef4567abcdef8987abcdef6543", "qwerty0123abcdef4567abcdef8987abcdef6543"},
AuthorEmail: "charlie@example.com",
}, result)

_, err = createBadBitbucketServerClient(t).GetLatestCommit(ctx, owner, repo1, "master")
assert.Error(t, err)
}

func TestBitbucketServer_GetCommits(t *testing.T) {
ctx := context.Background()
response, err := os.ReadFile(filepath.Join("testdata", "bitbucketserver", "commit_list_response.json"))
assert.NoError(t, err)

client, serverUrl, cleanUp := createServerWithUrlAndClientReturningStatus(t, vcsutils.BitbucketServer, false,
response,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=50&limit=50&until=master", owner, repo1),
http.StatusOK, createBitbucketServerHandler)
defer cleanUp()

result, err := client.GetCommits(ctx, owner, repo1, "master")

assert.NoError(t, err)
expectedUrl := fmt.Sprintf("%s/rest/api/1.0/projects/jfrog/repos/repo-1"+
"/commits/def0123abcdef4567abcdef8987abcdef6543abc", serverUrl)
assert.Equal(t, CommitInfo{
Hash: "def0123abcdef4567abcdef8987abcdef6543abc",
AuthorName: "charlie",
CommitterName: "mark",
Url: expectedUrl,
Timestamp: 1548720847610,
Message: "More work on feature 1",
ParentHashes: []string{"abcdef0123abcdef4567abcdef8987abcdef6543", "qwerty0123abcdef4567abcdef8987abcdef6543"},
AuthorEmail: "charlie@example.com",
}, result[0])
assert.Equal(t, CommitInfo{
Hash: "def0123abcdef4567abcdef8987abcdef6543abc",
AuthorName: "marly",
CommitterName: "marly",
Url: expectedUrl,
Timestamp: 1548720847610,
Message: "More work on feature 2",
ParentHashes: []string{"abcdef0123abcdef4567abcdef8987abcdef6543", "qwerty0123abcdef4567abcdef8987abcdef6543"},
AuthorEmail: "marly@example.com",
}, result[1])

_, err = createBadBitbucketServerClient(t).GetCommits(ctx, owner, repo1, "master")
assert.Error(t, err)
}

func TestBitbucketServer_GetLatestCommitNotFound(t *testing.T) {
ctx := context.Background()
response := []byte(`{
Expand All @@ -342,7 +384,7 @@ func TestBitbucketServer_GetLatestCommitNotFound(t *testing.T) {
]
}`)
client, cleanUp := createServerAndClientReturningStatus(t, vcsutils.BitbucketServer, false, response,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=1&limit=1&until=master", owner, repo1),
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=50&limit=50&until=master", owner, repo1),
http.StatusNotFound, createBitbucketServerHandler)
defer cleanUp()

Expand All @@ -365,7 +407,7 @@ func TestBitbucketServer_GetLatestCommitUnknownBranch(t *testing.T) {
]
}`)
client, cleanUp := createServerAndClientReturningStatus(t, vcsutils.BitbucketServer, false, response,
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=1&limit=1&until=unknown", owner, repo1),
fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s/commits?limit=50&limit=50&until=unknown", owner, repo1),
http.StatusNotFound, createBitbucketServerHandler)
defer cleanUp()

Expand Down Expand Up @@ -545,6 +587,7 @@ func TestBitbucketServer_GetCommitBySha(t *testing.T) {
Timestamp: 1636089306104,
Message: "WIP on feature 1",
ParentHashes: []string{"bbcdef0123abcdef4567abcdef8987abcdef6543"},
AuthorEmail: "charlie@example.com",
}, result)

_, err = createBadBitbucketServerClient(t).GetCommitBySha(ctx, owner, repo1, sha)
Expand Down
Loading