detached d1c609e

feat(proto): add MarkReady, mr:force-merge and ignore_checks, drop failing_checks_block

commit
d1c609e1c109abef55c26edd9485ad65479e0da1
author
brice · · 2026-10-21 13:32 UTC
parent
c54bf5d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
1/2
9 files · +339 -144
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`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `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`) |
99 | `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 |
1010 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |
1111 | `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` |
@@ -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`, `EditComment`, `DeleteComment`, `ResolveComment`, `CloseMergeRequest`, `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, `closed_by_merge_request`), `AddIssueComment`, `CloseIssue`, `ReopenIssue`; owner only: `ListPendingIssues`, `ApproveIssue`, `RejectIssue`. Features `issues`, `issues.links`. 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` |
M gen/ermite/ermiteconnect/merge_request.connect.go +57 -12
@@ -59,6 +59,9 @@ const (
5959 // MergeRequestServiceCloseMergeRequestProcedure is the fully-qualified name of the
6060 // MergeRequestService's CloseMergeRequest RPC.
6161 MergeRequestServiceCloseMergeRequestProcedure = "/ermite.MergeRequestService/CloseMergeRequest"
62+ // MergeRequestServiceMarkReadyProcedure is the fully-qualified name of the MergeRequestService's
63+ // MarkReady RPC.
64+ MergeRequestServiceMarkReadyProcedure = "/ermite.MergeRequestService/MarkReady"
6265 // MergeRequestServiceMergeMergeRequestProcedure is the fully-qualified name of the
6366 // MergeRequestService's MergeMergeRequest RPC.
6467 MergeRequestServiceMergeMergeRequestProcedure = "/ermite.MergeRequestService/MergeMergeRequest"
@@ -127,7 +130,16 @@ type MergeRequestServiceClient interface {
127130 // the mr:write scope. Fails with failed_precondition if the merge request
128131 // is not open. A closed merge request cannot be reopened: open a new one.
129132 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)
130- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.
133+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
134+ // the merge request can be merged. Needs the mr:write scope. Fails with
135+ // failed_precondition if the merge request is not open or is not a draft.
136+ // Publishes no event: there is none for a change of title. Needs the
137+ // "merge_requests.ready" feature.
138+ MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error)
139+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
140+ // which merges only when the checks on the head allow it: none failed and
141+ // none queued or running (a head with no checks may be merged; success,
142+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
131143 // The caller passes the head it reviewed: the server merges only if the
132144 // source branch still points to it, so a push between review and merge is
133145 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -137,17 +149,17 @@ type MergeRequestServiceClient interface {
137149 // ancestor of the head (rebase and push again, or merge with squash or
138150 // merge commit), if the mode is squash or merge commit and the head
139151 // conflicts with the target or shares no history with it (rebase and push
140- // again), if the mode is not allowed by RepoSettings, or if a check fails
141- // and RepoSettings.failing_checks_block is set. Merges of one
152+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
153+ // has not finished, unless ignore_checks is set. Merges of one
142154 // repository run one at a time. Repeating a call that succeeded fails with
143155 // failed_precondition (not open). On success the server publishes
144156 // MergeRequestMerged then Pushed for the target branch.
145157 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)
146158 // EnableAutoMerge asks the server to merge an open merge request by itself
147159 // once at least one check passed on its head, every run created on that head
148- // is complete, and the merge would be accepted whatever
149- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a
150- // token limited to branches, write access to the target branch
160+ // is complete, and no check failed. It does not take ignore_checks. Needs
161+ // the mr:merge scope and, for a token limited to branches, write access to
162+ // the target branch
151163 // (permission_denied otherwise). The server records the caller, the mode and
152164 // the head the caller saw; it merges as the caller, after resolving the caller
153165 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -232,6 +244,12 @@ func NewMergeRequestServiceClient(httpClient connect.HTTPClient, baseURL string,
232244 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),
233245 connect.WithClientOptions(opts...),
234246 ),
247+ markReady: connect.NewClient[ermite.MarkReadyRequest, ermite.MarkReadyResponse](
248+ httpClient,
249+ baseURL+MergeRequestServiceMarkReadyProcedure,
250+ connect.WithSchema(mergeRequestServiceMethods.ByName("MarkReady")),
251+ connect.WithClientOptions(opts...),
252+ ),
235253 mergeMergeRequest: connect.NewClient[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse](
236254 httpClient,
237255 baseURL+MergeRequestServiceMergeMergeRequestProcedure,
@@ -269,6 +287,7 @@ type mergeRequestServiceClient struct {
269287 deleteComment *connect.Client[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse]
270288 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]
271289 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]
290+ markReady *connect.Client[ermite.MarkReadyRequest, ermite.MarkReadyResponse]
272291 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]
273292 enableAutoMerge *connect.Client[ermite.EnableAutoMergeRequest, ermite.EnableAutoMergeResponse]
274293 cancelAutoMerge *connect.Client[ermite.CancelAutoMergeRequest, ermite.CancelAutoMergeResponse]
@@ -315,6 +334,11 @@ func (c *mergeRequestServiceClient) CloseMergeRequest(ctx context.Context, req *
315334 return c.closeMergeRequest.CallUnary(ctx, req)
316335 }
317336
337+// MarkReady calls ermite.MergeRequestService.MarkReady.
338+func (c *mergeRequestServiceClient) MarkReady(ctx context.Context, req *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error) {
339+ return c.markReady.CallUnary(ctx, req)
340+}
341+
318342 // MergeMergeRequest calls ermite.MergeRequestService.MergeMergeRequest.
319343 func (c *mergeRequestServiceClient) MergeMergeRequest(ctx context.Context, req *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {
320344 return c.mergeMergeRequest.CallUnary(ctx, req)
@@ -389,7 +413,16 @@ type MergeRequestServiceHandler interface {
389413 // the mr:write scope. Fails with failed_precondition if the merge request
390414 // is not open. A closed merge request cannot be reopened: open a new one.
391415 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)
392- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.
416+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
417+ // the merge request can be merged. Needs the mr:write scope. Fails with
418+ // failed_precondition if the merge request is not open or is not a draft.
419+ // Publishes no event: there is none for a change of title. Needs the
420+ // "merge_requests.ready" feature.
421+ MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error)
422+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
423+ // which merges only when the checks on the head allow it: none failed and
424+ // none queued or running (a head with no checks may be merged; success,
425+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
393426 // The caller passes the head it reviewed: the server merges only if the
394427 // source branch still points to it, so a push between review and merge is
395428 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -399,17 +432,17 @@ type MergeRequestServiceHandler interface {
399432 // ancestor of the head (rebase and push again, or merge with squash or
400433 // merge commit), if the mode is squash or merge commit and the head
401434 // conflicts with the target or shares no history with it (rebase and push
402- // again), if the mode is not allowed by RepoSettings, or if a check fails
403- // and RepoSettings.failing_checks_block is set. Merges of one
435+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
436+ // has not finished, unless ignore_checks is set. Merges of one
404437 // repository run one at a time. Repeating a call that succeeded fails with
405438 // failed_precondition (not open). On success the server publishes
406439 // MergeRequestMerged then Pushed for the target branch.
407440 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)
408441 // EnableAutoMerge asks the server to merge an open merge request by itself
409442 // once at least one check passed on its head, every run created on that head
410- // is complete, and the merge would be accepted whatever
411- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a
412- // token limited to branches, write access to the target branch
443+ // is complete, and no check failed. It does not take ignore_checks. Needs
444+ // the mr:merge scope and, for a token limited to branches, write access to
445+ // the target branch
413446 // (permission_denied otherwise). The server records the caller, the mode and
414447 // the head the caller saw; it merges as the caller, after resolving the caller
415448 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -490,6 +523,12 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
490523 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),
491524 connect.WithHandlerOptions(opts...),
492525 )
526+ mergeRequestServiceMarkReadyHandler := connect.NewUnaryHandler(
527+ MergeRequestServiceMarkReadyProcedure,
528+ svc.MarkReady,
529+ connect.WithSchema(mergeRequestServiceMethods.ByName("MarkReady")),
530+ connect.WithHandlerOptions(opts...),
531+ )
493532 mergeRequestServiceMergeMergeRequestHandler := connect.NewUnaryHandler(
494533 MergeRequestServiceMergeMergeRequestProcedure,
495534 svc.MergeMergeRequest,
@@ -532,6 +571,8 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
532571 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)
533572 case MergeRequestServiceCloseMergeRequestProcedure:
534573 mergeRequestServiceCloseMergeRequestHandler.ServeHTTP(w, r)
574+ case MergeRequestServiceMarkReadyProcedure:
575+ mergeRequestServiceMarkReadyHandler.ServeHTTP(w, r)
535576 case MergeRequestServiceMergeMergeRequestProcedure:
536577 mergeRequestServiceMergeMergeRequestHandler.ServeHTTP(w, r)
537578 case MergeRequestServiceEnableAutoMergeProcedure:
@@ -581,6 +622,10 @@ func (UnimplementedMergeRequestServiceHandler) CloseMergeRequest(context.Context
581622 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.CloseMergeRequest is not implemented"))
582623 }
583624
625+func (UnimplementedMergeRequestServiceHandler) MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error) {
626+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.MarkReady is not implemented"))
627+}
628+
584629 func (UnimplementedMergeRequestServiceHandler) MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {
585630 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.MergeMergeRequest is not implemented"))
586631 }
@@ -59,6 +59,9 @@ const (
59 // MergeRequestServiceCloseMergeRequestProcedure is the fully-qualified name of the59 // MergeRequestServiceCloseMergeRequestProcedure is the fully-qualified name of the
60 // MergeRequestService's CloseMergeRequest RPC.60 // MergeRequestService's CloseMergeRequest RPC.
61 MergeRequestServiceCloseMergeRequestProcedure = "/ermite.MergeRequestService/CloseMergeRequest"61 MergeRequestServiceCloseMergeRequestProcedure = "/ermite.MergeRequestService/CloseMergeRequest"
62+ // MergeRequestServiceMarkReadyProcedure is the fully-qualified name of the MergeRequestService's
63+ // MarkReady RPC.
64+ MergeRequestServiceMarkReadyProcedure = "/ermite.MergeRequestService/MarkReady"
62 // MergeRequestServiceMergeMergeRequestProcedure is the fully-qualified name of the65 // MergeRequestServiceMergeMergeRequestProcedure is the fully-qualified name of the
63 // MergeRequestService's MergeMergeRequest RPC.66 // MergeRequestService's MergeMergeRequest RPC.
64 MergeRequestServiceMergeMergeRequestProcedure = "/ermite.MergeRequestService/MergeMergeRequest"67 MergeRequestServiceMergeMergeRequestProcedure = "/ermite.MergeRequestService/MergeMergeRequest"
@@ -127,7 +130,16 @@ type MergeRequestServiceClient interface {
127 // the mr:write scope. Fails with failed_precondition if the merge request130 // the mr:write scope. Fails with failed_precondition if the merge request
128 // is not open. A closed merge request cannot be reopened: open a new one.131 // is not open. A closed merge request cannot be reopened: open a new one.
129 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)132 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)
130- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.133+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
134+ // the merge request can be merged. Needs the mr:write scope. Fails with
135+ // failed_precondition if the merge request is not open or is not a draft.
136+ // Publishes no event: there is none for a change of title. Needs the
137+ // "merge_requests.ready" feature.
138+ MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error)
139+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
140+ // which merges only when the checks on the head allow it: none failed and
141+ // none queued or running (a head with no checks may be merged; success,
142+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
131 // The caller passes the head it reviewed: the server merges only if the143 // The caller passes the head it reviewed: the server merges only if the
132 // source branch still points to it, so a push between review and merge is144 // source branch still points to it, so a push between review and merge is
133 // never merged unseen. Fails with invalid_argument if head_id is empty or145 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -137,17 +149,17 @@ type MergeRequestServiceClient interface {
137 // ancestor of the head (rebase and push again, or merge with squash or149 // ancestor of the head (rebase and push again, or merge with squash or
138 // merge commit), if the mode is squash or merge commit and the head150 // merge commit), if the mode is squash or merge commit and the head
139 // conflicts with the target or shares no history with it (rebase and push151 // conflicts with the target or shares no history with it (rebase and push
140- // again), if the mode is not allowed by RepoSettings, or if a check fails152+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
141- // and RepoSettings.failing_checks_block is set. Merges of one153+ // has not finished, unless ignore_checks is set. Merges of one
142 // repository run one at a time. Repeating a call that succeeded fails with154 // repository run one at a time. Repeating a call that succeeded fails with
143 // failed_precondition (not open). On success the server publishes155 // failed_precondition (not open). On success the server publishes
144 // MergeRequestMerged then Pushed for the target branch.156 // MergeRequestMerged then Pushed for the target branch.
145 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)157 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)
146 // EnableAutoMerge asks the server to merge an open merge request by itself158 // EnableAutoMerge asks the server to merge an open merge request by itself
147 // once at least one check passed on its head, every run created on that head159 // once at least one check passed on its head, every run created on that head
148- // is complete, and the merge would be accepted whatever160+ // is complete, and no check failed. It does not take ignore_checks. Needs
149- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a161+ // the mr:merge scope and, for a token limited to branches, write access to
150- // token limited to branches, write access to the target branch162+ // the target branch
151 // (permission_denied otherwise). The server records the caller, the mode and163 // (permission_denied otherwise). The server records the caller, the mode and
152 // the head the caller saw; it merges as the caller, after resolving the caller164 // the head the caller saw; it merges as the caller, after resolving the caller
153 // again, and cancels the auto-merge if the caller can no longer merge, if the165 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -232,6 +244,12 @@ func NewMergeRequestServiceClient(httpClient connect.HTTPClient, baseURL string,
232 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),244 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),
233 connect.WithClientOptions(opts...),245 connect.WithClientOptions(opts...),
234 ),246 ),
247+ markReady: connect.NewClient[ermite.MarkReadyRequest, ermite.MarkReadyResponse](
248+ httpClient,
249+ baseURL+MergeRequestServiceMarkReadyProcedure,
250+ connect.WithSchema(mergeRequestServiceMethods.ByName("MarkReady")),
251+ connect.WithClientOptions(opts...),
252+ ),
235 mergeMergeRequest: connect.NewClient[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse](253 mergeMergeRequest: connect.NewClient[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse](
236 httpClient,254 httpClient,
237 baseURL+MergeRequestServiceMergeMergeRequestProcedure,255 baseURL+MergeRequestServiceMergeMergeRequestProcedure,
@@ -269,6 +287,7 @@ type mergeRequestServiceClient struct {
269 deleteComment *connect.Client[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse]287 deleteComment *connect.Client[ermite.DeleteCommentRequest, ermite.DeleteCommentResponse]
270 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]288 resolveComment *connect.Client[ermite.ResolveCommentRequest, ermite.ResolveCommentResponse]
271 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]289 closeMergeRequest *connect.Client[ermite.CloseMergeRequestRequest, ermite.CloseMergeRequestResponse]
290+ markReady *connect.Client[ermite.MarkReadyRequest, ermite.MarkReadyResponse]
272 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]291 mergeMergeRequest *connect.Client[ermite.MergeMergeRequestRequest, ermite.MergeMergeRequestResponse]
273 enableAutoMerge *connect.Client[ermite.EnableAutoMergeRequest, ermite.EnableAutoMergeResponse]292 enableAutoMerge *connect.Client[ermite.EnableAutoMergeRequest, ermite.EnableAutoMergeResponse]
274 cancelAutoMerge *connect.Client[ermite.CancelAutoMergeRequest, ermite.CancelAutoMergeResponse]293 cancelAutoMerge *connect.Client[ermite.CancelAutoMergeRequest, ermite.CancelAutoMergeResponse]
@@ -315,6 +334,11 @@ func (c *mergeRequestServiceClient) CloseMergeRequest(ctx context.Context, req *
315 return c.closeMergeRequest.CallUnary(ctx, req)334 return c.closeMergeRequest.CallUnary(ctx, req)
316 }335 }
317 336
337+// MarkReady calls ermite.MergeRequestService.MarkReady.
338+func (c *mergeRequestServiceClient) MarkReady(ctx context.Context, req *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error) {
339+ return c.markReady.CallUnary(ctx, req)
340+}
341+
318 // MergeMergeRequest calls ermite.MergeRequestService.MergeMergeRequest.342 // MergeMergeRequest calls ermite.MergeRequestService.MergeMergeRequest.
319 func (c *mergeRequestServiceClient) MergeMergeRequest(ctx context.Context, req *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {343 func (c *mergeRequestServiceClient) MergeMergeRequest(ctx context.Context, req *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {
320 return c.mergeMergeRequest.CallUnary(ctx, req)344 return c.mergeMergeRequest.CallUnary(ctx, req)
@@ -389,7 +413,16 @@ type MergeRequestServiceHandler interface {
389 // the mr:write scope. Fails with failed_precondition if the merge request413 // the mr:write scope. Fails with failed_precondition if the merge request
390 // is not open. A closed merge request cannot be reopened: open a new one.414 // is not open. A closed merge request cannot be reopened: open a new one.
391 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)415 CloseMergeRequest(context.Context, *connect.Request[ermite.CloseMergeRequestRequest]) (*connect.Response[ermite.CloseMergeRequestResponse], error)
392- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.416+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
417+ // the merge request can be merged. Needs the mr:write scope. Fails with
418+ // failed_precondition if the merge request is not open or is not a draft.
419+ // Publishes no event: there is none for a change of title. Needs the
420+ // "merge_requests.ready" feature.
421+ MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error)
422+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
423+ // which merges only when the checks on the head allow it: none failed and
424+ // none queued or running (a head with no checks may be merged; success,
425+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
393 // The caller passes the head it reviewed: the server merges only if the426 // The caller passes the head it reviewed: the server merges only if the
394 // source branch still points to it, so a push between review and merge is427 // source branch still points to it, so a push between review and merge is
395 // never merged unseen. Fails with invalid_argument if head_id is empty or428 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -399,17 +432,17 @@ type MergeRequestServiceHandler interface {
399 // ancestor of the head (rebase and push again, or merge with squash or432 // ancestor of the head (rebase and push again, or merge with squash or
400 // merge commit), if the mode is squash or merge commit and the head433 // merge commit), if the mode is squash or merge commit and the head
401 // conflicts with the target or shares no history with it (rebase and push434 // conflicts with the target or shares no history with it (rebase and push
402- // again), if the mode is not allowed by RepoSettings, or if a check fails435+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
403- // and RepoSettings.failing_checks_block is set. Merges of one436+ // has not finished, unless ignore_checks is set. Merges of one
404 // repository run one at a time. Repeating a call that succeeded fails with437 // repository run one at a time. Repeating a call that succeeded fails with
405 // failed_precondition (not open). On success the server publishes438 // failed_precondition (not open). On success the server publishes
406 // MergeRequestMerged then Pushed for the target branch.439 // MergeRequestMerged then Pushed for the target branch.
407 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)440 MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error)
408 // EnableAutoMerge asks the server to merge an open merge request by itself441 // EnableAutoMerge asks the server to merge an open merge request by itself
409 // once at least one check passed on its head, every run created on that head442 // once at least one check passed on its head, every run created on that head
410- // is complete, and the merge would be accepted whatever443+ // is complete, and no check failed. It does not take ignore_checks. Needs
411- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a444+ // the mr:merge scope and, for a token limited to branches, write access to
412- // token limited to branches, write access to the target branch445+ // the target branch
413 // (permission_denied otherwise). The server records the caller, the mode and446 // (permission_denied otherwise). The server records the caller, the mode and
414 // the head the caller saw; it merges as the caller, after resolving the caller447 // the head the caller saw; it merges as the caller, after resolving the caller
415 // again, and cancels the auto-merge if the caller can no longer merge, if the448 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -490,6 +523,12 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
490 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),523 connect.WithSchema(mergeRequestServiceMethods.ByName("CloseMergeRequest")),
491 connect.WithHandlerOptions(opts...),524 connect.WithHandlerOptions(opts...),
492 )525 )
526+ mergeRequestServiceMarkReadyHandler := connect.NewUnaryHandler(
527+ MergeRequestServiceMarkReadyProcedure,
528+ svc.MarkReady,
529+ connect.WithSchema(mergeRequestServiceMethods.ByName("MarkReady")),
530+ connect.WithHandlerOptions(opts...),
531+ )
493 mergeRequestServiceMergeMergeRequestHandler := connect.NewUnaryHandler(532 mergeRequestServiceMergeMergeRequestHandler := connect.NewUnaryHandler(
494 MergeRequestServiceMergeMergeRequestProcedure,533 MergeRequestServiceMergeMergeRequestProcedure,
495 svc.MergeMergeRequest,534 svc.MergeMergeRequest,
@@ -532,6 +571,8 @@ func NewMergeRequestServiceHandler(svc MergeRequestServiceHandler, opts ...conne
532 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)571 mergeRequestServiceResolveCommentHandler.ServeHTTP(w, r)
533 case MergeRequestServiceCloseMergeRequestProcedure:572 case MergeRequestServiceCloseMergeRequestProcedure:
534 mergeRequestServiceCloseMergeRequestHandler.ServeHTTP(w, r)573 mergeRequestServiceCloseMergeRequestHandler.ServeHTTP(w, r)
574+ case MergeRequestServiceMarkReadyProcedure:
575+ mergeRequestServiceMarkReadyHandler.ServeHTTP(w, r)
535 case MergeRequestServiceMergeMergeRequestProcedure:576 case MergeRequestServiceMergeMergeRequestProcedure:
536 mergeRequestServiceMergeMergeRequestHandler.ServeHTTP(w, r)577 mergeRequestServiceMergeMergeRequestHandler.ServeHTTP(w, r)
537 case MergeRequestServiceEnableAutoMergeProcedure:578 case MergeRequestServiceEnableAutoMergeProcedure:
@@ -581,6 +622,10 @@ func (UnimplementedMergeRequestServiceHandler) CloseMergeRequest(context.Context
581 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.CloseMergeRequest is not implemented"))622 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.CloseMergeRequest is not implemented"))
582 }623 }
583 624
625+func (UnimplementedMergeRequestServiceHandler) MarkReady(context.Context, *connect.Request[ermite.MarkReadyRequest]) (*connect.Response[ermite.MarkReadyResponse], error) {
626+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.MarkReady is not implemented"))
627+}
628+
584 func (UnimplementedMergeRequestServiceHandler) MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {629 func (UnimplementedMergeRequestServiceHandler) MergeMergeRequest(context.Context, *connect.Request[ermite.MergeMergeRequestRequest]) (*connect.Response[ermite.MergeMergeRequestResponse], error) {
585 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.MergeMergeRequest is not implemented"))630 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MergeRequestService.MergeMergeRequest is not implemented"))
586 }631 }
M gen/ermite/merge_request.pb.go +217 -91 generated file: collapsed
M gen/ermite/repo.pb.go +6 -19
@@ -146,11 +146,6 @@ type RepoSettings struct {
146146 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
147147 // rejected.
148148 AllowedMergeModes []MergeMode `protobuf:"varint,1,rep,packed,name=allowed_merge_modes,json=allowedMergeModes,proto3,enum=ermite.MergeMode" json:"allowed_merge_modes,omitempty"`
149- // FailingChecksBlock says whether a merge request whose checks fail cannot be
150- // merged. It is true at creation of the repository and always stored
151- // explicitly, so a later change of the server default never alters an
152- // existing repository.
153- FailingChecksBlock bool `protobuf:"varint,2,opt,name=failing_checks_block,json=failingChecksBlock,proto3" json:"failing_checks_block,omitempty"`
154149 // Issues is the issue participation mode of the repository.
155150 Issues IssuesMode `protobuf:"varint,3,opt,name=issues,proto3,enum=ermite.IssuesMode" json:"issues,omitempty"`
156151 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests
@@ -198,13 +193,6 @@ func (x *RepoSettings) GetAllowedMergeModes() []MergeMode {
198193 return nil
199194 }
200195
201-func (x *RepoSettings) GetFailingChecksBlock() bool {
202- if x != nil {
203- return x.FailingChecksBlock
204- }
205- return false
206-}
207-
208196 func (x *RepoSettings) GetIssues() IssuesMode {
209197 if x != nil {
210198 return x.Issues
@@ -678,9 +666,9 @@ type UpdateRepoRequest struct {
678666 // the call fails with failed_precondition.
679667 DefaultBranch string `protobuf:"bytes,4,opt,name=default_branch,json=defaultBranch,proto3" json:"default_branch,omitempty"`
680668 // UpdateMask lists the fields to change: "description", "visibility",
681- // "default_branch", "topics", "settings.allowed_merge_modes",
682- // "settings.failing_checks_block" and/or "settings.allow_auto_merge".
683- // "settings" stands for the three merge settings paths. It must not be empty unless issues is set. Other paths are
669+ // "default_branch", "topics", "settings.allowed_merge_modes" and/or
670+ // "settings.allow_auto_merge". "settings" stands for the two merge settings
671+ // paths. It must not be empty unless issues is set. Other paths are
684672 // invalid_argument, including "settings.issues" and "issues": the issues
685673 // field is applied outside the mask.
686674 UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
@@ -922,12 +910,11 @@ var File_ermite_repo_proto protoreflect.FileDescriptor
922910
923911 const file_ermite_repo_proto_rawDesc = "" +
924912 "\n" +
925- "\x11ermite/repo.proto\x12\x06ermite\x1a google/protobuf/field_mask.proto\x1a\x12ermite/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd9\x01\n" +
913+ "\x11ermite/repo.proto\x12\x06ermite\x1a google/protobuf/field_mask.proto\x1a\x12ermite/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc3\x01\n" +
926914 "\fRepoSettings\x12A\n" +
927- "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x11.ermite.MergeModeR\x11allowedMergeModes\x120\n" +
928- "\x14failing_checks_block\x18\x02 \x01(\bR\x12failingChecksBlock\x12*\n" +
915+ "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x11.ermite.MergeModeR\x11allowedMergeModes\x12*\n" +
929916 "\x06issues\x18\x03 \x01(\x0e2\x12.ermite.IssuesModeR\x06issues\x12(\n" +
930- "\x10allow_auto_merge\x18\x04 \x01(\bR\x0eallowAutoMerge\"\xd5\x02\n" +
917+ "\x10allow_auto_merge\x18\x04 \x01(\bR\x0eallowAutoMergeJ\x04\b\x02\x10\x03R\x14failing_checks_block\"\xd5\x02\n" +
931918 "\x04Repo\x12\x12\n" +
932919 "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" +
933920 "\vdescription\x18\x02 \x01(\tR\vdescription\x122\n" +
@@ -146,11 +146,6 @@ type RepoSettings struct {
146 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is146 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
147 // rejected.147 // rejected.
148 AllowedMergeModes []MergeMode `protobuf:"varint,1,rep,packed,name=allowed_merge_modes,json=allowedMergeModes,proto3,enum=ermite.MergeMode" json:"allowed_merge_modes,omitempty"`148 AllowedMergeModes []MergeMode `protobuf:"varint,1,rep,packed,name=allowed_merge_modes,json=allowedMergeModes,proto3,enum=ermite.MergeMode" json:"allowed_merge_modes,omitempty"`
149- // FailingChecksBlock says whether a merge request whose checks fail cannot be
150- // merged. It is true at creation of the repository and always stored
151- // explicitly, so a later change of the server default never alters an
152- // existing repository.
153- FailingChecksBlock bool `protobuf:"varint,2,opt,name=failing_checks_block,json=failingChecksBlock,proto3" json:"failing_checks_block,omitempty"`
154 // Issues is the issue participation mode of the repository.149 // Issues is the issue participation mode of the repository.
155 Issues IssuesMode `protobuf:"varint,3,opt,name=issues,proto3,enum=ermite.IssuesMode" json:"issues,omitempty"`150 Issues IssuesMode `protobuf:"varint,3,opt,name=issues,proto3,enum=ermite.IssuesMode" json:"issues,omitempty"`
156 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests151 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests
@@ -198,13 +193,6 @@ func (x *RepoSettings) GetAllowedMergeModes() []MergeMode {
198 return nil193 return nil
199 }194 }
200 195
201-func (x *RepoSettings) GetFailingChecksBlock() bool {
202- if x != nil {
203- return x.FailingChecksBlock
204- }
205- return false
206-}
207-
208 func (x *RepoSettings) GetIssues() IssuesMode {196 func (x *RepoSettings) GetIssues() IssuesMode {
209 if x != nil {197 if x != nil {
210 return x.Issues198 return x.Issues
@@ -678,9 +666,9 @@ type UpdateRepoRequest struct {
678 // the call fails with failed_precondition.666 // the call fails with failed_precondition.
679 DefaultBranch string `protobuf:"bytes,4,opt,name=default_branch,json=defaultBranch,proto3" json:"default_branch,omitempty"`667 DefaultBranch string `protobuf:"bytes,4,opt,name=default_branch,json=defaultBranch,proto3" json:"default_branch,omitempty"`
680 // UpdateMask lists the fields to change: "description", "visibility",668 // UpdateMask lists the fields to change: "description", "visibility",
681- // "default_branch", "topics", "settings.allowed_merge_modes",669+ // "default_branch", "topics", "settings.allowed_merge_modes" and/or
682- // "settings.failing_checks_block" and/or "settings.allow_auto_merge".670+ // "settings.allow_auto_merge". "settings" stands for the two merge settings
683- // "settings" stands for the three merge settings paths. It must not be empty unless issues is set. Other paths are671+ // paths. It must not be empty unless issues is set. Other paths are
684 // invalid_argument, including "settings.issues" and "issues": the issues672 // invalid_argument, including "settings.issues" and "issues": the issues
685 // field is applied outside the mask.673 // field is applied outside the mask.
686 UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`674 UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
@@ -922,12 +910,11 @@ var File_ermite_repo_proto protoreflect.FileDescriptor
922 910
923 const file_ermite_repo_proto_rawDesc = "" +911 const file_ermite_repo_proto_rawDesc = "" +
924 "\n" +912 "\n" +
925- "\x11ermite/repo.proto\x12\x06ermite\x1a google/protobuf/field_mask.proto\x1a\x12ermite/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd9\x01\n" +913+ "\x11ermite/repo.proto\x12\x06ermite\x1a google/protobuf/field_mask.proto\x1a\x12ermite/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xc3\x01\n" +
926 "\fRepoSettings\x12A\n" +914 "\fRepoSettings\x12A\n" +
927- "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x11.ermite.MergeModeR\x11allowedMergeModes\x120\n" +915+ "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x11.ermite.MergeModeR\x11allowedMergeModes\x12*\n" +
928- "\x14failing_checks_block\x18\x02 \x01(\bR\x12failingChecksBlock\x12*\n" +
929 "\x06issues\x18\x03 \x01(\x0e2\x12.ermite.IssuesModeR\x06issues\x12(\n" +916 "\x06issues\x18\x03 \x01(\x0e2\x12.ermite.IssuesModeR\x06issues\x12(\n" +
930- "\x10allow_auto_merge\x18\x04 \x01(\bR\x0eallowAutoMerge\"\xd5\x02\n" +917+ "\x10allow_auto_merge\x18\x04 \x01(\bR\x0eallowAutoMergeJ\x04\b\x02\x10\x03R\x14failing_checks_block\"\xd5\x02\n" +
931 "\x04Repo\x12\x12\n" +918 "\x04Repo\x12\x12\n" +
932 "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" +919 "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" +
933 "\vdescription\x18\x02 \x01(\tR\vdescription\x122\n" +920 "\vdescription\x18\x02 \x01(\tR\vdescription\x122\n" +
M gen/ermite/token.pb.go +10 -3 generated file: collapsed
M gen_test.go +2 -3
@@ -254,10 +254,9 @@ func TestMergeRequestEventRoundTrip(t *testing.T) {
254254 req := &ermite.UpdateRepoRequest{
255255 Repo: "ermite",
256256 Settings: &ermite.RepoSettings{
257- AllowedMergeModes: []ermite.MergeMode{ermite.MergeMode_MERGE_MODE_SQUASH},
258- FailingChecksBlock: true,
257+ AllowedMergeModes: []ermite.MergeMode{ermite.MergeMode_MERGE_MODE_SQUASH},
259258 },
260- UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"settings.allowed_merge_modes", "settings.failing_checks_block"}},
259+ UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"settings.allowed_merge_modes"}},
261260 }
262261 if got := req.GetSettings().GetAllowedMergeModes(); len(got) != 1 || got[0] != ermite.MergeMode_MERGE_MODE_SQUASH {
263262 t.Errorf("modes = %v", got)
@@ -254,10 +254,9 @@ func TestMergeRequestEventRoundTrip(t *testing.T) {
254 req := &ermite.UpdateRepoRequest{254 req := &ermite.UpdateRepoRequest{
255 Repo: "ermite",255 Repo: "ermite",
256 Settings: &ermite.RepoSettings{256 Settings: &ermite.RepoSettings{
257- AllowedMergeModes: []ermite.MergeMode{ermite.MergeMode_MERGE_MODE_SQUASH},257+ AllowedMergeModes: []ermite.MergeMode{ermite.MergeMode_MERGE_MODE_SQUASH},
258- FailingChecksBlock: true,
259 },258 },
260- UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"settings.allowed_merge_modes", "settings.failing_checks_block"}},259+ UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"settings.allowed_merge_modes"}},
261 }260 }
262 if got := req.GetSettings().GetAllowedMergeModes(); len(got) != 1 || got[0] != ermite.MergeMode_MERGE_MODE_SQUASH {261 if got := req.GetSettings().GetAllowedMergeModes(); len(got) != 1 || got[0] != ermite.MergeMode_MERGE_MODE_SQUASH {
263 t.Errorf("modes = %v", got)262 t.Errorf("modes = %v", got)
M proto/ermite/merge_request.proto +35 -6
@@ -300,7 +300,16 @@ service MergeRequestService {
300300 // the mr:write scope. Fails with failed_precondition if the merge request
301301 // is not open. A closed merge request cannot be reopened: open a new one.
302302 rpc CloseMergeRequest(CloseMergeRequestRequest) returns (CloseMergeRequestResponse);
303- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.
303+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
304+ // the merge request can be merged. Needs the mr:write scope. Fails with
305+ // failed_precondition if the merge request is not open or is not a draft.
306+ // Publishes no event: there is none for a change of title. Needs the
307+ // "merge_requests.ready" feature.
308+ rpc MarkReady(MarkReadyRequest) returns (MarkReadyResponse);
309+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
310+ // which merges only when the checks on the head allow it: none failed and
311+ // none queued or running (a head with no checks may be merged; success,
312+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
304313 // The caller passes the head it reviewed: the server merges only if the
305314 // source branch still points to it, so a push between review and merge is
306315 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -310,17 +319,17 @@ service MergeRequestService {
310319 // ancestor of the head (rebase and push again, or merge with squash or
311320 // merge commit), if the mode is squash or merge commit and the head
312321 // conflicts with the target or shares no history with it (rebase and push
313- // again), if the mode is not allowed by RepoSettings, or if a check fails
314- // and RepoSettings.failing_checks_block is set. Merges of one
322+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
323+ // has not finished, unless ignore_checks is set. Merges of one
315324 // repository run one at a time. Repeating a call that succeeded fails with
316325 // failed_precondition (not open). On success the server publishes
317326 // MergeRequestMerged then Pushed for the target branch.
318327 rpc MergeMergeRequest(MergeMergeRequestRequest) returns (MergeMergeRequestResponse);
319328 // EnableAutoMerge asks the server to merge an open merge request by itself
320329 // once at least one check passed on its head, every run created on that head
321- // is complete, and the merge would be accepted whatever
322- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a
323- // token limited to branches, write access to the target branch
330+ // is complete, and no check failed. It does not take ignore_checks. Needs
331+ // the mr:merge scope and, for a token limited to branches, write access to
332+ // the target branch
324333 // (permission_denied otherwise). The server records the caller, the mode and
325334 // the head the caller saw; it merges as the caller, after resolving the caller
326335 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -549,6 +558,21 @@ message CloseMergeRequestResponse {
549558 MergeRequest merge_request = 1;
550559 }
551560
561+// MarkReadyRequest names the draft merge request to mark ready.
562+message MarkReadyRequest {
563+ // Repo is the repository name.
564+ string repo = 1;
565+ // Number is the merge request number.
566+ int64 number = 2;
567+}
568+
569+// MarkReadyResponse holds the merge request after marking it ready.
570+message MarkReadyResponse {
571+ // MergeRequest is the merge request with its title stripped of the draft
572+ // prefix.
573+ MergeRequest merge_request = 1;
574+}
575+
552576 // MergeMergeRequestRequest describes the merge to perform.
553577 message MergeMergeRequestRequest {
554578 // Repo is the repository name.
@@ -568,6 +592,11 @@ message MergeMergeRequestRequest {
568592 // request. Servers without the "merge_requests.delete_branch" feature ignore
569593 // it.
570594 bool delete_source_branch = 5;
595+ // IgnoreChecks merges whatever the checks say. Needs the mr:force-merge
596+ // scope (permission_denied otherwise). Servers without the
597+ // "merge_requests.ignore_checks" feature ignore it: check the feature
598+ // before setting it.
599+ bool ignore_checks = 6;
571600 }
572601
573602 // MergeMergeRequestResponse holds the merged merge request.
@@ -300,7 +300,16 @@ service MergeRequestService {
300 // the mr:write scope. Fails with failed_precondition if the merge request300 // the mr:write scope. Fails with failed_precondition if the merge request
301 // is not open. A closed merge request cannot be reopened: open a new one.301 // is not open. A closed merge request cannot be reopened: open a new one.
302 rpc CloseMergeRequest(CloseMergeRequestRequest) returns (CloseMergeRequestResponse);302 rpc CloseMergeRequest(CloseMergeRequestRequest) returns (CloseMergeRequestResponse);
303- // MergeMergeRequest merges an open merge request. Needs the mr:merge scope.303+ // MarkReady removes the draft prefix ("WIP:" or "[WIP]") from the title so
304+ // the merge request can be merged. Needs the mr:write scope. Fails with
305+ // failed_precondition if the merge request is not open or is not a draft.
306+ // Publishes no event: there is none for a change of title. Needs the
307+ // "merge_requests.ready" feature.
308+ rpc MarkReady(MarkReadyRequest) returns (MarkReadyResponse);
309+ // MergeMergeRequest merges an open merge request. Needs the mr:merge scope,
310+ // which merges only when the checks on the head allow it: none failed and
311+ // none queued or running (a head with no checks may be merged; success,
312+ // skipped and neutral pass). The mr:force-merge scope allows ignore_checks.
304 // The caller passes the head it reviewed: the server merges only if the313 // The caller passes the head it reviewed: the server merges only if the
305 // source branch still points to it, so a push between review and merge is314 // source branch still points to it, so a push between review and merge is
306 // never merged unseen. Fails with invalid_argument if head_id is empty or315 // never merged unseen. Fails with invalid_argument if head_id is empty or
@@ -310,17 +319,17 @@ service MergeRequestService {
310 // ancestor of the head (rebase and push again, or merge with squash or319 // ancestor of the head (rebase and push again, or merge with squash or
311 // merge commit), if the mode is squash or merge commit and the head320 // merge commit), if the mode is squash or merge commit and the head
312 // conflicts with the target or shares no history with it (rebase and push321 // conflicts with the target or shares no history with it (rebase and push
313- // again), if the mode is not allowed by RepoSettings, or if a check fails322+ // again), if the mode is not allowed by RepoSettings, or if a check failed or
314- // and RepoSettings.failing_checks_block is set. Merges of one323+ // has not finished, unless ignore_checks is set. Merges of one
315 // repository run one at a time. Repeating a call that succeeded fails with324 // repository run one at a time. Repeating a call that succeeded fails with
316 // failed_precondition (not open). On success the server publishes325 // failed_precondition (not open). On success the server publishes
317 // MergeRequestMerged then Pushed for the target branch.326 // MergeRequestMerged then Pushed for the target branch.
318 rpc MergeMergeRequest(MergeMergeRequestRequest) returns (MergeMergeRequestResponse);327 rpc MergeMergeRequest(MergeMergeRequestRequest) returns (MergeMergeRequestResponse);
319 // EnableAutoMerge asks the server to merge an open merge request by itself328 // EnableAutoMerge asks the server to merge an open merge request by itself
320 // once at least one check passed on its head, every run created on that head329 // once at least one check passed on its head, every run created on that head
321- // is complete, and the merge would be accepted whatever330+ // is complete, and no check failed. It does not take ignore_checks. Needs
322- // RepoSettings.failing_checks_block says. Needs the mr:merge scope and, for a331+ // the mr:merge scope and, for a token limited to branches, write access to
323- // token limited to branches, write access to the target branch332+ // the target branch
324 // (permission_denied otherwise). The server records the caller, the mode and333 // (permission_denied otherwise). The server records the caller, the mode and
325 // the head the caller saw; it merges as the caller, after resolving the caller334 // the head the caller saw; it merges as the caller, after resolving the caller
326 // again, and cancels the auto-merge if the caller can no longer merge, if the335 // again, and cancels the auto-merge if the caller can no longer merge, if the
@@ -549,6 +558,21 @@ message CloseMergeRequestResponse {
549 MergeRequest merge_request = 1;558 MergeRequest merge_request = 1;
550 }559 }
551 560
561+// MarkReadyRequest names the draft merge request to mark ready.
562+message MarkReadyRequest {
563+ // Repo is the repository name.
564+ string repo = 1;
565+ // Number is the merge request number.
566+ int64 number = 2;
567+}
568+
569+// MarkReadyResponse holds the merge request after marking it ready.
570+message MarkReadyResponse {
571+ // MergeRequest is the merge request with its title stripped of the draft
572+ // prefix.
573+ MergeRequest merge_request = 1;
574+}
575+
552 // MergeMergeRequestRequest describes the merge to perform.576 // MergeMergeRequestRequest describes the merge to perform.
553 message MergeMergeRequestRequest {577 message MergeMergeRequestRequest {
554 // Repo is the repository name.578 // Repo is the repository name.
@@ -568,6 +592,11 @@ message MergeMergeRequestRequest {
568 // request. Servers without the "merge_requests.delete_branch" feature ignore592 // request. Servers without the "merge_requests.delete_branch" feature ignore
569 // it.593 // it.
570 bool delete_source_branch = 5;594 bool delete_source_branch = 5;
595+ // IgnoreChecks merges whatever the checks say. Needs the mr:force-merge
596+ // scope (permission_denied otherwise). Servers without the
597+ // "merge_requests.ignore_checks" feature ignore it: check the feature
598+ // before setting it.
599+ bool ignore_checks = 6;
571 }600 }
572 601
573 // MergeMergeRequestResponse holds the merged merge request.602 // MergeMergeRequestResponse holds the merged merge request.
M proto/ermite/repo.proto +6 -8
@@ -35,16 +35,14 @@ enum IssuesMode {
3535 // RepoSettings are the settings of a repository that govern its merge
3636 // requests and issues.
3737 message RepoSettings {
38+ reserved 2;
39+ reserved "failing_checks_block";
40+
3841 // AllowedMergeModes are the modes with which a merge request of the
3942 // repository may be merged. It is never empty in a response and has no
4043 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
4144 // rejected.
4245 repeated MergeMode allowed_merge_modes = 1;
43- // FailingChecksBlock says whether a merge request whose checks fail cannot be
44- // merged. It is true at creation of the repository and always stored
45- // explicitly, so a later change of the server default never alters an
46- // existing repository.
47- bool failing_checks_block = 2;
4846 // Issues is the issue participation mode of the repository.
4947 IssuesMode issues = 3;
5048 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests
@@ -170,9 +168,9 @@ message UpdateRepoRequest {
170168 // the call fails with failed_precondition.
171169 string default_branch = 4;
172170 // UpdateMask lists the fields to change: "description", "visibility",
173- // "default_branch", "topics", "settings.allowed_merge_modes",
174- // "settings.failing_checks_block" and/or "settings.allow_auto_merge".
175- // "settings" stands for the three merge settings paths. It must not be empty unless issues is set. Other paths are
171+ // "default_branch", "topics", "settings.allowed_merge_modes" and/or
172+ // "settings.allow_auto_merge". "settings" stands for the two merge settings
173+ // paths. It must not be empty unless issues is set. Other paths are
176174 // invalid_argument, including "settings.issues" and "issues": the issues
177175 // field is applied outside the mask.
178176 google.protobuf.FieldMask update_mask = 5;
@@ -35,16 +35,14 @@ enum IssuesMode {
35 // RepoSettings are the settings of a repository that govern its merge35 // RepoSettings are the settings of a repository that govern its merge
36 // requests and issues.36 // requests and issues.
37 message RepoSettings {37 message RepoSettings {
38+ reserved 2;
39+ reserved "failing_checks_block";
40+
38 // AllowedMergeModes are the modes with which a merge request of the41 // AllowedMergeModes are the modes with which a merge request of the
39 // repository may be merged. It is never empty in a response and has no42 // repository may be merged. It is never empty in a response and has no
40 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is43 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
41 // rejected.44 // rejected.
42 repeated MergeMode allowed_merge_modes = 1;45 repeated MergeMode allowed_merge_modes = 1;
43- // FailingChecksBlock says whether a merge request whose checks fail cannot be
44- // merged. It is true at creation of the repository and always stored
45- // explicitly, so a later change of the server default never alters an
46- // existing repository.
47- bool failing_checks_block = 2;
48 // Issues is the issue participation mode of the repository.46 // Issues is the issue participation mode of the repository.
49 IssuesMode issues = 3;47 IssuesMode issues = 3;
50 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests48 // AllowAutoMerge says whether auto-merge can be enabled on the merge requests
@@ -170,9 +168,9 @@ message UpdateRepoRequest {
170 // the call fails with failed_precondition.168 // the call fails with failed_precondition.
171 string default_branch = 4;169 string default_branch = 4;
172 // UpdateMask lists the fields to change: "description", "visibility",170 // UpdateMask lists the fields to change: "description", "visibility",
173- // "default_branch", "topics", "settings.allowed_merge_modes",171+ // "default_branch", "topics", "settings.allowed_merge_modes" and/or
174- // "settings.failing_checks_block" and/or "settings.allow_auto_merge".172+ // "settings.allow_auto_merge". "settings" stands for the two merge settings
175- // "settings" stands for the three merge settings paths. It must not be empty unless issues is set. Other paths are173+ // paths. It must not be empty unless issues is set. Other paths are
176 // invalid_argument, including "settings.issues" and "issues": the issues174 // invalid_argument, including "settings.issues" and "issues": the issues
177 // field is applied outside the mask.175 // field is applied outside the mask.
178 google.protobuf.FieldMask update_mask = 5;176 google.protobuf.FieldMask update_mask = 5;
M proto/ermite/token.proto +5 -1
@@ -23,7 +23,8 @@ enum Scope {
2323 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.
2424 // Wire name: mr:write.
2525 SCOPE_MR_WRITE = 4;
26- // SCOPE_MR_MERGE allows merging merge requests. Wire name: mr:merge.
26+ // SCOPE_MR_MERGE allows merging merge requests whose checks allow it. Wire name:
27+ // mr:merge.
2728 SCOPE_MR_MERGE = 5;
2829 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:
2930 // ci:write.
@@ -45,6 +46,9 @@ enum Scope {
4546 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
4647 // issues. Wire name: issue:write.
4748 SCOPE_ISSUE_WRITE = 11;
49+ // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
50+ // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
51+ SCOPE_MR_FORCE_MERGE = 12;
4852 }
4953
5054 // Token describes a stored token. It never contains the secret nor its hash.
@@ -23,7 +23,8 @@ enum Scope {
23 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.23 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.
24 // Wire name: mr:write.24 // Wire name: mr:write.
25 SCOPE_MR_WRITE = 4;25 SCOPE_MR_WRITE = 4;
26- // SCOPE_MR_MERGE allows merging merge requests. Wire name: mr:merge.26+ // SCOPE_MR_MERGE allows merging merge requests whose checks allow it. Wire name:
27+ // mr:merge.
27 SCOPE_MR_MERGE = 5;28 SCOPE_MR_MERGE = 5;
28 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:29 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:
29 // ci:write.30 // ci:write.
@@ -45,6 +46,9 @@ enum Scope {
45 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening46 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
46 // issues. Wire name: issue:write.47 // issues. Wire name: issue:write.
47 SCOPE_ISSUE_WRITE = 11;48 SCOPE_ISSUE_WRITE = 11;
49+ // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
50+ // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
51+ SCOPE_MR_FORCE_MERGE = 12;
48 }52 }
49 53
50 // Token describes a stored token. It never contains the secret nor its hash.54 // Token describes a stored token. It never contains the secret nor its hash.

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
esc
close a dialog, leave a field

Branches 2

Tags 18

↑↓ moveenter openesc close