1
2
3
4
5
6 package github
7
8 import (
9 "context"
10 "errors"
11 "fmt"
12 "time"
13 )
14
15 var ErrMixedCommentStyles = errors.New("cannot use both position and side/line form comments")
16
17
18 type PullRequestReview struct {
19 ID *int64 `json:"id,omitempty"`
20 NodeID *string `json:"node_id,omitempty"`
21 User *User `json:"user,omitempty"`
22 Body *string `json:"body,omitempty"`
23 SubmittedAt *time.Time `json:"submitted_at,omitempty"`
24 CommitID *string `json:"commit_id,omitempty"`
25 HTMLURL *string `json:"html_url,omitempty"`
26 PullRequestURL *string `json:"pull_request_url,omitempty"`
27 State *string `json:"state,omitempty"`
28
29
30 AuthorAssociation *string `json:"author_association,omitempty"`
31 }
32
33 func (p PullRequestReview) String() string {
34 return Stringify(p)
35 }
36
37
38 type DraftReviewComment struct {
39 Path *string `json:"path,omitempty"`
40 Position *int `json:"position,omitempty"`
41 Body *string `json:"body,omitempty"`
42
43
44 StartSide *string `json:"start_side,omitempty"`
45 Side *string `json:"side,omitempty"`
46 StartLine *int `json:"start_line,omitempty"`
47 Line *int `json:"line,omitempty"`
48 }
49
50 func (c DraftReviewComment) String() string {
51 return Stringify(c)
52 }
53
54
55 type PullRequestReviewRequest struct {
56 NodeID *string `json:"node_id,omitempty"`
57 CommitID *string `json:"commit_id,omitempty"`
58 Body *string `json:"body,omitempty"`
59 Event *string `json:"event,omitempty"`
60 Comments []*DraftReviewComment `json:"comments,omitempty"`
61 }
62
63 func (r PullRequestReviewRequest) String() string {
64 return Stringify(r)
65 }
66
67 func (r *PullRequestReviewRequest) isComfortFadePreview() (bool, error) {
68 var isCF *bool
69 for _, comment := range r.Comments {
70 if comment == nil {
71 continue
72 }
73 hasPos := comment.Position != nil
74 hasComfortFade := (comment.StartSide != nil) || (comment.Side != nil) ||
75 (comment.StartLine != nil) || (comment.Line != nil)
76
77 switch {
78 case hasPos && hasComfortFade:
79 return false, ErrMixedCommentStyles
80 case hasPos && isCF != nil && *isCF:
81 return false, ErrMixedCommentStyles
82 case hasComfortFade && isCF != nil && !*isCF:
83 return false, ErrMixedCommentStyles
84 }
85 isCF = &hasComfortFade
86 }
87 if isCF != nil {
88 return *isCF, nil
89 }
90 return false, nil
91 }
92
93
94 type PullRequestReviewDismissalRequest struct {
95 Message *string `json:"message,omitempty"`
96 }
97
98 func (r PullRequestReviewDismissalRequest) String() string {
99 return Stringify(r)
100 }
101
102
103
104
105 func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) {
106 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
107 u, err := addOptions(u, opts)
108 if err != nil {
109 return nil, nil, err
110 }
111
112 req, err := s.client.NewRequest("GET", u, nil)
113 if err != nil {
114 return nil, nil, err
115 }
116
117 var reviews []*PullRequestReview
118 resp, err := s.client.Do(ctx, req, &reviews)
119 if err != nil {
120 return nil, resp, err
121 }
122
123 return reviews, resp, nil
124 }
125
126
127
128
129 func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
130 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
131
132 req, err := s.client.NewRequest("GET", u, nil)
133 if err != nil {
134 return nil, nil, err
135 }
136
137 review := new(PullRequestReview)
138 resp, err := s.client.Do(ctx, req, review)
139 if err != nil {
140 return nil, resp, err
141 }
142
143 return review, resp, nil
144 }
145
146
147
148
149 func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
150 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
151
152 req, err := s.client.NewRequest("DELETE", u, nil)
153 if err != nil {
154 return nil, nil, err
155 }
156
157 review := new(PullRequestReview)
158 resp, err := s.client.Do(ctx, req, review)
159 if err != nil {
160 return nil, resp, err
161 }
162
163 return review, resp, nil
164 }
165
166
167
168
169 func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) {
170 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID)
171 u, err := addOptions(u, opts)
172 if err != nil {
173 return nil, nil, err
174 }
175
176 req, err := s.client.NewRequest("GET", u, nil)
177 if err != nil {
178 return nil, nil, err
179 }
180
181 var comments []*PullRequestComment
182 resp, err := s.client.Do(ctx, req, &comments)
183 if err != nil {
184 return nil, resp, err
185 }
186
187 return comments, resp, nil
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
226 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
227
228 req, err := s.client.NewRequest("POST", u, review)
229 if err != nil {
230 return nil, nil, err
231 }
232
233
234 if isCF, err := review.isComfortFadePreview(); err != nil {
235 return nil, nil, err
236 } else if isCF {
237
238
239 req.Header.Set("Accept", mediaTypeMultiLineCommentsPreview)
240 }
241
242 r := new(PullRequestReview)
243 resp, err := s.client.Do(ctx, req, r)
244 if err != nil {
245 return nil, resp, err
246 }
247
248 return r, resp, nil
249 }
250
251
252
253
254 func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) {
255 opts := &struct {
256 Body string `json:"body"`
257 }{Body: body}
258 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
259
260 req, err := s.client.NewRequest("PUT", u, opts)
261 if err != nil {
262 return nil, nil, err
263 }
264
265 review := &PullRequestReview{}
266 resp, err := s.client.Do(ctx, req, review)
267 if err != nil {
268 return nil, resp, err
269 }
270
271 return review, resp, nil
272 }
273
274
275
276
277 func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
278 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID)
279
280 req, err := s.client.NewRequest("POST", u, review)
281 if err != nil {
282 return nil, nil, err
283 }
284
285 r := new(PullRequestReview)
286 resp, err := s.client.Do(ctx, req, r)
287 if err != nil {
288 return nil, resp, err
289 }
290
291 return r, resp, nil
292 }
293
294
295
296
297 func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) {
298 u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID)
299
300 req, err := s.client.NewRequest("PUT", u, review)
301 if err != nil {
302 return nil, nil, err
303 }
304
305 r := new(PullRequestReview)
306 resp, err := s.client.Do(ctx, req, r)
307 if err != nil {
308 return nil, resp, err
309 }
310
311 return r, resp, nil
312 }
313
View as plain text