github.com/OnkarRuikar/reviewdog@v0.0.0-20230802094019-bc1001e3b2e5/service/gerrit/change_review.go (about)

     1  package gerrit
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  	"sync"
     8  
     9  	"golang.org/x/build/gerrit"
    10  
    11  	"github.com/reviewdog/reviewdog"
    12  	"github.com/reviewdog/reviewdog/service/serviceutil"
    13  )
    14  
    15  var _ reviewdog.CommentService = &ChangeReviewCommenter{}
    16  
    17  // ChangeReviewCommenter is a comment service for Gerrit Change Review
    18  // API:
    19  // 	https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#set-review
    20  // 	POST /changes/{change-id}/revisions/{revision-id}/review
    21  type ChangeReviewCommenter struct {
    22  	cli        *gerrit.Client
    23  	changeID   string
    24  	revisionID string
    25  
    26  	muComments   sync.Mutex
    27  	postComments []*reviewdog.Comment
    28  
    29  	// wd is working directory relative to root of repository.
    30  	wd string
    31  }
    32  
    33  // NewChangeReviewCommenter returns a new NewChangeReviewCommenter service.
    34  // ChangeReviewCommenter service needs git command in $PATH.
    35  func NewChangeReviewCommenter(cli *gerrit.Client, changeID, revisionID string) (*ChangeReviewCommenter, error) {
    36  	workDir, err := serviceutil.GitRelWorkdir()
    37  	if err != nil {
    38  		return nil, fmt.Errorf("ChangeReviewCommenter needs 'git' command: %w", err)
    39  	}
    40  
    41  	return &ChangeReviewCommenter{
    42  		cli:          cli,
    43  		changeID:     changeID,
    44  		revisionID:   revisionID,
    45  		postComments: []*reviewdog.Comment{},
    46  		wd:           workDir,
    47  	}, nil
    48  }
    49  
    50  // Post accepts a comment and holds it. Flush method actually posts comments to Gerrit
    51  func (g *ChangeReviewCommenter) Post(_ context.Context, c *reviewdog.Comment) error {
    52  	c.Result.Diagnostic.GetLocation().Path = filepath.Join(g.wd, c.Result.Diagnostic.GetLocation().GetPath())
    53  	g.muComments.Lock()
    54  	defer g.muComments.Unlock()
    55  	g.postComments = append(g.postComments, c)
    56  	return nil
    57  }
    58  
    59  // Flush posts comments which has not been posted yet.
    60  func (g *ChangeReviewCommenter) Flush(ctx context.Context) error {
    61  	g.muComments.Lock()
    62  	defer g.muComments.Unlock()
    63  
    64  	return g.postAllComments(ctx)
    65  }
    66  
    67  func (g *ChangeReviewCommenter) postAllComments(ctx context.Context) error {
    68  	review := gerrit.ReviewInput{
    69  		Comments: map[string][]gerrit.CommentInput{},
    70  	}
    71  	for _, c := range g.postComments {
    72  		if !c.Result.InDiffFile {
    73  			continue
    74  		}
    75  		loc := c.Result.Diagnostic.GetLocation()
    76  		path := loc.GetPath()
    77  		review.Comments[path] = append(review.Comments[path], gerrit.CommentInput{
    78  			Line:    int(loc.GetRange().GetStart().GetLine()),
    79  			Message: c.Result.Diagnostic.GetMessage(),
    80  		})
    81  	}
    82  
    83  	return g.cli.SetReview(ctx, g.changeID, g.revisionID, review)
    84  }