Skip to content

Commit

Permalink
[GH-61]: RHS Support (#300)
Browse files Browse the repository at this point in the history
* Added RHS support to gilab plugin. (#1)

* Added RHS Support
1. Opening right hand sidebar onclick of LHS buttons.
2. Displaying users merge requests, assignments, reviews and todos.
3. Displaying Labels on reviews , merge requests and assignments.

* Adding RHS to gitlab
1. Displaying unread todos in RHS.

* Review fixes
1. String in sigle quotes.
2. indentation.
3.removing extra spaces

* Review Fixes
1. Fixing dependencies.
2. Adding EOF.

* used string literals

* use nullish coalescing operator

* Error in api
1. Error while fetching reviews and pr's.

* review fixes

* review fixes

* Review fixes.
1. Upgraded dependency versions.
2. Convertes sider_right.jsx to .tsx

* Fixed linting errors and changed some eslint config
Added a new dependency eslint-plugin-react-hooks and used that in .eslintrc.json
Added some new rules in eslintrc related to typescript from the Github plugin

* Fixed some more spacing issues

* Apply suggestions from code review

* Review fixes
1. Upgraded mattermost-redux version.
2. Moved constants.

* Changed file extensions

Co-authored-by: Manoj <manoj@brightscout.com>

* Fix label details issue (#6)

* Fixed issue with label details
1. Created a new func to get label details from api

* Moved struct to top of file

* Review fixes
1. Added logic to get label details in "yourAssignments" func.

* Fixes name of struct

* Fixed names of variables

* Update RHS UI (#3)

* Added RHS Support
1. Opening right hand sidebar onclick of LHS buttons.
2. Displaying users merge requests, assignments, reviews and todos.
3. Displaying Labels on reviews , merge requests and assignments.

* Adding RHS to gitlab
1. Displaying unread todos in RHS.

* Review fixes
1. String in sigle quotes.
2. indentation.
3.removing extra spaces

* Displayed PR status

* Improving RHS UI
1. Added status icon to PR's and reviews.
2. Added details of how many reviewers approved the PR.

* fixed error in command_test file

* Review Fixes
1. Fixing dependencies.
2. Adding EOF.

* used string literals

* use nullish coalescing operator

* Error in api
1. Error while fetching reviews and pr's.

* review fixes

* review fixes

* Review fixes.
1. Upgraded dependency versions.
2. Convertes sider_right.jsx to .tsx

* Fixed issue with label details
1. Created a new func to get label details from api

* Review fixes
1. Fixed warning in "npm run lint" command
2. Logged error while fetching pr details.
3. Removed extra variables.

* Indentation fixes

* Added space after semicolons

* Review fixes
1. Added label details functionality to assignments.
2. Fixed error messages.

* Review fixes
1. Removed trailing spaces.
2. Removed logger.Logger from "fetchPrDetails" func.

* Review fixes
1. Fixed spacing in error message.

* Review fixes
1. Passed logger to function

* Fixed linting error

* [MI-1823 & MI-1839]Review fixes for PR in mattermost
1. Defined abdolute paths.
2. Fixed indentation.
3. Removed redundant code.
4. Defined constants for strings.

* [MI-1823]Indentation fix and removed white space

* Review fix: Added blank line in gitlab_items.tsx

* [MI-1823]Fixed getReviews api
1. Get reviews api was fetching merge requests assigned to the user. Fixed it to fetch the merge requests in which user is added as a reviewer.

* Review fixes

* [MI-1957] Review fixes of RHS support PR (#14)

* [MI-1957] Do review fixes

* [MI-1957] Self review fixes

* [MI-1957] Bug fix

* [MI-1957] Review fixes 1

* [MI-1957] Review fix 2

* [MI-1957] Review fix

* [MI-1957] Review fixes 3

* [MI-1957] Add eof

* [MI-1957] Correct translations

* [MI-1957] Review fix

* [MI-1957] Add a comment

* [MI-1957] Correct comment

* [MI-1957] Review fixes

* [MI-2024] Gitlab PR review fixes (#19)

* [MI-2024] Gitlab PR review fixes

* [MI-2024] Fix error

* [MI-2024] Review fix

* [MI-2024] Revert changes

* [MI-2024] Review fixes

* Fix a constant for storing author

* [MI-2389] Fix review fixes for PR rhs support

* [MI-2389] Update a comment

* [MI-2407] Review fixes for PR rhs support

* [MI-2433] Review fixes
1. Removed extra useEffect for componentDidMount

* [MI-2433] Review fixes
1. Created a generic usePrevious hook

* Fix lint errors

* [MI-2595] Review fixes on Gitlab PR #300 (Add RHS Support)

* [MI-2845] Added space after link in RHS card.

---------

Co-authored-by: Manoj <manoj@brightscout.com>
Co-authored-by: ayusht2810 <100013900+ayusht2810@users.noreply.github.com>
Co-authored-by: ayusht2810 <ayush.thakur@joshtechnologygroup.com>
Co-authored-by: ayusht2810 <ayush.thakur@brightscout.com>
  • Loading branch information
5 people authored Mar 2, 2023
1 parent 2534105 commit d041aba
Show file tree
Hide file tree
Showing 33 changed files with 5,066 additions and 3,001 deletions.
19 changes: 18 additions & 1 deletion server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc("/todo", p.checkAuth(p.attachUserContext(p.postToDo), ResponseTypeJSON)).Methods(http.MethodPost)
apiRouter.HandleFunc("/reviews", p.checkAuth(p.attachUserContext(p.getReviews), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/yourprs", p.checkAuth(p.attachUserContext(p.getYourPrs), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/prdetails", p.checkAuth(p.attachUserContext(p.getPrDetails), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/yourassignments", p.checkAuth(p.attachUserContext(p.getYourAssignments), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/unreads", p.checkAuth(p.attachUserContext(p.getUnreads), ResponseTypePlain)).Methods(http.MethodGet)

apiRouter.HandleFunc("/settings", p.checkAuth(p.attachUserContext(p.updateSettings), ResponseTypePlain)).Methods(http.MethodPost)

apiRouter.HandleFunc("/channel/{channel_id:[A-Za-z0-9]+}/subscriptions", p.checkAuth(p.attachUserContext(p.getChannelSubscriptions), ResponseTypeJSON)).Methods(http.MethodGet)
Expand Down Expand Up @@ -551,6 +551,23 @@ func (p *Plugin) getYourPrs(c *UserContext, w http.ResponseWriter, r *http.Reque
p.writeAPIResponse(w, result)
}

func (p *Plugin) getPrDetails(c *UserContext, w http.ResponseWriter, r *http.Request) {
var prList []*gitlab.PRDetails
if err := json.NewDecoder(r.Body).Decode(&prList); err != nil {
c.Log.WithError(err).Warnf("Error decoding PRDetails JSON body")
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("Error decoding PRDetails JSON body. Error: %s", err.Error()), StatusCode: http.StatusBadRequest})
return
}
result, err := p.GitlabClient.GetYourPrDetails(c.Ctx, c.Log, c.GitlabInfo, prList)
if err != nil {
c.Log.WithError(err).Warnf("Can't list merge-request details in GitLab API")
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("Can't list merge-request details in GitLab API. Error: %s", err.Error()), StatusCode: http.StatusInternalServerError})
return
}

p.writeAPIResponse(w, result)
}

func (p *Plugin) getYourAssignments(c *UserContext, w http.ResponseWriter, r *http.Request) {
result, err := p.GitlabClient.GetYourAssignments(c.Ctx, c.GitlabInfo)
if err != nil {
Expand Down
176 changes: 168 additions & 8 deletions server/gitlab/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"fmt"
"net/http"
"strings"
"sync"

"github.com/mattermost/mattermost-plugin-api/experimental/bot/logger"

"github.com/pkg/errors"
internGitlab "github.com/xanzy/go-gitlab"
Expand All @@ -16,6 +19,24 @@ const (
scopeAll = "all"
)

type PRDetails struct {
IID int `json:"iid"`
Status *internGitlab.BuildStateValue `json:"status"`
SHA string `json:"sha"`
NumApprovers int `json:"num_approvers"`
ProjectID int `json:"project_id"`
}

type MergeRequest struct {
*internGitlab.MergeRequest
LabelsWithDetails []*internGitlab.Label `json:"labels_with_details,omitempty"`
}

type Issue struct {
*internGitlab.Issue
LabelsWithDetails []*internGitlab.Label `json:"labels_with_details,omitempty"`
}

// NewGroupHook creates a webhook associated with a GitLab group
func (g *gitlab) NewGroupHook(ctx context.Context, user *UserInfo, groupName string, webhookOptions *AddWebhookOptions) (*WebhookInfo, error) {
client, err := g.gitlabConnect(*user.Token)
Expand Down Expand Up @@ -246,7 +267,7 @@ func (g *gitlab) GetProject(ctx context.Context, user *UserInfo, owner, repo str
return result, nil
}

func (g *gitlab) GetReviews(ctx context.Context, user *UserInfo) ([]*internGitlab.MergeRequest, error) {
func (g *gitlab) GetReviews(ctx context.Context, user *UserInfo) ([]*MergeRequest, error) {
client, err := g.gitlabConnect(*user.Token)
if err != nil {
return nil, err
Expand All @@ -259,26 +280,42 @@ func (g *gitlab) GetReviews(ctx context.Context, user *UserInfo) ([]*internGitla

if g.gitlabGroup == "" {
result, _, err = client.MergeRequests.ListMergeRequests(&internGitlab.ListMergeRequestsOptions{
AssigneeID: internGitlab.AssigneeID(user.GitlabUserID),
ReviewerID: internGitlab.ReviewerID(user.GitlabUserID),
State: &opened,
Scope: &scope,
},
internGitlab.WithContext(ctx),
)
} else {
result, _, err = client.MergeRequests.ListGroupMergeRequests(g.gitlabGroup, &internGitlab.ListGroupMergeRequestsOptions{
AssigneeID: internGitlab.AssigneeID(user.GitlabUserID),
ReviewerID: internGitlab.ReviewerID(user.GitlabUserID),
State: &opened,
Scope: &scope,
},
internGitlab.WithContext(ctx),
)
}

return result, err
mergeRequests := []*MergeRequest{}
for _, res := range result {
if res.Labels != nil {
var labelsWithDetails []*internGitlab.Label
labelsWithDetails, err = g.GetLabelDetails(client, res.ProjectID, res.Labels)
if err != nil {
return nil, err
}
mergeRequest := &MergeRequest{
MergeRequest: res,
LabelsWithDetails: labelsWithDetails,
}
mergeRequests = append(mergeRequests, mergeRequest)
}
}

return mergeRequests, err
}

func (g *gitlab) GetYourPrs(ctx context.Context, user *UserInfo) ([]*internGitlab.MergeRequest, error) {
func (g *gitlab) GetYourPrs(ctx context.Context, user *UserInfo) ([]*MergeRequest, error) {
client, err := g.gitlabConnect(*user.Token)
if err != nil {
return nil, err
Expand Down Expand Up @@ -314,15 +351,123 @@ func (g *gitlab) GetYourPrs(ctx context.Context, user *UserInfo) ([]*internGitla
return nil, err
}

return result, nil
mergeRequests := []*MergeRequest{}
for _, res := range result {
if res.Labels != nil {
var labelsWithDetails []*internGitlab.Label
labelsWithDetails, err = g.GetLabelDetails(client, res.ProjectID, res.Labels)
if err != nil {
return nil, err
}
mergeRequest := &MergeRequest{
MergeRequest: res,
LabelsWithDetails: labelsWithDetails,
}
mergeRequests = append(mergeRequests, mergeRequest)
}
}
return mergeRequests, nil
}

func (g *gitlab) GetLabelDetails(client *internGitlab.Client, pid int, labels internGitlab.Labels) ([]*internGitlab.Label, error) {
// Get list of all labels.
labelList, resp, err := client.Labels.ListLabels(pid, nil)
if respErr := checkResponse(resp); respErr != nil {
return nil, respErr
}
if err != nil {
return nil, errors.Wrap(err, "can't get list of labels in GitLab")
}

allLabels := map[string]*internGitlab.Label{}
for _, label := range labelList {
allLabels[label.Name] = label
}

labelsWithDetails := []*internGitlab.Label{}
for _, label := range labels {
if allLabels[label] == nil {
return nil, errors.Wrap(err, "can't get label in GitLab api")
}
labelsWithDetails = append(labelsWithDetails, allLabels[label])
}

return labelsWithDetails, nil
}

func (g *gitlab) GetYourAssignments(ctx context.Context, user *UserInfo) ([]*internGitlab.Issue, error) {
func (g *gitlab) GetYourPrDetails(ctx context.Context, log logger.Logger, user *UserInfo, prList []*PRDetails) ([]*PRDetails, error) {
client, err := g.gitlabConnect(*user.Token)
if err != nil {
return nil, err
}

result := []*PRDetails{}
var wg sync.WaitGroup
for _, pr := range prList {
wg.Add(1)
go func(pid, iid int, sha string) {
defer wg.Done()
res := g.fetchYourPrDetails(ctx, log, client, pid, iid, sha)
if res != nil {
result = append(result, res)
}
}(pr.ProjectID, pr.IID, pr.SHA)
}
wg.Wait()
return result, nil
}

func (g *gitlab) fetchYourPrDetails(c context.Context, log logger.Logger, client *internGitlab.Client, pid, iid int, sha string) *PRDetails {
var commitDetails *internGitlab.Commit
var approvalDetails *internGitlab.MergeRequestApprovals
var err error
var resp *internGitlab.Response
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
commitDetails, resp, err = client.Commits.GetCommit(pid, sha, internGitlab.WithContext(c))
if respErr := checkResponse(resp); respErr != nil {
log.WithError(respErr).Warnf("Failed to fetch commit details for PR with project_id %d", pid)
return
}
if err != nil {
log.WithError(err).Warnf("Failed to fetch commit details for PR with project_id %d", pid)
return
}
}()

wg.Add(1)
go func() {
defer wg.Done()
approvalDetails, resp, err = client.MergeRequestApprovals.GetConfiguration(pid, iid, internGitlab.WithContext(c))
if respErr := checkResponse(resp); respErr != nil {
log.WithError(respErr).Warnf("Failed to fetch approval details for PR with project_id %d", pid)
return
}
if err != nil {
log.WithError(err).Warnf("Failed to fetch approval details for PR with project_id %d", pid)
return
}
}()

wg.Wait()
if commitDetails != nil && approvalDetails != nil {
return &PRDetails{
ProjectID: pid,
SHA: sha,
Status: commitDetails.Status,
NumApprovers: len(approvalDetails.ApprovedBy),
}
}
return nil
}

func (g *gitlab) GetYourAssignments(ctx context.Context, user *UserInfo) ([]*Issue, error) {
client, err := g.gitlabConnect(*user.Token)
if err != nil {
return nil, err
}
opened := stateOpened
scope := scopeAll

Expand Down Expand Up @@ -353,7 +498,22 @@ func (g *gitlab) GetYourAssignments(ctx context.Context, user *UserInfo) ([]*int
return nil, err
}

return result, nil
issues := []*Issue{}
for _, res := range result {
if res.Labels != nil {
var labelsWithDetails []*internGitlab.Label
labelsWithDetails, err = g.GetLabelDetails(client, res.ProjectID, res.Labels)
if err != nil {
return nil, err
}
issue := &Issue{
Issue: res,
LabelsWithDetails: labelsWithDetails,
}
issues = append(issues, issue)
}
}
return issues, nil
}

func (g *gitlab) GetUnreads(ctx context.Context, user *UserInfo) ([]*internGitlab.Todo, error) {
Expand Down
9 changes: 6 additions & 3 deletions server/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"net/http"
"strings"

"github.com/mattermost/mattermost-plugin-api/experimental/bot/logger"

"github.com/pkg/errors"
internGitlab "github.com/xanzy/go-gitlab"
"golang.org/x/oauth2"
Expand All @@ -24,9 +26,10 @@ type Gitlab interface {
GetCurrentUser(ctx context.Context, userID string, token oauth2.Token) (*UserInfo, error)
GetUserDetails(ctx context.Context, user *UserInfo) (*internGitlab.User, error)
GetProject(ctx context.Context, user *UserInfo, owner, repo string) (*internGitlab.Project, error)
GetReviews(ctx context.Context, user *UserInfo) ([]*internGitlab.MergeRequest, error)
GetYourPrs(ctx context.Context, user *UserInfo) ([]*internGitlab.MergeRequest, error)
GetYourAssignments(ctx context.Context, user *UserInfo) ([]*internGitlab.Issue, error)
GetYourPrDetails(ctx context.Context, log logger.Logger, user *UserInfo, prList []*PRDetails) ([]*PRDetails, error)
GetReviews(ctx context.Context, user *UserInfo) ([]*MergeRequest, error)
GetYourPrs(ctx context.Context, user *UserInfo) ([]*MergeRequest, error)
GetYourAssignments(ctx context.Context, user *UserInfo) ([]*Issue, error)
GetUnreads(ctx context.Context, user *UserInfo) ([]*internGitlab.Todo, error)
GetProjectHooks(ctx context.Context, user *UserInfo, owner string, repo string) ([]*WebhookInfo, error)
GetGroupHooks(ctx context.Context, user *UserInfo, owner string) ([]*WebhookInfo, error)
Expand Down
Loading

0 comments on commit d041aba

Please sign in to comment.