Skip to content

Commit

Permalink
[#4244] Feature/GitLab MR Comments
Browse files Browse the repository at this point in the history
- Handle author and assocaited commits

Signed-off-by: Harold Wanyama <[email protected]>
  • Loading branch information
nickmango committed Dec 20, 2024
1 parent c515e62 commit f5fc5d0
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 77 deletions.
99 changes: 97 additions & 2 deletions cla-backend-go/gitlab_api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,27 @@ import (
goGitLab "github.com/xanzy/go-gitlab"
)

type GitLabClient interface {
GetMergeRequestCommits(projectID int, mergeID int, opts *goGitLab.GetMergeRequestCommitsOptions) ([]*goGitLab.Commit, error)
ListUsers(opts *goGitLab.ListUsersOptions) ([]*goGitLab.User, error)
SetCommitStatus(projectID int, commitSHA string, opts *goGitLab.SetCommitStatusOptions) error
GetProject(gitLabProjectID int, opts *goGitLab.GetProjectOptions) (*goGitLab.Project, error)
// EditProject(projectID int,)
ListGroupProjects(groupID int, opts *goGitLab.ListGroupProjectsOptions) ([]*goGitLab.Project, *goGitLab.Response, error)
ListGroupMembers(gid interface{}, opt *goGitLab.ListGroupMembersOptions) ([]*goGitLab.GroupMember, *goGitLab.Response, error)
CurrentUser() (*goGitLab.User, *goGitLab.Response, error)
ListUserProjects(user interface{}, opt *goGitLab.ListProjectsOptions) ([]*goGitLab.Project, *goGitLab.Response, error)
DeleteProjectHook(projectID, webhookID int) (*goGitLab.Response, error)
ListProjectHooks(projectID int, opts *goGitLab.ListProjectHooksOptions) ([]*goGitLab.ProjectHook, *goGitLab.Response, error)
AddProjectHook(projectID int, opts *goGitLab.AddProjectHookOptions) (*goGitLab.ProjectHook, *goGitLab.Response, error)
EditProjectHook(projectID, existingID int, opts *goGitLab.EditProjectHookOptions) (*goGitLab.ProjectHook, *goGitLab.Response, error)
}

// Client is the gitlab client
type GitLabClientWrapper struct {
gitlabClient *goGitLab.Client
}

// OauthSuccessResponse is success response from Gitlab
type OauthSuccessResponse struct {
AccessToken string `json:"access_token"`
Expand All @@ -29,7 +50,7 @@ type OauthSuccessResponse struct {
}

// NewGitlabOauthClient creates a new gitlab client from the given oauth info, authInfo is encrypted
func NewGitlabOauthClient(authInfo string, gitLabApp *App) (*goGitLab.Client, error) {
func NewGitlabOauthClient(authInfo string, gitLabApp *App) (GitLabClient, error) {
if authInfo == "" {
return nil, errors.New("unable to decrypt auth info - authentication info input is nil")
}
Expand All @@ -47,7 +68,14 @@ func NewGitlabOauthClient(authInfo string, gitLabApp *App) (*goGitLab.Client, er
}

log.Infof("creating oauth client with access token : %s", oauthResp.AccessToken)
return goGitLab.NewOAuthClient(oauthResp.AccessToken)
client, err := goGitLab.NewOAuthClient(oauthResp.AccessToken)
if err != nil {
return nil, err
}

return &GitLabClientWrapper{
gitlabClient: client,
}, nil
}

// NewGitlabOauthClientFromAccessToken creates a new gitlab client from the given access token
Expand Down Expand Up @@ -154,3 +182,70 @@ func decrypt(key, cipherText []byte) ([]byte, error) {

return cipherText, nil
}

func (c *GitLabClientWrapper) ListGroupMembers(gid interface{}, opt *goGitLab.ListGroupMembersOptions) ([]*goGitLab.GroupMember, *goGitLab.Response, error) {
return c.gitlabClient.Groups.ListGroupMembers(gid, opt)
}

func (c *GitLabClientWrapper) GetProject(gitLabProjectID int, opts *goGitLab.GetProjectOptions) (*goGitLab.Project, error) {
project, _, err := c.gitlabClient.Projects.GetProject(gitLabProjectID, opts)
if err != nil {
return nil, err
}
return project, err
}

func (c *GitLabClientWrapper) CurrentUser() (*goGitLab.User, *goGitLab.Response, error) {
return c.gitlabClient.Users.CurrentUser()
}

// GetMergeRequestCommits returns the commits for the given merge request
func (c *GitLabClientWrapper) GetMergeRequestCommits(projectID int, mergeID int, opts *goGitLab.GetMergeRequestCommitsOptions) ([]*goGitLab.Commit, error) {
commits, _, err := c.gitlabClient.MergeRequests.GetMergeRequestCommits(projectID, mergeID, opts)
if err != nil {
return nil, err
}
return commits, nil
}

// ListUsers returns the list of users
func (c *GitLabClientWrapper) ListUsers(opts *goGitLab.ListUsersOptions) ([]*goGitLab.User, error) {
users, _, err := c.gitlabClient.Users.ListUsers(opts)
if err != nil {
return nil, err
}
return users, nil
}

// SetCommitStatus sets the commit status
func (c *GitLabClientWrapper) SetCommitStatus(projectID int, commitSHA string, opts *goGitLab.SetCommitStatusOptions) error {
_, _, err := c.gitlabClient.Commits.SetCommitStatus(projectID, commitSHA, opts)
if err != nil {
return err
}
return nil
}

func (c *GitLabClientWrapper) ListGroupProjects(groupID int, opts *goGitLab.ListGroupProjectsOptions) ([]*goGitLab.Project, *goGitLab.Response, error) {
return c.gitlabClient.Groups.ListGroupProjects(groupID, opts)
}

func (c *GitLabClientWrapper) ListUserProjects(user interface{}, opt *goGitLab.ListProjectsOptions) ([]*goGitLab.Project, *goGitLab.Response, error) {
return c.gitlabClient.Projects.ListUserProjects(user, opt)
}

func (c *GitLabClientWrapper) DeleteProjectHook(projectID, webhookID int) (*goGitLab.Response, error) {
return c.gitlabClient.Projects.DeleteProjectHook(projectID, webhookID)
}

func (c *GitLabClientWrapper) ListProjectHooks(projectID int, opts *goGitLab.ListProjectHooksOptions) ([]*goGitLab.ProjectHook, *goGitLab.Response, error) {
return c.gitlabClient.Projects.ListProjectHooks(projectID, opts)
}

func (c *GitLabClientWrapper) AddProjectHook(projectID int, opts *goGitLab.AddProjectHookOptions) (*goGitLab.ProjectHook, *goGitLab.Response, error) {
return c.gitlabClient.Projects.AddProjectHook(projectID, opts)
}

func (c *GitLabClientWrapper) EditProjectHook(projectID, existingID int, opts *goGitLab.EditProjectHookOptions) (*goGitLab.ProjectHook, *goGitLab.Response, error) {
return c.gitlabClient.Projects.EditProjectHook(projectID, existingID, opts)
}
12 changes: 6 additions & 6 deletions cla-backend-go/gitlab_api/client_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func GetGroupByFullPath(ctx context.Context, client *goGitLab.Client, fullPath s
}

// GetGroupProjectListByGroupID returns a list of GitLab projects under the specified Organization
func GetGroupProjectListByGroupID(ctx context.Context, client *goGitLab.Client, groupID int) ([]*goGitLab.Project, error) {
func GetGroupProjectListByGroupID(ctx context.Context, client GitLabClient, groupID int) ([]*goGitLab.Project, error) {
f := logrus.Fields{
"functionName": "gitlab_api.client_groups.GetGroupProjectListByGroupID",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
Expand All @@ -168,7 +168,7 @@ func GetGroupProjectListByGroupID(ctx context.Context, client *goGitLab.Client,
var projectList []*goGitLab.Project
for {
// https://docs.gitlab.com/ee/api/groups.html#list-a-groups-projects
projects, resp, listProjectsErr := client.Groups.ListGroupProjects(groupID, opts)
projects, resp, listProjectsErr := client.ListGroupProjects(groupID, opts)
if listProjectsErr != nil {
msg := fmt.Sprintf("unable to list projects, error: %+v", listProjectsErr)
log.WithFields(f).WithError(listProjectsErr).Warn(msg)
Expand All @@ -193,7 +193,7 @@ func GetGroupProjectListByGroupID(ctx context.Context, client *goGitLab.Client,
}

// ListGroupMembers lists the members of a given groupID
func ListGroupMembers(ctx context.Context, client *goGitLab.Client, groupID int) ([]*goGitLab.GroupMember, error) {
func ListGroupMembers(ctx context.Context, client GitLabClient, groupID int) ([]*goGitLab.GroupMember, error) {
f := logrus.Fields{
"functionName": "gitlab_api.client_groups.GetGroupMembers",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
Expand All @@ -202,7 +202,7 @@ func ListGroupMembers(ctx context.Context, client *goGitLab.Client, groupID int)
log.WithFields(f).Debugf("fetching gitlab members for groupID: %d", groupID)

opts := &goGitLab.ListGroupMembersOptions{}
members, _, err := client.Groups.ListGroupMembers(groupID, opts)
members, _, err := client.ListGroupMembers(groupID, opts)
if err != nil {
log.WithFields(f).Debugf("unable to fetch members for gitlab GroupID : %d", groupID)
return nil, err
Expand All @@ -212,7 +212,7 @@ func ListGroupMembers(ctx context.Context, client *goGitLab.Client, groupID int)

// ListUserProjectGroups fetches the unique groups of a gitlab users groups,
// note: it doesn't list the projects/groups the user is member of ..., it's very limited
func ListUserProjectGroups(ctx context.Context, client *goGitLab.Client, userID int) ([]*UserGroup, error) {
func ListUserProjectGroups(ctx context.Context, client GitLabClient, userID int) ([]*UserGroup, error) {
f := logrus.Fields{
"functionName": "gitlab_api.client_groups.ListUserProjectGroups",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
Expand All @@ -226,7 +226,7 @@ func ListUserProjectGroups(ctx context.Context, client *goGitLab.Client, userID
userGroupsMap := map[string]*UserGroup{}
for {
log.WithFields(f).Debugf("fetching projects for user id : %d with options : %v", userID, listOptions.ListOptions)
projects, resp, err := client.Projects.ListUserProjects(userID, listOptions)
projects, resp, err := client.ListUserProjects(userID, listOptions)
if err != nil {
msg := fmt.Sprintf("listing user : %d projects failed : %v", userID, err)
log.WithFields(f).Warn(msg)
Expand Down
15 changes: 5 additions & 10 deletions cla-backend-go/gitlab_api/client_projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,25 +85,20 @@ func getProjectListWithOptions(ctx context.Context, client *goGitLab.Client, opt
}

// GetProjectByID returns the GitLab project for the specified ID
func GetProjectByID(ctx context.Context, client *goGitLab.Client, gitLabProjectID int) (*goGitLab.Project, error) {
func GetProjectByID(ctx context.Context, client GitLabClient, gitLabProjectID int) (*goGitLab.Project, error) {
f := logrus.Fields{
"functionName": "gitlab.client.GetProjectByID",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"gitLabProjectID": gitLabProjectID,
}

// Query GitLab for repos - fetch the list of repositories available to the GitLab App
project, resp, getProjectErr := client.Projects.GetProject(gitLabProjectID, &goGitLab.GetProjectOptions{})
project, getProjectErr := client.GetProject(gitLabProjectID, &goGitLab.GetProjectOptions{})
if getProjectErr != nil {
msg := fmt.Sprintf("unable to get project by ID: %d, error: %+v", gitLabProjectID, getProjectErr)
log.WithFields(f).WithError(getProjectErr).Warn(msg)
return nil, errors.New(msg)
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
msg := fmt.Sprintf("unable to get project by ID: %d, status code: %d", gitLabProjectID, resp.StatusCode)
log.WithFields(f).WithError(getProjectErr).Warn(msg)
return nil, errors.New(msg)
}
if project == nil {
msg := fmt.Sprintf("unable to get project by ID: %d, project is empty", gitLabProjectID)
log.WithFields(f).WithError(getProjectErr).Warn(msg)
Expand All @@ -116,14 +111,14 @@ func GetProjectByID(ctx context.Context, client *goGitLab.Client, gitLabProjectI
// EnableMergePipelineProtection enables the pipeline protection on given project, by default it's
// turned off and when a new MR is raised users can merge requests bypassing the pipelines. With this
// setting gitlab disables the Merge button if any of the pipelines are failing
func EnableMergePipelineProtection(ctx context.Context, gitlabClient *goGitLab.Client, projectID int) error {
func EnableMergePipelineProtection(ctx context.Context, gitlabClient GitLabClient, projectID int) error {
f := logrus.Fields{
"functionName": "gitlab.client.EnableMergePipelineProtection",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"gitLabProjectID": projectID,
}

project, _, err := gitlabClient.Projects.GetProject(projectID, &goGitLab.GetProjectOptions{})
project, err := gitlabClient.GetProject(projectID, &goGitLab.GetProjectOptions{})
if err != nil {
return fmt.Errorf("fetching project failed : %v", err)
}
Expand All @@ -135,7 +130,7 @@ func EnableMergePipelineProtection(ctx context.Context, gitlabClient *goGitLab.C

project.OnlyAllowMergeIfPipelineSucceeds = true
log.WithFields(f).Debugf("Enabling Merge Pipeline protection")
_, _, err = gitlabClient.Projects.EditProject(projectID, &goGitLab.EditProjectOptions{
_, _, err = gitlabClient.EditProject(projectID, &goGitLab.EditProjectOptions{
OnlyAllowMergeIfPipelineSucceeds: goGitLab.Bool(true),
})

Expand Down
9 changes: 2 additions & 7 deletions cla-backend-go/gitlab_api/client_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import (
)

// GetUserByName gets a gitlab user object by the given name
func GetUserByName(ctx context.Context, client *goGitLab.Client, name string) (*goGitLab.User, error) {
func GetUserByName(ctx context.Context, client GitLabClient, name string) (*goGitLab.User, error) {
f := logrus.Fields{
"functionName": "gitlab_api.client_users.GetUserByName",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"name": name,
}

users, resp, err := client.Users.ListUsers(&goGitLab.ListUsersOptions{
users, err := client.ListUsers(&goGitLab.ListUsersOptions{
ListOptions: goGitLab.ListOptions{
Page: 0,
PerPage: 10,
Expand All @@ -35,11 +35,6 @@ func GetUserByName(ctx context.Context, client *goGitLab.Client, name string) (*
log.WithFields(f).WithError(err).Warn(msg)
return nil, errors.New(msg)
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
msg := fmt.Sprintf("unable to get user using query: %s, status code: %d", name, resp.StatusCode)
log.WithFields(f).Warn(msg)
return nil, errors.New(msg)
}

if len(users) == 0 {
return nil, nil
Expand Down
79 changes: 79 additions & 0 deletions cla-backend-go/gitlab_api/mocks/mock_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f5fc5d0

Please sign in to comment.