Merge 81ede3b81040f2594180d0ca4f180a63b2cea9fd into ffa9a5ed3b92f780404c89cbe9288e74108a1ed0
10 files · +1123 -390
M docs/services.md +2 -2
| @@ -6,9 +6,9 @@ | |||
| 6 | 6 | | `GitService` | `ListRefs`, `GetTree`, `ListPaths`, `GetBlob` (streamed), `ListCommits`, `GetCommit` (structured diff), `ResolveRevision` | | |
| 7 | 7 | | `TokenService` | `CreateToken` (secret shown once), `ListTokens`, `RevokeToken` | | |
| 8 | 8 | | `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `MarkReady`, `MergeMergeRequest` (modes fast-forward, squash, merge commit), `MarkRead`, `EnableAutoMerge`, `CancelAutoMerge` (merge by itself once a check passed on the head and all its runs are complete; setting `allow_auto_merge`, `MergeRequest.auto_merge`, events `MergeRequestAutoMergeEnabled` and `MergeRequestAutoMergeCancelled`, `MergeRequestMerged.auto`; feature `merge_requests.auto_merge`). Open merge requests carry `mergeability` (up to date, behind, conflict, or checking) and `Watch` publishes `MergeRequestMergeability` each time a result is settled for new branch tips (feature `merge_requests.mergeability`) | | |
| 9 | - | | `IssueService` | `CreateIssue`, `ListIssues`, `GetIssue` (comments, merge requests naming the issue, `closed_by_merge_request`), `AddIssueComment`, `CloseIssue`, `ReopenIssue`; owner only: `ListPendingIssues`, `ApproveIssue`, `RejectIssue`. Features `issues`, `issues.links`. Issues share numbers with merge requests | | |
| 9 | + | | `IssueService` | `CreateIssue`, `ListIssues`, `GetIssue` (comments, merge requests naming the issue, history events, `closed_by_merge_request`), `AddIssueComment`, `CloseIssue`, `ResolveIssue`, `ReopenIssue`; owner only: `ListPendingIssues`, `ApproveIssue`, `RejectIssue`. States `OPEN`, `CLOSED`, `RESOLVED`; `ResolveIssue` needs `issue:write`. Features `issues`, `issues.links`, `issues.resolve`. Issues share numbers with merge requests | | |
| 10 | 10 | | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) | | |
| 11 | - | | `EventService` | `Watch` (streamed, resumable). Topics `home`, `repo:<name>` and `owner` (owner rights only). Events 17–21: `issue_opened`, `issue_closed`, `issue_reopened`, `issue_commented`, and `issue_submitted` (only on `owner`, no content). Event 22: `merge_request_mergeability` | | |
| 11 | + | | `EventService` | `Watch` (streamed, resumable). Topics `home`, `repo:<name>` and `owner` (owner rights only). Events 17–21: `issue_opened`, `issue_closed`, `issue_reopened`, `issue_commented`, and `issue_submitted` (only on `owner`, no content). Event 22: `merge_request_mergeability`. Event 31: `issue_resolved` | | |
| 12 | 12 | | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) | | |
| 13 | 13 | | `TrustedKeyService` | `ListTrustedKeys`, `AddTrustedKey` and `RemoveTrustedKey` (owner only). `Commit.verification` carries the result of the check (feature `commit_signatures`) | | |
| 14 | 14 | | `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `ListAnnotations`, `GetStepSummaries`, `CancelRun`, `RerunRun`, `DispatchWorkflow`, `ListWorkflows`, `DisableWorkflow`, `EnableWorkflow`, `ListChecks`, `ListRunners`, `RemoveRunner` | | |
| @@ -6,9 +6,9 @@ | |||||
| 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`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `MarkReady`, `MergeMergeRequest` (modes fast-forward, squash, merge commit), `MarkRead`, `EnableAutoMerge`, `CancelAutoMerge` (merge by itself once a check passed on the head and all its runs are complete; setting `allow_auto_merge`, `MergeRequest.auto_merge`, events `MergeRequestAutoMergeEnabled` and `MergeRequestAutoMergeCancelled`, `MergeRequestMerged.auto`; feature `merge_requests.auto_merge`). Open merge requests carry `mergeability` (up to date, behind, conflict, or checking) and `Watch` publishes `MergeRequestMergeability` each time a result is settled for new branch tips (feature `merge_requests.mergeability`) | | 8 | | `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `MarkReady`, `MergeMergeRequest` (modes fast-forward, squash, merge commit), `MarkRead`, `EnableAutoMerge`, `CancelAutoMerge` (merge by itself once a check passed on the head and all its runs are complete; setting `allow_auto_merge`, `MergeRequest.auto_merge`, events `MergeRequestAutoMergeEnabled` and `MergeRequestAutoMergeCancelled`, `MergeRequestMerged.auto`; feature `merge_requests.auto_merge`). Open merge requests carry `mergeability` (up to date, behind, conflict, or checking) and `Watch` publishes `MergeRequestMergeability` each time a result is settled for new branch tips (feature `merge_requests.mergeability`) | | ||
| 9 | - | | `IssueService` | `CreateIssue`, `ListIssues`, `GetIssue` (comments, merge requests naming the issue, `closed_by_merge_request`), `AddIssueComment`, `CloseIssue`, `ReopenIssue`; owner only: `ListPendingIssues`, `ApproveIssue`, `RejectIssue`. Features `issues`, `issues.links`. Issues share numbers with merge requests | | 9 | + | | `IssueService` | `CreateIssue`, `ListIssues`, `GetIssue` (comments, merge requests naming the issue, history events, `closed_by_merge_request`), `AddIssueComment`, `CloseIssue`, `ResolveIssue`, `ReopenIssue`; owner only: `ListPendingIssues`, `ApproveIssue`, `RejectIssue`. States `OPEN`, `CLOSED`, `RESOLVED`; `ResolveIssue` needs `issue:write`. Features `issues`, `issues.links`, `issues.resolve`. Issues share numbers with merge requests | |
| 10 | | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) | | 10 | | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) | | ||
| 11 | - | | `EventService` | `Watch` (streamed, resumable). Topics `home`, `repo:<name>` and `owner` (owner rights only). Events 17–21: `issue_opened`, `issue_closed`, `issue_reopened`, `issue_commented`, and `issue_submitted` (only on `owner`, no content). Event 22: `merge_request_mergeability` | | 11 | + | | `EventService` | `Watch` (streamed, resumable). Topics `home`, `repo:<name>` and `owner` (owner rights only). Events 17–21: `issue_opened`, `issue_closed`, `issue_reopened`, `issue_commented`, and `issue_submitted` (only on `owner`, no content). Event 22: `merge_request_mergeability`. Event 31: `issue_resolved` | |
| 12 | | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) | | 12 | | `ServerService` | `GetVersion` (version and features), `GetSigningKey`, `RotateOIDCKey` (owner only) | | ||
| 13 | | `TrustedKeyService` | `ListTrustedKeys`, `AddTrustedKey` and `RemoveTrustedKey` (owner only). `Commit.verification` carries the result of the check (feature `commit_signatures`) | | 13 | | `TrustedKeyService` | `ListTrustedKeys`, `AddTrustedKey` and `RemoveTrustedKey` (owner only). `Commit.verification` carries the result of the check (feature `commit_signatures`) | | ||
| 14 | | `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `ListAnnotations`, `GetStepSummaries`, `CancelRun`, `RerunRun`, `DispatchWorkflow`, `ListWorkflows`, `DisableWorkflow`, `EnableWorkflow`, `ListChecks`, `ListRunners`, `RemoveRunner` | | 14 | | `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `ListAnnotations`, `GetStepSummaries`, `CancelRun`, `RerunRun`, `DispatchWorkflow`, `ListWorkflows`, `DisableWorkflow`, `EnableWorkflow`, `ListChecks`, `ListRunners`, `RemoveRunner` | | ||
M gen/ermite/ermiteconnect/event.connect.go +8 -6
| @@ -49,9 +49,10 @@ type EventServiceClient interface { | |||
| 49 | 49 | // for merge requests, merge_request_opened, merge_request_merged, | |
| 50 | 50 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | |
| 51 | 51 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | |
| 52 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | |
| 53 | - | // one is delivered on the "repo:<name>" topic of its repository and on | |
| 54 | - | // "home", subject to the visibility of the repository, except | |
| 52 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and | |
| 53 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its | |
| 54 | + | // repository and on "home", subject to the visibility of the repository, | |
| 55 | + | // except | |
| 55 | 56 | // issue_submitted: it is delivered only on the "owner" topic, never on | |
| 56 | 57 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | |
| 57 | 58 | // | |
| @@ -125,9 +126,10 @@ type EventServiceHandler interface { | |||
| 125 | 126 | // for merge requests, merge_request_opened, merge_request_merged, | |
| 126 | 127 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | |
| 127 | 128 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | |
| 128 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | |
| 129 | - | // one is delivered on the "repo:<name>" topic of its repository and on | |
| 130 | - | // "home", subject to the visibility of the repository, except | |
| 129 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and | |
| 130 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its | |
| 131 | + | // repository and on "home", subject to the visibility of the repository, | |
| 132 | + | // except | |
| 131 | 133 | // issue_submitted: it is delivered only on the "owner" topic, never on | |
| 132 | 134 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | |
| 133 | 135 | // | |
| @@ -49,9 +49,10 @@ type EventServiceClient interface { | |||||
| 49 | // for merge requests, merge_request_opened, merge_request_merged, | 49 | // for merge requests, merge_request_opened, merge_request_merged, | ||
| 50 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | 50 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | ||
| 51 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | 51 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | ||
| 52 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | 52 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and |
| 53 | - | // one is delivered on the "repo:<name>" topic of its repository and on | 53 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its |
| 54 | - | // "home", subject to the visibility of the repository, except | 54 | + | // repository and on "home", subject to the visibility of the repository, |
| 55 | + | // except | |||
| 55 | // issue_submitted: it is delivered only on the "owner" topic, never on | 56 | // issue_submitted: it is delivered only on the "owner" topic, never on | ||
| 56 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | 57 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | ||
| 57 | // | 58 | // | ||
| @@ -125,9 +126,10 @@ type EventServiceHandler interface { | |||||
| 125 | // for merge requests, merge_request_opened, merge_request_merged, | 126 | // for merge requests, merge_request_opened, merge_request_merged, | ||
| 126 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | 127 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | ||
| 127 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | 128 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | ||
| 128 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | 129 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and |
| 129 | - | // one is delivered on the "repo:<name>" topic of its repository and on | 130 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its |
| 130 | - | // "home", subject to the visibility of the repository, except | 131 | + | // repository and on "home", subject to the visibility of the repository, |
| 132 | + | // except | |||
| 131 | // issue_submitted: it is delivered only on the "owner" topic, never on | 133 | // issue_submitted: it is delivered only on the "owner" topic, never on | ||
| 132 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | 134 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | ||
| 133 | // | 135 | // | ||
M gen/ermite/ermiteconnect/issue.connect.go +35 -2
| @@ -47,6 +47,9 @@ const ( | |||
| 47 | 47 | IssueServiceAddIssueCommentProcedure = "/ermite.IssueService/AddIssueComment" | |
| 48 | 48 | // IssueServiceCloseIssueProcedure is the fully-qualified name of the IssueService's CloseIssue RPC. | |
| 49 | 49 | IssueServiceCloseIssueProcedure = "/ermite.IssueService/CloseIssue" | |
| 50 | + | // IssueServiceResolveIssueProcedure is the fully-qualified name of the IssueService's ResolveIssue | |
| 51 | + | // RPC. | |
| 52 | + | IssueServiceResolveIssueProcedure = "/ermite.IssueService/ResolveIssue" | |
| 50 | 53 | // IssueServiceReopenIssueProcedure is the fully-qualified name of the IssueService's ReopenIssue | |
| 51 | 54 | // RPC. | |
| 52 | 55 | IssueServiceReopenIssueProcedure = "/ermite.IssueService/ReopenIssue" | |
| @@ -73,7 +76,10 @@ type IssueServiceClient interface { | |||
| 73 | 76 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | |
| 74 | 77 | // CloseIssue closes an issue. Needs the issue:write scope. | |
| 75 | 78 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | |
| 76 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | |
| 79 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. | |
| 80 | + | ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) | |
| 81 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |
| 82 | + | // scope. | |
| 77 | 83 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | |
| 78 | 84 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | |
| 79 | 85 | // rights only; anyone else gets NOT_FOUND. | |
| @@ -127,6 +133,12 @@ func NewIssueServiceClient(httpClient connect.HTTPClient, baseURL string, opts . | |||
| 127 | 133 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | |
| 128 | 134 | connect.WithClientOptions(opts...), | |
| 129 | 135 | ), | |
| 136 | + | resolveIssue: connect.NewClient[ermite.ResolveIssueRequest, ermite.ResolveIssueResponse]( | |
| 137 | + | httpClient, | |
| 138 | + | baseURL+IssueServiceResolveIssueProcedure, | |
| 139 | + | connect.WithSchema(issueServiceMethods.ByName("ResolveIssue")), | |
| 140 | + | connect.WithClientOptions(opts...), | |
| 141 | + | ), | |
| 130 | 142 | reopenIssue: connect.NewClient[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse]( | |
| 131 | 143 | httpClient, | |
| 132 | 144 | baseURL+IssueServiceReopenIssueProcedure, | |
| @@ -161,6 +173,7 @@ type issueServiceClient struct { | |||
| 161 | 173 | getIssue *connect.Client[ermite.GetIssueRequest, ermite.GetIssueResponse] | |
| 162 | 174 | addIssueComment *connect.Client[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse] | |
| 163 | 175 | closeIssue *connect.Client[ermite.CloseIssueRequest, ermite.CloseIssueResponse] | |
| 176 | + | resolveIssue *connect.Client[ermite.ResolveIssueRequest, ermite.ResolveIssueResponse] | |
| 164 | 177 | reopenIssue *connect.Client[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse] | |
| 165 | 178 | listPendingIssues *connect.Client[ermite.ListPendingIssuesRequest, ermite.ListPendingIssuesResponse] | |
| 166 | 179 | approveIssue *connect.Client[ermite.ApproveIssueRequest, ermite.ApproveIssueResponse] | |
| @@ -192,6 +205,11 @@ func (c *issueServiceClient) CloseIssue(ctx context.Context, req *connect.Reques | |||
| 192 | 205 | return c.closeIssue.CallUnary(ctx, req) | |
| 193 | 206 | } | |
| 194 | 207 | ||
| 208 | + | // ResolveIssue calls ermite.IssueService.ResolveIssue. | |
| 209 | + | func (c *issueServiceClient) ResolveIssue(ctx context.Context, req *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) { | |
| 210 | + | return c.resolveIssue.CallUnary(ctx, req) | |
| 211 | + | } | |
| 212 | + | ||
| 195 | 213 | // ReopenIssue calls ermite.IssueService.ReopenIssue. | |
| 196 | 214 | func (c *issueServiceClient) ReopenIssue(ctx context.Context, req *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | |
| 197 | 215 | return c.reopenIssue.CallUnary(ctx, req) | |
| @@ -224,7 +242,10 @@ type IssueServiceHandler interface { | |||
| 224 | 242 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | |
| 225 | 243 | // CloseIssue closes an issue. Needs the issue:write scope. | |
| 226 | 244 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | |
| 227 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | |
| 245 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. | |
| 246 | + | ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) | |
| 247 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |
| 248 | + | // scope. | |
| 228 | 249 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | |
| 229 | 250 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | |
| 230 | 251 | // rights only; anyone else gets NOT_FOUND. | |
| @@ -274,6 +295,12 @@ func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOpti | |||
| 274 | 295 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | |
| 275 | 296 | connect.WithHandlerOptions(opts...), | |
| 276 | 297 | ) | |
| 298 | + | issueServiceResolveIssueHandler := connect.NewUnaryHandler( | |
| 299 | + | IssueServiceResolveIssueProcedure, | |
| 300 | + | svc.ResolveIssue, | |
| 301 | + | connect.WithSchema(issueServiceMethods.ByName("ResolveIssue")), | |
| 302 | + | connect.WithHandlerOptions(opts...), | |
| 303 | + | ) | |
| 277 | 304 | issueServiceReopenIssueHandler := connect.NewUnaryHandler( | |
| 278 | 305 | IssueServiceReopenIssueProcedure, | |
| 279 | 306 | svc.ReopenIssue, | |
| @@ -310,6 +337,8 @@ func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOpti | |||
| 310 | 337 | issueServiceAddIssueCommentHandler.ServeHTTP(w, r) | |
| 311 | 338 | case IssueServiceCloseIssueProcedure: | |
| 312 | 339 | issueServiceCloseIssueHandler.ServeHTTP(w, r) | |
| 340 | + | case IssueServiceResolveIssueProcedure: | |
| 341 | + | issueServiceResolveIssueHandler.ServeHTTP(w, r) | |
| 313 | 342 | case IssueServiceReopenIssueProcedure: | |
| 314 | 343 | issueServiceReopenIssueHandler.ServeHTTP(w, r) | |
| 315 | 344 | case IssueServiceListPendingIssuesProcedure: | |
| @@ -347,6 +376,10 @@ func (UnimplementedIssueServiceHandler) CloseIssue(context.Context, *connect.Req | |||
| 347 | 376 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CloseIssue is not implemented")) | |
| 348 | 377 | } | |
| 349 | 378 | ||
| 379 | + | func (UnimplementedIssueServiceHandler) ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) { | |
| 380 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ResolveIssue is not implemented")) | |
| 381 | + | } | |
| 382 | + | ||
| 350 | 383 | func (UnimplementedIssueServiceHandler) ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | |
| 351 | 384 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ReopenIssue is not implemented")) | |
| 352 | 385 | } | |
| @@ -47,6 +47,9 @@ const ( | |||||
| 47 | IssueServiceAddIssueCommentProcedure = "/ermite.IssueService/AddIssueComment" | 47 | IssueServiceAddIssueCommentProcedure = "/ermite.IssueService/AddIssueComment" | ||
| 48 | // IssueServiceCloseIssueProcedure is the fully-qualified name of the IssueService's CloseIssue RPC. | 48 | // IssueServiceCloseIssueProcedure is the fully-qualified name of the IssueService's CloseIssue RPC. | ||
| 49 | IssueServiceCloseIssueProcedure = "/ermite.IssueService/CloseIssue" | 49 | IssueServiceCloseIssueProcedure = "/ermite.IssueService/CloseIssue" | ||
| 50 | + | // IssueServiceResolveIssueProcedure is the fully-qualified name of the IssueService's ResolveIssue | |||
| 51 | + | // RPC. | |||
| 52 | + | IssueServiceResolveIssueProcedure = "/ermite.IssueService/ResolveIssue" | |||
| 50 | // IssueServiceReopenIssueProcedure is the fully-qualified name of the IssueService's ReopenIssue | 53 | // IssueServiceReopenIssueProcedure is the fully-qualified name of the IssueService's ReopenIssue | ||
| 51 | // RPC. | 54 | // RPC. | ||
| 52 | IssueServiceReopenIssueProcedure = "/ermite.IssueService/ReopenIssue" | 55 | IssueServiceReopenIssueProcedure = "/ermite.IssueService/ReopenIssue" | ||
| @@ -73,7 +76,10 @@ type IssueServiceClient interface { | |||||
| 73 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | 76 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | ||
| 74 | // CloseIssue closes an issue. Needs the issue:write scope. | 77 | // CloseIssue closes an issue. Needs the issue:write scope. | ||
| 75 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | 78 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | ||
| 76 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | 79 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. |
| 80 | + | ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) | |||
| 81 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |||
| 82 | + | // scope. | |||
| 77 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | 83 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | ||
| 78 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | 84 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | ||
| 79 | // rights only; anyone else gets NOT_FOUND. | 85 | // rights only; anyone else gets NOT_FOUND. | ||
| @@ -127,6 +133,12 @@ func NewIssueServiceClient(httpClient connect.HTTPClient, baseURL string, opts . | |||||
| 127 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | 133 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | ||
| 128 | connect.WithClientOptions(opts...), | 134 | connect.WithClientOptions(opts...), | ||
| 129 | ), | 135 | ), | ||
| 136 | + | resolveIssue: connect.NewClient[ermite.ResolveIssueRequest, ermite.ResolveIssueResponse]( | |||
| 137 | + | httpClient, | |||
| 138 | + | baseURL+IssueServiceResolveIssueProcedure, | |||
| 139 | + | connect.WithSchema(issueServiceMethods.ByName("ResolveIssue")), | |||
| 140 | + | connect.WithClientOptions(opts...), | |||
| 141 | + | ), | |||
| 130 | reopenIssue: connect.NewClient[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse]( | 142 | reopenIssue: connect.NewClient[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse]( | ||
| 131 | httpClient, | 143 | httpClient, | ||
| 132 | baseURL+IssueServiceReopenIssueProcedure, | 144 | baseURL+IssueServiceReopenIssueProcedure, | ||
| @@ -161,6 +173,7 @@ type issueServiceClient struct { | |||||
| 161 | getIssue *connect.Client[ermite.GetIssueRequest, ermite.GetIssueResponse] | 173 | getIssue *connect.Client[ermite.GetIssueRequest, ermite.GetIssueResponse] | ||
| 162 | addIssueComment *connect.Client[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse] | 174 | addIssueComment *connect.Client[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse] | ||
| 163 | closeIssue *connect.Client[ermite.CloseIssueRequest, ermite.CloseIssueResponse] | 175 | closeIssue *connect.Client[ermite.CloseIssueRequest, ermite.CloseIssueResponse] | ||
| 176 | + | resolveIssue *connect.Client[ermite.ResolveIssueRequest, ermite.ResolveIssueResponse] | |||
| 164 | reopenIssue *connect.Client[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse] | 177 | reopenIssue *connect.Client[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse] | ||
| 165 | listPendingIssues *connect.Client[ermite.ListPendingIssuesRequest, ermite.ListPendingIssuesResponse] | 178 | listPendingIssues *connect.Client[ermite.ListPendingIssuesRequest, ermite.ListPendingIssuesResponse] | ||
| 166 | approveIssue *connect.Client[ermite.ApproveIssueRequest, ermite.ApproveIssueResponse] | 179 | approveIssue *connect.Client[ermite.ApproveIssueRequest, ermite.ApproveIssueResponse] | ||
| @@ -192,6 +205,11 @@ func (c *issueServiceClient) CloseIssue(ctx context.Context, req *connect.Reques | |||||
| 192 | return c.closeIssue.CallUnary(ctx, req) | 205 | return c.closeIssue.CallUnary(ctx, req) | ||
| 193 | } | 206 | } | ||
| 194 | 207 | ||||
| 208 | + | // ResolveIssue calls ermite.IssueService.ResolveIssue. | |||
| 209 | + | func (c *issueServiceClient) ResolveIssue(ctx context.Context, req *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) { | |||
| 210 | + | return c.resolveIssue.CallUnary(ctx, req) | |||
| 211 | + | } | |||
| 212 | + | ||||
| 195 | // ReopenIssue calls ermite.IssueService.ReopenIssue. | 213 | // ReopenIssue calls ermite.IssueService.ReopenIssue. | ||
| 196 | func (c *issueServiceClient) ReopenIssue(ctx context.Context, req *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | 214 | func (c *issueServiceClient) ReopenIssue(ctx context.Context, req *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | ||
| 197 | return c.reopenIssue.CallUnary(ctx, req) | 215 | return c.reopenIssue.CallUnary(ctx, req) | ||
| @@ -224,7 +242,10 @@ type IssueServiceHandler interface { | |||||
| 224 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | 242 | AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) | ||
| 225 | // CloseIssue closes an issue. Needs the issue:write scope. | 243 | // CloseIssue closes an issue. Needs the issue:write scope. | ||
| 226 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | 244 | CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) | ||
| 227 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | 245 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. |
| 246 | + | ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) | |||
| 247 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |||
| 248 | + | // scope. | |||
| 228 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | 249 | ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) | ||
| 229 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | 250 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | ||
| 230 | // rights only; anyone else gets NOT_FOUND. | 251 | // rights only; anyone else gets NOT_FOUND. | ||
| @@ -274,6 +295,12 @@ func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOpti | |||||
| 274 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | 295 | connect.WithSchema(issueServiceMethods.ByName("CloseIssue")), | ||
| 275 | connect.WithHandlerOptions(opts...), | 296 | connect.WithHandlerOptions(opts...), | ||
| 276 | ) | 297 | ) | ||
| 298 | + | issueServiceResolveIssueHandler := connect.NewUnaryHandler( | |||
| 299 | + | IssueServiceResolveIssueProcedure, | |||
| 300 | + | svc.ResolveIssue, | |||
| 301 | + | connect.WithSchema(issueServiceMethods.ByName("ResolveIssue")), | |||
| 302 | + | connect.WithHandlerOptions(opts...), | |||
| 303 | + | ) | |||
| 277 | issueServiceReopenIssueHandler := connect.NewUnaryHandler( | 304 | issueServiceReopenIssueHandler := connect.NewUnaryHandler( | ||
| 278 | IssueServiceReopenIssueProcedure, | 305 | IssueServiceReopenIssueProcedure, | ||
| 279 | svc.ReopenIssue, | 306 | svc.ReopenIssue, | ||
| @@ -310,6 +337,8 @@ func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOpti | |||||
| 310 | issueServiceAddIssueCommentHandler.ServeHTTP(w, r) | 337 | issueServiceAddIssueCommentHandler.ServeHTTP(w, r) | ||
| 311 | case IssueServiceCloseIssueProcedure: | 338 | case IssueServiceCloseIssueProcedure: | ||
| 312 | issueServiceCloseIssueHandler.ServeHTTP(w, r) | 339 | issueServiceCloseIssueHandler.ServeHTTP(w, r) | ||
| 340 | + | case IssueServiceResolveIssueProcedure: | |||
| 341 | + | issueServiceResolveIssueHandler.ServeHTTP(w, r) | |||
| 313 | case IssueServiceReopenIssueProcedure: | 342 | case IssueServiceReopenIssueProcedure: | ||
| 314 | issueServiceReopenIssueHandler.ServeHTTP(w, r) | 343 | issueServiceReopenIssueHandler.ServeHTTP(w, r) | ||
| 315 | case IssueServiceListPendingIssuesProcedure: | 344 | case IssueServiceListPendingIssuesProcedure: | ||
| @@ -347,6 +376,10 @@ func (UnimplementedIssueServiceHandler) CloseIssue(context.Context, *connect.Req | |||||
| 347 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CloseIssue is not implemented")) | 376 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CloseIssue is not implemented")) | ||
| 348 | } | 377 | } | ||
| 349 | 378 | ||||
| 379 | + | func (UnimplementedIssueServiceHandler) ResolveIssue(context.Context, *connect.Request[ermite.ResolveIssueRequest]) (*connect.Response[ermite.ResolveIssueResponse], error) { | |||
| 380 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ResolveIssue is not implemented")) | |||
| 381 | + | } | |||
| 382 | + | ||||
| 350 | func (UnimplementedIssueServiceHandler) ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | 383 | func (UnimplementedIssueServiceHandler) ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) { | ||
| 351 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ReopenIssue is not implemented")) | 384 | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ReopenIssue is not implemented")) | ||
| 352 | } | 385 | } | ||
M gen/ermite/event.pb.go +175 -103 generated file: collapsed
M gen/ermite/issue.pb.go +216 -83 generated file: collapsed
M gen/ermite/merge_request.pb.go +546 -174 generated file: collapsed
M issue_test.go +2 -1
| @@ -19,6 +19,7 @@ func TestIssueProcedures(t *testing.T) { | |||
| 19 | 19 | ermiteconnect.IssueServiceAddIssueCommentProcedure: "AddIssueComment", | |
| 20 | 20 | ermiteconnect.IssueServiceCloseIssueProcedure: "CloseIssue", | |
| 21 | 21 | ermiteconnect.IssueServiceReopenIssueProcedure: "ReopenIssue", | |
| 22 | + | ermiteconnect.IssueServiceResolveIssueProcedure: "ResolveIssue", | |
| 22 | 23 | ermiteconnect.IssueServiceListPendingIssuesProcedure: "ListPendingIssues", | |
| 23 | 24 | ermiteconnect.IssueServiceApproveIssueProcedure: "ApproveIssue", | |
| 24 | 25 | ermiteconnect.IssueServiceRejectIssueProcedure: "RejectIssue", | |
| @@ -58,7 +59,7 @@ func TestIssueContract(t *testing.T) { | |||
| 58 | 59 | if ermite.Scope_SCOPE_ISSUE_WRITE != 11 { | |
| 59 | 60 | t.Fatal("issue:write scope number changed") | |
| 60 | 61 | } | |
| 61 | - | for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3} { | |
| 62 | + | for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3, "ISSUE_STATE_RESOLVED": 4} { | |
| 62 | 63 | if got := ermite.IssueState_value[name]; got != want { | |
| 63 | 64 | t.Errorf("%s = %d, want %d", name, got, want) | |
| 64 | 65 | } | |
| @@ -19,6 +19,7 @@ func TestIssueProcedures(t *testing.T) { | |||||
| 19 | ermiteconnect.IssueServiceAddIssueCommentProcedure: "AddIssueComment", | 19 | ermiteconnect.IssueServiceAddIssueCommentProcedure: "AddIssueComment", | ||
| 20 | ermiteconnect.IssueServiceCloseIssueProcedure: "CloseIssue", | 20 | ermiteconnect.IssueServiceCloseIssueProcedure: "CloseIssue", | ||
| 21 | ermiteconnect.IssueServiceReopenIssueProcedure: "ReopenIssue", | 21 | ermiteconnect.IssueServiceReopenIssueProcedure: "ReopenIssue", | ||
| 22 | + | ermiteconnect.IssueServiceResolveIssueProcedure: "ResolveIssue", | |||
| 22 | ermiteconnect.IssueServiceListPendingIssuesProcedure: "ListPendingIssues", | 23 | ermiteconnect.IssueServiceListPendingIssuesProcedure: "ListPendingIssues", | ||
| 23 | ermiteconnect.IssueServiceApproveIssueProcedure: "ApproveIssue", | 24 | ermiteconnect.IssueServiceApproveIssueProcedure: "ApproveIssue", | ||
| 24 | ermiteconnect.IssueServiceRejectIssueProcedure: "RejectIssue", | 25 | ermiteconnect.IssueServiceRejectIssueProcedure: "RejectIssue", | ||
| @@ -58,7 +59,7 @@ func TestIssueContract(t *testing.T) { | |||||
| 58 | if ermite.Scope_SCOPE_ISSUE_WRITE != 11 { | 59 | if ermite.Scope_SCOPE_ISSUE_WRITE != 11 { | ||
| 59 | t.Fatal("issue:write scope number changed") | 60 | t.Fatal("issue:write scope number changed") | ||
| 60 | } | 61 | } | ||
| 61 | - | for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3} { | 62 | + | for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3, "ISSUE_STATE_RESOLVED": 4} { |
| 62 | if got := ermite.IssueState_value[name]; got != want { | 63 | if got := ermite.IssueState_value[name]; got != want { | ||
| 63 | t.Errorf("%s = %d, want %d", name, got, want) | 64 | t.Errorf("%s = %d, want %d", name, got, want) | ||
| 64 | } | 65 | } | ||
M proto/ermite/event.proto +15 -4
| @@ -21,9 +21,10 @@ service EventService { | |||
| 21 | 21 | // for merge requests, merge_request_opened, merge_request_merged, | |
| 22 | 22 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | |
| 23 | 23 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | |
| 24 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | |
| 25 | - | // one is delivered on the "repo:<name>" topic of its repository and on | |
| 26 | - | // "home", subject to the visibility of the repository, except | |
| 24 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and | |
| 25 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its | |
| 26 | + | // repository and on "home", subject to the visibility of the repository, | |
| 27 | + | // except | |
| 27 | 28 | // issue_submitted: it is delivered only on the "owner" topic, never on | |
| 28 | 29 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | |
| 29 | 30 | // | |
| @@ -153,6 +154,8 @@ message Event { | |||
| 153 | 154 | ReleaseDeleted release_deleted = 29; | |
| 154 | 155 | // ReleaseUnpublished reports a release turned into a draft after tag deletion. | |
| 155 | 156 | ReleaseUnpublished release_unpublished = 30; | |
| 157 | + | // IssueResolved: an issue was resolved. | |
| 158 | + | IssueResolved issue_resolved = 31; | |
| 156 | 159 | } | |
| 157 | 160 | } | |
| 158 | 161 | ||
| @@ -290,12 +293,20 @@ message IssueOpened { | |||
| 290 | 293 | Issue issue = 1; | |
| 291 | 294 | } | |
| 292 | 295 | ||
| 293 | - | // IssueClosed reports a closed issue. | |
| 296 | + | // IssueClosed reports a closed issue. A merge that resolves an issue sends | |
| 297 | + | // issue_resolved, not issue_closed. | |
| 294 | 298 | message IssueClosed { | |
| 295 | 299 | // Issue is the issue after closing, including its repository and number. | |
| 296 | 300 | Issue issue = 1; | |
| 297 | 301 | } | |
| 298 | 302 | ||
| 303 | + | // IssueResolved reports a resolved issue. | |
| 304 | + | message IssueResolved { | |
| 305 | + | // Issue is the issue after resolving, including its repository, number and | |
| 306 | + | // closed_by_merge_request. | |
| 307 | + | Issue issue = 1; | |
| 308 | + | } | |
| 309 | + | ||
| 299 | 310 | // IssueReopened reports a reopened issue. | |
| 300 | 311 | message IssueReopened { | |
| 301 | 312 | // Issue is the issue after reopening, including its repository and number. | |
| @@ -21,9 +21,10 @@ service EventService { | |||||
| 21 | // for merge requests, merge_request_opened, merge_request_merged, | 21 | // for merge requests, merge_request_opened, merge_request_merged, | ||
| 22 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | 22 | // merge_request_closed, comment_added, comment_edited, comment_deleted and | ||
| 23 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | 23 | // comment_resolved (a thread resolved or reopened); for issues, issue_opened, | ||
| 24 | - | // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each | 24 | + | // issue_closed, issue_resolved, issue_reopened and issue_commented, and |
| 25 | - | // one is delivered on the "repo:<name>" topic of its repository and on | 25 | + | // issue_submitted. Each one is delivered on the "repo:<name>" topic of its |
| 26 | - | // "home", subject to the visibility of the repository, except | 26 | + | // repository and on "home", subject to the visibility of the repository, |
| 27 | + | // except | |||
| 27 | // issue_submitted: it is delivered only on the "owner" topic, never on | 28 | // issue_submitted: it is delivered only on the "owner" topic, never on | ||
| 28 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | 29 | // "home" or "repo:<name>", and carries no content (see IssueSubmitted). | ||
| 29 | // | 30 | // | ||
| @@ -153,6 +154,8 @@ message Event { | |||||
| 153 | ReleaseDeleted release_deleted = 29; | 154 | ReleaseDeleted release_deleted = 29; | ||
| 154 | // ReleaseUnpublished reports a release turned into a draft after tag deletion. | 155 | // ReleaseUnpublished reports a release turned into a draft after tag deletion. | ||
| 155 | ReleaseUnpublished release_unpublished = 30; | 156 | ReleaseUnpublished release_unpublished = 30; | ||
| 157 | + | // IssueResolved: an issue was resolved. | |||
| 158 | + | IssueResolved issue_resolved = 31; | |||
| 156 | } | 159 | } | ||
| 157 | } | 160 | } | ||
| 158 | 161 | ||||
| @@ -290,12 +293,20 @@ message IssueOpened { | |||||
| 290 | Issue issue = 1; | 293 | Issue issue = 1; | ||
| 291 | } | 294 | } | ||
| 292 | 295 | ||||
| 293 | - | // IssueClosed reports a closed issue. | 296 | + | // IssueClosed reports a closed issue. A merge that resolves an issue sends |
| 297 | + | // issue_resolved, not issue_closed. | |||
| 294 | message IssueClosed { | 298 | message IssueClosed { | ||
| 295 | // Issue is the issue after closing, including its repository and number. | 299 | // Issue is the issue after closing, including its repository and number. | ||
| 296 | Issue issue = 1; | 300 | Issue issue = 1; | ||
| 297 | } | 301 | } | ||
| 298 | 302 | ||||
| 303 | + | // IssueResolved reports a resolved issue. | |||
| 304 | + | message IssueResolved { | |||
| 305 | + | // Issue is the issue after resolving, including its repository, number and | |||
| 306 | + | // closed_by_merge_request. | |||
| 307 | + | Issue issue = 1; | |||
| 308 | + | } | |||
| 309 | + | ||||
| 299 | // IssueReopened reports a reopened issue. | 310 | // IssueReopened reports a reopened issue. | ||
| 300 | message IssueReopened { | 311 | message IssueReopened { | ||
| 301 | // Issue is the issue after reopening, including its repository and number. | 312 | // Issue is the issue after reopening, including its repository and number. | ||
M proto/ermite/issue.proto +46 -15
| @@ -14,10 +14,14 @@ enum IssueState { | |||
| 14 | 14 | ISSUE_STATE_UNSPECIFIED = 0; | |
| 15 | 15 | // The issue is open. | |
| 16 | 16 | ISSUE_STATE_OPEN = 1; | |
| 17 | - | // The issue is closed. | |
| 17 | + | // The issue is closed without being resolved (won't fix, duplicate, ...). | |
| 18 | 18 | ISSUE_STATE_CLOSED = 2; | |
| 19 | 19 | // Reserved for later use: awaiting moderation, owner-only. | |
| 20 | 20 | ISSUE_STATE_PENDING = 3; | |
| 21 | + | // The issue was fixed: by the merge of a merge request with a closing | |
| 22 | + | // reference, or by hand (ResolveIssue). CLOSED means closed without being | |
| 23 | + | // resolved. | |
| 24 | + | ISSUE_STATE_RESOLVED = 4; | |
| 21 | 25 | } | |
| 22 | 26 | ||
| 23 | 27 | // Issue is a discussion in a repository. | |
| @@ -45,9 +49,10 @@ message Issue { | |||
| 45 | 49 | google.protobuf.Timestamp updated_at = 8; | |
| 46 | 50 | // CommentCount is the number of comments on the issue. | |
| 47 | 51 | int32 comment_count = 9; | |
| 48 | - | // ClosedByMergeRequest is the number of the merge request whose merge closed | |
| 49 | - | // the issue (a closing reference such as "Fixes #N"); 0 when the issue was | |
| 50 | - | // closed by hand or is open. Reset when the issue is reopened. | |
| 52 | + | // ClosedByMergeRequest is the number of the merge request whose merge | |
| 53 | + | // resolved the issue (a closing reference such as "Fixes #N"); 0 when the | |
| 54 | + | // issue was resolved by hand, is closed, or is open. Reset when the issue is | |
| 55 | + | // reopened. | |
| 51 | 56 | int64 closed_by_merge_request = 10; | |
| 52 | 57 | } | |
| 53 | 58 | ||
| @@ -86,29 +91,35 @@ message IssueComment { | |||
| 86 | 91 | // | |
| 87 | 92 | // Reading (ListIssues, GetIssue) needs the same access as reading the | |
| 88 | 93 | // repository: nothing for a public one, the repo:read scope for a private one. | |
| 89 | - | // Writing (CreateIssue, AddIssueComment, CloseIssue, ReopenIssue) needs the | |
| 94 | + | // Writing (CreateIssue, AddIssueComment, CloseIssue, ResolveIssue, | |
| 95 | + | // ReopenIssue) needs the | |
| 90 | 96 | // owner or a token with the issue:write scope on the repository; branch | |
| 91 | 97 | // prefixes do not restrict it. A caller without credentials gets | |
| 92 | 98 | // unauthenticated, one with an insufficient scope gets permission_denied, and | |
| 93 | 99 | // one that cannot read the repository gets not_found. | |
| 94 | 100 | // | |
| 95 | 101 | // A closing reference ("Fixes #N", "Closes #N", "Resolves #N") in the title, | |
| 96 | - | // description or commit messages of a merge request closes the issue when the | |
| 97 | - | // request is merged, and only then; the issue.closed event and Issue carry | |
| 98 | - | // closed_by_merge_request. Servers that report these links (GetIssueResponse. | |
| 99 | - | // references, Issue.closed_by_merge_request) list "issues.links" in | |
| 100 | - | // GetVersionResponse.features; older servers leave them empty. | |
| 102 | + | // description or commit messages of a merge request resolves the issue when the | |
| 103 | + | // request is merged, and only then: the issue gets the state RESOLVED, an | |
| 104 | + | // issue.resolved event is sent, and Issue carries closed_by_merge_request. | |
| 105 | + | // Servers that report these links (GetIssueResponse.references, | |
| 106 | + | // Issue.closed_by_merge_request) list "issues.links" in | |
| 107 | + | // GetVersionResponse.features; older servers leave them empty. Servers that | |
| 108 | + | // also keep the history of issues (GetIssueResponse.events), implement | |
| 109 | + | // ResolveIssue and the RESOLVED state list "issues.resolve". | |
| 101 | 110 | // | |
| 102 | 111 | // Text fields are normalized to NFC and stripped of control and Unicode | |
| 103 | 112 | // bidirectional characters (line breaks and tabs stay in bodies and comments). | |
| 104 | 113 | // The title is one line of 1 to 120 code points; body and comment text are at | |
| 105 | 114 | // most 10,000 code points and a comment must not be blank. A text that breaks | |
| 106 | 115 | // a rule is rejected with invalid_argument. A comment on an issue that already | |
| 107 | - | // holds 1,000 comments gives resource_exhausted. Closing an issue that is not | |
| 108 | - | // open, or reopening one that is not closed, gives failed_precondition. | |
| 116 | + | // holds 1,000 comments gives resource_exhausted. Closing or resolving an issue | |
| 117 | + | // that is not open, or reopening one that is neither closed nor resolved, | |
| 118 | + | // gives failed_precondition. | |
| 109 | 119 | // | |
| 110 | - | // The ordinary RPCs only return issues in state OPEN or CLOSED, and | |
| 111 | - | // ListIssues with state ISSUE_STATE_PENDING is invalid_argument. Submissions | |
| 120 | + | // The ordinary RPCs return issues in state OPEN, CLOSED or RESOLVED, and | |
| 121 | + | // ListIssues accepts these three states; ISSUE_STATE_PENDING is | |
| 122 | + | // invalid_argument. Submissions | |
| 112 | 123 | // from the public form wait as PendingIssue records, reachable only through | |
| 113 | 124 | // the three moderation RPCs (ListPendingIssues, ApproveIssue, RejectIssue). | |
| 114 | 125 | // These need owner rights (root, an owner session, or a token holding every | |
| @@ -126,7 +137,10 @@ service IssueService { | |||
| 126 | 137 | rpc AddIssueComment(AddIssueCommentRequest) returns (AddIssueCommentResponse); | |
| 127 | 138 | // CloseIssue closes an issue. Needs the issue:write scope. | |
| 128 | 139 | rpc CloseIssue(CloseIssueRequest) returns (CloseIssueResponse); | |
| 129 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | |
| 140 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. | |
| 141 | + | rpc ResolveIssue(ResolveIssueRequest) returns (ResolveIssueResponse); | |
| 142 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |
| 143 | + | // scope. | |
| 130 | 144 | rpc ReopenIssue(ReopenIssueRequest) returns (ReopenIssueResponse); | |
| 131 | 145 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | |
| 132 | 146 | // rights only; anyone else gets NOT_FOUND. | |
| @@ -196,6 +210,9 @@ message GetIssueResponse { | |||
| 196 | 210 | // References are the merge requests naming the issue, ascending by number, | |
| 197 | 211 | // at most 100. | |
| 198 | 212 | repeated IssueReference references = 3; | |
| 213 | + | // Events are the history of the issue, oldest first, at most 500 (a server | |
| 214 | + | // limit). Clients interleave them with the comments by created_at. | |
| 215 | + | repeated IssueEvent events = 4; | |
| 199 | 216 | } | |
| 200 | 217 | ||
| 201 | 218 | // AddIssueCommentRequest describes the comment to add. | |
| @@ -228,6 +245,20 @@ message CloseIssueResponse { | |||
| 228 | 245 | Issue issue = 1; | |
| 229 | 246 | } | |
| 230 | 247 | ||
| 248 | + | // ResolveIssueRequest names the issue to resolve. | |
| 249 | + | message ResolveIssueRequest { | |
| 250 | + | // Repo is the repository name. | |
| 251 | + | string repo = 1; | |
| 252 | + | // Number is the issue number. | |
| 253 | + | int64 number = 2; | |
| 254 | + | } | |
| 255 | + | ||
| 256 | + | // ResolveIssueResponse holds the issue after resolving. | |
| 257 | + | message ResolveIssueResponse { | |
| 258 | + | // Issue is the resolved issue. | |
| 259 | + | Issue issue = 1; | |
| 260 | + | } | |
| 261 | + | ||
| 231 | 262 | // ReopenIssueRequest names the issue to reopen. | |
| 232 | 263 | message ReopenIssueRequest { | |
| 233 | 264 | // Repo is the repository name. | |
| @@ -14,10 +14,14 @@ enum IssueState { | |||||
| 14 | ISSUE_STATE_UNSPECIFIED = 0; | 14 | ISSUE_STATE_UNSPECIFIED = 0; | ||
| 15 | // The issue is open. | 15 | // The issue is open. | ||
| 16 | ISSUE_STATE_OPEN = 1; | 16 | ISSUE_STATE_OPEN = 1; | ||
| 17 | - | // The issue is closed. | 17 | + | // The issue is closed without being resolved (won't fix, duplicate, ...). |
| 18 | ISSUE_STATE_CLOSED = 2; | 18 | ISSUE_STATE_CLOSED = 2; | ||
| 19 | // Reserved for later use: awaiting moderation, owner-only. | 19 | // Reserved for later use: awaiting moderation, owner-only. | ||
| 20 | ISSUE_STATE_PENDING = 3; | 20 | ISSUE_STATE_PENDING = 3; | ||
| 21 | + | // The issue was fixed: by the merge of a merge request with a closing | |||
| 22 | + | // reference, or by hand (ResolveIssue). CLOSED means closed without being | |||
| 23 | + | // resolved. | |||
| 24 | + | ISSUE_STATE_RESOLVED = 4; | |||
| 21 | } | 25 | } | ||
| 22 | 26 | ||||
| 23 | // Issue is a discussion in a repository. | 27 | // Issue is a discussion in a repository. | ||
| @@ -45,9 +49,10 @@ message Issue { | |||||
| 45 | google.protobuf.Timestamp updated_at = 8; | 49 | google.protobuf.Timestamp updated_at = 8; | ||
| 46 | // CommentCount is the number of comments on the issue. | 50 | // CommentCount is the number of comments on the issue. | ||
| 47 | int32 comment_count = 9; | 51 | int32 comment_count = 9; | ||
| 48 | - | // ClosedByMergeRequest is the number of the merge request whose merge closed | 52 | + | // ClosedByMergeRequest is the number of the merge request whose merge |
| 49 | - | // the issue (a closing reference such as "Fixes #N"); 0 when the issue was | 53 | + | // resolved the issue (a closing reference such as "Fixes #N"); 0 when the |
| 50 | - | // closed by hand or is open. Reset when the issue is reopened. | 54 | + | // issue was resolved by hand, is closed, or is open. Reset when the issue is |
| 55 | + | // reopened. | |||
| 51 | int64 closed_by_merge_request = 10; | 56 | int64 closed_by_merge_request = 10; | ||
| 52 | } | 57 | } | ||
| 53 | 58 | ||||
| @@ -86,29 +91,35 @@ message IssueComment { | |||||
| 86 | // | 91 | // | ||
| 87 | // Reading (ListIssues, GetIssue) needs the same access as reading the | 92 | // Reading (ListIssues, GetIssue) needs the same access as reading the | ||
| 88 | // repository: nothing for a public one, the repo:read scope for a private one. | 93 | // repository: nothing for a public one, the repo:read scope for a private one. | ||
| 89 | - | // Writing (CreateIssue, AddIssueComment, CloseIssue, ReopenIssue) needs the | 94 | + | // Writing (CreateIssue, AddIssueComment, CloseIssue, ResolveIssue, |
| 95 | + | // ReopenIssue) needs the | |||
| 90 | // owner or a token with the issue:write scope on the repository; branch | 96 | // owner or a token with the issue:write scope on the repository; branch | ||
| 91 | // prefixes do not restrict it. A caller without credentials gets | 97 | // prefixes do not restrict it. A caller without credentials gets | ||
| 92 | // unauthenticated, one with an insufficient scope gets permission_denied, and | 98 | // unauthenticated, one with an insufficient scope gets permission_denied, and | ||
| 93 | // one that cannot read the repository gets not_found. | 99 | // one that cannot read the repository gets not_found. | ||
| 94 | // | 100 | // | ||
| 95 | // A closing reference ("Fixes #N", "Closes #N", "Resolves #N") in the title, | 101 | // A closing reference ("Fixes #N", "Closes #N", "Resolves #N") in the title, | ||
| 96 | - | // description or commit messages of a merge request closes the issue when the | 102 | + | // description or commit messages of a merge request resolves the issue when the |
| 97 | - | // request is merged, and only then; the issue.closed event and Issue carry | 103 | + | // request is merged, and only then: the issue gets the state RESOLVED, an |
| 98 | - | // closed_by_merge_request. Servers that report these links (GetIssueResponse. | 104 | + | // issue.resolved event is sent, and Issue carries closed_by_merge_request. |
| 99 | - | // references, Issue.closed_by_merge_request) list "issues.links" in | 105 | + | // Servers that report these links (GetIssueResponse.references, |
| 100 | - | // GetVersionResponse.features; older servers leave them empty. | 106 | + | // Issue.closed_by_merge_request) list "issues.links" in |
| 107 | + | // GetVersionResponse.features; older servers leave them empty. Servers that | |||
| 108 | + | // also keep the history of issues (GetIssueResponse.events), implement | |||
| 109 | + | // ResolveIssue and the RESOLVED state list "issues.resolve". | |||
| 101 | // | 110 | // | ||
| 102 | // Text fields are normalized to NFC and stripped of control and Unicode | 111 | // Text fields are normalized to NFC and stripped of control and Unicode | ||
| 103 | // bidirectional characters (line breaks and tabs stay in bodies and comments). | 112 | // bidirectional characters (line breaks and tabs stay in bodies and comments). | ||
| 104 | // The title is one line of 1 to 120 code points; body and comment text are at | 113 | // The title is one line of 1 to 120 code points; body and comment text are at | ||
| 105 | // most 10,000 code points and a comment must not be blank. A text that breaks | 114 | // most 10,000 code points and a comment must not be blank. A text that breaks | ||
| 106 | // a rule is rejected with invalid_argument. A comment on an issue that already | 115 | // a rule is rejected with invalid_argument. A comment on an issue that already | ||
| 107 | - | // holds 1,000 comments gives resource_exhausted. Closing an issue that is not | 116 | + | // holds 1,000 comments gives resource_exhausted. Closing or resolving an issue |
| 108 | - | // open, or reopening one that is not closed, gives failed_precondition. | 117 | + | // that is not open, or reopening one that is neither closed nor resolved, |
| 118 | + | // gives failed_precondition. | |||
| 109 | // | 119 | // | ||
| 110 | - | // The ordinary RPCs only return issues in state OPEN or CLOSED, and | 120 | + | // The ordinary RPCs return issues in state OPEN, CLOSED or RESOLVED, and |
| 111 | - | // ListIssues with state ISSUE_STATE_PENDING is invalid_argument. Submissions | 121 | + | // ListIssues accepts these three states; ISSUE_STATE_PENDING is |
| 122 | + | // invalid_argument. Submissions | |||
| 112 | // from the public form wait as PendingIssue records, reachable only through | 123 | // from the public form wait as PendingIssue records, reachable only through | ||
| 113 | // the three moderation RPCs (ListPendingIssues, ApproveIssue, RejectIssue). | 124 | // the three moderation RPCs (ListPendingIssues, ApproveIssue, RejectIssue). | ||
| 114 | // These need owner rights (root, an owner session, or a token holding every | 125 | // These need owner rights (root, an owner session, or a token holding every | ||
| @@ -126,7 +137,10 @@ service IssueService { | |||||
| 126 | rpc AddIssueComment(AddIssueCommentRequest) returns (AddIssueCommentResponse); | 137 | rpc AddIssueComment(AddIssueCommentRequest) returns (AddIssueCommentResponse); | ||
| 127 | // CloseIssue closes an issue. Needs the issue:write scope. | 138 | // CloseIssue closes an issue. Needs the issue:write scope. | ||
| 128 | rpc CloseIssue(CloseIssueRequest) returns (CloseIssueResponse); | 139 | rpc CloseIssue(CloseIssueRequest) returns (CloseIssueResponse); | ||
| 129 | - | // ReopenIssue reopens an issue. Needs the issue:write scope. | 140 | + | // ResolveIssue marks an open issue as resolved. Needs the issue:write scope. |
| 141 | + | rpc ResolveIssue(ResolveIssueRequest) returns (ResolveIssueResponse); | |||
| 142 | + | // ReopenIssue reopens a closed or resolved issue. Needs the issue:write | |||
| 143 | + | // scope. | |||
| 130 | rpc ReopenIssue(ReopenIssueRequest) returns (ReopenIssueResponse); | 144 | rpc ReopenIssue(ReopenIssueRequest) returns (ReopenIssueResponse); | ||
| 131 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | 145 | // ListPendingIssues lists issues awaiting moderation, oldest first. Owner | ||
| 132 | // rights only; anyone else gets NOT_FOUND. | 146 | // rights only; anyone else gets NOT_FOUND. | ||
| @@ -196,6 +210,9 @@ message GetIssueResponse { | |||||
| 196 | // References are the merge requests naming the issue, ascending by number, | 210 | // References are the merge requests naming the issue, ascending by number, | ||
| 197 | // at most 100. | 211 | // at most 100. | ||
| 198 | repeated IssueReference references = 3; | 212 | repeated IssueReference references = 3; | ||
| 213 | + | // Events are the history of the issue, oldest first, at most 500 (a server | |||
| 214 | + | // limit). Clients interleave them with the comments by created_at. | |||
| 215 | + | repeated IssueEvent events = 4; | |||
| 199 | } | 216 | } | ||
| 200 | 217 | ||||
| 201 | // AddIssueCommentRequest describes the comment to add. | 218 | // AddIssueCommentRequest describes the comment to add. | ||
| @@ -228,6 +245,20 @@ message CloseIssueResponse { | |||||
| 228 | Issue issue = 1; | 245 | Issue issue = 1; | ||
| 229 | } | 246 | } | ||
| 230 | 247 | ||||
| 248 | + | // ResolveIssueRequest names the issue to resolve. | |||
| 249 | + | message ResolveIssueRequest { | |||
| 250 | + | // Repo is the repository name. | |||
| 251 | + | string repo = 1; | |||
| 252 | + | // Number is the issue number. | |||
| 253 | + | int64 number = 2; | |||
| 254 | + | } | |||
| 255 | + | ||||
| 256 | + | // ResolveIssueResponse holds the issue after resolving. | |||
| 257 | + | message ResolveIssueResponse { | |||
| 258 | + | // Issue is the resolved issue. | |||
| 259 | + | Issue issue = 1; | |||
| 260 | + | } | |||
| 261 | + | ||||
| 231 | // ReopenIssueRequest names the issue to reopen. | 262 | // ReopenIssueRequest names the issue to reopen. | ||
| 232 | message ReopenIssueRequest { | 263 | message ReopenIssueRequest { | ||
| 233 | // Repo is the repository name. | 264 | // Repo is the repository name. | ||
M proto/ermite/merge_request.proto +78 -0
| @@ -402,6 +402,76 @@ message ListMergeRequestsResponse { | |||
| 402 | 402 | string next_page_token = 2; | |
| 403 | 403 | } | |
| 404 | 404 | ||
| 405 | + | // MergeRequestIssueState is where an issue named by a merge request is in its | |
| 406 | + | // life. Values share their numbers with IssueState (3, awaiting moderation, | |
| 407 | + | // is never shown here). It exists because issue.proto imports this file and | |
| 408 | + | // cannot be imported back. | |
| 409 | + | enum MergeRequestIssueState { | |
| 410 | + | // Not set. Never returned by the server. | |
| 411 | + | MERGE_REQUEST_ISSUE_STATE_UNSPECIFIED = 0; | |
| 412 | + | // The issue is open. | |
| 413 | + | MERGE_REQUEST_ISSUE_STATE_OPEN = 1; | |
| 414 | + | // The issue is closed without being resolved. | |
| 415 | + | MERGE_REQUEST_ISSUE_STATE_CLOSED = 2; | |
| 416 | + | // The issue was resolved, by a merge or by hand. | |
| 417 | + | MERGE_REQUEST_ISSUE_STATE_RESOLVED = 4; | |
| 418 | + | } | |
| 419 | + | ||
| 420 | + | // MergeRequestIssue is an issue of the same repository that a merge request | |
| 421 | + | // names ("#N"). | |
| 422 | + | message MergeRequestIssue { | |
| 423 | + | // Number is the number of the issue. | |
| 424 | + | int64 number = 1; | |
| 425 | + | // Title is the title of the issue. | |
| 426 | + | string title = 2; | |
| 427 | + | // State is where the issue is in its life. | |
| 428 | + | MergeRequestIssueState state = 3; | |
| 429 | + | // Closes says that a closing reference names the issue: merging the request | |
| 430 | + | // resolves it. | |
| 431 | + | bool closes = 4; | |
| 432 | + | } | |
| 433 | + | ||
| 434 | + | // IssueEventKind is what happened in an IssueEvent. | |
| 435 | + | enum IssueEventKind { | |
| 436 | + | // Not set. Never returned by the server. | |
| 437 | + | ISSUE_EVENT_KIND_UNSPECIFIED = 0; | |
| 438 | + | // A merge request started naming the issue; closes says whether with a | |
| 439 | + | // closing reference. | |
| 440 | + | ISSUE_EVENT_KIND_REFERENCED = 1; | |
| 441 | + | // The issue was closed without being resolved. | |
| 442 | + | ISSUE_EVENT_KIND_CLOSED = 2; | |
| 443 | + | // The issue was reopened. | |
| 444 | + | ISSUE_EVENT_KIND_REOPENED = 3; | |
| 445 | + | // The issue was resolved; merge_request is set when a merge resolved it. | |
| 446 | + | ISSUE_EVENT_KIND_RESOLVED = 4; | |
| 447 | + | } | |
| 448 | + | ||
| 449 | + | // IssueEvent is one entry in the history of an issue. Events are append-only: | |
| 450 | + | // a reference that later disappears does not remove its event. | |
| 451 | + | message IssueEvent { | |
| 452 | + | // Id identifies the event within its issue. Opaque. Events of different | |
| 453 | + | // issues can share an id: key them by (issue, id). | |
| 454 | + | string id = 1; | |
| 455 | + | // Kind is what happened. | |
| 456 | + | IssueEventKind kind = 2; | |
| 457 | + | // Issue is the number of the issue. | |
| 458 | + | int64 issue = 3; | |
| 459 | + | // MergeRequest is the number of the merge request involved; 0 if none. | |
| 460 | + | int64 merge_request = 4; | |
| 461 | + | // MergeRequestTitle is the title of that merge request at read time; empty | |
| 462 | + | // if none. | |
| 463 | + | string merge_request_title = 5; | |
| 464 | + | // Closes says that the reference was a closing one. Only set for | |
| 465 | + | // ISSUE_EVENT_KIND_REFERENCED. | |
| 466 | + | bool closes = 6; | |
| 467 | + | // Actor names who caused the event, like Issue.author: the label of the | |
| 468 | + | // token or session. For events triggered by a merge, the label of who | |
| 469 | + | // merged. | |
| 470 | + | string actor = 7; | |
| 471 | + | // CreatedAt is when the event happened. | |
| 472 | + | google.protobuf.Timestamp created_at = 8; | |
| 473 | + | } | |
| 474 | + | ||
| 405 | 475 | // GetMergeRequestRequest selects a merge request. | |
| 406 | 476 | message GetMergeRequestRequest { | |
| 407 | 477 | // Repo is the repository name. | |
| @@ -452,6 +522,14 @@ message GetMergeRequestResponse { | |||
| 452 | 522 | // Verdicts are the current verdicts, one per author who gave one, ordered | |
| 453 | 523 | // by the comment that carries them, oldest first. | |
| 454 | 524 | repeated AuthorVerdict verdicts = 10; | |
| 525 | + | // Issues are the issues of the same repository that the merge request names, | |
| 526 | + | // ascending by number, at most 100. Empty when issues are off. | |
| 527 | + | repeated MergeRequestIssue issues = 11; | |
| 528 | + | // IssueEvents are the history entries that involve this merge request: the | |
| 529 | + | // REFERENCED and RESOLVED events of the issues it names or once named, | |
| 530 | + | // oldest first, at most 500. An event can name an issue that is no longer | |
| 531 | + | // in issues. Empty when issues are off. | |
| 532 | + | repeated IssueEvent issue_events = 12; | |
| 455 | 533 | } | |
| 456 | 534 | ||
| 457 | 535 | // AddCommentRequest describes the comment to add. | |
| @@ -402,6 +402,76 @@ message ListMergeRequestsResponse { | |||||
| 402 | string next_page_token = 2; | 402 | string next_page_token = 2; | ||
| 403 | } | 403 | } | ||
| 404 | 404 | ||||
| 405 | + | // MergeRequestIssueState is where an issue named by a merge request is in its | |||
| 406 | + | // life. Values share their numbers with IssueState (3, awaiting moderation, | |||
| 407 | + | // is never shown here). It exists because issue.proto imports this file and | |||
| 408 | + | // cannot be imported back. | |||
| 409 | + | enum MergeRequestIssueState { | |||
| 410 | + | // Not set. Never returned by the server. | |||
| 411 | + | MERGE_REQUEST_ISSUE_STATE_UNSPECIFIED = 0; | |||
| 412 | + | // The issue is open. | |||
| 413 | + | MERGE_REQUEST_ISSUE_STATE_OPEN = 1; | |||
| 414 | + | // The issue is closed without being resolved. | |||
| 415 | + | MERGE_REQUEST_ISSUE_STATE_CLOSED = 2; | |||
| 416 | + | // The issue was resolved, by a merge or by hand. | |||
| 417 | + | MERGE_REQUEST_ISSUE_STATE_RESOLVED = 4; | |||
| 418 | + | } | |||
| 419 | + | ||||
| 420 | + | // MergeRequestIssue is an issue of the same repository that a merge request | |||
| 421 | + | // names ("#N"). | |||
| 422 | + | message MergeRequestIssue { | |||
| 423 | + | // Number is the number of the issue. | |||
| 424 | + | int64 number = 1; | |||
| 425 | + | // Title is the title of the issue. | |||
| 426 | + | string title = 2; | |||
| 427 | + | // State is where the issue is in its life. | |||
| 428 | + | MergeRequestIssueState state = 3; | |||
| 429 | + | // Closes says that a closing reference names the issue: merging the request | |||
| 430 | + | // resolves it. | |||
| 431 | + | bool closes = 4; | |||
| 432 | + | } | |||
| 433 | + | ||||
| 434 | + | // IssueEventKind is what happened in an IssueEvent. | |||
| 435 | + | enum IssueEventKind { | |||
| 436 | + | // Not set. Never returned by the server. | |||
| 437 | + | ISSUE_EVENT_KIND_UNSPECIFIED = 0; | |||
| 438 | + | // A merge request started naming the issue; closes says whether with a | |||
| 439 | + | // closing reference. | |||
| 440 | + | ISSUE_EVENT_KIND_REFERENCED = 1; | |||
| 441 | + | // The issue was closed without being resolved. | |||
| 442 | + | ISSUE_EVENT_KIND_CLOSED = 2; | |||
| 443 | + | // The issue was reopened. | |||
| 444 | + | ISSUE_EVENT_KIND_REOPENED = 3; | |||
| 445 | + | // The issue was resolved; merge_request is set when a merge resolved it. | |||
| 446 | + | ISSUE_EVENT_KIND_RESOLVED = 4; | |||
| 447 | + | } | |||
| 448 | + | ||||
| 449 | + | // IssueEvent is one entry in the history of an issue. Events are append-only: | |||
| 450 | + | // a reference that later disappears does not remove its event. | |||
| 451 | + | message IssueEvent { | |||
| 452 | + | // Id identifies the event within its issue. Opaque. Events of different | |||
| 453 | + | // issues can share an id: key them by (issue, id). | |||
| 454 | + | string id = 1; | |||
| 455 | + | // Kind is what happened. | |||
| 456 | + | IssueEventKind kind = 2; | |||
| 457 | + | // Issue is the number of the issue. | |||
| 458 | + | int64 issue = 3; | |||
| 459 | + | // MergeRequest is the number of the merge request involved; 0 if none. | |||
| 460 | + | int64 merge_request = 4; | |||
| 461 | + | // MergeRequestTitle is the title of that merge request at read time; empty | |||
| 462 | + | // if none. | |||
| 463 | + | string merge_request_title = 5; | |||
| 464 | + | // Closes says that the reference was a closing one. Only set for | |||
| 465 | + | // ISSUE_EVENT_KIND_REFERENCED. | |||
| 466 | + | bool closes = 6; | |||
| 467 | + | // Actor names who caused the event, like Issue.author: the label of the | |||
| 468 | + | // token or session. For events triggered by a merge, the label of who | |||
| 469 | + | // merged. | |||
| 470 | + | string actor = 7; | |||
| 471 | + | // CreatedAt is when the event happened. | |||
| 472 | + | google.protobuf.Timestamp created_at = 8; | |||
| 473 | + | } | |||
| 474 | + | ||||
| 405 | // GetMergeRequestRequest selects a merge request. | 475 | // GetMergeRequestRequest selects a merge request. | ||
| 406 | message GetMergeRequestRequest { | 476 | message GetMergeRequestRequest { | ||
| 407 | // Repo is the repository name. | 477 | // Repo is the repository name. | ||
| @@ -452,6 +522,14 @@ message GetMergeRequestResponse { | |||||
| 452 | // Verdicts are the current verdicts, one per author who gave one, ordered | 522 | // Verdicts are the current verdicts, one per author who gave one, ordered | ||
| 453 | // by the comment that carries them, oldest first. | 523 | // by the comment that carries them, oldest first. | ||
| 454 | repeated AuthorVerdict verdicts = 10; | 524 | repeated AuthorVerdict verdicts = 10; | ||
| 525 | + | // Issues are the issues of the same repository that the merge request names, | |||
| 526 | + | // ascending by number, at most 100. Empty when issues are off. | |||
| 527 | + | repeated MergeRequestIssue issues = 11; | |||
| 528 | + | // IssueEvents are the history entries that involve this merge request: the | |||
| 529 | + | // REFERENCED and RESOLVED events of the issues it names or once named, | |||
| 530 | + | // oldest first, at most 500. An event can name an issue that is no longer | |||
| 531 | + | // in issues. Empty when issues are off. | |||
| 532 | + | repeated IssueEvent issue_events = 12; | |||
| 455 | } | 533 | } | ||
| 456 | 534 | ||||
| 457 | // AddCommentRequest describes the comment to add. | 535 | // AddCommentRequest describes the comment to add. | ||