Skip to content

Commit

Permalink
Add GetCommits API (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
omerzi authored Aug 13, 2023
1 parent 0b1f383 commit e1ade55
Show file tree
Hide file tree
Showing 17 changed files with 434 additions and 58 deletions.
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 @@ -368,7 +368,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 @@ -379,6 +379,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 @@ -388,6 +389,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 @@ -468,34 +468,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 @@ -697,6 +712,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 @@ -310,7 +310,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 @@ -327,12 +327,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 @@ -345,7 +387,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 @@ -368,7 +410,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 @@ -548,6 +590,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

0 comments on commit e1ade55

Please sign in to comment.