detached e4b332d

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

state
merged · e4b332d · fast-forward
branch
feat/mr-ready-merge-checks → main
opened
bnema ·
updated

Contract for ermite#22 and the merge check rules.

  • MergeRequestService.MarkReady: removes the draft prefix (mr:write), feature merge_requests.ready.
  • MergeMergeRequestRequest.ignore_checks (field 6): merge whatever the checks say, needs the new scope mr:force-merge (SCOPE_MR_FORCE_MERGE = 12), feature merge_requests.ignore_checks.
  • A merge without ignore_checks needs passing checks (none failed, queued or running; no checks is fine).
  • RepoSettings.failing_checks_block removed (field 2 reserved). Breaking (v0.x).

Release: tag v0.15.0 after merge; ermite then drops its local replace.

CommitSubjectAuthorDateSignatureStatus
e4b332dfix(proto): keep failing_checks_block as a deprecated field instead of removing itbriceGPG Verified
d1c609efeat(proto): add MarkReady, mr:force-merge and ignore_checks, drop failing_checks_blockbriceGPG Verified

Checks 4

9 files · +344 -135
4/4
M docs/services.md +1 -1
@@ -5,7 +5,7 @@
55 | `RepoService` | `ListRepos`, `GetRepo`, `CreateRepo`, `UpdateRepo` (field mask, merge settings), `DeleteRepo` |
66 | `GitService` | `ListRefs`, `GetTree`, `ListPaths`, `GetBlob` (streamed), `ListCommits`, `GetCommit` (structured diff), `ResolveRevision` |
77 | `TokenService` | `CreateToken` (secret shown once), `ListTokens`, `RevokeToken` |
8-| `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `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 +11 -10 generated file: collapsed
M gen/ermite/token.pb.go +10 -3
@@ -43,7 +43,8 @@ const (
4343 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.
4444 // Wire name: mr:write.
4545 Scope_SCOPE_MR_WRITE Scope = 4
46- // SCOPE_MR_MERGE allows merging merge requests. Wire name: mr:merge.
46+ // SCOPE_MR_MERGE allows merging merge requests whose checks allow it. Wire name:
47+ // mr:merge.
4748 Scope_SCOPE_MR_MERGE Scope = 5
4849 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:
4950 // ci:write.
@@ -65,6 +66,9 @@ const (
6566 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
6667 // issues. Wire name: issue:write.
6768 Scope_SCOPE_ISSUE_WRITE Scope = 11
69+ // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
70+ // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
71+ Scope_SCOPE_MR_FORCE_MERGE Scope = 12
6872 )
6973
7074 // Enum value maps for Scope.
@@ -82,6 +86,7 @@ var (
8286 9: "SCOPE_TOKEN_ADMIN",
8387 10: "SCOPE_MR_REVIEW",
8488 11: "SCOPE_ISSUE_WRITE",
89+ 12: "SCOPE_MR_FORCE_MERGE",
8590 }
8691 Scope_value = map[string]int32{
8792 "SCOPE_UNSPECIFIED": 0,
@@ -96,6 +101,7 @@ var (
96101 "SCOPE_TOKEN_ADMIN": 9,
97102 "SCOPE_MR_REVIEW": 10,
98103 "SCOPE_ISSUE_WRITE": 11,
104+ "SCOPE_MR_FORCE_MERGE": 12,
99105 }
100106 )
101107
@@ -620,7 +626,7 @@ const file_ermite_token_proto_rawDesc = "" +
620626 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"$\n" +
621627 "\x12RevokeTokenRequest\x12\x0e\n" +
622628 "\x02id\x18\x01 \x01(\tR\x02id\"\x15\n" +
623- "\x13RevokeTokenResponse*\x92\x02\n" +
629+ "\x13RevokeTokenResponse*\xac\x02\n" +
624630 "\x05Scope\x12\x15\n" +
625631 "\x11SCOPE_UNSPECIFIED\x10\x00\x12\x13\n" +
626632 "\x0fSCOPE_REPO_READ\x10\x01\x12\x14\n" +
@@ -634,7 +640,8 @@ const file_ermite_token_proto_rawDesc = "" +
634640 "\x11SCOPE_TOKEN_ADMIN\x10\t\x12\x13\n" +
635641 "\x0fSCOPE_MR_REVIEW\x10\n" +
636642 "\x12\x15\n" +
637- "\x11SCOPE_ISSUE_WRITE\x10\v2\xe3\x01\n" +
643+ "\x11SCOPE_ISSUE_WRITE\x10\v\x12\x18\n" +
644+ "\x14SCOPE_MR_FORCE_MERGE\x10\f2\xe3\x01\n" +
638645 "\fTokenService\x12F\n" +
639646 "\vCreateToken\x12\x1a.ermite.CreateTokenRequest\x1a\x1b.ermite.CreateTokenResponse\x12C\n" +
640647 "\n" +
@@ -43,7 +43,8 @@ const (
43 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.43 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.
44 // Wire name: mr:write.44 // Wire name: mr:write.
45 Scope_SCOPE_MR_WRITE Scope = 445 Scope_SCOPE_MR_WRITE Scope = 4
46- // SCOPE_MR_MERGE allows merging merge requests. Wire name: mr:merge.46+ // SCOPE_MR_MERGE allows merging merge requests whose checks allow it. Wire name:
47+ // mr:merge.
47 Scope_SCOPE_MR_MERGE Scope = 548 Scope_SCOPE_MR_MERGE Scope = 5
48 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:49 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:
49 // ci:write.50 // ci:write.
@@ -65,6 +66,9 @@ const (
65 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening66 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
66 // issues. Wire name: issue:write.67 // issues. Wire name: issue:write.
67 Scope_SCOPE_ISSUE_WRITE Scope = 1168 Scope_SCOPE_ISSUE_WRITE Scope = 11
69+ // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
70+ // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
71+ Scope_SCOPE_MR_FORCE_MERGE Scope = 12
68 )72 )
69 73
70 // Enum value maps for Scope.74 // Enum value maps for Scope.
@@ -82,6 +86,7 @@ var (
82 9: "SCOPE_TOKEN_ADMIN",86 9: "SCOPE_TOKEN_ADMIN",
83 10: "SCOPE_MR_REVIEW",87 10: "SCOPE_MR_REVIEW",
84 11: "SCOPE_ISSUE_WRITE",88 11: "SCOPE_ISSUE_WRITE",
89+ 12: "SCOPE_MR_FORCE_MERGE",
85 }90 }
86 Scope_value = map[string]int32{91 Scope_value = map[string]int32{
87 "SCOPE_UNSPECIFIED": 0,92 "SCOPE_UNSPECIFIED": 0,
@@ -96,6 +101,7 @@ var (
96 "SCOPE_TOKEN_ADMIN": 9,101 "SCOPE_TOKEN_ADMIN": 9,
97 "SCOPE_MR_REVIEW": 10,102 "SCOPE_MR_REVIEW": 10,
98 "SCOPE_ISSUE_WRITE": 11,103 "SCOPE_ISSUE_WRITE": 11,
104+ "SCOPE_MR_FORCE_MERGE": 12,
99 }105 }
100 )106 )
101 107
@@ -620,7 +626,7 @@ const file_ermite_token_proto_rawDesc = "" +
620 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"$\n" +626 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"$\n" +
621 "\x12RevokeTokenRequest\x12\x0e\n" +627 "\x12RevokeTokenRequest\x12\x0e\n" +
622 "\x02id\x18\x01 \x01(\tR\x02id\"\x15\n" +628 "\x02id\x18\x01 \x01(\tR\x02id\"\x15\n" +
623- "\x13RevokeTokenResponse*\x92\x02\n" +629+ "\x13RevokeTokenResponse*\xac\x02\n" +
624 "\x05Scope\x12\x15\n" +630 "\x05Scope\x12\x15\n" +
625 "\x11SCOPE_UNSPECIFIED\x10\x00\x12\x13\n" +631 "\x11SCOPE_UNSPECIFIED\x10\x00\x12\x13\n" +
626 "\x0fSCOPE_REPO_READ\x10\x01\x12\x14\n" +632 "\x0fSCOPE_REPO_READ\x10\x01\x12\x14\n" +
@@ -634,7 +640,8 @@ const file_ermite_token_proto_rawDesc = "" +
634 "\x11SCOPE_TOKEN_ADMIN\x10\t\x12\x13\n" +640 "\x11SCOPE_TOKEN_ADMIN\x10\t\x12\x13\n" +
635 "\x0fSCOPE_MR_REVIEW\x10\n" +641 "\x0fSCOPE_MR_REVIEW\x10\n" +
636 "\x12\x15\n" +642 "\x12\x15\n" +
637- "\x11SCOPE_ISSUE_WRITE\x10\v2\xe3\x01\n" +643+ "\x11SCOPE_ISSUE_WRITE\x10\v\x12\x18\n" +
644+ "\x14SCOPE_MR_FORCE_MERGE\x10\f2\xe3\x01\n" +
638 "\fTokenService\x12F\n" +645 "\fTokenService\x12F\n" +
639 "\vCreateToken\x12\x1a.ermite.CreateTokenRequest\x1a\x1b.ermite.CreateTokenResponse\x12C\n" +646 "\vCreateToken\x12\x1a.ermite.CreateTokenRequest\x1a\x1b.ermite.CreateTokenResponse\x12C\n" +
640 "\n" +647 "\n" +
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
@@ -40,11 +40,9 @@ message RepoSettings {
4040 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
4141 // rejected.
4242 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;
43+ // FailingChecksBlock is unused: servers ignore it and never set it. A merge
44+ // needs passing checks unless MergeMergeRequestRequest.ignore_checks is set.
45+ bool failing_checks_block = 2 [deprecated = true];
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;
@@ -40,11 +40,9 @@ message RepoSettings {
40 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is40 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
41 // rejected.41 // rejected.
42 repeated MergeMode allowed_merge_modes = 1;42 repeated MergeMode allowed_merge_modes = 1;
43- // FailingChecksBlock says whether a merge request whose checks fail cannot be43+ // FailingChecksBlock is unused: servers ignore it and never set it. A merge
44- // merged. It is true at creation of the repository and always stored44+ // needs passing checks unless MergeMergeRequestRequest.ignore_checks is set.
45- // explicitly, so a later change of the server default never alters an45+ bool failing_checks_block = 2 [deprecated = true];
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.

Comments1 open / 1

bnema

RepoSettings.failing_checks_block is kept as a deprecated field ([deprecated = true], ignored by servers) instead of being removed: buf breaking (FILE rules) refuses a field deletion. The contract change is now additive only.

Keyboard shortcuts

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

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

Branches 2

Tags 18

↑↓ moveenter openesc close