From 726e34d09366e85edd60c87f0e170de3ebb9d1c7 Mon Sep 17 00:00:00 2001 From: Moby von Briesen Date: Mon, 24 Apr 2023 20:28:27 -0400 Subject: [PATCH] Add command to list comments on PR Only comments in the configured "users to listen to" are listed Still need to add additional filtering in the future --- cmd/list-comments.go | 55 ++++++++++++++++++++++++++++++++++++++++++++ cmd/list-issues.go | 1 + pullpal/common.go | 13 +++++++++++ vc/common.go | 14 +++++++---- vc/github.go | 42 ++++++++++++++++++++++++++++++++- 5 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 cmd/list-comments.go diff --git a/cmd/list-comments.go b/cmd/list-comments.go new file mode 100644 index 0000000..cfd5f0e --- /dev/null +++ b/cmd/list-comments.go @@ -0,0 +1,55 @@ +package cmd + +import ( + "fmt" + + "github.com/mobyvb/pull-pal/pullpal" + "github.com/mobyvb/pull-pal/vc" + + "github.com/spf13/cobra" + "go.uber.org/zap" +) + +var listCommentsCmd = &cobra.Command{ + Use: "list-comments", + Short: "Lists comments on a Github PR meeting the configured criteria", + Long: "Lists comments on a Github PR meeting the configured criteria", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + cfg := getConfig() + + log := zap.L() + + author := vc.Author{ + Email: cfg.selfEmail, + Handle: cfg.selfHandle, + Token: cfg.githubToken, + } + repo := vc.Repository{ + LocalPath: cfg.localRepoPath, + HostDomain: cfg.repoDomain, + Name: cfg.repoName, + Owner: vc.Author{ + Handle: cfg.repoHandle, + }, + } + p, err := pullpal.NewPullPal(cmd.Context(), log.Named("pullpal"), author, repo) + if err != nil { + fmt.Println("error creating new pull pal", err) + return + } + fmt.Println("Successfully initialized pull pal") + + prID := args[0] + issueList, err := p.ListComments(prID, cfg.usersToListenTo) + if err != nil { + fmt.Println("error listing issues", err) + return + } + fmt.Println(issueList) + }, +} + +func init() { + rootCmd.AddCommand(listCommentsCmd) +} diff --git a/cmd/list-issues.go b/cmd/list-issues.go index 3878451..47836e3 100644 --- a/cmd/list-issues.go +++ b/cmd/list-issues.go @@ -5,6 +5,7 @@ import ( "github.com/mobyvb/pull-pal/pullpal" "github.com/mobyvb/pull-pal/vc" + "github.com/spf13/cobra" "go.uber.org/zap" ) diff --git a/pullpal/common.go b/pullpal/common.go index 1c9e44b..db8f904 100644 --- a/pullpal/common.go +++ b/pullpal/common.go @@ -167,3 +167,16 @@ func (p *PullPal) ListIssues(handles, labels []string) ([]vc.Issue, error) { return issues, nil } + +// ListComments gets a list of all comments meeting the provided criteria on a PR. +func (p *PullPal) ListComments(changeID string, handles []string) ([]vc.Comment, error) { + comments, err := p.vcClient.ListOpenComments(vc.ListCommentOptions{ + ChangeID: changeID, + Handles: handles, + }) + if err != nil { + return nil, err + } + + return comments, nil +} diff --git a/vc/common.go b/vc/common.go index 09ce011..9570601 100644 --- a/vc/common.go +++ b/vc/common.go @@ -34,12 +34,18 @@ type ListIssueOptions struct { // Comment represents a comment on a code change request. // TODO comments on issue? type Comment struct { + ID string // ChangeID is the local identifier for the code change request this comment was left on (e.g. Github PR number) ChangeID string - // Line is the contents of the code on the line where this comment was left - Line string - Body string - Author Author + Author Author + Body string + Position int + DiffHunk string + URL string +} + +func (c Comment) String() string { + return fmt.Sprintf("Comment ID: %s\nAuthor: %s\nBody: %s\nPosition: %d\n\nDiffHunk:\n%s\n\nURL: %s\n", c.ID, c.Author.Handle, c.Body, c.Position, c.DiffHunk, c.URL) } // ListCommentOptions defines options for listing comments. diff --git a/vc/github.go b/vc/github.go index c4b666d..2aa4f7c 100644 --- a/vc/github.go +++ b/vc/github.go @@ -208,7 +208,47 @@ func (gc *GithubClient) ListOpenIssues(options ListIssueOptions) ([]Issue, error // ListOpenComments lists unresolved comments in the Github repository. func (gc *GithubClient) ListOpenComments(options ListCommentOptions) ([]Comment, error) { - return nil, nil + toReturn := []Comment{} + prNumber, err := strconv.Atoi(options.ChangeID) + if err != nil { + return nil, err + } + comments, _, err := gc.client.PullRequests.ListComments(gc.ctx, gc.repo.Owner.Handle, gc.repo.Name, prNumber, nil) + if err != nil { + return nil, err + } + + // TODO: filter out comments that "self" has already replied to + // TODO: ignore resolved comments + for _, c := range comments { + commentUser := c.GetUser().GetLogin() + allowedUser := false + for _, u := range options.Handles { + if commentUser == u { + allowedUser = true + break + } + } + if !allowedUser { + continue + } + + nextComment := Comment{ + ID: strconv.FormatInt(c.GetID(), 10), + ChangeID: options.ChangeID, + URL: c.GetHTMLURL(), + Author: Author{ + Email: c.GetUser().GetEmail(), + Handle: c.GetUser().GetLogin(), + }, + Body: c.GetBody(), + Position: c.GetPosition(), + DiffHunk: c.GetDiffHunk(), + } + toReturn = append(toReturn, nextComment) + } + + return toReturn, nil } // GetLocalFile gets the current representation of the file at the provided path from the local git repo.