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