detached 11411cf

#1 feat(proto): merge request note threads, ranges, edits and verdicts

state
merged · 11411cf · fast-forward
branch
feat/mr-notes → main
opened
bnema ·
updated

Additive contract changes for merge request notes (ADR 0032: notes with threads, line ranges, edits and verdicts).

  • Verdict enum (approve, changes requested) and AuthorVerdict.
  • Comment: reply_to, start_line, verdict, edited_at, deleted; text is Markdown and ^N refers to a note.
  • AddCommentRequest: reply_to, start_line, verdict.
  • New EditComment and DeleteComment RPCs; GetMergeRequestResponse.verdicts.
  • Events: comment_edited, comment_deleted, comment_resolved.
  • Scope SCOPE_MR_REVIEW (mr:review).

Checks: buf lint, buf breaking against main, buf generate (gen up to date), go vet, go build, go mod tidy.

Release: after merge, tag v0.8.0 (signed) and mirror main and the tag to GitHub; ermite then requires bnema.dev/ermite-api v0.8.0.

CommitSubjectAuthorDateSignatureStatus
11411cfdocs(proto): list the note events of WatchbriceGPG Verified
0be2bc9feat(proto): merge request note threads, ranges, edits and verdictsbriceGPG Verified

Checks 4

9 files · +1286 -215
4/4
M docs/services.md +1 -1
@@ -5,7 +5,7 @@
55 | `RepoService` | `ListRepos`, `GetRepo`, `CreateRepo`, `UpdateRepo` (field mask, merge settings), `DeleteRepo` |
66 | `GitService` | `ListRefs`, `GetTree`, `ListPaths`, `GetBlob` (streamed), `ListCommits`, `GetCommit` (structured diff), `ResolveRevision` |
77 | `TokenService` | `CreateToken` (secret shown once), `ListTokens`, `RevokeToken` |
8-| `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |
8+| `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |
99 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |
1010 | `EventService` | `Watch` (streamed, resumable) |
1111 | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) |
@@ -5,7 +5,7 @@
5 | `RepoService` | `ListRepos`, `GetRepo`, `CreateRepo`, `UpdateRepo` (field mask, merge settings), `DeleteRepo` |5 | `RepoService` | `ListRepos`, `GetRepo`, `CreateRepo`, `UpdateRepo` (field mask, merge settings), `DeleteRepo` |
6 | `GitService` | `ListRefs`, `GetTree`, `ListPaths`, `GetBlob` (streamed), `ListCommits`, `GetCommit` (structured diff), `ResolveRevision` |6 | `GitService` | `ListRefs`, `GetTree`, `ListPaths`, `GetBlob` (streamed), `ListCommits`, `GetCommit` (structured diff), `ResolveRevision` |
7 | `TokenService` | `CreateToken` (secret shown once), `ListTokens`, `RevokeToken` |7 | `TokenService` | `CreateToken` (secret shown once), `ListTokens`, `RevokeToken` |
8-| `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |8+| `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |
9 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |9 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |
10 | `EventService` | `Watch` (streamed, resumable) |10 | `EventService` | `Watch` (streamed, resumable) |
11 | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) |11 | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) |
M gen/ermite/ermiteconnect/event.connect.go +8 -6
@@ -47,7 +47,8 @@ type EventServiceClient interface {
4747 //
4848 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
4949 // for merge requests, merge_request_opened, merge_request_merged,
50- // merge_request_closed and comment_added. Each one is delivered on the
50+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
51+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
5152 // "repo:<name>" topic of its repository and on "home", subject to the
5253 // visibility of the repository.
5354 //
@@ -60,8 +61,8 @@ type EventServiceClient interface {
6061 // is not guaranteed, between jobs and runs or between two updates of the same
6162 // one: a client keeps the copy with the higher Run.version or
6263 // RunJob.version and drops the other. There is no event for a change of title or
63- // description, nor for a resolved comment: after a gap, or to see such
64- // changes, clients read the merge request again. A merge publishes
64+ // description: after a gap, or to see such changes, clients read the merge
65+ // request again. A merge publishes
6566 // merge_request_merged, then pushed for the target branch.
6667 //
6768 // The server keeps a bounded buffer of recent events. With resume_after set,
@@ -119,7 +120,8 @@ type EventServiceHandler interface {
119120 //
120121 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
121122 // for merge requests, merge_request_opened, merge_request_merged,
122- // merge_request_closed and comment_added. Each one is delivered on the
123+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
124+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
123125 // "repo:<name>" topic of its repository and on "home", subject to the
124126 // visibility of the repository.
125127 //
@@ -132,8 +134,8 @@ type EventServiceHandler interface {
132134 // is not guaranteed, between jobs and runs or between two updates of the same
133135 // one: a client keeps the copy with the higher Run.version or
134136 // RunJob.version and drops the other. There is no event for a change of title or
135- // description, nor for a resolved comment: after a gap, or to see such
136- // changes, clients read the merge request again. A merge publishes
137+ // description: after a gap, or to see such changes, clients read the merge
138+ // request again. A merge publishes
137139 // merge_request_merged, then pushed for the target branch.
138140 //
139141 // The server keeps a bounded buffer of recent events. With resume_after set,
@@ -47,7 +47,8 @@ type EventServiceClient interface {
47 //47 //
48 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,48 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
49 // for merge requests, merge_request_opened, merge_request_merged,49 // for merge requests, merge_request_opened, merge_request_merged,
50- // merge_request_closed and comment_added. Each one is delivered on the50+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
51+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
51 // "repo:<name>" topic of its repository and on "home", subject to the52 // "repo:<name>" topic of its repository and on "home", subject to the
52 // visibility of the repository.53 // visibility of the repository.
53 //54 //
@@ -60,8 +61,8 @@ type EventServiceClient interface {
60 // is not guaranteed, between jobs and runs or between two updates of the same61 // is not guaranteed, between jobs and runs or between two updates of the same
61 // one: a client keeps the copy with the higher Run.version or62 // one: a client keeps the copy with the higher Run.version or
62 // RunJob.version and drops the other. There is no event for a change of title or63 // RunJob.version and drops the other. There is no event for a change of title or
63- // description, nor for a resolved comment: after a gap, or to see such64+ // description: after a gap, or to see such changes, clients read the merge
64- // changes, clients read the merge request again. A merge publishes65+ // request again. A merge publishes
65 // merge_request_merged, then pushed for the target branch.66 // merge_request_merged, then pushed for the target branch.
66 //67 //
67 // The server keeps a bounded buffer of recent events. With resume_after set,68 // The server keeps a bounded buffer of recent events. With resume_after set,
@@ -119,7 +120,8 @@ type EventServiceHandler interface {
119 //120 //
120 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,121 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
121 // for merge requests, merge_request_opened, merge_request_merged,122 // for merge requests, merge_request_opened, merge_request_merged,
122- // merge_request_closed and comment_added. Each one is delivered on the123+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
124+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
123 // "repo:<name>" topic of its repository and on "home", subject to the125 // "repo:<name>" topic of its repository and on "home", subject to the
124 // visibility of the repository.126 // visibility of the repository.
125 //127 //
@@ -132,8 +134,8 @@ type EventServiceHandler interface {
132 // is not guaranteed, between jobs and runs or between two updates of the same134 // is not guaranteed, between jobs and runs or between two updates of the same
133 // one: a client keeps the copy with the higher Run.version or135 // one: a client keeps the copy with the higher Run.version or
134 // RunJob.version and drops the other. There is no event for a change of title or136 // RunJob.version and drops the other. There is no event for a change of title or
135- // description, nor for a resolved comment: after a gap, or to see such137+ // description: after a gap, or to see such changes, clients read the merge
136- // changes, clients read the merge request again. A merge publishes138+ // request again. A merge publishes
137 // merge_request_merged, then pushed for the target branch.139 // merge_request_merged, then pushed for the target branch.
138 //140 //
139 // The server keeps a bounded buffer of recent events. With resume_after set,141 // The server keeps a bounded buffer of recent events. With resume_after set,
M gen/ermite/ermiteconnect/merge_request.connect.go +110 -14
@@ -47,6 +47,12 @@ const (
4747 // MergeRequestServiceAddCommentProcedure is the fully-qualified name of the MergeRequestService's
4848 // AddComment RPC.
4949 MergeRequestServiceAddCommentProcedure = "/ermite.MergeRequestService/AddComment"
50+ // MergeRequestServiceEditCommentProcedure is the fully-qualified name of the MergeRequestService's
51+ // EditComment RPC.
52+ MergeRequestServiceEditCommentProcedure = "/ermite.MergeRequestService/EditComment"
53+ // MergeRequestServiceDeleteCommentProcedure is the fully-qualified name of the
54+ // MergeRequestService's DeleteComment RPC.
55+ MergeRequestServiceDeleteCommentProcedure = "/ermite.MergeRequestService/DeleteComment"
5056 // MergeRequestServiceResolveCommentProcedure is the fully-qualified name of the
5157 // MergeRequestService's ResolveComment RPC.
5258 MergeRequestServiceResolveCommentProcedure = "/ermite.MergeRequestService/ResolveComment"
@@ -79,14 +85,35 @@ type MergeRequestServiceClient interface {
7985 // caller last marked read with the current head. Fails with not_found if
8086 // the repository or the number is unknown.
8187 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)
82- // AddComment adds a general comment or a comment on a line of the diff.
83- // Needs the mr:write scope. Fails with invalid_argument if the text breaks
84- // a rule or if path, line and side do not designate a line of the current
85- // diff of the merge request, and with failed_precondition if the merge
86- // request is not open.
88+ // AddComment adds a general comment, a comment on a line or a range of
89+ // lines of the diff, or a reply to a root comment. Needs the mr:write
90+ // scope; setting a verdict also needs the mr:review scope (permission_denied
91+ // without it). Fails with invalid_argument if the text breaks a rule (it may
92+ // be empty only with a verdict), if path, line, start_line and side do not
93+ // designate lines of the current diff of the merge request, if reply_to is
94+ // not the id of a root comment that is not deleted, if a reply sets path,
95+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
96+ // with failed_precondition if the merge request is not open. A comment with
97+ // VERDICT_APPROVE is created resolved.
8798 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)
88- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write
89- // scope. Fails with not_found if the comment is unknown and with
99+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
100+ // only the author of the comment can edit it (permission_denied
101+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
102+ // be empty only for a comment with a verdict), with not_found if the comment
103+ // is unknown, and with failed_precondition if the merge request is not open
104+ // or the comment was deleted. Sending the current text succeeds and changes
105+ // nothing.
106+ EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error)
107+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
108+ // while its id, anchor, replies and verdict remain. Needs the mr:write
109+ // scope, and only the author of the comment can delete it
110+ // (permission_denied otherwise). Fails with not_found if the comment is
111+ // unknown and with failed_precondition if the merge request is not open.
112+ // Deleting a comment already deleted succeeds and changes nothing.
113+ DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error)
114+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
115+ // scope. Resolution belongs to the root comment: on a reply it fails with
116+ // invalid_argument. Fails with not_found if the comment is unknown and with
90117 // failed_precondition if the merge request is not open. Setting the state
91118 // the comment already has succeeds and changes nothing.
92119 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)
@@ -149,6 +176,18 @@ func NewMergeRequestServiceClient(httpClient connect.HTTPClient, baseURL string,
149176 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),
150177 connect.WithClientOptions(opts...),
151178 ),
179+ editComment: connect.NewClient[ermite.EditCommentRequest, ermite.EditCommentResponse](
180+ httpClient,
181+ baseURL+MergeRequestServiceEditCommentProcedure,
182+ connect.WithSchema(mergeRequestServiceMethods.ByName("EditComment")),
183+ connect.WithClientOptions(opts...),
184+ ),
185+ deleteComment: connect.NewClient[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse](
186+ httpClient,
187+ baseURL+MergeRequestServiceDeleteCommentProcedure,
188+ connect.WithSchema(mergeRequestServiceMethods.ByName("DeleteComment")),
189+ connect.WithClientOptions(opts...),
190+ ),
152191 resolveComment: connect.NewClient[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse](
153192 httpClient,
154193 baseURL+MergeRequestServiceResolveCommentProcedure,
@@ -182,6 +221,8 @@ type mergeRequestServiceClient struct {
182221 listMergeRequests *connect.Client[ermite.ListMergeRequestsRequest, ermite.ListMergeRequestsResponse]
183222 getMergeRequest *connect.Client[ermite.GetMergeRequestRequest, ermite.GetMergeRequestResponse]
184223 addComment *connect.Client[ermite.AddCommentRequest, ermite.AddCommentResponse]
224+ editComment *connect.Client[ermite.EditCommentRequest, ermite.EditCommentResponse]
225+ deleteComment *connect.Client[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse]
185226 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]
186227 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]
187228 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]
@@ -208,6 +249,16 @@ func (c *mergeRequestServiceClient) AddComment(ctx context.Context, req *connect
208249 return c.addComment.CallUnary(ctx, req)
209250 }
210251
252+// EditComment calls ermite.MergeRequestService.EditComment.
253+func (c *mergeRequestServiceClient) EditComment(ctx context.Context, req *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error) {
254+ return c.editComment.CallUnary(ctx, req)
255+}
256+
257+// DeleteComment calls ermite.MergeRequestService.DeleteComment.
258+func (c *mergeRequestServiceClient) DeleteComment(ctx context.Context, req *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error) {
259+ return c.deleteComment.CallUnary(ctx, req)
260+}
261+
211262 // ResolveComment calls ermite.MergeRequestService.ResolveComment.
212263 func (c *mergeRequestServiceClient) ResolveComment(ctx context.Context, req *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {
213264 return c.resolveComment.CallUnary(ctx, req)
@@ -246,14 +297,35 @@ type MergeRequestServiceHandler interface {
246297 // caller last marked read with the current head. Fails with not_found if
247298 // the repository or the number is unknown.
248299 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)
249- // AddComment adds a general comment or a comment on a line of the diff.
250- // Needs the mr:write scope. Fails with invalid_argument if the text breaks
251- // a rule or if path, line and side do not designate a line of the current
252- // diff of the merge request, and with failed_precondition if the merge
253- // request is not open.
300+ // AddComment adds a general comment, a comment on a line or a range of
301+ // lines of the diff, or a reply to a root comment. Needs the mr:write
302+ // scope; setting a verdict also needs the mr:review scope (permission_denied
303+ // without it). Fails with invalid_argument if the text breaks a rule (it may
304+ // be empty only with a verdict), if path, line, start_line and side do not
305+ // designate lines of the current diff of the merge request, if reply_to is
306+ // not the id of a root comment that is not deleted, if a reply sets path,
307+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
308+ // with failed_precondition if the merge request is not open. A comment with
309+ // VERDICT_APPROVE is created resolved.
254310 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)
255- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write
256- // scope. Fails with not_found if the comment is unknown and with
311+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
312+ // only the author of the comment can edit it (permission_denied
313+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
314+ // be empty only for a comment with a verdict), with not_found if the comment
315+ // is unknown, and with failed_precondition if the merge request is not open
316+ // or the comment was deleted. Sending the current text succeeds and changes
317+ // nothing.
318+ EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error)
319+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
320+ // while its id, anchor, replies and verdict remain. Needs the mr:write
321+ // scope, and only the author of the comment can delete it
322+ // (permission_denied otherwise). Fails with not_found if the comment is
323+ // unknown and with failed_precondition if the merge request is not open.
324+ // Deleting a comment already deleted succeeds and changes nothing.
325+ DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error)
326+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
327+ // scope. Resolution belongs to the root comment: on a reply it fails with
328+ // invalid_argument. Fails with not_found if the comment is unknown and with
257329 // failed_precondition if the merge request is not open. Setting the state
258330 // the comment already has succeeds and changes nothing.
259331 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)
@@ -312,6 +384,18 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
312384 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),
313385 connect.WithHandlerOptions(opts...),
314386 )
387+ mergeRequestServiceEditCommentHandler := connect.NewUnaryHandler(
388+ MergeRequestServiceEditCommentProcedure,
389+ svc.EditComment,
390+ connect.WithSchema(mergeRequestServiceMethods.ByName("EditComment")),
391+ connect.WithHandlerOptions(opts...),
392+ )
393+ mergeRequestServiceDeleteCommentHandler := connect.NewUnaryHandler(
394+ MergeRequestServiceDeleteCommentProcedure,
395+ svc.DeleteComment,
396+ connect.WithSchema(mergeRequestServiceMethods.ByName("DeleteComment")),
397+ connect.WithHandlerOptions(opts...),
398+ )
315399 mergeRequestServiceResolveCommentHandler := connect.NewUnaryHandler(
316400 MergeRequestServiceResolveCommentProcedure,
317401 svc.ResolveComment,
@@ -346,6 +430,10 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
346430 mergeRequestServiceGetMergeRequestHandler.ServeHTTP(w, r)
347431 case MergeRequestServiceAddCommentProcedure:
348432 mergeRequestServiceAddCommentHandler.ServeHTTP(w, r)
433+ case MergeRequestServiceEditCommentProcedure:
434+ mergeRequestServiceEditCommentHandler.ServeHTTP(w, r)
435+ case MergeRequestServiceDeleteCommentProcedure:
436+ mergeRequestServiceDeleteCommentHandler.ServeHTTP(w, r)
349437 case MergeRequestServiceResolveCommentProcedure:
350438 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)
351439 case MergeRequestServiceCloseMergeRequestProcedure:
@@ -379,6 +467,14 @@ func (UnimplementedMergeRequestServiceHandler) AddComment(context.Context, *conn
379467 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.AddComment is not implemented"))
380468 }
381469
470+func (UnimplementedMergeRequestServiceHandler) EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error) {
471+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.EditComment is not implemented"))
472+}
473+
474+func (UnimplementedMergeRequestServiceHandler) DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error) {
475+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.DeleteComment is not implemented"))
476+}
477+
382478 func (UnimplementedMergeRequestServiceHandler) ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {
383479 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.ResolveComment is not implemented"))
384480 }
@@ -47,6 +47,12 @@ const (
47 // MergeRequestServiceAddCommentProcedure is the fully-qualified name of the MergeRequestService's47 // MergeRequestServiceAddCommentProcedure is the fully-qualified name of the MergeRequestService's
48 // AddComment RPC.48 // AddComment RPC.
49 MergeRequestServiceAddCommentProcedure = "/ermite.MergeRequestService/AddComment"49 MergeRequestServiceAddCommentProcedure = "/ermite.MergeRequestService/AddComment"
50+ // MergeRequestServiceEditCommentProcedure is the fully-qualified name of the MergeRequestService's
51+ // EditComment RPC.
52+ MergeRequestServiceEditCommentProcedure = "/ermite.MergeRequestService/EditComment"
53+ // MergeRequestServiceDeleteCommentProcedure is the fully-qualified name of the
54+ // MergeRequestService's DeleteComment RPC.
55+ MergeRequestServiceDeleteCommentProcedure = "/ermite.MergeRequestService/DeleteComment"
50 // MergeRequestServiceResolveCommentProcedure is the fully-qualified name of the56 // MergeRequestServiceResolveCommentProcedure is the fully-qualified name of the
51 // MergeRequestService's ResolveComment RPC.57 // MergeRequestService's ResolveComment RPC.
52 MergeRequestServiceResolveCommentProcedure = "/ermite.MergeRequestService/ResolveComment"58 MergeRequestServiceResolveCommentProcedure = "/ermite.MergeRequestService/ResolveComment"
@@ -79,14 +85,35 @@ type MergeRequestServiceClient interface {
79 // caller last marked read with the current head. Fails with not_found if85 // caller last marked read with the current head. Fails with not_found if
80 // the repository or the number is unknown.86 // the repository or the number is unknown.
81 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)87 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)
82- // AddComment adds a general comment or a comment on a line of the diff.88+ // AddComment adds a general comment, a comment on a line or a range of
83- // Needs the mr:write scope. Fails with invalid_argument if the text breaks89+ // lines of the diff, or a reply to a root comment. Needs the mr:write
84- // a rule or if path, line and side do not designate a line of the current90+ // scope; setting a verdict also needs the mr:review scope (permission_denied
85- // diff of the merge request, and with failed_precondition if the merge91+ // without it). Fails with invalid_argument if the text breaks a rule (it may
86- // request is not open.92+ // be empty only with a verdict), if path, line, start_line and side do not
93+ // designate lines of the current diff of the merge request, if reply_to is
94+ // not the id of a root comment that is not deleted, if a reply sets path,
95+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
96+ // with failed_precondition if the merge request is not open. A comment with
97+ // VERDICT_APPROVE is created resolved.
87 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)98 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)
88- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write99+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
89- // scope. Fails with not_found if the comment is unknown and with100+ // only the author of the comment can edit it (permission_denied
101+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
102+ // be empty only for a comment with a verdict), with not_found if the comment
103+ // is unknown, and with failed_precondition if the merge request is not open
104+ // or the comment was deleted. Sending the current text succeeds and changes
105+ // nothing.
106+ EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error)
107+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
108+ // while its id, anchor, replies and verdict remain. Needs the mr:write
109+ // scope, and only the author of the comment can delete it
110+ // (permission_denied otherwise). Fails with not_found if the comment is
111+ // unknown and with failed_precondition if the merge request is not open.
112+ // Deleting a comment already deleted succeeds and changes nothing.
113+ DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error)
114+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
115+ // scope. Resolution belongs to the root comment: on a reply it fails with
116+ // invalid_argument. Fails with not_found if the comment is unknown and with
90 // failed_precondition if the merge request is not open. Setting the state117 // failed_precondition if the merge request is not open. Setting the state
91 // the comment already has succeeds and changes nothing.118 // the comment already has succeeds and changes nothing.
92 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)119 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)
@@ -149,6 +176,18 @@ func NewMergeRequestServiceClient(httpClient connect.HTTPClient, baseURL string,
149 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),176 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),
150 connect.WithClientOptions(opts...),177 connect.WithClientOptions(opts...),
151 ),178 ),
179+ editComment: connect.NewClient[ermite.EditCommentRequest, ermite.EditCommentResponse](
180+ httpClient,
181+ baseURL+MergeRequestServiceEditCommentProcedure,
182+ connect.WithSchema(mergeRequestServiceMethods.ByName("EditComment")),
183+ connect.WithClientOptions(opts...),
184+ ),
185+ deleteComment: connect.NewClient[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse](
186+ httpClient,
187+ baseURL+MergeRequestServiceDeleteCommentProcedure,
188+ connect.WithSchema(mergeRequestServiceMethods.ByName("DeleteComment")),
189+ connect.WithClientOptions(opts...),
190+ ),
152 resolveComment: connect.NewClient[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse](191 resolveComment: connect.NewClient[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse](
153 httpClient,192 httpClient,
154 baseURL+MergeRequestServiceResolveCommentProcedure,193 baseURL+MergeRequestServiceResolveCommentProcedure,
@@ -182,6 +221,8 @@ type mergeRequestServiceClient struct {
182 listMergeRequests *connect.Client[ermite.ListMergeRequestsRequest, ermite.ListMergeRequestsResponse]221 listMergeRequests *connect.Client[ermite.ListMergeRequestsRequest, ermite.ListMergeRequestsResponse]
183 getMergeRequest *connect.Client[ermite.GetMergeRequestRequest, ermite.GetMergeRequestResponse]222 getMergeRequest *connect.Client[ermite.GetMergeRequestRequest, ermite.GetMergeRequestResponse]
184 addComment *connect.Client[ermite.AddCommentRequest, ermite.AddCommentResponse]223 addComment *connect.Client[ermite.AddCommentRequest, ermite.AddCommentResponse]
224+ editComment *connect.Client[ermite.EditCommentRequest, ermite.EditCommentResponse]
225+ deleteComment *connect.Client[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse]
185 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]226 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]
186 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]227 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]
187 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]228 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]
@@ -208,6 +249,16 @@ func (c *mergeRequestServiceClient) AddComment(ctx context.Context, req *connect
208 return c.addComment.CallUnary(ctx, req)249 return c.addComment.CallUnary(ctx, req)
209 }250 }
210 251
252+// EditComment calls ermite.MergeRequestService.EditComment.
253+func (c *mergeRequestServiceClient) EditComment(ctx context.Context, req *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error) {
254+ return c.editComment.CallUnary(ctx, req)
255+}
256+
257+// DeleteComment calls ermite.MergeRequestService.DeleteComment.
258+func (c *mergeRequestServiceClient) DeleteComment(ctx context.Context, req *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error) {
259+ return c.deleteComment.CallUnary(ctx, req)
260+}
261+
211 // ResolveComment calls ermite.MergeRequestService.ResolveComment.262 // ResolveComment calls ermite.MergeRequestService.ResolveComment.
212 func (c *mergeRequestServiceClient) ResolveComment(ctx context.Context, req *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {263 func (c *mergeRequestServiceClient) ResolveComment(ctx context.Context, req *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {
213 return c.resolveComment.CallUnary(ctx, req)264 return c.resolveComment.CallUnary(ctx, req)
@@ -246,14 +297,35 @@ type MergeRequestServiceHandler interface {
246 // caller last marked read with the current head. Fails with not_found if297 // caller last marked read with the current head. Fails with not_found if
247 // the repository or the number is unknown.298 // the repository or the number is unknown.
248 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)299 GetMergeRequest(context.Context, *connect.Request[ermite.GetMergeRequestRequest]) (*connect.Response[ermite.GetMergeRequestResponse], error)
249- // AddComment adds a general comment or a comment on a line of the diff.300+ // AddComment adds a general comment, a comment on a line or a range of
250- // Needs the mr:write scope. Fails with invalid_argument if the text breaks301+ // lines of the diff, or a reply to a root comment. Needs the mr:write
251- // a rule or if path, line and side do not designate a line of the current302+ // scope; setting a verdict also needs the mr:review scope (permission_denied
252- // diff of the merge request, and with failed_precondition if the merge303+ // without it). Fails with invalid_argument if the text breaks a rule (it may
253- // request is not open.304+ // be empty only with a verdict), if path, line, start_line and side do not
305+ // designate lines of the current diff of the merge request, if reply_to is
306+ // not the id of a root comment that is not deleted, if a reply sets path,
307+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
308+ // with failed_precondition if the merge request is not open. A comment with
309+ // VERDICT_APPROVE is created resolved.
254 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)310 AddComment(context.Context, *connect.Request[ermite.AddCommentRequest]) (*connect.Response[ermite.AddCommentResponse], error)
255- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write311+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
256- // scope. Fails with not_found if the comment is unknown and with312+ // only the author of the comment can edit it (permission_denied
313+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
314+ // be empty only for a comment with a verdict), with not_found if the comment
315+ // is unknown, and with failed_precondition if the merge request is not open
316+ // or the comment was deleted. Sending the current text succeeds and changes
317+ // nothing.
318+ EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error)
319+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
320+ // while its id, anchor, replies and verdict remain. Needs the mr:write
321+ // scope, and only the author of the comment can delete it
322+ // (permission_denied otherwise). Fails with not_found if the comment is
323+ // unknown and with failed_precondition if the merge request is not open.
324+ // Deleting a comment already deleted succeeds and changes nothing.
325+ DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error)
326+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
327+ // scope. Resolution belongs to the root comment: on a reply it fails with
328+ // invalid_argument. Fails with not_found if the comment is unknown and with
257 // failed_precondition if the merge request is not open. Setting the state329 // failed_precondition if the merge request is not open. Setting the state
258 // the comment already has succeeds and changes nothing.330 // the comment already has succeeds and changes nothing.
259 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)331 ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error)
@@ -312,6 +384,18 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
312 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),384 connect.WithSchema(mergeRequestServiceMethods.ByName("AddComment")),
313 connect.WithHandlerOptions(opts...),385 connect.WithHandlerOptions(opts...),
314 )386 )
387+ mergeRequestServiceEditCommentHandler := connect.NewUnaryHandler(
388+ MergeRequestServiceEditCommentProcedure,
389+ svc.EditComment,
390+ connect.WithSchema(mergeRequestServiceMethods.ByName("EditComment")),
391+ connect.WithHandlerOptions(opts...),
392+ )
393+ mergeRequestServiceDeleteCommentHandler := connect.NewUnaryHandler(
394+ MergeRequestServiceDeleteCommentProcedure,
395+ svc.DeleteComment,
396+ connect.WithSchema(mergeRequestServiceMethods.ByName("DeleteComment")),
397+ connect.WithHandlerOptions(opts...),
398+ )
315 mergeRequestServiceResolveCommentHandler := connect.NewUnaryHandler(399 mergeRequestServiceResolveCommentHandler := connect.NewUnaryHandler(
316 MergeRequestServiceResolveCommentProcedure,400 MergeRequestServiceResolveCommentProcedure,
317 svc.ResolveComment,401 svc.ResolveComment,
@@ -346,6 +430,10 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
346 mergeRequestServiceGetMergeRequestHandler.ServeHTTP(w, r)430 mergeRequestServiceGetMergeRequestHandler.ServeHTTP(w, r)
347 case MergeRequestServiceAddCommentProcedure:431 case MergeRequestServiceAddCommentProcedure:
348 mergeRequestServiceAddCommentHandler.ServeHTTP(w, r)432 mergeRequestServiceAddCommentHandler.ServeHTTP(w, r)
433+ case MergeRequestServiceEditCommentProcedure:
434+ mergeRequestServiceEditCommentHandler.ServeHTTP(w, r)
435+ case MergeRequestServiceDeleteCommentProcedure:
436+ mergeRequestServiceDeleteCommentHandler.ServeHTTP(w, r)
349 case MergeRequestServiceResolveCommentProcedure:437 case MergeRequestServiceResolveCommentProcedure:
350 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)438 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)
351 case MergeRequestServiceCloseMergeRequestProcedure:439 case MergeRequestServiceCloseMergeRequestProcedure:
@@ -379,6 +467,14 @@ func (UnimplementedMergeRequestServiceHandler) AddComment(context.Context, *conn
379 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.AddComment is not implemented"))467 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.AddComment is not implemented"))
380 }468 }
381 469
470+func (UnimplementedMergeRequestServiceHandler) EditComment(context.Context, *connect.Request[ermite.EditCommentRequest]) (*connect.Response[ermite.EditCommentResponse], error) {
471+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.EditComment is not implemented"))
472+}
473+
474+func (UnimplementedMergeRequestServiceHandler) DeleteComment(context.Context, *connect.Request[ermite.DeleteCommentRequest]) (*connect.Response[ermite.DeleteCommentResponse], error) {
475+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.DeleteComment is not implemented"))
476+}
477+
382 func (UnimplementedMergeRequestServiceHandler) ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {478 func (UnimplementedMergeRequestServiceHandler) ResolveComment(context.Context, *connect.Request[ermite.ResolveCommentRequest]) (*connect.Response[ermite.ResolveCommentResponse], error) {
383 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.ResolveComment is not implemented"))479 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.ResolveComment is not implemented"))
384 }480 }
M gen/ermite/event.pb.go +314 -42
@@ -154,6 +154,9 @@ type Event struct {
154154 // *Event_CommentAdded
155155 // *Event_RunUpdated
156156 // *Event_JobUpdated
157+ // *Event_CommentEdited
158+ // *Event_CommentDeleted
159+ // *Event_CommentResolved
157160 Kind isEvent_Kind `protobuf_oneof:"kind"`
158161 unknownFields protoimpl.UnknownFields
159162 sizeCache protoimpl.SizeCache
@@ -309,6 +312,33 @@ func (x *Event) GetJobUpdated() *JobUpdated {
309312 return nil
310313 }
311314
315+func (x *Event) GetCommentEdited() *CommentEdited {
316+ if x != nil {
317+ if x, ok := x.Kind.(*Event_CommentEdited); ok {
318+ return x.CommentEdited
319+ }
320+ }
321+ return nil
322+}
323+
324+func (x *Event) GetCommentDeleted() *CommentDeleted {
325+ if x != nil {
326+ if x, ok := x.Kind.(*Event_CommentDeleted); ok {
327+ return x.CommentDeleted
328+ }
329+ }
330+ return nil
331+}
332+
333+func (x *Event) GetCommentResolved() *CommentResolved {
334+ if x != nil {
335+ if x, ok := x.Kind.(*Event_CommentResolved); ok {
336+ return x.CommentResolved
337+ }
338+ }
339+ return nil
340+}
341+
312342 type isEvent_Kind interface {
313343 isEvent_Kind()
314344 }
@@ -368,6 +398,21 @@ type Event_JobUpdated struct {
368398 JobUpdated *JobUpdated `protobuf:"bytes,13,opt,name=job_updated,json=jobUpdated,proto3,oneof"`
369399 }
370400
401+type Event_CommentEdited struct {
402+ // CommentEdited: the text of a merge request comment was changed.
403+ CommentEdited *CommentEdited `protobuf:"bytes,14,opt,name=comment_edited,json=commentEdited,proto3,oneof"`
404+}
405+
406+type Event_CommentDeleted struct {
407+ // CommentDeleted: a merge request comment was deleted.
408+ CommentDeleted *CommentDeleted `protobuf:"bytes,15,opt,name=comment_deleted,json=commentDeleted,proto3,oneof"`
409+}
410+
411+type Event_CommentResolved struct {
412+ // CommentResolved: a merge request comment was resolved or unresolved.
413+ CommentResolved *CommentResolved `protobuf:"bytes,16,opt,name=comment_resolved,json=commentResolved,proto3,oneof"`
414+}
415+
371416 func (*Event_RepoCreated) isEvent_Kind() {}
372417
373418 func (*Event_RepoUpdated) isEvent_Kind() {}
@@ -390,6 +435,12 @@ func (*Event_RunUpdated) isEvent_Kind() {}
390435
391436 func (*Event_JobUpdated) isEvent_Kind() {}
392437
438+func (*Event_CommentEdited) isEvent_Kind() {}
439+
440+func (*Event_CommentDeleted) isEvent_Kind() {}
441+
442+func (*Event_CommentResolved) isEvent_Kind() {}
443+
393444 // RepoCreated reports a new repository.
394445 type RepoCreated struct {
395446 state protoimpl.MessageState `protogen:"open.v1"`
@@ -850,6 +901,200 @@ func (x *CommentAdded) GetComment() *Comment {
850901 return nil
851902 }
852903
904+// CommentEdited reports a comment of a merge request whose text was changed.
905+type CommentEdited struct {
906+ state protoimpl.MessageState `protogen:"open.v1"`
907+ // Repo is the name of the repository.
908+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
909+ // Number is the number of the merge request.
910+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
911+ // Comment is the comment after the edit.
912+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
913+ unknownFields protoimpl.UnknownFields
914+ sizeCache protoimpl.SizeCache
915+}
916+
917+func (x *CommentEdited) Reset() {
918+ *x = CommentEdited{}
919+ mi := &file_ermite_event_proto_msgTypes[12]
920+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
921+ ms.StoreMessageInfo(mi)
922+}
923+
924+func (x *CommentEdited) String() string {
925+ return protoimpl.X.MessageStringOf(x)
926+}
927+
928+func (*CommentEdited) ProtoMessage() {}
929+
930+func (x *CommentEdited) ProtoReflect() protoreflect.Message {
931+ mi := &file_ermite_event_proto_msgTypes[12]
932+ if x != nil {
933+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
934+ if ms.LoadMessageInfo() == nil {
935+ ms.StoreMessageInfo(mi)
936+ }
937+ return ms
938+ }
939+ return mi.MessageOf(x)
940+}
941+
942+// Deprecated: Use CommentEdited.ProtoReflect.Descriptor instead.
943+func (*CommentEdited) Descriptor() ([]byte, []int) {
944+ return file_ermite_event_proto_rawDescGZIP(), []int{12}
945+}
946+
947+func (x *CommentEdited) GetRepo() string {
948+ if x != nil {
949+ return x.Repo
950+ }
951+ return ""
952+}
953+
954+func (x *CommentEdited) GetNumber() int64 {
955+ if x != nil {
956+ return x.Number
957+ }
958+ return 0
959+}
960+
961+func (x *CommentEdited) GetComment() *Comment {
962+ if x != nil {
963+ return x.Comment
964+ }
965+ return nil
966+}
967+
968+// CommentDeleted reports a comment of a merge request that was deleted. The
969+// comment stays in the thread with deleted set and an empty text.
970+type CommentDeleted struct {
971+ state protoimpl.MessageState `protogen:"open.v1"`
972+ // Repo is the name of the repository.
973+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
974+ // Number is the number of the merge request.
975+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
976+ // Comment is the comment after the deletion.
977+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
978+ unknownFields protoimpl.UnknownFields
979+ sizeCache protoimpl.SizeCache
980+}
981+
982+func (x *CommentDeleted) Reset() {
983+ *x = CommentDeleted{}
984+ mi := &file_ermite_event_proto_msgTypes[13]
985+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
986+ ms.StoreMessageInfo(mi)
987+}
988+
989+func (x *CommentDeleted) String() string {
990+ return protoimpl.X.MessageStringOf(x)
991+}
992+
993+func (*CommentDeleted) ProtoMessage() {}
994+
995+func (x *CommentDeleted) ProtoReflect() protoreflect.Message {
996+ mi := &file_ermite_event_proto_msgTypes[13]
997+ if x != nil {
998+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
999+ if ms.LoadMessageInfo() == nil {
1000+ ms.StoreMessageInfo(mi)
1001+ }
1002+ return ms
1003+ }
1004+ return mi.MessageOf(x)
1005+}
1006+
1007+// Deprecated: Use CommentDeleted.ProtoReflect.Descriptor instead.
1008+func (*CommentDeleted) Descriptor() ([]byte, []int) {
1009+ return file_ermite_event_proto_rawDescGZIP(), []int{13}
1010+}
1011+
1012+func (x *CommentDeleted) GetRepo() string {
1013+ if x != nil {
1014+ return x.Repo
1015+ }
1016+ return ""
1017+}
1018+
1019+func (x *CommentDeleted) GetNumber() int64 {
1020+ if x != nil {
1021+ return x.Number
1022+ }
1023+ return 0
1024+}
1025+
1026+func (x *CommentDeleted) GetComment() *Comment {
1027+ if x != nil {
1028+ return x.Comment
1029+ }
1030+ return nil
1031+}
1032+
1033+// CommentResolved reports a comment of a merge request whose resolved state
1034+// changed.
1035+type CommentResolved struct {
1036+ state protoimpl.MessageState `protogen:"open.v1"`
1037+ // Repo is the name of the repository.
1038+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1039+ // Number is the number of the merge request.
1040+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
1041+ // Comment is the comment after the change.
1042+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
1043+ unknownFields protoimpl.UnknownFields
1044+ sizeCache protoimpl.SizeCache
1045+}
1046+
1047+func (x *CommentResolved) Reset() {
1048+ *x = CommentResolved{}
1049+ mi := &file_ermite_event_proto_msgTypes[14]
1050+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1051+ ms.StoreMessageInfo(mi)
1052+}
1053+
1054+func (x *CommentResolved) String() string {
1055+ return protoimpl.X.MessageStringOf(x)
1056+}
1057+
1058+func (*CommentResolved) ProtoMessage() {}
1059+
1060+func (x *CommentResolved) ProtoReflect() protoreflect.Message {
1061+ mi := &file_ermite_event_proto_msgTypes[14]
1062+ if x != nil {
1063+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1064+ if ms.LoadMessageInfo() == nil {
1065+ ms.StoreMessageInfo(mi)
1066+ }
1067+ return ms
1068+ }
1069+ return mi.MessageOf(x)
1070+}
1071+
1072+// Deprecated: Use CommentResolved.ProtoReflect.Descriptor instead.
1073+func (*CommentResolved) Descriptor() ([]byte, []int) {
1074+ return file_ermite_event_proto_rawDescGZIP(), []int{14}
1075+}
1076+
1077+func (x *CommentResolved) GetRepo() string {
1078+ if x != nil {
1079+ return x.Repo
1080+ }
1081+ return ""
1082+}
1083+
1084+func (x *CommentResolved) GetNumber() int64 {
1085+ if x != nil {
1086+ return x.Number
1087+ }
1088+ return 0
1089+}
1090+
1091+func (x *CommentResolved) GetComment() *Comment {
1092+ if x != nil {
1093+ return x.Comment
1094+ }
1095+ return nil
1096+}
1097+
8531098 // Gap tells the client that events were lost: the requested resume point is
8541099 // older than the server's buffer. It has no fields. The client should reload
8551100 // the state it displays (repositories, refs, merge requests and their
@@ -862,7 +1107,7 @@ type Gap struct {
8621107
8631108 func (x *Gap) Reset() {
8641109 *x = Gap{}
865- mi := &file_ermite_event_proto_msgTypes[12]
1110+ mi := &file_ermite_event_proto_msgTypes[15]
8661111 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8671112 ms.StoreMessageInfo(mi)
8681113 }
@@ -874,7 +1119,7 @@ func (x *Gap) String() string {
8741119 func (*Gap) ProtoMessage() {}
8751120
8761121 func (x *Gap) ProtoReflect() protoreflect.Message {
877- mi := &file_ermite_event_proto_msgTypes[12]
1122+ mi := &file_ermite_event_proto_msgTypes[15]
8781123 if x != nil {
8791124 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8801125 if ms.LoadMessageInfo() == nil {
@@ -887,7 +1132,7 @@ func (x *Gap) ProtoReflect() protoreflect.Message {
8871132
8881133 // Deprecated: Use Gap.ProtoReflect.Descriptor instead.
8891134 func (*Gap) Descriptor() ([]byte, []int) {
890- return file_ermite_event_proto_rawDescGZIP(), []int{12}
1135+ return file_ermite_event_proto_rawDescGZIP(), []int{15}
8911136 }
8921137
8931138 // RunUpdated reports a CI run that was created or whose status, conclusion or
@@ -902,7 +1147,7 @@ type RunUpdated struct {
9021147
9031148 func (x *RunUpdated) Reset() {
9041149 *x = RunUpdated{}
905- mi := &file_ermite_event_proto_msgTypes[13]
1150+ mi := &file_ermite_event_proto_msgTypes[16]
9061151 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9071152 ms.StoreMessageInfo(mi)
9081153 }
@@ -914,7 +1159,7 @@ func (x *RunUpdated) String() string {
9141159 func (*RunUpdated) ProtoMessage() {}
9151160
9161161 func (x *RunUpdated) ProtoReflect() protoreflect.Message {
917- mi := &file_ermite_event_proto_msgTypes[13]
1162+ mi := &file_ermite_event_proto_msgTypes[16]
9181163 if x != nil {
9191164 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9201165 if ms.LoadMessageInfo() == nil {
@@ -927,7 +1172,7 @@ func (x *RunUpdated) ProtoReflect() protoreflect.Message {
9271172
9281173 // Deprecated: Use RunUpdated.ProtoReflect.Descriptor instead.
9291174 func (*RunUpdated) Descriptor() ([]byte, []int) {
930- return file_ermite_event_proto_rawDescGZIP(), []int{13}
1175+ return file_ermite_event_proto_rawDescGZIP(), []int{16}
9311176 }
9321177
9331178 func (x *RunUpdated) GetRun() *Run {
@@ -949,7 +1194,7 @@ type JobUpdated struct {
9491194
9501195 func (x *JobUpdated) Reset() {
9511196 *x = JobUpdated{}
952- mi := &file_ermite_event_proto_msgTypes[14]
1197+ mi := &file_ermite_event_proto_msgTypes[17]
9531198 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9541199 ms.StoreMessageInfo(mi)
9551200 }
@@ -961,7 +1206,7 @@ func (x *JobUpdated) String() string {
9611206 func (*JobUpdated) ProtoMessage() {}
9621207
9631208 func (x *JobUpdated) ProtoReflect() protoreflect.Message {
964- mi := &file_ermite_event_proto_msgTypes[14]
1209+ mi := &file_ermite_event_proto_msgTypes[17]
9651210 if x != nil {
9661211 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9671212 if ms.LoadMessageInfo() == nil {
@@ -974,7 +1219,7 @@ func (x *JobUpdated) ProtoReflect() protoreflect.Message {
9741219
9751220 // Deprecated: Use JobUpdated.ProtoReflect.Descriptor instead.
9761221 func (*JobUpdated) Descriptor() ([]byte, []int) {
977- return file_ermite_event_proto_rawDescGZIP(), []int{14}
1222+ return file_ermite_event_proto_rawDescGZIP(), []int{17}
9781223 }
9791224
9801225 func (x *JobUpdated) GetJob() *RunJob {
@@ -993,7 +1238,7 @@ const file_ermite_event_proto_rawDesc = "" +
9931238 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +
9941239 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +
9951240 "\rWatchResponse\x12#\n" +
996- "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xe3\x05\n" +
1241+ "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xac\a\n" +
9971242 "\x05Event\x12\x0e\n" +
9981243 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +
9991244 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +
@@ -1010,7 +1255,10 @@ const file_ermite_event_proto_rawDesc = "" +
10101255 "\vrun_updated\x18\f \x01(\v2\x12.ermite.RunUpdatedH\x00R\n" +
10111256 "runUpdated\x125\n" +
10121257 "\vjob_updated\x18\r \x01(\v2\x12.ermite.JobUpdatedH\x00R\n" +
1013- "jobUpdatedB\x06\n" +
1258+ "jobUpdated\x12>\n" +
1259+ "\x0ecomment_edited\x18\x0e \x01(\v2\x15.ermite.CommentEditedH\x00R\rcommentEdited\x12A\n" +
1260+ "\x0fcomment_deleted\x18\x0f \x01(\v2\x16.ermite.CommentDeletedH\x00R\x0ecommentDeleted\x12D\n" +
1261+ "\x10comment_resolved\x18\x10 \x01(\v2\x17.ermite.CommentResolvedH\x00R\x0fcommentResolvedB\x06\n" +
10141262 "\x04kind\"/\n" +
10151263 "\vRepoCreated\x12 \n" +
10161264 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +
@@ -1035,6 +1283,18 @@ const file_ermite_event_proto_rawDesc = "" +
10351283 "\fCommentAdded\x12\x12\n" +
10361284 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
10371285 "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1286+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"f\n" +
1287+ "\rCommentEdited\x12\x12\n" +
1288+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1289+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1290+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"g\n" +
1291+ "\x0eCommentDeleted\x12\x12\n" +
1292+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1293+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1294+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"h\n" +
1295+ "\x0fCommentResolved\x12\x12\n" +
1296+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1297+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
10381298 "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"\x05\n" +
10391299 "\x03Gap\"+\n" +
10401300 "\n" +
@@ -1061,7 +1321,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte {
10611321 return file_ermite_event_proto_rawDescData
10621322 }
10631323
1064-var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
1324+var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
10651325 var file_ermite_event_proto_goTypes = []any{
10661326 (*WatchRequest)(nil), // 0: ermite.WatchRequest
10671327 (*WatchResponse)(nil), // 1: ermite.WatchResponse
@@ -1075,46 +1335,55 @@ var file_ermite_event_proto_goTypes = []any{
10751335 (*MergeRequestMerged)(nil), // 9: ermite.MergeRequestMerged
10761336 (*MergeRequestClosed)(nil), // 10: ermite.MergeRequestClosed
10771337 (*CommentAdded)(nil), // 11: ermite.CommentAdded
1078- (*Gap)(nil), // 12: ermite.Gap
1079- (*RunUpdated)(nil), // 13: ermite.RunUpdated
1080- (*JobUpdated)(nil), // 14: ermite.JobUpdated
1081- (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
1082- (*Repo)(nil), // 16: ermite.Repo
1083- (*MergeRequest)(nil), // 17: ermite.MergeRequest
1084- (*Comment)(nil), // 18: ermite.Comment
1085- (*Run)(nil), // 19: ermite.Run
1086- (*RunJob)(nil), // 20: ermite.RunJob
1338+ (*CommentEdited)(nil), // 12: ermite.CommentEdited
1339+ (*CommentDeleted)(nil), // 13: ermite.CommentDeleted
1340+ (*CommentResolved)(nil), // 14: ermite.CommentResolved
1341+ (*Gap)(nil), // 15: ermite.Gap
1342+ (*RunUpdated)(nil), // 16: ermite.RunUpdated
1343+ (*JobUpdated)(nil), // 17: ermite.JobUpdated
1344+ (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp
1345+ (*Repo)(nil), // 19: ermite.Repo
1346+ (*MergeRequest)(nil), // 20: ermite.MergeRequest
1347+ (*Comment)(nil), // 21: ermite.Comment
1348+ (*Run)(nil), // 22: ermite.Run
1349+ (*RunJob)(nil), // 23: ermite.RunJob
10871350 }
10881351 var file_ermite_event_proto_depIdxs = []int32{
10891352 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event
1090- 15, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
1353+ 18, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
10911354 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated
10921355 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated
10931356 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted
10941357 6, // 5: ermite.Event.pushed:type_name -> ermite.Pushed
1095- 12, // 6: ermite.Event.gap:type_name -> ermite.Gap
1358+ 15, // 6: ermite.Event.gap:type_name -> ermite.Gap
10961359 8, // 7: ermite.Event.merge_request_opened:type_name -> ermite.MergeRequestOpened
10971360 9, // 8: ermite.Event.merge_request_merged:type_name -> ermite.MergeRequestMerged
10981361 10, // 9: ermite.Event.merge_request_closed:type_name -> ermite.MergeRequestClosed
10991362 11, // 10: ermite.Event.comment_added:type_name -> ermite.CommentAdded
1100- 13, // 11: ermite.Event.run_updated:type_name -> ermite.RunUpdated
1101- 14, // 12: ermite.Event.job_updated:type_name -> ermite.JobUpdated
1102- 16, // 13: ermite.RepoCreated.repo:type_name -> ermite.Repo
1103- 16, // 14: ermite.RepoUpdated.repo:type_name -> ermite.Repo
1104- 7, // 15: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
1105- 17, // 16: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
1106- 17, // 17: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
1107- 17, // 18: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
1108- 18, // 19: ermite.CommentAdded.comment:type_name -> ermite.Comment
1109- 19, // 20: ermite.RunUpdated.run:type_name -> ermite.Run
1110- 20, // 21: ermite.JobUpdated.job:type_name -> ermite.RunJob
1111- 0, // 22: ermite.EventService.Watch:input_type -> ermite.WatchRequest
1112- 1, // 23: ermite.EventService.Watch:output_type -> ermite.WatchResponse
1113- 23, // [23:24] is the sub-list for method output_type
1114- 22, // [22:23] is the sub-list for method input_type
1115- 22, // [22:22] is the sub-list for extension type_name
1116- 22, // [22:22] is the sub-list for extension extendee
1117- 0, // [0:22] is the sub-list for field type_name
1363+ 16, // 11: ermite.Event.run_updated:type_name -> ermite.RunUpdated
1364+ 17, // 12: ermite.Event.job_updated:type_name -> ermite.JobUpdated
1365+ 12, // 13: ermite.Event.comment_edited:type_name -> ermite.CommentEdited
1366+ 13, // 14: ermite.Event.comment_deleted:type_name -> ermite.CommentDeleted
1367+ 14, // 15: ermite.Event.comment_resolved:type_name -> ermite.CommentResolved
1368+ 19, // 16: ermite.RepoCreated.repo:type_name -> ermite.Repo
1369+ 19, // 17: ermite.RepoUpdated.repo:type_name -> ermite.Repo
1370+ 7, // 18: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
1371+ 20, // 19: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
1372+ 20, // 20: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
1373+ 20, // 21: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
1374+ 21, // 22: ermite.CommentAdded.comment:type_name -> ermite.Comment
1375+ 21, // 23: ermite.CommentEdited.comment:type_name -> ermite.Comment
1376+ 21, // 24: ermite.CommentDeleted.comment:type_name -> ermite.Comment
1377+ 21, // 25: ermite.CommentResolved.comment:type_name -> ermite.Comment
1378+ 22, // 26: ermite.RunUpdated.run:type_name -> ermite.Run
1379+ 23, // 27: ermite.JobUpdated.job:type_name -> ermite.RunJob
1380+ 0, // 28: ermite.EventService.Watch:input_type -> ermite.WatchRequest
1381+ 1, // 29: ermite.EventService.Watch:output_type -> ermite.WatchResponse
1382+ 29, // [29:30] is the sub-list for method output_type
1383+ 28, // [28:29] is the sub-list for method input_type
1384+ 28, // [28:28] is the sub-list for extension type_name
1385+ 28, // [28:28] is the sub-list for extension extendee
1386+ 0, // [0:28] is the sub-list for field type_name
11181387 }
11191388
11201389 func init() { file_ermite_event_proto_init() }
@@ -1137,6 +1406,9 @@ func file_ermite_event_proto_init() {
11371406 (*Event_CommentAdded)(nil),
11381407 (*Event_RunUpdated)(nil),
11391408 (*Event_JobUpdated)(nil),
1409+ (*Event_CommentEdited)(nil),
1410+ (*Event_CommentDeleted)(nil),
1411+ (*Event_CommentResolved)(nil),
11401412 }
11411413 type x struct{}
11421414 out := protoimpl.TypeBuilder{
@@ -1144,7 +1416,7 @@ func file_ermite_event_proto_init() {
11441416 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
11451417 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),
11461418 NumEnums: 0,
1147- NumMessages: 15,
1419+ NumMessages: 18,
11481420 NumExtensions: 0,
11491421 NumServices: 1,
11501422 },
@@ -154,6 +154,9 @@ type Event struct {
154 // *Event_CommentAdded154 // *Event_CommentAdded
155 // *Event_RunUpdated155 // *Event_RunUpdated
156 // *Event_JobUpdated156 // *Event_JobUpdated
157+ // *Event_CommentEdited
158+ // *Event_CommentDeleted
159+ // *Event_CommentResolved
157 Kind isEvent_Kind `protobuf_oneof:"kind"`160 Kind isEvent_Kind `protobuf_oneof:"kind"`
158 unknownFields protoimpl.UnknownFields161 unknownFields protoimpl.UnknownFields
159 sizeCache protoimpl.SizeCache162 sizeCache protoimpl.SizeCache
@@ -309,6 +312,33 @@ func (x *Event) GetJobUpdated() *JobUpdated {
309 return nil312 return nil
310 }313 }
311 314
315+func (x *Event) GetCommentEdited() *CommentEdited {
316+ if x != nil {
317+ if x, ok := x.Kind.(*Event_CommentEdited); ok {
318+ return x.CommentEdited
319+ }
320+ }
321+ return nil
322+}
323+
324+func (x *Event) GetCommentDeleted() *CommentDeleted {
325+ if x != nil {
326+ if x, ok := x.Kind.(*Event_CommentDeleted); ok {
327+ return x.CommentDeleted
328+ }
329+ }
330+ return nil
331+}
332+
333+func (x *Event) GetCommentResolved() *CommentResolved {
334+ if x != nil {
335+ if x, ok := x.Kind.(*Event_CommentResolved); ok {
336+ return x.CommentResolved
337+ }
338+ }
339+ return nil
340+}
341+
312 type isEvent_Kind interface {342 type isEvent_Kind interface {
313 isEvent_Kind()343 isEvent_Kind()
314 }344 }
@@ -368,6 +398,21 @@ type Event_JobUpdated struct {
368 JobUpdated *JobUpdated `protobuf:"bytes,13,opt,name=job_updated,json=jobUpdated,proto3,oneof"`398 JobUpdated *JobUpdated `protobuf:"bytes,13,opt,name=job_updated,json=jobUpdated,proto3,oneof"`
369 }399 }
370 400
401+type Event_CommentEdited struct {
402+ // CommentEdited: the text of a merge request comment was changed.
403+ CommentEdited *CommentEdited `protobuf:"bytes,14,opt,name=comment_edited,json=commentEdited,proto3,oneof"`
404+}
405+
406+type Event_CommentDeleted struct {
407+ // CommentDeleted: a merge request comment was deleted.
408+ CommentDeleted *CommentDeleted `protobuf:"bytes,15,opt,name=comment_deleted,json=commentDeleted,proto3,oneof"`
409+}
410+
411+type Event_CommentResolved struct {
412+ // CommentResolved: a merge request comment was resolved or unresolved.
413+ CommentResolved *CommentResolved `protobuf:"bytes,16,opt,name=comment_resolved,json=commentResolved,proto3,oneof"`
414+}
415+
371 func (*Event_RepoCreated) isEvent_Kind() {}416 func (*Event_RepoCreated) isEvent_Kind() {}
372 417
373 func (*Event_RepoUpdated) isEvent_Kind() {}418 func (*Event_RepoUpdated) isEvent_Kind() {}
@@ -390,6 +435,12 @@ func (*Event_RunUpdated) isEvent_Kind() {}
390 435
391 func (*Event_JobUpdated) isEvent_Kind() {}436 func (*Event_JobUpdated) isEvent_Kind() {}
392 437
438+func (*Event_CommentEdited) isEvent_Kind() {}
439+
440+func (*Event_CommentDeleted) isEvent_Kind() {}
441+
442+func (*Event_CommentResolved) isEvent_Kind() {}
443+
393 // RepoCreated reports a new repository.444 // RepoCreated reports a new repository.
394 type RepoCreated struct {445 type RepoCreated struct {
395 state protoimpl.MessageState `protogen:"open.v1"`446 state protoimpl.MessageState `protogen:"open.v1"`
@@ -850,6 +901,200 @@ func (x *CommentAdded) GetComment() *Comment {
850 return nil901 return nil
851 }902 }
852 903
904+// CommentEdited reports a comment of a merge request whose text was changed.
905+type CommentEdited struct {
906+ state protoimpl.MessageState `protogen:"open.v1"`
907+ // Repo is the name of the repository.
908+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
909+ // Number is the number of the merge request.
910+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
911+ // Comment is the comment after the edit.
912+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
913+ unknownFields protoimpl.UnknownFields
914+ sizeCache protoimpl.SizeCache
915+}
916+
917+func (x *CommentEdited) Reset() {
918+ *x = CommentEdited{}
919+ mi := &file_ermite_event_proto_msgTypes[12]
920+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
921+ ms.StoreMessageInfo(mi)
922+}
923+
924+func (x *CommentEdited) String() string {
925+ return protoimpl.X.MessageStringOf(x)
926+}
927+
928+func (*CommentEdited) ProtoMessage() {}
929+
930+func (x *CommentEdited) ProtoReflect() protoreflect.Message {
931+ mi := &file_ermite_event_proto_msgTypes[12]
932+ if x != nil {
933+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
934+ if ms.LoadMessageInfo() == nil {
935+ ms.StoreMessageInfo(mi)
936+ }
937+ return ms
938+ }
939+ return mi.MessageOf(x)
940+}
941+
942+// Deprecated: Use CommentEdited.ProtoReflect.Descriptor instead.
943+func (*CommentEdited) Descriptor() ([]byte, []int) {
944+ return file_ermite_event_proto_rawDescGZIP(), []int{12}
945+}
946+
947+func (x *CommentEdited) GetRepo() string {
948+ if x != nil {
949+ return x.Repo
950+ }
951+ return ""
952+}
953+
954+func (x *CommentEdited) GetNumber() int64 {
955+ if x != nil {
956+ return x.Number
957+ }
958+ return 0
959+}
960+
961+func (x *CommentEdited) GetComment() *Comment {
962+ if x != nil {
963+ return x.Comment
964+ }
965+ return nil
966+}
967+
968+// CommentDeleted reports a comment of a merge request that was deleted. The
969+// comment stays in the thread with deleted set and an empty text.
970+type CommentDeleted struct {
971+ state protoimpl.MessageState `protogen:"open.v1"`
972+ // Repo is the name of the repository.
973+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
974+ // Number is the number of the merge request.
975+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
976+ // Comment is the comment after the deletion.
977+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
978+ unknownFields protoimpl.UnknownFields
979+ sizeCache protoimpl.SizeCache
980+}
981+
982+func (x *CommentDeleted) Reset() {
983+ *x = CommentDeleted{}
984+ mi := &file_ermite_event_proto_msgTypes[13]
985+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
986+ ms.StoreMessageInfo(mi)
987+}
988+
989+func (x *CommentDeleted) String() string {
990+ return protoimpl.X.MessageStringOf(x)
991+}
992+
993+func (*CommentDeleted) ProtoMessage() {}
994+
995+func (x *CommentDeleted) ProtoReflect() protoreflect.Message {
996+ mi := &file_ermite_event_proto_msgTypes[13]
997+ if x != nil {
998+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
999+ if ms.LoadMessageInfo() == nil {
1000+ ms.StoreMessageInfo(mi)
1001+ }
1002+ return ms
1003+ }
1004+ return mi.MessageOf(x)
1005+}
1006+
1007+// Deprecated: Use CommentDeleted.ProtoReflect.Descriptor instead.
1008+func (*CommentDeleted) Descriptor() ([]byte, []int) {
1009+ return file_ermite_event_proto_rawDescGZIP(), []int{13}
1010+}
1011+
1012+func (x *CommentDeleted) GetRepo() string {
1013+ if x != nil {
1014+ return x.Repo
1015+ }
1016+ return ""
1017+}
1018+
1019+func (x *CommentDeleted) GetNumber() int64 {
1020+ if x != nil {
1021+ return x.Number
1022+ }
1023+ return 0
1024+}
1025+
1026+func (x *CommentDeleted) GetComment() *Comment {
1027+ if x != nil {
1028+ return x.Comment
1029+ }
1030+ return nil
1031+}
1032+
1033+// CommentResolved reports a comment of a merge request whose resolved state
1034+// changed.
1035+type CommentResolved struct {
1036+ state protoimpl.MessageState `protogen:"open.v1"`
1037+ // Repo is the name of the repository.
1038+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1039+ // Number is the number of the merge request.
1040+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
1041+ // Comment is the comment after the change.
1042+ Comment *Comment `protobuf:"bytes,3,opt,name=comment,proto3" json:"comment,omitempty"`
1043+ unknownFields protoimpl.UnknownFields
1044+ sizeCache protoimpl.SizeCache
1045+}
1046+
1047+func (x *CommentResolved) Reset() {
1048+ *x = CommentResolved{}
1049+ mi := &file_ermite_event_proto_msgTypes[14]
1050+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1051+ ms.StoreMessageInfo(mi)
1052+}
1053+
1054+func (x *CommentResolved) String() string {
1055+ return protoimpl.X.MessageStringOf(x)
1056+}
1057+
1058+func (*CommentResolved) ProtoMessage() {}
1059+
1060+func (x *CommentResolved) ProtoReflect() protoreflect.Message {
1061+ mi := &file_ermite_event_proto_msgTypes[14]
1062+ if x != nil {
1063+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1064+ if ms.LoadMessageInfo() == nil {
1065+ ms.StoreMessageInfo(mi)
1066+ }
1067+ return ms
1068+ }
1069+ return mi.MessageOf(x)
1070+}
1071+
1072+// Deprecated: Use CommentResolved.ProtoReflect.Descriptor instead.
1073+func (*CommentResolved) Descriptor() ([]byte, []int) {
1074+ return file_ermite_event_proto_rawDescGZIP(), []int{14}
1075+}
1076+
1077+func (x *CommentResolved) GetRepo() string {
1078+ if x != nil {
1079+ return x.Repo
1080+ }
1081+ return ""
1082+}
1083+
1084+func (x *CommentResolved) GetNumber() int64 {
1085+ if x != nil {
1086+ return x.Number
1087+ }
1088+ return 0
1089+}
1090+
1091+func (x *CommentResolved) GetComment() *Comment {
1092+ if x != nil {
1093+ return x.Comment
1094+ }
1095+ return nil
1096+}
1097+
853 // Gap tells the client that events were lost: the requested resume point is1098 // Gap tells the client that events were lost: the requested resume point is
854 // older than the server's buffer. It has no fields. The client should reload1099 // older than the server's buffer. It has no fields. The client should reload
855 // the state it displays (repositories, refs, merge requests and their1100 // the state it displays (repositories, refs, merge requests and their
@@ -862,7 +1107,7 @@ type Gap struct {
862 1107
863 func (x *Gap) Reset() {1108 func (x *Gap) Reset() {
864 *x = Gap{}1109 *x = Gap{}
865- mi := &file_ermite_event_proto_msgTypes[12]1110+ mi := &file_ermite_event_proto_msgTypes[15]
866 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1111 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
867 ms.StoreMessageInfo(mi)1112 ms.StoreMessageInfo(mi)
868 }1113 }
@@ -874,7 +1119,7 @@ func (x *Gap) String() string {
874 func (*Gap) ProtoMessage() {}1119 func (*Gap) ProtoMessage() {}
875 1120
876 func (x *Gap) ProtoReflect() protoreflect.Message {1121 func (x *Gap) ProtoReflect() protoreflect.Message {
877- mi := &file_ermite_event_proto_msgTypes[12]1122+ mi := &file_ermite_event_proto_msgTypes[15]
878 if x != nil {1123 if x != nil {
879 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1124 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
880 if ms.LoadMessageInfo() == nil {1125 if ms.LoadMessageInfo() == nil {
@@ -887,7 +1132,7 @@ func (x *Gap) ProtoReflect() protoreflect.Message {
887 1132
888 // Deprecated: Use Gap.ProtoReflect.Descriptor instead.1133 // Deprecated: Use Gap.ProtoReflect.Descriptor instead.
889 func (*Gap) Descriptor() ([]byte, []int) {1134 func (*Gap) Descriptor() ([]byte, []int) {
890- return file_ermite_event_proto_rawDescGZIP(), []int{12}1135+ return file_ermite_event_proto_rawDescGZIP(), []int{15}
891 }1136 }
892 1137
893 // RunUpdated reports a CI run that was created or whose status, conclusion or1138 // RunUpdated reports a CI run that was created or whose status, conclusion or
@@ -902,7 +1147,7 @@ type RunUpdated struct {
902 1147
903 func (x *RunUpdated) Reset() {1148 func (x *RunUpdated) Reset() {
904 *x = RunUpdated{}1149 *x = RunUpdated{}
905- mi := &file_ermite_event_proto_msgTypes[13]1150+ mi := &file_ermite_event_proto_msgTypes[16]
906 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1151 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
907 ms.StoreMessageInfo(mi)1152 ms.StoreMessageInfo(mi)
908 }1153 }
@@ -914,7 +1159,7 @@ func (x *RunUpdated) String() string {
914 func (*RunUpdated) ProtoMessage() {}1159 func (*RunUpdated) ProtoMessage() {}
915 1160
916 func (x *RunUpdated) ProtoReflect() protoreflect.Message {1161 func (x *RunUpdated) ProtoReflect() protoreflect.Message {
917- mi := &file_ermite_event_proto_msgTypes[13]1162+ mi := &file_ermite_event_proto_msgTypes[16]
918 if x != nil {1163 if x != nil {
919 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1164 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
920 if ms.LoadMessageInfo() == nil {1165 if ms.LoadMessageInfo() == nil {
@@ -927,7 +1172,7 @@ func (x *RunUpdated) ProtoReflect() protoreflect.Message {
927 1172
928 // Deprecated: Use RunUpdated.ProtoReflect.Descriptor instead.1173 // Deprecated: Use RunUpdated.ProtoReflect.Descriptor instead.
929 func (*RunUpdated) Descriptor() ([]byte, []int) {1174 func (*RunUpdated) Descriptor() ([]byte, []int) {
930- return file_ermite_event_proto_rawDescGZIP(), []int{13}1175+ return file_ermite_event_proto_rawDescGZIP(), []int{16}
931 }1176 }
932 1177
933 func (x *RunUpdated) GetRun() *Run {1178 func (x *RunUpdated) GetRun() *Run {
@@ -949,7 +1194,7 @@ type JobUpdated struct {
949 1194
950 func (x *JobUpdated) Reset() {1195 func (x *JobUpdated) Reset() {
951 *x = JobUpdated{}1196 *x = JobUpdated{}
952- mi := &file_ermite_event_proto_msgTypes[14]1197+ mi := &file_ermite_event_proto_msgTypes[17]
953 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1198 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
954 ms.StoreMessageInfo(mi)1199 ms.StoreMessageInfo(mi)
955 }1200 }
@@ -961,7 +1206,7 @@ func (x *JobUpdated) String() string {
961 func (*JobUpdated) ProtoMessage() {}1206 func (*JobUpdated) ProtoMessage() {}
962 1207
963 func (x *JobUpdated) ProtoReflect() protoreflect.Message {1208 func (x *JobUpdated) ProtoReflect() protoreflect.Message {
964- mi := &file_ermite_event_proto_msgTypes[14]1209+ mi := &file_ermite_event_proto_msgTypes[17]
965 if x != nil {1210 if x != nil {
966 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1211 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
967 if ms.LoadMessageInfo() == nil {1212 if ms.LoadMessageInfo() == nil {
@@ -974,7 +1219,7 @@ func (x *JobUpdated) ProtoReflect() protoreflect.Message {
974 1219
975 // Deprecated: Use JobUpdated.ProtoReflect.Descriptor instead.1220 // Deprecated: Use JobUpdated.ProtoReflect.Descriptor instead.
976 func (*JobUpdated) Descriptor() ([]byte, []int) {1221 func (*JobUpdated) Descriptor() ([]byte, []int) {
977- return file_ermite_event_proto_rawDescGZIP(), []int{14}1222+ return file_ermite_event_proto_rawDescGZIP(), []int{17}
978 }1223 }
979 1224
980 func (x *JobUpdated) GetJob() *RunJob {1225 func (x *JobUpdated) GetJob() *RunJob {
@@ -993,7 +1238,7 @@ const file_ermite_event_proto_rawDesc = "" +
993 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +1238 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +
994 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +1239 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +
995 "\rWatchResponse\x12#\n" +1240 "\rWatchResponse\x12#\n" +
996- "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xe3\x05\n" +1241+ "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xac\a\n" +
997 "\x05Event\x12\x0e\n" +1242 "\x05Event\x12\x0e\n" +
998 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +1243 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +
999 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +1244 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +
@@ -1010,7 +1255,10 @@ const file_ermite_event_proto_rawDesc = "" +
1010 "\vrun_updated\x18\f \x01(\v2\x12.ermite.RunUpdatedH\x00R\n" +1255 "\vrun_updated\x18\f \x01(\v2\x12.ermite.RunUpdatedH\x00R\n" +
1011 "runUpdated\x125\n" +1256 "runUpdated\x125\n" +
1012 "\vjob_updated\x18\r \x01(\v2\x12.ermite.JobUpdatedH\x00R\n" +1257 "\vjob_updated\x18\r \x01(\v2\x12.ermite.JobUpdatedH\x00R\n" +
1013- "jobUpdatedB\x06\n" +1258+ "jobUpdated\x12>\n" +
1259+ "\x0ecomment_edited\x18\x0e \x01(\v2\x15.ermite.CommentEditedH\x00R\rcommentEdited\x12A\n" +
1260+ "\x0fcomment_deleted\x18\x0f \x01(\v2\x16.ermite.CommentDeletedH\x00R\x0ecommentDeleted\x12D\n" +
1261+ "\x10comment_resolved\x18\x10 \x01(\v2\x17.ermite.CommentResolvedH\x00R\x0fcommentResolvedB\x06\n" +
1014 "\x04kind\"/\n" +1262 "\x04kind\"/\n" +
1015 "\vRepoCreated\x12 \n" +1263 "\vRepoCreated\x12 \n" +
1016 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +1264 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +
@@ -1035,6 +1283,18 @@ const file_ermite_event_proto_rawDesc = "" +
1035 "\fCommentAdded\x12\x12\n" +1283 "\fCommentAdded\x12\x12\n" +
1036 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +1284 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1037 "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +1285 "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1286+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"f\n" +
1287+ "\rCommentEdited\x12\x12\n" +
1288+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1289+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1290+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"g\n" +
1291+ "\x0eCommentDeleted\x12\x12\n" +
1292+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1293+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1294+ "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"h\n" +
1295+ "\x0fCommentResolved\x12\x12\n" +
1296+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
1297+ "\x06number\x18\x02 \x01(\x03R\x06number\x12)\n" +
1038 "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"\x05\n" +1298 "\acomment\x18\x03 \x01(\v2\x0f.ermite.CommentR\acomment\"\x05\n" +
1039 "\x03Gap\"+\n" +1299 "\x03Gap\"+\n" +
1040 "\n" +1300 "\n" +
@@ -1061,7 +1321,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte {
1061 return file_ermite_event_proto_rawDescData1321 return file_ermite_event_proto_rawDescData
1062 }1322 }
1063 1323
1064-var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 15)1324+var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
1065 var file_ermite_event_proto_goTypes = []any{1325 var file_ermite_event_proto_goTypes = []any{
1066 (*WatchRequest)(nil), // 0: ermite.WatchRequest1326 (*WatchRequest)(nil), // 0: ermite.WatchRequest
1067 (*WatchResponse)(nil), // 1: ermite.WatchResponse1327 (*WatchResponse)(nil), // 1: ermite.WatchResponse
@@ -1075,46 +1335,55 @@ var file_ermite_event_proto_goTypes = []any{
1075 (*MergeRequestMerged)(nil), // 9: ermite.MergeRequestMerged1335 (*MergeRequestMerged)(nil), // 9: ermite.MergeRequestMerged
1076 (*MergeRequestClosed)(nil), // 10: ermite.MergeRequestClosed1336 (*MergeRequestClosed)(nil), // 10: ermite.MergeRequestClosed
1077 (*CommentAdded)(nil), // 11: ermite.CommentAdded1337 (*CommentAdded)(nil), // 11: ermite.CommentAdded
1078- (*Gap)(nil), // 12: ermite.Gap1338+ (*CommentEdited)(nil), // 12: ermite.CommentEdited
1079- (*RunUpdated)(nil), // 13: ermite.RunUpdated1339+ (*CommentDeleted)(nil), // 13: ermite.CommentDeleted
1080- (*JobUpdated)(nil), // 14: ermite.JobUpdated1340+ (*CommentResolved)(nil), // 14: ermite.CommentResolved
1081- (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp1341+ (*Gap)(nil), // 15: ermite.Gap
1082- (*Repo)(nil), // 16: ermite.Repo1342+ (*RunUpdated)(nil), // 16: ermite.RunUpdated
1083- (*MergeRequest)(nil), // 17: ermite.MergeRequest1343+ (*JobUpdated)(nil), // 17: ermite.JobUpdated
1084- (*Comment)(nil), // 18: ermite.Comment1344+ (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp
1085- (*Run)(nil), // 19: ermite.Run1345+ (*Repo)(nil), // 19: ermite.Repo
1086- (*RunJob)(nil), // 20: ermite.RunJob1346+ (*MergeRequest)(nil), // 20: ermite.MergeRequest
1347+ (*Comment)(nil), // 21: ermite.Comment
1348+ (*Run)(nil), // 22: ermite.Run
1349+ (*RunJob)(nil), // 23: ermite.RunJob
1087 }1350 }
1088 var file_ermite_event_proto_depIdxs = []int32{1351 var file_ermite_event_proto_depIdxs = []int32{
1089 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event1352 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event
1090- 15, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp1353+ 18, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
1091 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated1354 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated
1092 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated1355 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated
1093 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted1356 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted
1094 6, // 5: ermite.Event.pushed:type_name -> ermite.Pushed1357 6, // 5: ermite.Event.pushed:type_name -> ermite.Pushed
1095- 12, // 6: ermite.Event.gap:type_name -> ermite.Gap1358+ 15, // 6: ermite.Event.gap:type_name -> ermite.Gap
1096 8, // 7: ermite.Event.merge_request_opened:type_name -> ermite.MergeRequestOpened1359 8, // 7: ermite.Event.merge_request_opened:type_name -> ermite.MergeRequestOpened
1097 9, // 8: ermite.Event.merge_request_merged:type_name -> ermite.MergeRequestMerged1360 9, // 8: ermite.Event.merge_request_merged:type_name -> ermite.MergeRequestMerged
1098 10, // 9: ermite.Event.merge_request_closed:type_name -> ermite.MergeRequestClosed1361 10, // 9: ermite.Event.merge_request_closed:type_name -> ermite.MergeRequestClosed
1099 11, // 10: ermite.Event.comment_added:type_name -> ermite.CommentAdded1362 11, // 10: ermite.Event.comment_added:type_name -> ermite.CommentAdded
1100- 13, // 11: ermite.Event.run_updated:type_name -> ermite.RunUpdated1363+ 16, // 11: ermite.Event.run_updated:type_name -> ermite.RunUpdated
1101- 14, // 12: ermite.Event.job_updated:type_name -> ermite.JobUpdated1364+ 17, // 12: ermite.Event.job_updated:type_name -> ermite.JobUpdated
1102- 16, // 13: ermite.RepoCreated.repo:type_name -> ermite.Repo1365+ 12, // 13: ermite.Event.comment_edited:type_name -> ermite.CommentEdited
1103- 16, // 14: ermite.RepoUpdated.repo:type_name -> ermite.Repo1366+ 13, // 14: ermite.Event.comment_deleted:type_name -> ermite.CommentDeleted
1104- 7, // 15: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate1367+ 14, // 15: ermite.Event.comment_resolved:type_name -> ermite.CommentResolved
1105- 17, // 16: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest1368+ 19, // 16: ermite.RepoCreated.repo:type_name -> ermite.Repo
1106- 17, // 17: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest1369+ 19, // 17: ermite.RepoUpdated.repo:type_name -> ermite.Repo
1107- 17, // 18: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest1370+ 7, // 18: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
1108- 18, // 19: ermite.CommentAdded.comment:type_name -> ermite.Comment1371+ 20, // 19: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
1109- 19, // 20: ermite.RunUpdated.run:type_name -> ermite.Run1372+ 20, // 20: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
1110- 20, // 21: ermite.JobUpdated.job:type_name -> ermite.RunJob1373+ 20, // 21: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
1111- 0, // 22: ermite.EventService.Watch:input_type -> ermite.WatchRequest1374+ 21, // 22: ermite.CommentAdded.comment:type_name -> ermite.Comment
1112- 1, // 23: ermite.EventService.Watch:output_type -> ermite.WatchResponse1375+ 21, // 23: ermite.CommentEdited.comment:type_name -> ermite.Comment
1113- 23, // [23:24] is the sub-list for method output_type1376+ 21, // 24: ermite.CommentDeleted.comment:type_name -> ermite.Comment
1114- 22, // [22:23] is the sub-list for method input_type1377+ 21, // 25: ermite.CommentResolved.comment:type_name -> ermite.Comment
1115- 22, // [22:22] is the sub-list for extension type_name1378+ 22, // 26: ermite.RunUpdated.run:type_name -> ermite.Run
1116- 22, // [22:22] is the sub-list for extension extendee1379+ 23, // 27: ermite.JobUpdated.job:type_name -> ermite.RunJob
1117- 0, // [0:22] is the sub-list for field type_name1380+ 0, // 28: ermite.EventService.Watch:input_type -> ermite.WatchRequest
1381+ 1, // 29: ermite.EventService.Watch:output_type -> ermite.WatchResponse
1382+ 29, // [29:30] is the sub-list for method output_type
1383+ 28, // [28:29] is the sub-list for method input_type
1384+ 28, // [28:28] is the sub-list for extension type_name
1385+ 28, // [28:28] is the sub-list for extension extendee
1386+ 0, // [0:28] is the sub-list for field type_name
1118 }1387 }
1119 1388
1120 func init() { file_ermite_event_proto_init() }1389 func init() { file_ermite_event_proto_init() }
@@ -1137,6 +1406,9 @@ func file_ermite_event_proto_init() {
1137 (*Event_CommentAdded)(nil),1406 (*Event_CommentAdded)(nil),
1138 (*Event_RunUpdated)(nil),1407 (*Event_RunUpdated)(nil),
1139 (*Event_JobUpdated)(nil),1408 (*Event_JobUpdated)(nil),
1409+ (*Event_CommentEdited)(nil),
1410+ (*Event_CommentDeleted)(nil),
1411+ (*Event_CommentResolved)(nil),
1140 }1412 }
1141 type x struct{}1413 type x struct{}
1142 out := protoimpl.TypeBuilder{1414 out := protoimpl.TypeBuilder{
@@ -1144,7 +1416,7 @@ func file_ermite_event_proto_init() {
1144 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),1416 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1145 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),1417 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),
1146 NumEnums: 0,1418 NumEnums: 0,
1147- NumMessages: 15,1419+ NumMessages: 18,
1148 NumExtensions: 0,1420 NumExtensions: 0,
1149 NumServices: 1,1421 NumServices: 1,
1150 },1422 },
M gen/ermite/merge_request.pb.go +661 -127 generated file: collapsed
M gen/ermite/token.pb.go +19 -12 generated file: collapsed
M proto/ermite/event.proto +42 -3
@@ -17,7 +17,8 @@ service EventService {
1717 //
1818 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
1919 // for merge requests, merge_request_opened, merge_request_merged,
20- // merge_request_closed and comment_added. Each one is delivered on the
20+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
21+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
2122 // "repo:<name>" topic of its repository and on "home", subject to the
2223 // visibility of the repository.
2324 //
@@ -30,8 +31,8 @@ service EventService {
3031 // is not guaranteed, between jobs and runs or between two updates of the same
3132 // one: a client keeps the copy with the higher Run.version or
3233 // RunJob.version and drops the other. There is no event for a change of title or
33- // description, nor for a resolved comment: after a gap, or to see such
34- // changes, clients read the merge request again. A merge publishes
34+ // description: after a gap, or to see such changes, clients read the merge
35+ // request again. A merge publishes
3536 // merge_request_merged, then pushed for the target branch.
3637 //
3738 // The server keeps a bounded buffer of recent events. With resume_after set,
@@ -102,6 +103,12 @@ message Event {
102103 RunUpdated run_updated = 12;
103104 // JobUpdated: a CI job was created or changed.
104105 JobUpdated job_updated = 13;
106+ // CommentEdited: the text of a merge request comment was changed.
107+ CommentEdited comment_edited = 14;
108+ // CommentDeleted: a merge request comment was deleted.
109+ CommentDeleted comment_deleted = 15;
110+ // CommentResolved: a merge request comment was resolved or unresolved.
111+ CommentResolved comment_resolved = 16;
105112 }
106113 }
107114
@@ -170,6 +177,38 @@ message CommentAdded {
170177 Comment comment = 3;
171178 }
172179
180+// CommentEdited reports a comment of a merge request whose text was changed.
181+message CommentEdited {
182+ // Repo is the name of the repository.
183+ string repo = 1;
184+ // Number is the number of the merge request.
185+ int64 number = 2;
186+ // Comment is the comment after the edit.
187+ Comment comment = 3;
188+}
189+
190+// CommentDeleted reports a comment of a merge request that was deleted. The
191+// comment stays in the thread with deleted set and an empty text.
192+message CommentDeleted {
193+ // Repo is the name of the repository.
194+ string repo = 1;
195+ // Number is the number of the merge request.
196+ int64 number = 2;
197+ // Comment is the comment after the deletion.
198+ Comment comment = 3;
199+}
200+
201+// CommentResolved reports a comment of a merge request whose resolved state
202+// changed.
203+message CommentResolved {
204+ // Repo is the name of the repository.
205+ string repo = 1;
206+ // Number is the number of the merge request.
207+ int64 number = 2;
208+ // Comment is the comment after the change.
209+ Comment comment = 3;
210+}
211+
173212 // Gap tells the client that events were lost: the requested resume point is
174213 // older than the server's buffer. It has no fields. The client should reload
175214 // the state it displays (repositories, refs, merge requests and their
@@ -17,7 +17,8 @@ service EventService {
17 //17 //
18 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,18 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
19 // for merge requests, merge_request_opened, merge_request_merged,19 // for merge requests, merge_request_opened, merge_request_merged,
20- // merge_request_closed and comment_added. Each one is delivered on the20+ // merge_request_closed, comment_added, comment_edited, comment_deleted and
21+ // comment_resolved (a thread resolved or reopened). Each one is delivered on the
21 // "repo:<name>" topic of its repository and on "home", subject to the22 // "repo:<name>" topic of its repository and on "home", subject to the
22 // visibility of the repository.23 // visibility of the repository.
23 //24 //
@@ -30,8 +31,8 @@ service EventService {
30 // is not guaranteed, between jobs and runs or between two updates of the same31 // is not guaranteed, between jobs and runs or between two updates of the same
31 // one: a client keeps the copy with the higher Run.version or32 // one: a client keeps the copy with the higher Run.version or
32 // RunJob.version and drops the other. There is no event for a change of title or33 // RunJob.version and drops the other. There is no event for a change of title or
33- // description, nor for a resolved comment: after a gap, or to see such34+ // description: after a gap, or to see such changes, clients read the merge
34- // changes, clients read the merge request again. A merge publishes35+ // request again. A merge publishes
35 // merge_request_merged, then pushed for the target branch.36 // merge_request_merged, then pushed for the target branch.
36 //37 //
37 // The server keeps a bounded buffer of recent events. With resume_after set,38 // The server keeps a bounded buffer of recent events. With resume_after set,
@@ -102,6 +103,12 @@ message Event {
102 RunUpdated run_updated = 12;103 RunUpdated run_updated = 12;
103 // JobUpdated: a CI job was created or changed.104 // JobUpdated: a CI job was created or changed.
104 JobUpdated job_updated = 13;105 JobUpdated job_updated = 13;
106+ // CommentEdited: the text of a merge request comment was changed.
107+ CommentEdited comment_edited = 14;
108+ // CommentDeleted: a merge request comment was deleted.
109+ CommentDeleted comment_deleted = 15;
110+ // CommentResolved: a merge request comment was resolved or unresolved.
111+ CommentResolved comment_resolved = 16;
105 }112 }
106 }113 }
107 114
@@ -170,6 +177,38 @@ message CommentAdded {
170 Comment comment = 3;177 Comment comment = 3;
171 }178 }
172 179
180+// CommentEdited reports a comment of a merge request whose text was changed.
181+message CommentEdited {
182+ // Repo is the name of the repository.
183+ string repo = 1;
184+ // Number is the number of the merge request.
185+ int64 number = 2;
186+ // Comment is the comment after the edit.
187+ Comment comment = 3;
188+}
189+
190+// CommentDeleted reports a comment of a merge request that was deleted. The
191+// comment stays in the thread with deleted set and an empty text.
192+message CommentDeleted {
193+ // Repo is the name of the repository.
194+ string repo = 1;
195+ // Number is the number of the merge request.
196+ int64 number = 2;
197+ // Comment is the comment after the deletion.
198+ Comment comment = 3;
199+}
200+
201+// CommentResolved reports a comment of a merge request whose resolved state
202+// changed.
203+message CommentResolved {
204+ // Repo is the name of the repository.
205+ string repo = 1;
206+ // Number is the number of the merge request.
207+ int64 number = 2;
208+ // Comment is the comment after the change.
209+ Comment comment = 3;
210+}
211+
173 // Gap tells the client that events were lost: the requested resume point is212 // Gap tells the client that events were lost: the requested resume point is
174 // older than the server's buffer. It has no fields. The client should reload213 // older than the server's buffer. It has no fields. The client should reload
175 // the state it displays (repositories, refs, merge requests and their214 // the state it displays (repositories, refs, merge requests and their
M proto/ermite/merge_request.proto +128 -10
@@ -33,6 +33,17 @@ enum DiffSide {
3333 DIFF_SIDE_NEW = 2;
3434 }
3535
36+// Verdict is the judgement a reviewer gives with a comment.
37+enum Verdict {
38+ // Not set. The comment carries no verdict. In AddCommentRequest it means a
39+ // plain comment.
40+ VERDICT_UNSPECIFIED = 0;
41+ // The reviewer approves the merge request. The comment is created resolved.
42+ VERDICT_APPROVE = 1;
43+ // The reviewer asks for changes. The comment starts unresolved.
44+ VERDICT_CHANGES_REQUESTED = 2;
45+}
46+
3647 // MergeRequest asks to merge one branch of a repository into another branch
3748 // of the same repository. It is about a branch, not about who wrote it.
3849 message MergeRequest {
@@ -97,13 +108,50 @@ message Comment {
97108 // When it differs from the current head the line may have moved; clients
98109 // may show the comment as outdated.
99110 string commit_id = 6;
100- // Text is the plain-text content, at most 8,000 characters. Clients show it
101- // escaped, with line breaks kept.
111+ // Text is the Markdown source, at most 8,000 characters. Clients render it
112+ // as Markdown without raw HTML; "^<id>" refers to a note of the same merge
113+ // request. Empty when deleted is true, and possibly empty for a comment
114+ // that carries a verdict.
102115 string text = 7;
103116 // Resolved is true once the comment was marked resolved.
104117 bool resolved = 8;
105118 // CreatedAt is when the comment was written.
106119 google.protobuf.Timestamp created_at = 9;
120+ // ReplyTo is the id of the root comment this comment replies to. Empty for
121+ // a root comment. A reply has the path, line, start_line and side of its
122+ // root, and its commit_id is the head when the reply was written. Threads
123+ // have one level: a reply never has replies.
124+ string reply_to = 10;
125+ // StartLine is the 1-based first line of a range that ends at line, on the
126+ // same side. 0 for a comment on a single line or a general comment.
127+ int32 start_line = 11;
128+ // Verdict is the judgement given with the comment. Only a root comment has
129+ // one; it never changes after creation.
130+ Verdict verdict = 12;
131+ // EditedAt is when the text was last changed or the comment was deleted.
132+ // Unset if it never was.
133+ google.protobuf.Timestamp edited_at = 13;
134+ // Deleted is true once the author deleted the comment. Its text is then
135+ // empty; its id, anchor, replies and verdict remain.
136+ bool deleted = 14;
137+}
138+
139+// AuthorVerdict is the current verdict of one author on a merge request: the
140+// one given with the author's latest comment that carries a verdict.
141+message AuthorVerdict {
142+ // Author names who gave the verdict, like Comment.author.
143+ string author = 1;
144+ // Verdict is the current verdict. Never VERDICT_UNSPECIFIED.
145+ Verdict verdict = 2;
146+ // CommentId is the id of the comment that carries the verdict.
147+ string comment_id = 3;
148+ // CommitId is the head of the merge request when the verdict was given.
149+ string commit_id = 4;
150+ // CreatedAt is when the verdict was given.
151+ google.protobuf.Timestamp created_at = 5;
152+ // Stale is true for an approval given on a commit that is not the current
153+ // head. A request for changes is never stale.
154+ bool stale = 6;
107155 }
108156
109157 // MergeRequestService reviews and merges branches.
@@ -143,14 +191,35 @@ service MergeRequestService {
143191 // caller last marked read with the current head. Fails with not_found if
144192 // the repository or the number is unknown.
145193 rpc GetMergeRequest(GetMergeRequestRequest) returns (GetMergeRequestResponse);
146- // AddComment adds a general comment or a comment on a line of the diff.
147- // Needs the mr:write scope. Fails with invalid_argument if the text breaks
148- // a rule or if path, line and side do not designate a line of the current
149- // diff of the merge request, and with failed_precondition if the merge
150- // request is not open.
194+ // AddComment adds a general comment, a comment on a line or a range of
195+ // lines of the diff, or a reply to a root comment. Needs the mr:write
196+ // scope; setting a verdict also needs the mr:review scope (permission_denied
197+ // without it). Fails with invalid_argument if the text breaks a rule (it may
198+ // be empty only with a verdict), if path, line, start_line and side do not
199+ // designate lines of the current diff of the merge request, if reply_to is
200+ // not the id of a root comment that is not deleted, if a reply sets path,
201+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
202+ // with failed_precondition if the merge request is not open. A comment with
203+ // VERDICT_APPROVE is created resolved.
151204 rpc AddComment(AddCommentRequest) returns (AddCommentResponse);
152- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write
153- // scope. Fails with not_found if the comment is unknown and with
205+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
206+ // only the author of the comment can edit it (permission_denied
207+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
208+ // be empty only for a comment with a verdict), with not_found if the comment
209+ // is unknown, and with failed_precondition if the merge request is not open
210+ // or the comment was deleted. Sending the current text succeeds and changes
211+ // nothing.
212+ rpc EditComment(EditCommentRequest) returns (EditCommentResponse);
213+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
214+ // while its id, anchor, replies and verdict remain. Needs the mr:write
215+ // scope, and only the author of the comment can delete it
216+ // (permission_denied otherwise). Fails with not_found if the comment is
217+ // unknown and with failed_precondition if the merge request is not open.
218+ // Deleting a comment already deleted succeeds and changes nothing.
219+ rpc DeleteComment(DeleteCommentRequest) returns (DeleteCommentResponse);
220+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
221+ // scope. Resolution belongs to the root comment: on a reply it fails with
222+ // invalid_argument. Fails with not_found if the comment is unknown and with
154223 // failed_precondition if the merge request is not open. Setting the state
155224 // the comment already has succeeds and changes nothing.
156225 rpc ResolveComment(ResolveCommentRequest) returns (ResolveCommentResponse);
@@ -272,6 +341,9 @@ message GetMergeRequestResponse {
272341 // diff against the target. A client should tell the reader to review the
273342 // whole change again.
274343 bool last_read_lost = 9;
344+ // Verdicts are the current verdicts, one per author who gave one, ordered
345+ // by the comment that carries them, oldest first.
346+ repeated AuthorVerdict verdicts = 10;
275347 }
276348
277349 // AddCommentRequest describes the comment to add.
@@ -290,8 +362,19 @@ message AddCommentRequest {
290362 int32 line = 4;
291363 // Side is the side line counts on. Required when path is set.
292364 DiffSide side = 5;
293- // Text is the plain-text content. Required.
365+ // Text is the Markdown source. Required, except when verdict is set.
294366 string text = 6;
367+ // ReplyTo is the id of the root comment to reply to. Empty for a new root
368+ // comment. A reply takes the anchor of its root: path, line, start_line,
369+ // side and verdict must then be unset.
370+ string reply_to = 7;
371+ // StartLine is the 1-based first line of a range ending at line. 0 for a
372+ // single line. Needs path; it must be lower than line, and both ends must
373+ // be lines of the diff on side.
374+ int32 start_line = 8;
375+ // Verdict is the judgement to give. Needs the mr:review scope and a root
376+ // comment. VERDICT_UNSPECIFIED for a plain comment.
377+ Verdict verdict = 9;
295378 }
296379
297380 // AddCommentResponse holds the new comment.
@@ -300,6 +383,41 @@ message AddCommentResponse {
300383 Comment comment = 1;
301384 }
302385
386+// EditCommentRequest describes the new text of a comment.
387+message EditCommentRequest {
388+ // Repo is the repository name.
389+ string repo = 1;
390+ // Number is the merge request number.
391+ int64 number = 2;
392+ // CommentId is the Comment.id to edit.
393+ string comment_id = 3;
394+ // Text is the new Markdown source. Required, except for a comment that
395+ // carries a verdict.
396+ string text = 4;
397+}
398+
399+// EditCommentResponse holds the comment after the edit.
400+message EditCommentResponse {
401+ // Comment is the updated comment.
402+ Comment comment = 1;
403+}
404+
405+// DeleteCommentRequest names the comment to delete.
406+message DeleteCommentRequest {
407+ // Repo is the repository name.
408+ string repo = 1;
409+ // Number is the merge request number.
410+ int64 number = 2;
411+ // CommentId is the Comment.id to delete.
412+ string comment_id = 3;
413+}
414+
415+// DeleteCommentResponse holds the comment after the deletion.
416+message DeleteCommentResponse {
417+ // Comment is the deleted comment.
418+ Comment comment = 1;
419+}
420+
303421 // ResolveCommentRequest changes the resolved state of a comment.
304422 message ResolveCommentRequest {
305423 // Repo is the repository name.
@@ -33,6 +33,17 @@ enum DiffSide {
33 DIFF_SIDE_NEW = 2;33 DIFF_SIDE_NEW = 2;
34 }34 }
35 35
36+// Verdict is the judgement a reviewer gives with a comment.
37+enum Verdict {
38+ // Not set. The comment carries no verdict. In AddCommentRequest it means a
39+ // plain comment.
40+ VERDICT_UNSPECIFIED = 0;
41+ // The reviewer approves the merge request. The comment is created resolved.
42+ VERDICT_APPROVE = 1;
43+ // The reviewer asks for changes. The comment starts unresolved.
44+ VERDICT_CHANGES_REQUESTED = 2;
45+}
46+
36 // MergeRequest asks to merge one branch of a repository into another branch47 // MergeRequest asks to merge one branch of a repository into another branch
37 // of the same repository. It is about a branch, not about who wrote it.48 // of the same repository. It is about a branch, not about who wrote it.
38 message MergeRequest {49 message MergeRequest {
@@ -97,13 +108,50 @@ message Comment {
97 // When it differs from the current head the line may have moved; clients108 // When it differs from the current head the line may have moved; clients
98 // may show the comment as outdated.109 // may show the comment as outdated.
99 string commit_id = 6;110 string commit_id = 6;
100- // Text is the plain-text content, at most 8,000 characters. Clients show it111+ // Text is the Markdown source, at most 8,000 characters. Clients render it
101- // escaped, with line breaks kept.112+ // as Markdown without raw HTML; "^<id>" refers to a note of the same merge
113+ // request. Empty when deleted is true, and possibly empty for a comment
114+ // that carries a verdict.
102 string text = 7;115 string text = 7;
103 // Resolved is true once the comment was marked resolved.116 // Resolved is true once the comment was marked resolved.
104 bool resolved = 8;117 bool resolved = 8;
105 // CreatedAt is when the comment was written.118 // CreatedAt is when the comment was written.
106 google.protobuf.Timestamp created_at = 9;119 google.protobuf.Timestamp created_at = 9;
120+ // ReplyTo is the id of the root comment this comment replies to. Empty for
121+ // a root comment. A reply has the path, line, start_line and side of its
122+ // root, and its commit_id is the head when the reply was written. Threads
123+ // have one level: a reply never has replies.
124+ string reply_to = 10;
125+ // StartLine is the 1-based first line of a range that ends at line, on the
126+ // same side. 0 for a comment on a single line or a general comment.
127+ int32 start_line = 11;
128+ // Verdict is the judgement given with the comment. Only a root comment has
129+ // one; it never changes after creation.
130+ Verdict verdict = 12;
131+ // EditedAt is when the text was last changed or the comment was deleted.
132+ // Unset if it never was.
133+ google.protobuf.Timestamp edited_at = 13;
134+ // Deleted is true once the author deleted the comment. Its text is then
135+ // empty; its id, anchor, replies and verdict remain.
136+ bool deleted = 14;
137+}
138+
139+// AuthorVerdict is the current verdict of one author on a merge request: the
140+// one given with the author's latest comment that carries a verdict.
141+message AuthorVerdict {
142+ // Author names who gave the verdict, like Comment.author.
143+ string author = 1;
144+ // Verdict is the current verdict. Never VERDICT_UNSPECIFIED.
145+ Verdict verdict = 2;
146+ // CommentId is the id of the comment that carries the verdict.
147+ string comment_id = 3;
148+ // CommitId is the head of the merge request when the verdict was given.
149+ string commit_id = 4;
150+ // CreatedAt is when the verdict was given.
151+ google.protobuf.Timestamp created_at = 5;
152+ // Stale is true for an approval given on a commit that is not the current
153+ // head. A request for changes is never stale.
154+ bool stale = 6;
107 }155 }
108 156
109 // MergeRequestService reviews and merges branches.157 // MergeRequestService reviews and merges branches.
@@ -143,14 +191,35 @@ service MergeRequestService {
143 // caller last marked read with the current head. Fails with not_found if191 // caller last marked read with the current head. Fails with not_found if
144 // the repository or the number is unknown.192 // the repository or the number is unknown.
145 rpc GetMergeRequest(GetMergeRequestRequest) returns (GetMergeRequestResponse);193 rpc GetMergeRequest(GetMergeRequestRequest) returns (GetMergeRequestResponse);
146- // AddComment adds a general comment or a comment on a line of the diff.194+ // AddComment adds a general comment, a comment on a line or a range of
147- // Needs the mr:write scope. Fails with invalid_argument if the text breaks195+ // lines of the diff, or a reply to a root comment. Needs the mr:write
148- // a rule or if path, line and side do not designate a line of the current196+ // scope; setting a verdict also needs the mr:review scope (permission_denied
149- // diff of the merge request, and with failed_precondition if the merge197+ // without it). Fails with invalid_argument if the text breaks a rule (it may
150- // request is not open.198+ // be empty only with a verdict), if path, line, start_line and side do not
199+ // designate lines of the current diff of the merge request, if reply_to is
200+ // not the id of a root comment that is not deleted, if a reply sets path,
201+ // line, start_line, side or verdict, or if a verdict is set on a reply; and
202+ // with failed_precondition if the merge request is not open. A comment with
203+ // VERDICT_APPROVE is created resolved.
151 rpc AddComment(AddCommentRequest) returns (AddCommentResponse);204 rpc AddComment(AddCommentRequest) returns (AddCommentResponse);
152- // ResolveComment marks a comment resolved or unresolved. Needs the mr:write205+ // EditComment replaces the text of a comment. Needs the mr:write scope, and
153- // scope. Fails with not_found if the comment is unknown and with206+ // only the author of the comment can edit it (permission_denied
207+ // otherwise). Fails with invalid_argument if the text breaks a rule (it may
208+ // be empty only for a comment with a verdict), with not_found if the comment
209+ // is unknown, and with failed_precondition if the merge request is not open
210+ // or the comment was deleted. Sending the current text succeeds and changes
211+ // nothing.
212+ rpc EditComment(EditCommentRequest) returns (EditCommentResponse);
213+ // DeleteComment deletes a comment: its text is emptied and deleted is set,
214+ // while its id, anchor, replies and verdict remain. Needs the mr:write
215+ // scope, and only the author of the comment can delete it
216+ // (permission_denied otherwise). Fails with not_found if the comment is
217+ // unknown and with failed_precondition if the merge request is not open.
218+ // Deleting a comment already deleted succeeds and changes nothing.
219+ rpc DeleteComment(DeleteCommentRequest) returns (DeleteCommentResponse);
220+ // ResolveComment marks a thread resolved or unresolved. Needs the mr:write
221+ // scope. Resolution belongs to the root comment: on a reply it fails with
222+ // invalid_argument. Fails with not_found if the comment is unknown and with
154 // failed_precondition if the merge request is not open. Setting the state223 // failed_precondition if the merge request is not open. Setting the state
155 // the comment already has succeeds and changes nothing.224 // the comment already has succeeds and changes nothing.
156 rpc ResolveComment(ResolveCommentRequest) returns (ResolveCommentResponse);225 rpc ResolveComment(ResolveCommentRequest) returns (ResolveCommentResponse);
@@ -272,6 +341,9 @@ message GetMergeRequestResponse {
272 // diff against the target. A client should tell the reader to review the341 // diff against the target. A client should tell the reader to review the
273 // whole change again.342 // whole change again.
274 bool last_read_lost = 9;343 bool last_read_lost = 9;
344+ // Verdicts are the current verdicts, one per author who gave one, ordered
345+ // by the comment that carries them, oldest first.
346+ repeated AuthorVerdict verdicts = 10;
275 }347 }
276 348
277 // AddCommentRequest describes the comment to add.349 // AddCommentRequest describes the comment to add.
@@ -290,8 +362,19 @@ message AddCommentRequest {
290 int32 line = 4;362 int32 line = 4;
291 // Side is the side line counts on. Required when path is set.363 // Side is the side line counts on. Required when path is set.
292 DiffSide side = 5;364 DiffSide side = 5;
293- // Text is the plain-text content. Required.365+ // Text is the Markdown source. Required, except when verdict is set.
294 string text = 6;366 string text = 6;
367+ // ReplyTo is the id of the root comment to reply to. Empty for a new root
368+ // comment. A reply takes the anchor of its root: path, line, start_line,
369+ // side and verdict must then be unset.
370+ string reply_to = 7;
371+ // StartLine is the 1-based first line of a range ending at line. 0 for a
372+ // single line. Needs path; it must be lower than line, and both ends must
373+ // be lines of the diff on side.
374+ int32 start_line = 8;
375+ // Verdict is the judgement to give. Needs the mr:review scope and a root
376+ // comment. VERDICT_UNSPECIFIED for a plain comment.
377+ Verdict verdict = 9;
295 }378 }
296 379
297 // AddCommentResponse holds the new comment.380 // AddCommentResponse holds the new comment.
@@ -300,6 +383,41 @@ message AddCommentResponse {
300 Comment comment = 1;383 Comment comment = 1;
301 }384 }
302 385
386+// EditCommentRequest describes the new text of a comment.
387+message EditCommentRequest {
388+ // Repo is the repository name.
389+ string repo = 1;
390+ // Number is the merge request number.
391+ int64 number = 2;
392+ // CommentId is the Comment.id to edit.
393+ string comment_id = 3;
394+ // Text is the new Markdown source. Required, except for a comment that
395+ // carries a verdict.
396+ string text = 4;
397+}
398+
399+// EditCommentResponse holds the comment after the edit.
400+message EditCommentResponse {
401+ // Comment is the updated comment.
402+ Comment comment = 1;
403+}
404+
405+// DeleteCommentRequest names the comment to delete.
406+message DeleteCommentRequest {
407+ // Repo is the repository name.
408+ string repo = 1;
409+ // Number is the merge request number.
410+ int64 number = 2;
411+ // CommentId is the Comment.id to delete.
412+ string comment_id = 3;
413+}
414+
415+// DeleteCommentResponse holds the comment after the deletion.
416+message DeleteCommentResponse {
417+ // Comment is the deleted comment.
418+ Comment comment = 1;
419+}
420+
303 // ResolveCommentRequest changes the resolved state of a comment.421 // ResolveCommentRequest changes the resolved state of a comment.
304 message ResolveCommentRequest {422 message ResolveCommentRequest {
305 // Repo is the repository name.423 // Repo is the repository name.
M proto/ermite/token.proto +3 -0
@@ -39,6 +39,9 @@ enum Scope {
3939 // SCOPE_TOKEN_ADMIN allows creating, listing and revoking tokens. Wire name:
4040 // token:admin.
4141 SCOPE_TOKEN_ADMIN = 9;
42+ // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on
43+ // merge request notes. Wire name: mr:review.
44+ SCOPE_MR_REVIEW = 10;
4245 }
4346
4447 // Token describes a stored token. It never contains the secret nor its hash.
@@ -39,6 +39,9 @@ enum Scope {
39 // SCOPE_TOKEN_ADMIN allows creating, listing and revoking tokens. Wire name:39 // SCOPE_TOKEN_ADMIN allows creating, listing and revoking tokens. Wire name:
40 // token:admin.40 // token:admin.
41 SCOPE_TOKEN_ADMIN = 9;41 SCOPE_TOKEN_ADMIN = 9;
42+ // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on
43+ // merge request notes. Wire name: mr:review.
44+ SCOPE_MR_REVIEW = 10;
42 }45 }
43 46
44 // Token describes a stored token. It never contains the secret nor its hash.47 // Token describes a stored token. It never contains the secret nor its hash.

Comments0 open / 0

no comments yet.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
l
merge request: the list of files (j k move, enter opens, esc back)
M
merge request: the merge menu; there 1–3 pick the mode, D deletes the branch, enter merges
R
merge request: mark the head read
esc
close a dialog, leave a field

Branches 2

Tags 18

↑↓ moveenter openesc close