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

Fix handle corrupted repos In BitBucket utils contributor-count (AST-76750) #980

Merged
merged 11 commits into from
Dec 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ func searchRepos(
*bitbucketServerToken,
)
if err != nil {
return nil, nil, nil, err
log.Printf("Skipping repository %s/%s: Repository is corrupted (error: %v)", project, repo, err)
Korjen97 marked this conversation as resolved.
Show resolved Hide resolved
continue
}
totalCommits = append(totalCommits, commits...)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package bitbucketserver

import (
"bytes"
"log"
"testing"

"github.com/checkmarx/ast-cli/internal/wrappers/mock"
"gotest.tools/assert"
)

func TestSearchReposWithCorruptedRepositories(t *testing.T) {
mockWrapper := mock.WrapperBitbucketServer{
CorruptedRepos: []string{"repo-2"},
}

var logOutput bytes.Buffer
log.SetOutput(&logOutput)
defer log.SetOutput(nil)

project := "mock-project"
repos := []string{"repo-1", "repo-2", "repo-3"}
token := "mock-token"

views, viewsUsers, err := mockWrapper.SearchRepos(project, repos, token)

assert.NilError(t, err, "SearchRepos should not return an error")

assert.Equal(t, len(views), 2, "Only valid repositories should be processed")
assert.Equal(t, views[0].Name, "mock-project/repo-1", "First repository name should match")
assert.Equal(t, views[1].Name, "mock-project/repo-3", "Second repository name should match")

assert.Equal(t, len(viewsUsers), 2, "Each repository should have 1 contributor")
assert.Equal(t, viewsUsers[0].Name, "mock-project/repo-1", "Contributor should match first repository")
assert.Equal(t, viewsUsers[1].Name, "mock-project/repo-3", "Contributor should match second repository")

logStr := logOutput.String()
assert.Assert(t, containsLog(logStr, "Skipping repository mock-project/repo-2: Repository is corrupted"), "Log should contain corrupted repository message")
assert.Assert(t, containsLog(logStr, "Processed repository mock-project/repo-1"), "Log should confirm successful processing of repo-1")
assert.Assert(t, containsLog(logStr, "Processed repository mock-project/repo-3"), "Log should confirm successful processing of repo-3")

t.Log("Captured Logs:")
t.Log(logStr)
}

func containsLog(logStr, expected string) bool {
return bytes.Contains([]byte(logStr), []byte(expected))
}
85 changes: 85 additions & 0 deletions internal/wrappers/mock/bitbucketServer-mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package mock

import (
"fmt"
"log"

"github.com/checkmarx/ast-cli/internal/wrappers/bitbucketserver"
"github.com/pkg/errors"
)

type WrapperBitbucketServer struct {
CorruptedRepos []string
}

type RepositoryView struct {
Name string `json:"name"`
UniqueContributors uint64 `json:"unique_contributors"`
}

type UserView struct {
Name string `json:"name"`
UniqueContributorsUsername string `json:"unique_contributors_username"`
}

func (m WrapperBitbucketServer) GetCommits(bitBucketURL, projectKey, repoSlug, bitBucketPassword string) ([]bitbucketserver.Commit, error) {
for _, corruptedRepo := range m.CorruptedRepos {
if repoSlug == corruptedRepo {
return nil, errors.New(fmt.Sprintf("repository %s is corrupted", repoSlug))
}
}
return []bitbucketserver.Commit{
{
Author: bitbucketserver.Author{Name: "Mock Author", Email: "mock-author@example.com"},
AuthorTimestamp: 1625078400000,
},
}, nil
}
func (m WrapperBitbucketServer) GetRepositories(bitBucketURL, projectKey, bitBucketPassword string) ([]bitbucketserver.Repo, error) {
return []bitbucketserver.Repo{
{Slug: "repo-1", Name: "Repository 1"},
{Slug: "repo-2", Name: "Repository 2"},
{Slug: "repo-3", Name: "Repository 3"},
}, nil
}
func (m WrapperBitbucketServer) GetProjects(bitBucketURL, bitBucketPassword string) ([]string, error) {
// Return mock projects
return []string{"project-1", "project-2"}, nil
}
func (m WrapperBitbucketServer) SearchRepos(
project string,
repos []string,
bitBucketToken string,
) ([]RepositoryView, []UserView, error) {
var views []RepositoryView
var viewsUsers []UserView
for _, repo := range repos {
_, err := m.GetCommits("mock-url", project, repo, bitBucketToken)
if err != nil {
log.Printf("Skipping repository %s/%s: Repository is corrupted (error: %v)", project, repo, err)
continue
}
log.Printf("Processed repository %s/%s", project, repo)

uniqueContributors := map[string]string{
"mock-email@example.com": "Mock Author",
}
views = append(
views,
RepositoryView{
Name: fmt.Sprintf("%s/%s", project, repo),
UniqueContributors: uint64(len(uniqueContributors)),
},
)
for email, name := range uniqueContributors {
viewsUsers = append(
viewsUsers,
UserView{
Name: fmt.Sprintf("%s/%s", project, repo),
UniqueContributorsUsername: fmt.Sprintf("%s - %s", name, email),
},
)
}
}
return views, viewsUsers, nil
}
Loading