#6 feat(proto): mirror service and mirror events
M docs/services.md +32 -0
| @@ -18,3 +18,35 @@ | |||
| 18 | 18 | | `EnvironmentService` | `CreateEnvironment`, `ListEnvironments`, `DeleteEnvironment` | | |
| 19 | 19 | | `ArtifactService` | `ListArtifacts`, `DownloadArtifact` (streamed, resumable), `DeleteArtifact` | | |
| 20 | 20 | | `JobArtifactService` | `CreateJobArtifact`, `UploadJobArtifactBlock` (client stream), `CommitJobArtifact`, `FinalizeJobArtifact`, `ListJobArtifacts`, `DownloadJobArtifact` (streamed, resumable), `DeleteJobArtifact`. Scoped to the run of the job token | | |
| 21 | + | ||
| 22 | + | ## MirrorService | |
| 23 | + | ||
| 24 | + | Servers implementing push mirrors advertise `mirror` in `GetVersionResponse.features`. | |
| 25 | + | No new token scope is introduced. | |
| 26 | + | ||
| 27 | + | | RPC | Access and behavior | | |
| 28 | + | |---|---| | |
| 29 | + | | `GetMirrorKey` | Non-anonymous caller; generates the public SSH key on first call. Without `ERMITE_SECRETS_KEY`, returns `failed_precondition` | | |
| 30 | + | | `RotateMirrorKey` | Owner rights: admin token or a token with every scope and no repository or branch limits. Replaces the key immediately and returns the previous fingerprint | | |
| 31 | + | | `GetMirrorConfig`, `SetMirrorConfig` | Owner rights. Set patches only present fields; invalid fields return `invalid_argument` with field violations | | |
| 32 | + | | `SetRepoMirror` | `repo:admin` on the repository. Sets an override, even if global mirroring is disabled; empty cron and absent all-branches inherit the global values | | |
| 33 | + | | `RemoveRepoMirror` | `repo:admin` on the repository. Removes the override | | |
| 34 | + | | `SetRepoMirrorExcluded` | `repo:admin` on the repository. Opts out of or into the global template; a URL override wins over exclusion | | |
| 35 | + | | `GetMirrorStatus` | Read access to the repository. Error `detail` is returned only with `repo:admin` | | |
| 36 | + | | `ListMirrorStatus` | Owner rights | | |
| 37 | + | | `SyncMirror` | `repo:admin` for `repo`, or owner rights for `all=true` (with empty `repo`). Returns per-repository results, including queued and no-op indicators and a per-repository `error`; `all=true` continues past failing repositories and skips disabled ones | | |
| 38 | + | ||
| 39 | + | Cron expressions have five fields, run in UTC and must be at least five minutes | |
| 40 | + | apart. Mirrors push the default branch (or every branch with `all_branches`) and | |
| 41 | + | tags. `force` lifts a pause, skips the no-op check and the 60-second manual sync | |
| 42 | + | throttle; it **never** performs a Git force push. Pushes are atomic: one rejected | |
| 43 | + | ref fails the whole push. After key rotation, add the new public key to remotes | |
| 44 | + | and sync with `force` to recover from authentication failures. Configuration can | |
| 45 | + | be saved without `ERMITE_SECRETS_KEY`, but pushes cannot run without it. | |
| 46 | + | ||
| 47 | + | `EventService.Watch` adds `mirror_failed` (field 23, `MirrorFailed`) when a mirror | |
| 48 | + | starts failing (ok or disabled to failing or paused, once per incident), and `mirror_recovered` | |
| 49 | + | (field 24, `MirrorRecovered`) when a failing or paused mirror succeeds again. | |
| 50 | + | These are transition events, not events for every attempt. They are delivered on | |
| 51 | + | `repo:<name>` and `home`, subject to repository visibility. Neither event carries | |
| 52 | + | a URL, reason or error detail (`MirrorFailed` field 4, `reason`, was removed). | |
| @@ -18,3 +18,35 @@ | |||||
| 18 | | `EnvironmentService` | `CreateEnvironment`, `ListEnvironments`, `DeleteEnvironment` | | 18 | | `EnvironmentService` | `CreateEnvironment`, `ListEnvironments`, `DeleteEnvironment` | | ||
| 19 | | `ArtifactService` | `ListArtifacts`, `DownloadArtifact` (streamed, resumable), `DeleteArtifact` | | 19 | | `ArtifactService` | `ListArtifacts`, `DownloadArtifact` (streamed, resumable), `DeleteArtifact` | | ||
| 20 | | `JobArtifactService` | `CreateJobArtifact`, `UploadJobArtifactBlock` (client stream), `CommitJobArtifact`, `FinalizeJobArtifact`, `ListJobArtifacts`, `DownloadJobArtifact` (streamed, resumable), `DeleteJobArtifact`. Scoped to the run of the job token | | 20 | | `JobArtifactService` | `CreateJobArtifact`, `UploadJobArtifactBlock` (client stream), `CommitJobArtifact`, `FinalizeJobArtifact`, `ListJobArtifacts`, `DownloadJobArtifact` (streamed, resumable), `DeleteJobArtifact`. Scoped to the run of the job token | | ||
| 21 | + | ||||
| 22 | + | ## MirrorService | |||
| 23 | + | ||||
| 24 | + | Servers implementing push mirrors advertise `mirror` in `GetVersionResponse.features`. | |||
| 25 | + | No new token scope is introduced. | |||
| 26 | + | ||||
| 27 | + | | RPC | Access and behavior | | |||
| 28 | + | |---|---| | |||
| 29 | + | | `GetMirrorKey` | Non-anonymous caller; generates the public SSH key on first call. Without `ERMITE_SECRETS_KEY`, returns `failed_precondition` | | |||
| 30 | + | | `RotateMirrorKey` | Owner rights: admin token or a token with every scope and no repository or branch limits. Replaces the key immediately and returns the previous fingerprint | | |||
| 31 | + | | `GetMirrorConfig`, `SetMirrorConfig` | Owner rights. Set patches only present fields; invalid fields return `invalid_argument` with field violations | | |||
| 32 | + | | `SetRepoMirror` | `repo:admin` on the repository. Sets an override, even if global mirroring is disabled; empty cron and absent all-branches inherit the global values | | |||
| 33 | + | | `RemoveRepoMirror` | `repo:admin` on the repository. Removes the override | | |||
| 34 | + | | `SetRepoMirrorExcluded` | `repo:admin` on the repository. Opts out of or into the global template; a URL override wins over exclusion | | |||
| 35 | + | | `GetMirrorStatus` | Read access to the repository. Error `detail` is returned only with `repo:admin` | | |||
| 36 | + | | `ListMirrorStatus` | Owner rights | | |||
| 37 | + | | `SyncMirror` | `repo:admin` for `repo`, or owner rights for `all=true` (with empty `repo`). Returns per-repository results, including queued and no-op indicators and a per-repository `error`; `all=true` continues past failing repositories and skips disabled ones | | |||
| 38 | + | ||||
| 39 | + | Cron expressions have five fields, run in UTC and must be at least five minutes | |||
| 40 | + | apart. Mirrors push the default branch (or every branch with `all_branches`) and | |||
| 41 | + | tags. `force` lifts a pause, skips the no-op check and the 60-second manual sync | |||
| 42 | + | throttle; it **never** performs a Git force push. Pushes are atomic: one rejected | |||
| 43 | + | ref fails the whole push. After key rotation, add the new public key to remotes | |||
| 44 | + | and sync with `force` to recover from authentication failures. Configuration can | |||
| 45 | + | be saved without `ERMITE_SECRETS_KEY`, but pushes cannot run without it. | |||
| 46 | + | ||||
| 47 | + | `EventService.Watch` adds `mirror_failed` (field 23, `MirrorFailed`) when a mirror | |||
| 48 | + | starts failing (ok or disabled to failing or paused, once per incident), and `mirror_recovered` | |||
| 49 | + | (field 24, `MirrorRecovered`) when a failing or paused mirror succeeds again. | |||
| 50 | + | These are transition events, not events for every attempt. They are delivered on | |||
| 51 | + | `repo:<name>` and `home`, subject to repository visibility. Neither event carries | |||
| 52 | + | a URL, reason or error detail (`MirrorFailed` field 4, `reason`, was removed). | |||
A gen/ermite/ermiteconnect/mirror.connect.go +404 -0
| @@ -0,0 +1,404 @@ | |||
| 1 | + | // SPDX-License-Identifier: MIT | |
| 2 | + | ||
| 3 | + | // Code generated by protoc-gen-connect-go. DO NOT EDIT. | |
| 4 | + | // | |
| 5 | + | // Source: ermite/mirror.proto | |
| 6 | + | ||
| 7 | + | package ermiteconnect | |
| 8 | + | ||
| 9 | + | import ( | |
| 10 | + | ermite "bnema.dev/ermite-api/gen/ermite" | |
| 11 | + | connect "connectrpc.com/connect" | |
| 12 | + | context "context" | |
| 13 | + | errors "errors" | |
| 14 | + | http "net/http" | |
| 15 | + | strings "strings" | |
| 16 | + | ) | |
| 17 | + | ||
| 18 | + | // This is a compile-time assertion to ensure that this generated file and the connect package are | |
| 19 | + | // compatible. If you get a compiler error that this constant is not defined, this code was | |
| 20 | + | // generated with a version of connect newer than the one compiled into your binary. You can fix the | |
| 21 | + | // problem by either regenerating this code with an older version of connect or updating the connect | |
| 22 | + | // version compiled into your binary. | |
| 23 | + | const _ = connect.IsAtLeastVersion1_13_0 | |
| 24 | + | ||
| 25 | + | const ( | |
| 26 | + | // MirrorServiceName is the fully-qualified name of the MirrorService service. | |
| 27 | + | MirrorServiceName = "ermite.MirrorService" | |
| 28 | + | ) | |
| 29 | + | ||
| 30 | + | // These constants are the fully-qualified names of the RPCs defined in this package. They're | |
| 31 | + | // exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. | |
| 32 | + | // | |
| 33 | + | // Note that these are different from the fully-qualified method names used by | |
| 34 | + | // google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to | |
| 35 | + | // reflection-formatted method names, remove the leading slash and convert the remaining slash to a | |
| 36 | + | // period. | |
| 37 | + | const ( | |
| 38 | + | // MirrorServiceGetMirrorKeyProcedure is the fully-qualified name of the MirrorService's | |
| 39 | + | // GetMirrorKey RPC. | |
| 40 | + | MirrorServiceGetMirrorKeyProcedure = "/ermite.MirrorService/GetMirrorKey" | |
| 41 | + | // MirrorServiceRotateMirrorKeyProcedure is the fully-qualified name of the MirrorService's | |
| 42 | + | // RotateMirrorKey RPC. | |
| 43 | + | MirrorServiceRotateMirrorKeyProcedure = "/ermite.MirrorService/RotateMirrorKey" | |
| 44 | + | // MirrorServiceGetMirrorConfigProcedure is the fully-qualified name of the MirrorService's | |
| 45 | + | // GetMirrorConfig RPC. | |
| 46 | + | MirrorServiceGetMirrorConfigProcedure = "/ermite.MirrorService/GetMirrorConfig" | |
| 47 | + | // MirrorServiceSetMirrorConfigProcedure is the fully-qualified name of the MirrorService's | |
| 48 | + | // SetMirrorConfig RPC. | |
| 49 | + | MirrorServiceSetMirrorConfigProcedure = "/ermite.MirrorService/SetMirrorConfig" | |
| 50 | + | // MirrorServiceSetRepoMirrorProcedure is the fully-qualified name of the MirrorService's | |
| 51 | + | // SetRepoMirror RPC. | |
| 52 | + | MirrorServiceSetRepoMirrorProcedure = "/ermite.MirrorService/SetRepoMirror" | |
| 53 | + | // MirrorServiceRemoveRepoMirrorProcedure is the fully-qualified name of the MirrorService's | |
| 54 | + | // RemoveRepoMirror RPC. | |
| 55 | + | MirrorServiceRemoveRepoMirrorProcedure = "/ermite.MirrorService/RemoveRepoMirror" | |
| 56 | + | // MirrorServiceSetRepoMirrorExcludedProcedure is the fully-qualified name of the MirrorService's | |
| 57 | + | // SetRepoMirrorExcluded RPC. | |
| 58 | + | MirrorServiceSetRepoMirrorExcludedProcedure = "/ermite.MirrorService/SetRepoMirrorExcluded" | |
| 59 | + | // MirrorServiceGetMirrorStatusProcedure is the fully-qualified name of the MirrorService's | |
| 60 | + | // GetMirrorStatus RPC. | |
| 61 | + | MirrorServiceGetMirrorStatusProcedure = "/ermite.MirrorService/GetMirrorStatus" | |
| 62 | + | // MirrorServiceListMirrorStatusProcedure is the fully-qualified name of the MirrorService's | |
| 63 | + | // ListMirrorStatus RPC. | |
| 64 | + | MirrorServiceListMirrorStatusProcedure = "/ermite.MirrorService/ListMirrorStatus" | |
| 65 | + | // MirrorServiceSyncMirrorProcedure is the fully-qualified name of the MirrorService's SyncMirror | |
| 66 | + | // RPC. | |
| 67 | + | MirrorServiceSyncMirrorProcedure = "/ermite.MirrorService/SyncMirror" | |
| 68 | + | ) | |
| 69 | + | ||
| 70 | + | // MirrorServiceClient is a client for the ermite.MirrorService service. | |
| 71 | + | type MirrorServiceClient interface { | |
| 72 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |
| 73 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |
| 74 | + | // ERMITE_SECRETS_KEY. | |
| 75 | + | GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) | |
| 76 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |
| 77 | + | // and sync with force to recover from authentication failures. | |
| 78 | + | RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) | |
| 79 | + | // GetMirrorConfig returns the global mirror policy. | |
| 80 | + | GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) | |
| 81 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |
| 82 | + | // Invalid fields give invalid_argument with field violations. | |
| 83 | + | SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) | |
| 84 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |
| 85 | + | SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) | |
| 86 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |
| 87 | + | RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) | |
| 88 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |
| 89 | + | // policy. An explicit URL override takes precedence. | |
| 90 | + | SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) | |
| 91 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |
| 92 | + | GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) | |
| 93 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |
| 94 | + | ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) | |
| 95 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |
| 96 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |
| 97 | + | SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) | |
| 98 | + | } | |
| 99 | + | ||
| 100 | + | // NewMirrorServiceClient constructs a client for the ermite.MirrorService service. By default, it | |
| 101 | + | // uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends | |
| 102 | + | // uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or | |
| 103 | + | // connect.WithGRPCWeb() options. | |
| 104 | + | // | |
| 105 | + | // The URL supplied here should be the base URL for the Connect or gRPC server (for example, | |
| 106 | + | // http://api.acme.com or https://acme.com/grpc). | |
| 107 | + | func NewMirrorServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) MirrorServiceClient { | |
| 108 | + | baseURL = strings.TrimRight(baseURL, "/") | |
| 109 | + | mirrorServiceMethods := ermite.File_ermite_mirror_proto.Services().ByName("MirrorService").Methods() | |
| 110 | + | return &mirrorServiceClient{ | |
| 111 | + | getMirrorKey: connect.NewClient[ermite.GetMirrorKeyRequest, ermite.GetMirrorKeyResponse]( | |
| 112 | + | httpClient, | |
| 113 | + | baseURL+MirrorServiceGetMirrorKeyProcedure, | |
| 114 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorKey")), | |
| 115 | + | connect.WithClientOptions(opts...), | |
| 116 | + | ), | |
| 117 | + | rotateMirrorKey: connect.NewClient[ermite.RotateMirrorKeyRequest, ermite.RotateMirrorKeyResponse]( | |
| 118 | + | httpClient, | |
| 119 | + | baseURL+MirrorServiceRotateMirrorKeyProcedure, | |
| 120 | + | connect.WithSchema(mirrorServiceMethods.ByName("RotateMirrorKey")), | |
| 121 | + | connect.WithClientOptions(opts...), | |
| 122 | + | ), | |
| 123 | + | getMirrorConfig: connect.NewClient[ermite.GetMirrorConfigRequest, ermite.GetMirrorConfigResponse]( | |
| 124 | + | httpClient, | |
| 125 | + | baseURL+MirrorServiceGetMirrorConfigProcedure, | |
| 126 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorConfig")), | |
| 127 | + | connect.WithClientOptions(opts...), | |
| 128 | + | ), | |
| 129 | + | setMirrorConfig: connect.NewClient[ermite.SetMirrorConfigRequest, ermite.SetMirrorConfigResponse]( | |
| 130 | + | httpClient, | |
| 131 | + | baseURL+MirrorServiceSetMirrorConfigProcedure, | |
| 132 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetMirrorConfig")), | |
| 133 | + | connect.WithClientOptions(opts...), | |
| 134 | + | ), | |
| 135 | + | setRepoMirror: connect.NewClient[ermite.SetRepoMirrorRequest, ermite.SetRepoMirrorResponse]( | |
| 136 | + | httpClient, | |
| 137 | + | baseURL+MirrorServiceSetRepoMirrorProcedure, | |
| 138 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirror")), | |
| 139 | + | connect.WithClientOptions(opts...), | |
| 140 | + | ), | |
| 141 | + | removeRepoMirror: connect.NewClient[ermite.RemoveRepoMirrorRequest, ermite.RemoveRepoMirrorResponse]( | |
| 142 | + | httpClient, | |
| 143 | + | baseURL+MirrorServiceRemoveRepoMirrorProcedure, | |
| 144 | + | connect.WithSchema(mirrorServiceMethods.ByName("RemoveRepoMirror")), | |
| 145 | + | connect.WithClientOptions(opts...), | |
| 146 | + | ), | |
| 147 | + | setRepoMirrorExcluded: connect.NewClient[ermite.SetRepoMirrorExcludedRequest, ermite.SetRepoMirrorExcludedResponse]( | |
| 148 | + | httpClient, | |
| 149 | + | baseURL+MirrorServiceSetRepoMirrorExcludedProcedure, | |
| 150 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirrorExcluded")), | |
| 151 | + | connect.WithClientOptions(opts...), | |
| 152 | + | ), | |
| 153 | + | getMirrorStatus: connect.NewClient[ermite.GetMirrorStatusRequest, ermite.GetMirrorStatusResponse]( | |
| 154 | + | httpClient, | |
| 155 | + | baseURL+MirrorServiceGetMirrorStatusProcedure, | |
| 156 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorStatus")), | |
| 157 | + | connect.WithClientOptions(opts...), | |
| 158 | + | ), | |
| 159 | + | listMirrorStatus: connect.NewClient[ermite.ListMirrorStatusRequest, ermite.ListMirrorStatusResponse]( | |
| 160 | + | httpClient, | |
| 161 | + | baseURL+MirrorServiceListMirrorStatusProcedure, | |
| 162 | + | connect.WithSchema(mirrorServiceMethods.ByName("ListMirrorStatus")), | |
| 163 | + | connect.WithClientOptions(opts...), | |
| 164 | + | ), | |
| 165 | + | syncMirror: connect.NewClient[ermite.SyncMirrorRequest, ermite.SyncMirrorResponse]( | |
| 166 | + | httpClient, | |
| 167 | + | baseURL+MirrorServiceSyncMirrorProcedure, | |
| 168 | + | connect.WithSchema(mirrorServiceMethods.ByName("SyncMirror")), | |
| 169 | + | connect.WithClientOptions(opts...), | |
| 170 | + | ), | |
| 171 | + | } | |
| 172 | + | } | |
| 173 | + | ||
| 174 | + | // mirrorServiceClient implements MirrorServiceClient. | |
| 175 | + | type mirrorServiceClient struct { | |
| 176 | + | getMirrorKey *connect.Client[ermite.GetMirrorKeyRequest, ermite.GetMirrorKeyResponse] | |
| 177 | + | rotateMirrorKey *connect.Client[ermite.RotateMirrorKeyRequest, ermite.RotateMirrorKeyResponse] | |
| 178 | + | getMirrorConfig *connect.Client[ermite.GetMirrorConfigRequest, ermite.GetMirrorConfigResponse] | |
| 179 | + | setMirrorConfig *connect.Client[ermite.SetMirrorConfigRequest, ermite.SetMirrorConfigResponse] | |
| 180 | + | setRepoMirror *connect.Client[ermite.SetRepoMirrorRequest, ermite.SetRepoMirrorResponse] | |
| 181 | + | removeRepoMirror *connect.Client[ermite.RemoveRepoMirrorRequest, ermite.RemoveRepoMirrorResponse] | |
| 182 | + | setRepoMirrorExcluded *connect.Client[ermite.SetRepoMirrorExcludedRequest, ermite.SetRepoMirrorExcludedResponse] | |
| 183 | + | getMirrorStatus *connect.Client[ermite.GetMirrorStatusRequest, ermite.GetMirrorStatusResponse] | |
| 184 | + | listMirrorStatus *connect.Client[ermite.ListMirrorStatusRequest, ermite.ListMirrorStatusResponse] | |
| 185 | + | syncMirror *connect.Client[ermite.SyncMirrorRequest, ermite.SyncMirrorResponse] | |
| 186 | + | } | |
| 187 | + | ||
| 188 | + | // GetMirrorKey calls ermite.MirrorService.GetMirrorKey. | |
| 189 | + | func (c *mirrorServiceClient) GetMirrorKey(ctx context.Context, req *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) { | |
| 190 | + | return c.getMirrorKey.CallUnary(ctx, req) | |
| 191 | + | } | |
| 192 | + | ||
| 193 | + | // RotateMirrorKey calls ermite.MirrorService.RotateMirrorKey. | |
| 194 | + | func (c *mirrorServiceClient) RotateMirrorKey(ctx context.Context, req *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) { | |
| 195 | + | return c.rotateMirrorKey.CallUnary(ctx, req) | |
| 196 | + | } | |
| 197 | + | ||
| 198 | + | // GetMirrorConfig calls ermite.MirrorService.GetMirrorConfig. | |
| 199 | + | func (c *mirrorServiceClient) GetMirrorConfig(ctx context.Context, req *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) { | |
| 200 | + | return c.getMirrorConfig.CallUnary(ctx, req) | |
| 201 | + | } | |
| 202 | + | ||
| 203 | + | // SetMirrorConfig calls ermite.MirrorService.SetMirrorConfig. | |
| 204 | + | func (c *mirrorServiceClient) SetMirrorConfig(ctx context.Context, req *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) { | |
| 205 | + | return c.setMirrorConfig.CallUnary(ctx, req) | |
| 206 | + | } | |
| 207 | + | ||
| 208 | + | // SetRepoMirror calls ermite.MirrorService.SetRepoMirror. | |
| 209 | + | func (c *mirrorServiceClient) SetRepoMirror(ctx context.Context, req *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) { | |
| 210 | + | return c.setRepoMirror.CallUnary(ctx, req) | |
| 211 | + | } | |
| 212 | + | ||
| 213 | + | // RemoveRepoMirror calls ermite.MirrorService.RemoveRepoMirror. | |
| 214 | + | func (c *mirrorServiceClient) RemoveRepoMirror(ctx context.Context, req *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) { | |
| 215 | + | return c.removeRepoMirror.CallUnary(ctx, req) | |
| 216 | + | } | |
| 217 | + | ||
| 218 | + | // SetRepoMirrorExcluded calls ermite.MirrorService.SetRepoMirrorExcluded. | |
| 219 | + | func (c *mirrorServiceClient) SetRepoMirrorExcluded(ctx context.Context, req *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) { | |
| 220 | + | return c.setRepoMirrorExcluded.CallUnary(ctx, req) | |
| 221 | + | } | |
| 222 | + | ||
| 223 | + | // GetMirrorStatus calls ermite.MirrorService.GetMirrorStatus. | |
| 224 | + | func (c *mirrorServiceClient) GetMirrorStatus(ctx context.Context, req *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) { | |
| 225 | + | return c.getMirrorStatus.CallUnary(ctx, req) | |
| 226 | + | } | |
| 227 | + | ||
| 228 | + | // ListMirrorStatus calls ermite.MirrorService.ListMirrorStatus. | |
| 229 | + | func (c *mirrorServiceClient) ListMirrorStatus(ctx context.Context, req *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) { | |
| 230 | + | return c.listMirrorStatus.CallUnary(ctx, req) | |
| 231 | + | } | |
| 232 | + | ||
| 233 | + | // SyncMirror calls ermite.MirrorService.SyncMirror. | |
| 234 | + | func (c *mirrorServiceClient) SyncMirror(ctx context.Context, req *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) { | |
| 235 | + | return c.syncMirror.CallUnary(ctx, req) | |
| 236 | + | } | |
| 237 | + | ||
| 238 | + | // MirrorServiceHandler is an implementation of the ermite.MirrorService service. | |
| 239 | + | type MirrorServiceHandler interface { | |
| 240 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |
| 241 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |
| 242 | + | // ERMITE_SECRETS_KEY. | |
| 243 | + | GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) | |
| 244 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |
| 245 | + | // and sync with force to recover from authentication failures. | |
| 246 | + | RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) | |
| 247 | + | // GetMirrorConfig returns the global mirror policy. | |
| 248 | + | GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) | |
| 249 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |
| 250 | + | // Invalid fields give invalid_argument with field violations. | |
| 251 | + | SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) | |
| 252 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |
| 253 | + | SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) | |
| 254 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |
| 255 | + | RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) | |
| 256 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |
| 257 | + | // policy. An explicit URL override takes precedence. | |
| 258 | + | SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) | |
| 259 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |
| 260 | + | GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) | |
| 261 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |
| 262 | + | ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) | |
| 263 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |
| 264 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |
| 265 | + | SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) | |
| 266 | + | } | |
| 267 | + | ||
| 268 | + | // NewMirrorServiceHandler builds an HTTP handler from the service implementation. It returns the | |
| 269 | + | // path on which to mount the handler and the handler itself. | |
| 270 | + | // | |
| 271 | + | // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf | |
| 272 | + | // and JSON codecs. They also support gzip compression. | |
| 273 | + | func NewMirrorServiceHandler(svc MirrorServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { | |
| 274 | + | mirrorServiceMethods := ermite.File_ermite_mirror_proto.Services().ByName("MirrorService").Methods() | |
| 275 | + | mirrorServiceGetMirrorKeyHandler := connect.NewUnaryHandler( | |
| 276 | + | MirrorServiceGetMirrorKeyProcedure, | |
| 277 | + | svc.GetMirrorKey, | |
| 278 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorKey")), | |
| 279 | + | connect.WithHandlerOptions(opts...), | |
| 280 | + | ) | |
| 281 | + | mirrorServiceRotateMirrorKeyHandler := connect.NewUnaryHandler( | |
| 282 | + | MirrorServiceRotateMirrorKeyProcedure, | |
| 283 | + | svc.RotateMirrorKey, | |
| 284 | + | connect.WithSchema(mirrorServiceMethods.ByName("RotateMirrorKey")), | |
| 285 | + | connect.WithHandlerOptions(opts...), | |
| 286 | + | ) | |
| 287 | + | mirrorServiceGetMirrorConfigHandler := connect.NewUnaryHandler( | |
| 288 | + | MirrorServiceGetMirrorConfigProcedure, | |
| 289 | + | svc.GetMirrorConfig, | |
| 290 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorConfig")), | |
| 291 | + | connect.WithHandlerOptions(opts...), | |
| 292 | + | ) | |
| 293 | + | mirrorServiceSetMirrorConfigHandler := connect.NewUnaryHandler( | |
| 294 | + | MirrorServiceSetMirrorConfigProcedure, | |
| 295 | + | svc.SetMirrorConfig, | |
| 296 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetMirrorConfig")), | |
| 297 | + | connect.WithHandlerOptions(opts...), | |
| 298 | + | ) | |
| 299 | + | mirrorServiceSetRepoMirrorHandler := connect.NewUnaryHandler( | |
| 300 | + | MirrorServiceSetRepoMirrorProcedure, | |
| 301 | + | svc.SetRepoMirror, | |
| 302 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirror")), | |
| 303 | + | connect.WithHandlerOptions(opts...), | |
| 304 | + | ) | |
| 305 | + | mirrorServiceRemoveRepoMirrorHandler := connect.NewUnaryHandler( | |
| 306 | + | MirrorServiceRemoveRepoMirrorProcedure, | |
| 307 | + | svc.RemoveRepoMirror, | |
| 308 | + | connect.WithSchema(mirrorServiceMethods.ByName("RemoveRepoMirror")), | |
| 309 | + | connect.WithHandlerOptions(opts...), | |
| 310 | + | ) | |
| 311 | + | mirrorServiceSetRepoMirrorExcludedHandler := connect.NewUnaryHandler( | |
| 312 | + | MirrorServiceSetRepoMirrorExcludedProcedure, | |
| 313 | + | svc.SetRepoMirrorExcluded, | |
| 314 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirrorExcluded")), | |
| 315 | + | connect.WithHandlerOptions(opts...), | |
| 316 | + | ) | |
| 317 | + | mirrorServiceGetMirrorStatusHandler := connect.NewUnaryHandler( | |
| 318 | + | MirrorServiceGetMirrorStatusProcedure, | |
| 319 | + | svc.GetMirrorStatus, | |
| 320 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorStatus")), | |
| 321 | + | connect.WithHandlerOptions(opts...), | |
| 322 | + | ) | |
| 323 | + | mirrorServiceListMirrorStatusHandler := connect.NewUnaryHandler( | |
| 324 | + | MirrorServiceListMirrorStatusProcedure, | |
| 325 | + | svc.ListMirrorStatus, | |
| 326 | + | connect.WithSchema(mirrorServiceMethods.ByName("ListMirrorStatus")), | |
| 327 | + | connect.WithHandlerOptions(opts...), | |
| 328 | + | ) | |
| 329 | + | mirrorServiceSyncMirrorHandler := connect.NewUnaryHandler( | |
| 330 | + | MirrorServiceSyncMirrorProcedure, | |
| 331 | + | svc.SyncMirror, | |
| 332 | + | connect.WithSchema(mirrorServiceMethods.ByName("SyncMirror")), | |
| 333 | + | connect.WithHandlerOptions(opts...), | |
| 334 | + | ) | |
| 335 | + | return "/ermite.MirrorService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| 336 | + | switch r.URL.Path { | |
| 337 | + | case MirrorServiceGetMirrorKeyProcedure: | |
| 338 | + | mirrorServiceGetMirrorKeyHandler.ServeHTTP(w, r) | |
| 339 | + | case MirrorServiceRotateMirrorKeyProcedure: | |
| 340 | + | mirrorServiceRotateMirrorKeyHandler.ServeHTTP(w, r) | |
| 341 | + | case MirrorServiceGetMirrorConfigProcedure: | |
| 342 | + | mirrorServiceGetMirrorConfigHandler.ServeHTTP(w, r) | |
| 343 | + | case MirrorServiceSetMirrorConfigProcedure: | |
| 344 | + | mirrorServiceSetMirrorConfigHandler.ServeHTTP(w, r) | |
| 345 | + | case MirrorServiceSetRepoMirrorProcedure: | |
| 346 | + | mirrorServiceSetRepoMirrorHandler.ServeHTTP(w, r) | |
| 347 | + | case MirrorServiceRemoveRepoMirrorProcedure: | |
| 348 | + | mirrorServiceRemoveRepoMirrorHandler.ServeHTTP(w, r) | |
| 349 | + | case MirrorServiceSetRepoMirrorExcludedProcedure: | |
| 350 | + | mirrorServiceSetRepoMirrorExcludedHandler.ServeHTTP(w, r) | |
| 351 | + | case MirrorServiceGetMirrorStatusProcedure: | |
| 352 | + | mirrorServiceGetMirrorStatusHandler.ServeHTTP(w, r) | |
| 353 | + | case MirrorServiceListMirrorStatusProcedure: | |
| 354 | + | mirrorServiceListMirrorStatusHandler.ServeHTTP(w, r) | |
| 355 | + | case MirrorServiceSyncMirrorProcedure: | |
| 356 | + | mirrorServiceSyncMirrorHandler.ServeHTTP(w, r) | |
| 357 | + | default: | |
| 358 | + | http.NotFound(w, r) | |
| 359 | + | } | |
| 360 | + | }) | |
| 361 | + | } | |
| 362 | + | ||
| 363 | + | // UnimplementedMirrorServiceHandler returns CodeUnimplemented from all methods. | |
| 364 | + | type UnimplementedMirrorServiceHandler struct{} | |
| 365 | + | ||
| 366 | + | func (UnimplementedMirrorServiceHandler) GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) { | |
| 367 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorKey is not implemented")) | |
| 368 | + | } | |
| 369 | + | ||
| 370 | + | func (UnimplementedMirrorServiceHandler) RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) { | |
| 371 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.RotateMirrorKey is not implemented")) | |
| 372 | + | } | |
| 373 | + | ||
| 374 | + | func (UnimplementedMirrorServiceHandler) GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) { | |
| 375 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorConfig is not implemented")) | |
| 376 | + | } | |
| 377 | + | ||
| 378 | + | func (UnimplementedMirrorServiceHandler) SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) { | |
| 379 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetMirrorConfig is not implemented")) | |
| 380 | + | } | |
| 381 | + | ||
| 382 | + | func (UnimplementedMirrorServiceHandler) SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) { | |
| 383 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetRepoMirror is not implemented")) | |
| 384 | + | } | |
| 385 | + | ||
| 386 | + | func (UnimplementedMirrorServiceHandler) RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) { | |
| 387 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.RemoveRepoMirror is not implemented")) | |
| 388 | + | } | |
| 389 | + | ||
| 390 | + | func (UnimplementedMirrorServiceHandler) SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) { | |
| 391 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetRepoMirrorExcluded is not implemented")) | |
| 392 | + | } | |
| 393 | + | ||
| 394 | + | func (UnimplementedMirrorServiceHandler) GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) { | |
| 395 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorStatus is not implemented")) | |
| 396 | + | } | |
| 397 | + | ||
| 398 | + | func (UnimplementedMirrorServiceHandler) ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) { | |
| 399 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.ListMirrorStatus is not implemented")) | |
| 400 | + | } | |
| 401 | + | ||
| 402 | + | func (UnimplementedMirrorServiceHandler) SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) { | |
| 403 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SyncMirror is not implemented")) | |
| 404 | + | } | |
| @@ -0,0 +1,404 @@ | |||||
| 1 | + | // SPDX-License-Identifier: MIT | |||
| 2 | + | ||||
| 3 | + | // Code generated by protoc-gen-connect-go. DO NOT EDIT. | |||
| 4 | + | // | |||
| 5 | + | // Source: ermite/mirror.proto | |||
| 6 | + | ||||
| 7 | + | package ermiteconnect | |||
| 8 | + | ||||
| 9 | + | import ( | |||
| 10 | + | ermite "bnema.dev/ermite-api/gen/ermite" | |||
| 11 | + | connect "connectrpc.com/connect" | |||
| 12 | + | context "context" | |||
| 13 | + | errors "errors" | |||
| 14 | + | http "net/http" | |||
| 15 | + | strings "strings" | |||
| 16 | + | ) | |||
| 17 | + | ||||
| 18 | + | // This is a compile-time assertion to ensure that this generated file and the connect package are | |||
| 19 | + | // compatible. If you get a compiler error that this constant is not defined, this code was | |||
| 20 | + | // generated with a version of connect newer than the one compiled into your binary. You can fix the | |||
| 21 | + | // problem by either regenerating this code with an older version of connect or updating the connect | |||
| 22 | + | // version compiled into your binary. | |||
| 23 | + | const _ = connect.IsAtLeastVersion1_13_0 | |||
| 24 | + | ||||
| 25 | + | const ( | |||
| 26 | + | // MirrorServiceName is the fully-qualified name of the MirrorService service. | |||
| 27 | + | MirrorServiceName = "ermite.MirrorService" | |||
| 28 | + | ) | |||
| 29 | + | ||||
| 30 | + | // These constants are the fully-qualified names of the RPCs defined in this package. They're | |||
| 31 | + | // exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. | |||
| 32 | + | // | |||
| 33 | + | // Note that these are different from the fully-qualified method names used by | |||
| 34 | + | // google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to | |||
| 35 | + | // reflection-formatted method names, remove the leading slash and convert the remaining slash to a | |||
| 36 | + | // period. | |||
| 37 | + | const ( | |||
| 38 | + | // MirrorServiceGetMirrorKeyProcedure is the fully-qualified name of the MirrorService's | |||
| 39 | + | // GetMirrorKey RPC. | |||
| 40 | + | MirrorServiceGetMirrorKeyProcedure = "/ermite.MirrorService/GetMirrorKey" | |||
| 41 | + | // MirrorServiceRotateMirrorKeyProcedure is the fully-qualified name of the MirrorService's | |||
| 42 | + | // RotateMirrorKey RPC. | |||
| 43 | + | MirrorServiceRotateMirrorKeyProcedure = "/ermite.MirrorService/RotateMirrorKey" | |||
| 44 | + | // MirrorServiceGetMirrorConfigProcedure is the fully-qualified name of the MirrorService's | |||
| 45 | + | // GetMirrorConfig RPC. | |||
| 46 | + | MirrorServiceGetMirrorConfigProcedure = "/ermite.MirrorService/GetMirrorConfig" | |||
| 47 | + | // MirrorServiceSetMirrorConfigProcedure is the fully-qualified name of the MirrorService's | |||
| 48 | + | // SetMirrorConfig RPC. | |||
| 49 | + | MirrorServiceSetMirrorConfigProcedure = "/ermite.MirrorService/SetMirrorConfig" | |||
| 50 | + | // MirrorServiceSetRepoMirrorProcedure is the fully-qualified name of the MirrorService's | |||
| 51 | + | // SetRepoMirror RPC. | |||
| 52 | + | MirrorServiceSetRepoMirrorProcedure = "/ermite.MirrorService/SetRepoMirror" | |||
| 53 | + | // MirrorServiceRemoveRepoMirrorProcedure is the fully-qualified name of the MirrorService's | |||
| 54 | + | // RemoveRepoMirror RPC. | |||
| 55 | + | MirrorServiceRemoveRepoMirrorProcedure = "/ermite.MirrorService/RemoveRepoMirror" | |||
| 56 | + | // MirrorServiceSetRepoMirrorExcludedProcedure is the fully-qualified name of the MirrorService's | |||
| 57 | + | // SetRepoMirrorExcluded RPC. | |||
| 58 | + | MirrorServiceSetRepoMirrorExcludedProcedure = "/ermite.MirrorService/SetRepoMirrorExcluded" | |||
| 59 | + | // MirrorServiceGetMirrorStatusProcedure is the fully-qualified name of the MirrorService's | |||
| 60 | + | // GetMirrorStatus RPC. | |||
| 61 | + | MirrorServiceGetMirrorStatusProcedure = "/ermite.MirrorService/GetMirrorStatus" | |||
| 62 | + | // MirrorServiceListMirrorStatusProcedure is the fully-qualified name of the MirrorService's | |||
| 63 | + | // ListMirrorStatus RPC. | |||
| 64 | + | MirrorServiceListMirrorStatusProcedure = "/ermite.MirrorService/ListMirrorStatus" | |||
| 65 | + | // MirrorServiceSyncMirrorProcedure is the fully-qualified name of the MirrorService's SyncMirror | |||
| 66 | + | // RPC. | |||
| 67 | + | MirrorServiceSyncMirrorProcedure = "/ermite.MirrorService/SyncMirror" | |||
| 68 | + | ) | |||
| 69 | + | ||||
| 70 | + | // MirrorServiceClient is a client for the ermite.MirrorService service. | |||
| 71 | + | type MirrorServiceClient interface { | |||
| 72 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |||
| 73 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |||
| 74 | + | // ERMITE_SECRETS_KEY. | |||
| 75 | + | GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) | |||
| 76 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |||
| 77 | + | // and sync with force to recover from authentication failures. | |||
| 78 | + | RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) | |||
| 79 | + | // GetMirrorConfig returns the global mirror policy. | |||
| 80 | + | GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) | |||
| 81 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |||
| 82 | + | // Invalid fields give invalid_argument with field violations. | |||
| 83 | + | SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) | |||
| 84 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |||
| 85 | + | SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) | |||
| 86 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |||
| 87 | + | RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) | |||
| 88 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |||
| 89 | + | // policy. An explicit URL override takes precedence. | |||
| 90 | + | SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) | |||
| 91 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |||
| 92 | + | GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) | |||
| 93 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |||
| 94 | + | ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) | |||
| 95 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |||
| 96 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |||
| 97 | + | SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) | |||
| 98 | + | } | |||
| 99 | + | ||||
| 100 | + | // NewMirrorServiceClient constructs a client for the ermite.MirrorService service. By default, it | |||
| 101 | + | // uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends | |||
| 102 | + | // uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or | |||
| 103 | + | // connect.WithGRPCWeb() options. | |||
| 104 | + | // | |||
| 105 | + | // The URL supplied here should be the base URL for the Connect or gRPC server (for example, | |||
| 106 | + | // http://api.acme.com or https://acme.com/grpc). | |||
| 107 | + | func NewMirrorServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) MirrorServiceClient { | |||
| 108 | + | baseURL = strings.TrimRight(baseURL, "/") | |||
| 109 | + | mirrorServiceMethods := ermite.File_ermite_mirror_proto.Services().ByName("MirrorService").Methods() | |||
| 110 | + | return &mirrorServiceClient{ | |||
| 111 | + | getMirrorKey: connect.NewClient[ermite.GetMirrorKeyRequest, ermite.GetMirrorKeyResponse]( | |||
| 112 | + | httpClient, | |||
| 113 | + | baseURL+MirrorServiceGetMirrorKeyProcedure, | |||
| 114 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorKey")), | |||
| 115 | + | connect.WithClientOptions(opts...), | |||
| 116 | + | ), | |||
| 117 | + | rotateMirrorKey: connect.NewClient[ermite.RotateMirrorKeyRequest, ermite.RotateMirrorKeyResponse]( | |||
| 118 | + | httpClient, | |||
| 119 | + | baseURL+MirrorServiceRotateMirrorKeyProcedure, | |||
| 120 | + | connect.WithSchema(mirrorServiceMethods.ByName("RotateMirrorKey")), | |||
| 121 | + | connect.WithClientOptions(opts...), | |||
| 122 | + | ), | |||
| 123 | + | getMirrorConfig: connect.NewClient[ermite.GetMirrorConfigRequest, ermite.GetMirrorConfigResponse]( | |||
| 124 | + | httpClient, | |||
| 125 | + | baseURL+MirrorServiceGetMirrorConfigProcedure, | |||
| 126 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorConfig")), | |||
| 127 | + | connect.WithClientOptions(opts...), | |||
| 128 | + | ), | |||
| 129 | + | setMirrorConfig: connect.NewClient[ermite.SetMirrorConfigRequest, ermite.SetMirrorConfigResponse]( | |||
| 130 | + | httpClient, | |||
| 131 | + | baseURL+MirrorServiceSetMirrorConfigProcedure, | |||
| 132 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetMirrorConfig")), | |||
| 133 | + | connect.WithClientOptions(opts...), | |||
| 134 | + | ), | |||
| 135 | + | setRepoMirror: connect.NewClient[ermite.SetRepoMirrorRequest, ermite.SetRepoMirrorResponse]( | |||
| 136 | + | httpClient, | |||
| 137 | + | baseURL+MirrorServiceSetRepoMirrorProcedure, | |||
| 138 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirror")), | |||
| 139 | + | connect.WithClientOptions(opts...), | |||
| 140 | + | ), | |||
| 141 | + | removeRepoMirror: connect.NewClient[ermite.RemoveRepoMirrorRequest, ermite.RemoveRepoMirrorResponse]( | |||
| 142 | + | httpClient, | |||
| 143 | + | baseURL+MirrorServiceRemoveRepoMirrorProcedure, | |||
| 144 | + | connect.WithSchema(mirrorServiceMethods.ByName("RemoveRepoMirror")), | |||
| 145 | + | connect.WithClientOptions(opts...), | |||
| 146 | + | ), | |||
| 147 | + | setRepoMirrorExcluded: connect.NewClient[ermite.SetRepoMirrorExcludedRequest, ermite.SetRepoMirrorExcludedResponse]( | |||
| 148 | + | httpClient, | |||
| 149 | + | baseURL+MirrorServiceSetRepoMirrorExcludedProcedure, | |||
| 150 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirrorExcluded")), | |||
| 151 | + | connect.WithClientOptions(opts...), | |||
| 152 | + | ), | |||
| 153 | + | getMirrorStatus: connect.NewClient[ermite.GetMirrorStatusRequest, ermite.GetMirrorStatusResponse]( | |||
| 154 | + | httpClient, | |||
| 155 | + | baseURL+MirrorServiceGetMirrorStatusProcedure, | |||
| 156 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorStatus")), | |||
| 157 | + | connect.WithClientOptions(opts...), | |||
| 158 | + | ), | |||
| 159 | + | listMirrorStatus: connect.NewClient[ermite.ListMirrorStatusRequest, ermite.ListMirrorStatusResponse]( | |||
| 160 | + | httpClient, | |||
| 161 | + | baseURL+MirrorServiceListMirrorStatusProcedure, | |||
| 162 | + | connect.WithSchema(mirrorServiceMethods.ByName("ListMirrorStatus")), | |||
| 163 | + | connect.WithClientOptions(opts...), | |||
| 164 | + | ), | |||
| 165 | + | syncMirror: connect.NewClient[ermite.SyncMirrorRequest, ermite.SyncMirrorResponse]( | |||
| 166 | + | httpClient, | |||
| 167 | + | baseURL+MirrorServiceSyncMirrorProcedure, | |||
| 168 | + | connect.WithSchema(mirrorServiceMethods.ByName("SyncMirror")), | |||
| 169 | + | connect.WithClientOptions(opts...), | |||
| 170 | + | ), | |||
| 171 | + | } | |||
| 172 | + | } | |||
| 173 | + | ||||
| 174 | + | // mirrorServiceClient implements MirrorServiceClient. | |||
| 175 | + | type mirrorServiceClient struct { | |||
| 176 | + | getMirrorKey *connect.Client[ermite.GetMirrorKeyRequest, ermite.GetMirrorKeyResponse] | |||
| 177 | + | rotateMirrorKey *connect.Client[ermite.RotateMirrorKeyRequest, ermite.RotateMirrorKeyResponse] | |||
| 178 | + | getMirrorConfig *connect.Client[ermite.GetMirrorConfigRequest, ermite.GetMirrorConfigResponse] | |||
| 179 | + | setMirrorConfig *connect.Client[ermite.SetMirrorConfigRequest, ermite.SetMirrorConfigResponse] | |||
| 180 | + | setRepoMirror *connect.Client[ermite.SetRepoMirrorRequest, ermite.SetRepoMirrorResponse] | |||
| 181 | + | removeRepoMirror *connect.Client[ermite.RemoveRepoMirrorRequest, ermite.RemoveRepoMirrorResponse] | |||
| 182 | + | setRepoMirrorExcluded *connect.Client[ermite.SetRepoMirrorExcludedRequest, ermite.SetRepoMirrorExcludedResponse] | |||
| 183 | + | getMirrorStatus *connect.Client[ermite.GetMirrorStatusRequest, ermite.GetMirrorStatusResponse] | |||
| 184 | + | listMirrorStatus *connect.Client[ermite.ListMirrorStatusRequest, ermite.ListMirrorStatusResponse] | |||
| 185 | + | syncMirror *connect.Client[ermite.SyncMirrorRequest, ermite.SyncMirrorResponse] | |||
| 186 | + | } | |||
| 187 | + | ||||
| 188 | + | // GetMirrorKey calls ermite.MirrorService.GetMirrorKey. | |||
| 189 | + | func (c *mirrorServiceClient) GetMirrorKey(ctx context.Context, req *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) { | |||
| 190 | + | return c.getMirrorKey.CallUnary(ctx, req) | |||
| 191 | + | } | |||
| 192 | + | ||||
| 193 | + | // RotateMirrorKey calls ermite.MirrorService.RotateMirrorKey. | |||
| 194 | + | func (c *mirrorServiceClient) RotateMirrorKey(ctx context.Context, req *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) { | |||
| 195 | + | return c.rotateMirrorKey.CallUnary(ctx, req) | |||
| 196 | + | } | |||
| 197 | + | ||||
| 198 | + | // GetMirrorConfig calls ermite.MirrorService.GetMirrorConfig. | |||
| 199 | + | func (c *mirrorServiceClient) GetMirrorConfig(ctx context.Context, req *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) { | |||
| 200 | + | return c.getMirrorConfig.CallUnary(ctx, req) | |||
| 201 | + | } | |||
| 202 | + | ||||
| 203 | + | // SetMirrorConfig calls ermite.MirrorService.SetMirrorConfig. | |||
| 204 | + | func (c *mirrorServiceClient) SetMirrorConfig(ctx context.Context, req *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) { | |||
| 205 | + | return c.setMirrorConfig.CallUnary(ctx, req) | |||
| 206 | + | } | |||
| 207 | + | ||||
| 208 | + | // SetRepoMirror calls ermite.MirrorService.SetRepoMirror. | |||
| 209 | + | func (c *mirrorServiceClient) SetRepoMirror(ctx context.Context, req *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) { | |||
| 210 | + | return c.setRepoMirror.CallUnary(ctx, req) | |||
| 211 | + | } | |||
| 212 | + | ||||
| 213 | + | // RemoveRepoMirror calls ermite.MirrorService.RemoveRepoMirror. | |||
| 214 | + | func (c *mirrorServiceClient) RemoveRepoMirror(ctx context.Context, req *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) { | |||
| 215 | + | return c.removeRepoMirror.CallUnary(ctx, req) | |||
| 216 | + | } | |||
| 217 | + | ||||
| 218 | + | // SetRepoMirrorExcluded calls ermite.MirrorService.SetRepoMirrorExcluded. | |||
| 219 | + | func (c *mirrorServiceClient) SetRepoMirrorExcluded(ctx context.Context, req *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) { | |||
| 220 | + | return c.setRepoMirrorExcluded.CallUnary(ctx, req) | |||
| 221 | + | } | |||
| 222 | + | ||||
| 223 | + | // GetMirrorStatus calls ermite.MirrorService.GetMirrorStatus. | |||
| 224 | + | func (c *mirrorServiceClient) GetMirrorStatus(ctx context.Context, req *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) { | |||
| 225 | + | return c.getMirrorStatus.CallUnary(ctx, req) | |||
| 226 | + | } | |||
| 227 | + | ||||
| 228 | + | // ListMirrorStatus calls ermite.MirrorService.ListMirrorStatus. | |||
| 229 | + | func (c *mirrorServiceClient) ListMirrorStatus(ctx context.Context, req *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) { | |||
| 230 | + | return c.listMirrorStatus.CallUnary(ctx, req) | |||
| 231 | + | } | |||
| 232 | + | ||||
| 233 | + | // SyncMirror calls ermite.MirrorService.SyncMirror. | |||
| 234 | + | func (c *mirrorServiceClient) SyncMirror(ctx context.Context, req *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) { | |||
| 235 | + | return c.syncMirror.CallUnary(ctx, req) | |||
| 236 | + | } | |||
| 237 | + | ||||
| 238 | + | // MirrorServiceHandler is an implementation of the ermite.MirrorService service. | |||
| 239 | + | type MirrorServiceHandler interface { | |||
| 240 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |||
| 241 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |||
| 242 | + | // ERMITE_SECRETS_KEY. | |||
| 243 | + | GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) | |||
| 244 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |||
| 245 | + | // and sync with force to recover from authentication failures. | |||
| 246 | + | RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) | |||
| 247 | + | // GetMirrorConfig returns the global mirror policy. | |||
| 248 | + | GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) | |||
| 249 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |||
| 250 | + | // Invalid fields give invalid_argument with field violations. | |||
| 251 | + | SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) | |||
| 252 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |||
| 253 | + | SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) | |||
| 254 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |||
| 255 | + | RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) | |||
| 256 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |||
| 257 | + | // policy. An explicit URL override takes precedence. | |||
| 258 | + | SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) | |||
| 259 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |||
| 260 | + | GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) | |||
| 261 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |||
| 262 | + | ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) | |||
| 263 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |||
| 264 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |||
| 265 | + | SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) | |||
| 266 | + | } | |||
| 267 | + | ||||
| 268 | + | // NewMirrorServiceHandler builds an HTTP handler from the service implementation. It returns the | |||
| 269 | + | // path on which to mount the handler and the handler itself. | |||
| 270 | + | // | |||
| 271 | + | // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf | |||
| 272 | + | // and JSON codecs. They also support gzip compression. | |||
| 273 | + | func NewMirrorServiceHandler(svc MirrorServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { | |||
| 274 | + | mirrorServiceMethods := ermite.File_ermite_mirror_proto.Services().ByName("MirrorService").Methods() | |||
| 275 | + | mirrorServiceGetMirrorKeyHandler := connect.NewUnaryHandler( | |||
| 276 | + | MirrorServiceGetMirrorKeyProcedure, | |||
| 277 | + | svc.GetMirrorKey, | |||
| 278 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorKey")), | |||
| 279 | + | connect.WithHandlerOptions(opts...), | |||
| 280 | + | ) | |||
| 281 | + | mirrorServiceRotateMirrorKeyHandler := connect.NewUnaryHandler( | |||
| 282 | + | MirrorServiceRotateMirrorKeyProcedure, | |||
| 283 | + | svc.RotateMirrorKey, | |||
| 284 | + | connect.WithSchema(mirrorServiceMethods.ByName("RotateMirrorKey")), | |||
| 285 | + | connect.WithHandlerOptions(opts...), | |||
| 286 | + | ) | |||
| 287 | + | mirrorServiceGetMirrorConfigHandler := connect.NewUnaryHandler( | |||
| 288 | + | MirrorServiceGetMirrorConfigProcedure, | |||
| 289 | + | svc.GetMirrorConfig, | |||
| 290 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorConfig")), | |||
| 291 | + | connect.WithHandlerOptions(opts...), | |||
| 292 | + | ) | |||
| 293 | + | mirrorServiceSetMirrorConfigHandler := connect.NewUnaryHandler( | |||
| 294 | + | MirrorServiceSetMirrorConfigProcedure, | |||
| 295 | + | svc.SetMirrorConfig, | |||
| 296 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetMirrorConfig")), | |||
| 297 | + | connect.WithHandlerOptions(opts...), | |||
| 298 | + | ) | |||
| 299 | + | mirrorServiceSetRepoMirrorHandler := connect.NewUnaryHandler( | |||
| 300 | + | MirrorServiceSetRepoMirrorProcedure, | |||
| 301 | + | svc.SetRepoMirror, | |||
| 302 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirror")), | |||
| 303 | + | connect.WithHandlerOptions(opts...), | |||
| 304 | + | ) | |||
| 305 | + | mirrorServiceRemoveRepoMirrorHandler := connect.NewUnaryHandler( | |||
| 306 | + | MirrorServiceRemoveRepoMirrorProcedure, | |||
| 307 | + | svc.RemoveRepoMirror, | |||
| 308 | + | connect.WithSchema(mirrorServiceMethods.ByName("RemoveRepoMirror")), | |||
| 309 | + | connect.WithHandlerOptions(opts...), | |||
| 310 | + | ) | |||
| 311 | + | mirrorServiceSetRepoMirrorExcludedHandler := connect.NewUnaryHandler( | |||
| 312 | + | MirrorServiceSetRepoMirrorExcludedProcedure, | |||
| 313 | + | svc.SetRepoMirrorExcluded, | |||
| 314 | + | connect.WithSchema(mirrorServiceMethods.ByName("SetRepoMirrorExcluded")), | |||
| 315 | + | connect.WithHandlerOptions(opts...), | |||
| 316 | + | ) | |||
| 317 | + | mirrorServiceGetMirrorStatusHandler := connect.NewUnaryHandler( | |||
| 318 | + | MirrorServiceGetMirrorStatusProcedure, | |||
| 319 | + | svc.GetMirrorStatus, | |||
| 320 | + | connect.WithSchema(mirrorServiceMethods.ByName("GetMirrorStatus")), | |||
| 321 | + | connect.WithHandlerOptions(opts...), | |||
| 322 | + | ) | |||
| 323 | + | mirrorServiceListMirrorStatusHandler := connect.NewUnaryHandler( | |||
| 324 | + | MirrorServiceListMirrorStatusProcedure, | |||
| 325 | + | svc.ListMirrorStatus, | |||
| 326 | + | connect.WithSchema(mirrorServiceMethods.ByName("ListMirrorStatus")), | |||
| 327 | + | connect.WithHandlerOptions(opts...), | |||
| 328 | + | ) | |||
| 329 | + | mirrorServiceSyncMirrorHandler := connect.NewUnaryHandler( | |||
| 330 | + | MirrorServiceSyncMirrorProcedure, | |||
| 331 | + | svc.SyncMirror, | |||
| 332 | + | connect.WithSchema(mirrorServiceMethods.ByName("SyncMirror")), | |||
| 333 | + | connect.WithHandlerOptions(opts...), | |||
| 334 | + | ) | |||
| 335 | + | return "/ermite.MirrorService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |||
| 336 | + | switch r.URL.Path { | |||
| 337 | + | case MirrorServiceGetMirrorKeyProcedure: | |||
| 338 | + | mirrorServiceGetMirrorKeyHandler.ServeHTTP(w, r) | |||
| 339 | + | case MirrorServiceRotateMirrorKeyProcedure: | |||
| 340 | + | mirrorServiceRotateMirrorKeyHandler.ServeHTTP(w, r) | |||
| 341 | + | case MirrorServiceGetMirrorConfigProcedure: | |||
| 342 | + | mirrorServiceGetMirrorConfigHandler.ServeHTTP(w, r) | |||
| 343 | + | case MirrorServiceSetMirrorConfigProcedure: | |||
| 344 | + | mirrorServiceSetMirrorConfigHandler.ServeHTTP(w, r) | |||
| 345 | + | case MirrorServiceSetRepoMirrorProcedure: | |||
| 346 | + | mirrorServiceSetRepoMirrorHandler.ServeHTTP(w, r) | |||
| 347 | + | case MirrorServiceRemoveRepoMirrorProcedure: | |||
| 348 | + | mirrorServiceRemoveRepoMirrorHandler.ServeHTTP(w, r) | |||
| 349 | + | case MirrorServiceSetRepoMirrorExcludedProcedure: | |||
| 350 | + | mirrorServiceSetRepoMirrorExcludedHandler.ServeHTTP(w, r) | |||
| 351 | + | case MirrorServiceGetMirrorStatusProcedure: | |||
| 352 | + | mirrorServiceGetMirrorStatusHandler.ServeHTTP(w, r) | |||
| 353 | + | case MirrorServiceListMirrorStatusProcedure: | |||
| 354 | + | mirrorServiceListMirrorStatusHandler.ServeHTTP(w, r) | |||
| 355 | + | case MirrorServiceSyncMirrorProcedure: | |||
| 356 | + | mirrorServiceSyncMirrorHandler.ServeHTTP(w, r) | |||
| 357 | + | default: | |||
| 358 | + | http.NotFound(w, r) | |||
| 359 | + | } | |||
| 360 | + | }) | |||
| 361 | + | } | |||
| 362 | + | ||||
| 363 | + | // UnimplementedMirrorServiceHandler returns CodeUnimplemented from all methods. | |||
| 364 | + | type UnimplementedMirrorServiceHandler struct{} | |||
| 365 | + | ||||
| 366 | + | func (UnimplementedMirrorServiceHandler) GetMirrorKey(context.Context, *connect.Request[ermite.GetMirrorKeyRequest]) (*connect.Response[ermite.GetMirrorKeyResponse], error) { | |||
| 367 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorKey is not implemented")) | |||
| 368 | + | } | |||
| 369 | + | ||||
| 370 | + | func (UnimplementedMirrorServiceHandler) RotateMirrorKey(context.Context, *connect.Request[ermite.RotateMirrorKeyRequest]) (*connect.Response[ermite.RotateMirrorKeyResponse], error) { | |||
| 371 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.RotateMirrorKey is not implemented")) | |||
| 372 | + | } | |||
| 373 | + | ||||
| 374 | + | func (UnimplementedMirrorServiceHandler) GetMirrorConfig(context.Context, *connect.Request[ermite.GetMirrorConfigRequest]) (*connect.Response[ermite.GetMirrorConfigResponse], error) { | |||
| 375 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorConfig is not implemented")) | |||
| 376 | + | } | |||
| 377 | + | ||||
| 378 | + | func (UnimplementedMirrorServiceHandler) SetMirrorConfig(context.Context, *connect.Request[ermite.SetMirrorConfigRequest]) (*connect.Response[ermite.SetMirrorConfigResponse], error) { | |||
| 379 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetMirrorConfig is not implemented")) | |||
| 380 | + | } | |||
| 381 | + | ||||
| 382 | + | func (UnimplementedMirrorServiceHandler) SetRepoMirror(context.Context, *connect.Request[ermite.SetRepoMirrorRequest]) (*connect.Response[ermite.SetRepoMirrorResponse], error) { | |||
| 383 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetRepoMirror is not implemented")) | |||
| 384 | + | } | |||
| 385 | + | ||||
| 386 | + | func (UnimplementedMirrorServiceHandler) RemoveRepoMirror(context.Context, *connect.Request[ermite.RemoveRepoMirrorRequest]) (*connect.Response[ermite.RemoveRepoMirrorResponse], error) { | |||
| 387 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.RemoveRepoMirror is not implemented")) | |||
| 388 | + | } | |||
| 389 | + | ||||
| 390 | + | func (UnimplementedMirrorServiceHandler) SetRepoMirrorExcluded(context.Context, *connect.Request[ermite.SetRepoMirrorExcludedRequest]) (*connect.Response[ermite.SetRepoMirrorExcludedResponse], error) { | |||
| 391 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SetRepoMirrorExcluded is not implemented")) | |||
| 392 | + | } | |||
| 393 | + | ||||
| 394 | + | func (UnimplementedMirrorServiceHandler) GetMirrorStatus(context.Context, *connect.Request[ermite.GetMirrorStatusRequest]) (*connect.Response[ermite.GetMirrorStatusResponse], error) { | |||
| 395 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.GetMirrorStatus is not implemented")) | |||
| 396 | + | } | |||
| 397 | + | ||||
| 398 | + | func (UnimplementedMirrorServiceHandler) ListMirrorStatus(context.Context, *connect.Request[ermite.ListMirrorStatusRequest]) (*connect.Response[ermite.ListMirrorStatusResponse], error) { | |||
| 399 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.ListMirrorStatus is not implemented")) | |||
| 400 | + | } | |||
| 401 | + | ||||
| 402 | + | func (UnimplementedMirrorServiceHandler) SyncMirror(context.Context, *connect.Request[ermite.SyncMirrorRequest]) (*connect.Response[ermite.SyncMirrorResponse], error) { | |||
| 403 | + | return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.MirrorService.SyncMirror is not implemented")) | |||
| 404 | + | } | |||
M gen/ermite/event.pb.go +206 -41
| @@ -171,6 +171,8 @@ type Event struct { | |||
| 171 | 171 | // *Event_IssueCommented | |
| 172 | 172 | // *Event_IssueSubmitted | |
| 173 | 173 | // *Event_MergeRequestMergeability | |
| 174 | + | // *Event_MirrorFailed | |
| 175 | + | // *Event_MirrorRecovered | |
| 174 | 176 | Kind isEvent_Kind `protobuf_oneof:"kind"` | |
| 175 | 177 | unknownFields protoimpl.UnknownFields | |
| 176 | 178 | sizeCache protoimpl.SizeCache | |
| @@ -407,6 +409,24 @@ func (x *Event) GetMergeRequestMergeability() *MergeRequestMergeability { | |||
| 407 | 409 | return nil | |
| 408 | 410 | } | |
| 409 | 411 | ||
| 412 | + | func (x *Event) GetMirrorFailed() *MirrorFailed { | |
| 413 | + | if x != nil { | |
| 414 | + | if x, ok := x.Kind.(*Event_MirrorFailed); ok { | |
| 415 | + | return x.MirrorFailed | |
| 416 | + | } | |
| 417 | + | } | |
| 418 | + | return nil | |
| 419 | + | } | |
| 420 | + | ||
| 421 | + | func (x *Event) GetMirrorRecovered() *MirrorRecovered { | |
| 422 | + | if x != nil { | |
| 423 | + | if x, ok := x.Kind.(*Event_MirrorRecovered); ok { | |
| 424 | + | return x.MirrorRecovered | |
| 425 | + | } | |
| 426 | + | } | |
| 427 | + | return nil | |
| 428 | + | } | |
| 429 | + | ||
| 410 | 430 | type isEvent_Kind interface { | |
| 411 | 431 | isEvent_Kind() | |
| 412 | 432 | } | |
| @@ -513,6 +533,16 @@ type Event_MergeRequestMergeability struct { | |||
| 513 | 533 | MergeRequestMergeability *MergeRequestMergeability `protobuf:"bytes,22,opt,name=merge_request_mergeability,json=mergeRequestMergeability,proto3,oneof"` | |
| 514 | 534 | } | |
| 515 | 535 | ||
| 536 | + | type Event_MirrorFailed struct { | |
| 537 | + | // MirrorFailed: a mirror entered failing or paused. | |
| 538 | + | MirrorFailed *MirrorFailed `protobuf:"bytes,23,opt,name=mirror_failed,json=mirrorFailed,proto3,oneof"` | |
| 539 | + | } | |
| 540 | + | ||
| 541 | + | type Event_MirrorRecovered struct { | |
| 542 | + | // MirrorRecovered: a failing or paused mirror succeeded again. | |
| 543 | + | MirrorRecovered *MirrorRecovered `protobuf:"bytes,24,opt,name=mirror_recovered,json=mirrorRecovered,proto3,oneof"` | |
| 544 | + | } | |
| 545 | + | ||
| 516 | 546 | func (*Event_RepoCreated) isEvent_Kind() {} | |
| 517 | 547 | ||
| 518 | 548 | func (*Event_RepoUpdated) isEvent_Kind() {} | |
| @@ -553,6 +583,10 @@ func (*Event_IssueSubmitted) isEvent_Kind() {} | |||
| 553 | 583 | ||
| 554 | 584 | func (*Event_MergeRequestMergeability) isEvent_Kind() {} | |
| 555 | 585 | ||
| 586 | + | func (*Event_MirrorFailed) isEvent_Kind() {} | |
| 587 | + | ||
| 588 | + | func (*Event_MirrorRecovered) isEvent_Kind() {} | |
| 589 | + | ||
| 556 | 590 | // RepoCreated reports a new repository. | |
| 557 | 591 | type RepoCreated struct { | |
| 558 | 592 | state protoimpl.MessageState `protogen:"open.v1"` | |
| @@ -1668,17 +1702,131 @@ func (x *JobUpdated) GetJob() *RunJob { | |||
| 1668 | 1702 | return nil | |
| 1669 | 1703 | } | |
| 1670 | 1704 | ||
| 1705 | + | // MirrorFailed reports the start of a failure incident: a transition from ok | |
| 1706 | + | // or disabled into failing or paused. It is sent once per incident, not for | |
| 1707 | + | // each failed attempt nor for failing to paused. Servers with feature "mirror" | |
| 1708 | + | // deliver it on "repo:<name>" and "home", subject to repository visibility. It | |
| 1709 | + | // carries no URL, reason or error detail; read the status for those. | |
| 1710 | + | type MirrorFailed struct { | |
| 1711 | + | state protoimpl.MessageState `protogen:"open.v1"` | |
| 1712 | + | // Repo is the repository name. | |
| 1713 | + | Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` | |
| 1714 | + | // State is the new mirror state. | |
| 1715 | + | State MirrorState `protobuf:"varint,2,opt,name=state,proto3,enum=ermite.MirrorState" json:"state,omitempty"` | |
| 1716 | + | // FailureClass is the failure category. | |
| 1717 | + | FailureClass string `protobuf:"bytes,3,opt,name=failure_class,json=failureClass,proto3" json:"failure_class,omitempty"` | |
| 1718 | + | unknownFields protoimpl.UnknownFields | |
| 1719 | + | sizeCache protoimpl.SizeCache | |
| 1720 | + | } | |
| 1721 | + | ||
| 1722 | + | func (x *MirrorFailed) Reset() { | |
| 1723 | + | *x = MirrorFailed{} | |
| 1724 | + | mi := &file_ermite_event_proto_msgTypes[24] | |
| 1725 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 1726 | + | ms.StoreMessageInfo(mi) | |
| 1727 | + | } | |
| 1728 | + | ||
| 1729 | + | func (x *MirrorFailed) String() string { | |
| 1730 | + | return protoimpl.X.MessageStringOf(x) | |
| 1731 | + | } | |
| 1732 | + | ||
| 1733 | + | func (*MirrorFailed) ProtoMessage() {} | |
| 1734 | + | ||
| 1735 | + | func (x *MirrorFailed) ProtoReflect() protoreflect.Message { | |
| 1736 | + | mi := &file_ermite_event_proto_msgTypes[24] | |
| 1737 | + | if x != nil { | |
| 1738 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 1739 | + | if ms.LoadMessageInfo() == nil { | |
| 1740 | + | ms.StoreMessageInfo(mi) | |
| 1741 | + | } | |
| 1742 | + | return ms | |
| 1743 | + | } | |
| 1744 | + | return mi.MessageOf(x) | |
| 1745 | + | } | |
| 1746 | + | ||
| 1747 | + | // Deprecated: Use MirrorFailed.ProtoReflect.Descriptor instead. | |
| 1748 | + | func (*MirrorFailed) Descriptor() ([]byte, []int) { | |
| 1749 | + | return file_ermite_event_proto_rawDescGZIP(), []int{24} | |
| 1750 | + | } | |
| 1751 | + | ||
| 1752 | + | func (x *MirrorFailed) GetRepo() string { | |
| 1753 | + | if x != nil { | |
| 1754 | + | return x.Repo | |
| 1755 | + | } | |
| 1756 | + | return "" | |
| 1757 | + | } | |
| 1758 | + | ||
| 1759 | + | func (x *MirrorFailed) GetState() MirrorState { | |
| 1760 | + | if x != nil { | |
| 1761 | + | return x.State | |
| 1762 | + | } | |
| 1763 | + | return MirrorState_MIRROR_STATE_UNSPECIFIED | |
| 1764 | + | } | |
| 1765 | + | ||
| 1766 | + | func (x *MirrorFailed) GetFailureClass() string { | |
| 1767 | + | if x != nil { | |
| 1768 | + | return x.FailureClass | |
| 1769 | + | } | |
| 1770 | + | return "" | |
| 1771 | + | } | |
| 1772 | + | ||
| 1773 | + | // MirrorRecovered reports a successful sync after failing or paused. Delivery | |
| 1774 | + | // follows MirrorFailed. It carries no URL or error detail. | |
| 1775 | + | type MirrorRecovered struct { | |
| 1776 | + | state protoimpl.MessageState `protogen:"open.v1"` | |
| 1777 | + | // Repo is the repository name. | |
| 1778 | + | Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` | |
| 1779 | + | unknownFields protoimpl.UnknownFields | |
| 1780 | + | sizeCache protoimpl.SizeCache | |
| 1781 | + | } | |
| 1782 | + | ||
| 1783 | + | func (x *MirrorRecovered) Reset() { | |
| 1784 | + | *x = MirrorRecovered{} | |
| 1785 | + | mi := &file_ermite_event_proto_msgTypes[25] | |
| 1786 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 1787 | + | ms.StoreMessageInfo(mi) | |
| 1788 | + | } | |
| 1789 | + | ||
| 1790 | + | func (x *MirrorRecovered) String() string { | |
| 1791 | + | return protoimpl.X.MessageStringOf(x) | |
| 1792 | + | } | |
| 1793 | + | ||
| 1794 | + | func (*MirrorRecovered) ProtoMessage() {} | |
| 1795 | + | ||
| 1796 | + | func (x *MirrorRecovered) ProtoReflect() protoreflect.Message { | |
| 1797 | + | mi := &file_ermite_event_proto_msgTypes[25] | |
| 1798 | + | if x != nil { | |
| 1799 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 1800 | + | if ms.LoadMessageInfo() == nil { | |
| 1801 | + | ms.StoreMessageInfo(mi) | |
| 1802 | + | } | |
| 1803 | + | return ms | |
| 1804 | + | } | |
| 1805 | + | return mi.MessageOf(x) | |
| 1806 | + | } | |
| 1807 | + | ||
| 1808 | + | // Deprecated: Use MirrorRecovered.ProtoReflect.Descriptor instead. | |
| 1809 | + | func (*MirrorRecovered) Descriptor() ([]byte, []int) { | |
| 1810 | + | return file_ermite_event_proto_rawDescGZIP(), []int{25} | |
| 1811 | + | } | |
| 1812 | + | ||
| 1813 | + | func (x *MirrorRecovered) GetRepo() string { | |
| 1814 | + | if x != nil { | |
| 1815 | + | return x.Repo | |
| 1816 | + | } | |
| 1817 | + | return "" | |
| 1818 | + | } | |
| 1819 | + | ||
| 1671 | 1820 | var File_ermite_event_proto protoreflect.FileDescriptor | |
| 1672 | 1821 | ||
| 1673 | 1822 | const file_ermite_event_proto_rawDesc = "" + | |
| 1674 | 1823 | "\n" + | |
| 1675 | - | "\x12ermite/event.proto\x12\x06ermite\x1a\x12ermite/issue.proto\x1a\x1aermite/merge_request.proto\x1a\x11ermite/repo.proto\x1a\x10ermite/run.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"I\n" + | |
| 1824 | + | "\x12ermite/event.proto\x12\x06ermite\x1a\x12ermite/issue.proto\x1a\x1aermite/merge_request.proto\x1a\x13ermite/mirror.proto\x1a\x11ermite/repo.proto\x1a\x10ermite/run.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"I\n" + | |
| 1676 | 1825 | "\fWatchRequest\x12\x16\n" + | |
| 1677 | 1826 | "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" + | |
| 1678 | 1827 | "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" + | |
| 1679 | 1828 | "\rWatchResponse\x12#\n" + | |
| 1680 | - | "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xc8\n" + | |
| 1681 | - | "\n" + | |
| 1829 | + | "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xcb\v\n" + | |
| 1682 | 1830 | "\x05Event\x12\x0e\n" + | |
| 1683 | 1831 | "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" + | |
| 1684 | 1832 | "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" + | |
| @@ -1704,7 +1852,9 @@ const file_ermite_event_proto_rawDesc = "" + | |||
| 1704 | 1852 | "\x0eissue_reopened\x18\x13 \x01(\v2\x15.ermite.IssueReopenedH\x00R\rissueReopened\x12A\n" + | |
| 1705 | 1853 | "\x0fissue_commented\x18\x14 \x01(\v2\x16.ermite.IssueCommentedH\x00R\x0eissueCommented\x12A\n" + | |
| 1706 | 1854 | "\x0fissue_submitted\x18\x15 \x01(\v2\x16.ermite.IssueSubmittedH\x00R\x0eissueSubmitted\x12`\n" + | |
| 1707 | - | "\x1amerge_request_mergeability\x18\x16 \x01(\v2 .ermite.MergeRequestMergeabilityH\x00R\x18mergeRequestMergeabilityB\x06\n" + | |
| 1855 | + | "\x1amerge_request_mergeability\x18\x16 \x01(\v2 .ermite.MergeRequestMergeabilityH\x00R\x18mergeRequestMergeability\x12;\n" + | |
| 1856 | + | "\rmirror_failed\x18\x17 \x01(\v2\x14.ermite.MirrorFailedH\x00R\fmirrorFailed\x12D\n" + | |
| 1857 | + | "\x10mirror_recovered\x18\x18 \x01(\v2\x17.ermite.MirrorRecoveredH\x00R\x0fmirrorRecoveredB\x06\n" + | |
| 1708 | 1858 | "\x04kind\"/\n" + | |
| 1709 | 1859 | "\vRepoCreated\x12 \n" + | |
| 1710 | 1860 | "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" + | |
| @@ -1765,7 +1915,13 @@ const file_ermite_event_proto_rawDesc = "" + | |||
| 1765 | 1915 | "\x03run\x18\x01 \x01(\v2\v.ermite.RunR\x03run\".\n" + | |
| 1766 | 1916 | "\n" + | |
| 1767 | 1917 | "JobUpdated\x12 \n" + | |
| 1768 | - | "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job2F\n" + | |
| 1918 | + | "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"\x80\x01\n" + | |
| 1919 | + | "\fMirrorFailed\x12\x12\n" + | |
| 1920 | + | "\x04repo\x18\x01 \x01(\tR\x04repo\x12)\n" + | |
| 1921 | + | "\x05state\x18\x02 \x01(\x0e2\x13.ermite.MirrorStateR\x05state\x12#\n" + | |
| 1922 | + | "\rfailure_class\x18\x03 \x01(\tR\ffailureClassJ\x04\b\x04\x10\x05R\x06reason\"%\n" + | |
| 1923 | + | "\x0fMirrorRecovered\x12\x12\n" + | |
| 1924 | + | "\x04repo\x18\x01 \x01(\tR\x04repo2F\n" + | |
| 1769 | 1925 | "\fEventService\x126\n" + | |
| 1770 | 1926 | "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" + | |
| 1771 | 1927 | "\n" + | |
| @@ -1784,7 +1940,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte { | |||
| 1784 | 1940 | return file_ermite_event_proto_rawDescData | |
| 1785 | 1941 | } | |
| 1786 | 1942 | ||
| 1787 | - | var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 24) | |
| 1943 | + | var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 26) | |
| 1788 | 1944 | var file_ermite_event_proto_goTypes = []any{ | |
| 1789 | 1945 | (*WatchRequest)(nil), // 0: ermite.WatchRequest | |
| 1790 | 1946 | (*WatchResponse)(nil), // 1: ermite.WatchResponse | |
| @@ -1810,19 +1966,22 @@ var file_ermite_event_proto_goTypes = []any{ | |||
| 1810 | 1966 | (*Gap)(nil), // 21: ermite.Gap | |
| 1811 | 1967 | (*RunUpdated)(nil), // 22: ermite.RunUpdated | |
| 1812 | 1968 | (*JobUpdated)(nil), // 23: ermite.JobUpdated | |
| 1813 | - | (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp | |
| 1814 | - | (*Repo)(nil), // 25: ermite.Repo | |
| 1815 | - | (*MergeRequest)(nil), // 26: ermite.MergeRequest | |
| 1816 | - | (*Mergeability)(nil), // 27: ermite.Mergeability | |
| 1817 | - | (*Comment)(nil), // 28: ermite.Comment | |
| 1818 | - | (*Issue)(nil), // 29: ermite.Issue | |
| 1819 | - | (*IssueComment)(nil), // 30: ermite.IssueComment | |
| 1820 | - | (*Run)(nil), // 31: ermite.Run | |
| 1821 | - | (*RunJob)(nil), // 32: ermite.RunJob | |
| 1969 | + | (*MirrorFailed)(nil), // 24: ermite.MirrorFailed | |
| 1970 | + | (*MirrorRecovered)(nil), // 25: ermite.MirrorRecovered | |
| 1971 | + | (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp | |
| 1972 | + | (*Repo)(nil), // 27: ermite.Repo | |
| 1973 | + | (*MergeRequest)(nil), // 28: ermite.MergeRequest | |
| 1974 | + | (*Mergeability)(nil), // 29: ermite.Mergeability | |
| 1975 | + | (*Comment)(nil), // 30: ermite.Comment | |
| 1976 | + | (*Issue)(nil), // 31: ermite.Issue | |
| 1977 | + | (*IssueComment)(nil), // 32: ermite.IssueComment | |
| 1978 | + | (*Run)(nil), // 33: ermite.Run | |
| 1979 | + | (*RunJob)(nil), // 34: ermite.RunJob | |
| 1980 | + | (MirrorState)(0), // 35: ermite.MirrorState | |
| 1822 | 1981 | } | |
| 1823 | 1982 | var file_ermite_event_proto_depIdxs = []int32{ | |
| 1824 | 1983 | 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event | |
| 1825 | - | 24, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp | |
| 1984 | + | 26, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp | |
| 1826 | 1985 | 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated | |
| 1827 | 1986 | 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated | |
| 1828 | 1987 | 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted | |
| @@ -1843,30 +2002,33 @@ var file_ermite_event_proto_depIdxs = []int32{ | |||
| 1843 | 2002 | 19, // 19: ermite.Event.issue_commented:type_name -> ermite.IssueCommented | |
| 1844 | 2003 | 20, // 20: ermite.Event.issue_submitted:type_name -> ermite.IssueSubmitted | |
| 1845 | 2004 | 10, // 21: ermite.Event.merge_request_mergeability:type_name -> ermite.MergeRequestMergeability | |
| 1846 | - | 25, // 22: ermite.RepoCreated.repo:type_name -> ermite.Repo | |
| 1847 | - | 25, // 23: ermite.RepoUpdated.repo:type_name -> ermite.Repo | |
| 1848 | - | 7, // 24: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate | |
| 1849 | - | 26, // 25: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest | |
| 1850 | - | 26, // 26: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest | |
| 1851 | - | 27, // 27: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability | |
| 1852 | - | 26, // 28: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest | |
| 1853 | - | 28, // 29: ermite.CommentAdded.comment:type_name -> ermite.Comment | |
| 1854 | - | 28, // 30: ermite.CommentEdited.comment:type_name -> ermite.Comment | |
| 1855 | - | 28, // 31: ermite.CommentDeleted.comment:type_name -> ermite.Comment | |
| 1856 | - | 28, // 32: ermite.CommentResolved.comment:type_name -> ermite.Comment | |
| 1857 | - | 29, // 33: ermite.IssueOpened.issue:type_name -> ermite.Issue | |
| 1858 | - | 29, // 34: ermite.IssueClosed.issue:type_name -> ermite.Issue | |
| 1859 | - | 29, // 35: ermite.IssueReopened.issue:type_name -> ermite.Issue | |
| 1860 | - | 30, // 36: ermite.IssueCommented.comment:type_name -> ermite.IssueComment | |
| 1861 | - | 31, // 37: ermite.RunUpdated.run:type_name -> ermite.Run | |
| 1862 | - | 32, // 38: ermite.JobUpdated.job:type_name -> ermite.RunJob | |
| 1863 | - | 0, // 39: ermite.EventService.Watch:input_type -> ermite.WatchRequest | |
| 1864 | - | 1, // 40: ermite.EventService.Watch:output_type -> ermite.WatchResponse | |
| 1865 | - | 40, // [40:41] is the sub-list for method output_type | |
| 1866 | - | 39, // [39:40] is the sub-list for method input_type | |
| 1867 | - | 39, // [39:39] is the sub-list for extension type_name | |
| 1868 | - | 39, // [39:39] is the sub-list for extension extendee | |
| 1869 | - | 0, // [0:39] is the sub-list for field type_name | |
| 2005 | + | 24, // 22: ermite.Event.mirror_failed:type_name -> ermite.MirrorFailed | |
| 2006 | + | 25, // 23: ermite.Event.mirror_recovered:type_name -> ermite.MirrorRecovered | |
| 2007 | + | 27, // 24: ermite.RepoCreated.repo:type_name -> ermite.Repo | |
| 2008 | + | 27, // 25: ermite.RepoUpdated.repo:type_name -> ermite.Repo | |
| 2009 | + | 7, // 26: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate | |
| 2010 | + | 28, // 27: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest | |
| 2011 | + | 28, // 28: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest | |
| 2012 | + | 29, // 29: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability | |
| 2013 | + | 28, // 30: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest | |
| 2014 | + | 30, // 31: ermite.CommentAdded.comment:type_name -> ermite.Comment | |
| 2015 | + | 30, // 32: ermite.CommentEdited.comment:type_name -> ermite.Comment | |
| 2016 | + | 30, // 33: ermite.CommentDeleted.comment:type_name -> ermite.Comment | |
| 2017 | + | 30, // 34: ermite.CommentResolved.comment:type_name -> ermite.Comment | |
| 2018 | + | 31, // 35: ermite.IssueOpened.issue:type_name -> ermite.Issue | |
| 2019 | + | 31, // 36: ermite.IssueClosed.issue:type_name -> ermite.Issue | |
| 2020 | + | 31, // 37: ermite.IssueReopened.issue:type_name -> ermite.Issue | |
| 2021 | + | 32, // 38: ermite.IssueCommented.comment:type_name -> ermite.IssueComment | |
| 2022 | + | 33, // 39: ermite.RunUpdated.run:type_name -> ermite.Run | |
| 2023 | + | 34, // 40: ermite.JobUpdated.job:type_name -> ermite.RunJob | |
| 2024 | + | 35, // 41: ermite.MirrorFailed.state:type_name -> ermite.MirrorState | |
| 2025 | + | 0, // 42: ermite.EventService.Watch:input_type -> ermite.WatchRequest | |
| 2026 | + | 1, // 43: ermite.EventService.Watch:output_type -> ermite.WatchResponse | |
| 2027 | + | 43, // [43:44] is the sub-list for method output_type | |
| 2028 | + | 42, // [42:43] is the sub-list for method input_type | |
| 2029 | + | 42, // [42:42] is the sub-list for extension type_name | |
| 2030 | + | 42, // [42:42] is the sub-list for extension extendee | |
| 2031 | + | 0, // [0:42] is the sub-list for field type_name | |
| 1870 | 2032 | } | |
| 1871 | 2033 | ||
| 1872 | 2034 | func init() { file_ermite_event_proto_init() } | |
| @@ -1876,6 +2038,7 @@ func file_ermite_event_proto_init() { | |||
| 1876 | 2038 | } | |
| 1877 | 2039 | file_ermite_issue_proto_init() | |
| 1878 | 2040 | file_ermite_merge_request_proto_init() | |
| 2041 | + | file_ermite_mirror_proto_init() | |
| 1879 | 2042 | file_ermite_repo_proto_init() | |
| 1880 | 2043 | file_ermite_run_proto_init() | |
| 1881 | 2044 | file_ermite_event_proto_msgTypes[2].OneofWrappers = []any{ | |
| @@ -1899,6 +2062,8 @@ func file_ermite_event_proto_init() { | |||
| 1899 | 2062 | (*Event_IssueCommented)(nil), | |
| 1900 | 2063 | (*Event_IssueSubmitted)(nil), | |
| 1901 | 2064 | (*Event_MergeRequestMergeability)(nil), | |
| 2065 | + | (*Event_MirrorFailed)(nil), | |
| 2066 | + | (*Event_MirrorRecovered)(nil), | |
| 1902 | 2067 | } | |
| 1903 | 2068 | type x struct{} | |
| 1904 | 2069 | out := protoimpl.TypeBuilder{ | |
| @@ -1906,7 +2071,7 @@ func file_ermite_event_proto_init() { | |||
| 1906 | 2071 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | |
| 1907 | 2072 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)), | |
| 1908 | 2073 | NumEnums: 0, | |
| 1909 | - | NumMessages: 24, | |
| 2074 | + | NumMessages: 26, | |
| 1910 | 2075 | NumExtensions: 0, | |
| 1911 | 2076 | NumServices: 1, | |
| 1912 | 2077 | }, | |
| @@ -171,6 +171,8 @@ type Event struct { | |||||
| 171 | // *Event_IssueCommented | 171 | // *Event_IssueCommented | ||
| 172 | // *Event_IssueSubmitted | 172 | // *Event_IssueSubmitted | ||
| 173 | // *Event_MergeRequestMergeability | 173 | // *Event_MergeRequestMergeability | ||
| 174 | + | // *Event_MirrorFailed | |||
| 175 | + | // *Event_MirrorRecovered | |||
| 174 | Kind isEvent_Kind `protobuf_oneof:"kind"` | 176 | Kind isEvent_Kind `protobuf_oneof:"kind"` | ||
| 175 | unknownFields protoimpl.UnknownFields | 177 | unknownFields protoimpl.UnknownFields | ||
| 176 | sizeCache protoimpl.SizeCache | 178 | sizeCache protoimpl.SizeCache | ||
| @@ -407,6 +409,24 @@ func (x *Event) GetMergeRequestMergeability() *MergeRequestMergeability { | |||||
| 407 | return nil | 409 | return nil | ||
| 408 | } | 410 | } | ||
| 409 | 411 | ||||
| 412 | + | func (x *Event) GetMirrorFailed() *MirrorFailed { | |||
| 413 | + | if x != nil { | |||
| 414 | + | if x, ok := x.Kind.(*Event_MirrorFailed); ok { | |||
| 415 | + | return x.MirrorFailed | |||
| 416 | + | } | |||
| 417 | + | } | |||
| 418 | + | return nil | |||
| 419 | + | } | |||
| 420 | + | ||||
| 421 | + | func (x *Event) GetMirrorRecovered() *MirrorRecovered { | |||
| 422 | + | if x != nil { | |||
| 423 | + | if x, ok := x.Kind.(*Event_MirrorRecovered); ok { | |||
| 424 | + | return x.MirrorRecovered | |||
| 425 | + | } | |||
| 426 | + | } | |||
| 427 | + | return nil | |||
| 428 | + | } | |||
| 429 | + | ||||
| 410 | type isEvent_Kind interface { | 430 | type isEvent_Kind interface { | ||
| 411 | isEvent_Kind() | 431 | isEvent_Kind() | ||
| 412 | } | 432 | } | ||
| @@ -513,6 +533,16 @@ type Event_MergeRequestMergeability struct { | |||||
| 513 | MergeRequestMergeability *MergeRequestMergeability `protobuf:"bytes,22,opt,name=merge_request_mergeability,json=mergeRequestMergeability,proto3,oneof"` | 533 | MergeRequestMergeability *MergeRequestMergeability `protobuf:"bytes,22,opt,name=merge_request_mergeability,json=mergeRequestMergeability,proto3,oneof"` | ||
| 514 | } | 534 | } | ||
| 515 | 535 | ||||
| 536 | + | type Event_MirrorFailed struct { | |||
| 537 | + | // MirrorFailed: a mirror entered failing or paused. | |||
| 538 | + | MirrorFailed *MirrorFailed `protobuf:"bytes,23,opt,name=mirror_failed,json=mirrorFailed,proto3,oneof"` | |||
| 539 | + | } | |||
| 540 | + | ||||
| 541 | + | type Event_MirrorRecovered struct { | |||
| 542 | + | // MirrorRecovered: a failing or paused mirror succeeded again. | |||
| 543 | + | MirrorRecovered *MirrorRecovered `protobuf:"bytes,24,opt,name=mirror_recovered,json=mirrorRecovered,proto3,oneof"` | |||
| 544 | + | } | |||
| 545 | + | ||||
| 516 | func (*Event_RepoCreated) isEvent_Kind() {} | 546 | func (*Event_RepoCreated) isEvent_Kind() {} | ||
| 517 | 547 | ||||
| 518 | func (*Event_RepoUpdated) isEvent_Kind() {} | 548 | func (*Event_RepoUpdated) isEvent_Kind() {} | ||
| @@ -553,6 +583,10 @@ func (*Event_IssueSubmitted) isEvent_Kind() {} | |||||
| 553 | 583 | ||||
| 554 | func (*Event_MergeRequestMergeability) isEvent_Kind() {} | 584 | func (*Event_MergeRequestMergeability) isEvent_Kind() {} | ||
| 555 | 585 | ||||
| 586 | + | func (*Event_MirrorFailed) isEvent_Kind() {} | |||
| 587 | + | ||||
| 588 | + | func (*Event_MirrorRecovered) isEvent_Kind() {} | |||
| 589 | + | ||||
| 556 | // RepoCreated reports a new repository. | 590 | // RepoCreated reports a new repository. | ||
| 557 | type RepoCreated struct { | 591 | type RepoCreated struct { | ||
| 558 | state protoimpl.MessageState `protogen:"open.v1"` | 592 | state protoimpl.MessageState `protogen:"open.v1"` | ||
| @@ -1668,17 +1702,131 @@ func (x *JobUpdated) GetJob() *RunJob { | |||||
| 1668 | return nil | 1702 | return nil | ||
| 1669 | } | 1703 | } | ||
| 1670 | 1704 | ||||
| 1705 | + | // MirrorFailed reports the start of a failure incident: a transition from ok | |||
| 1706 | + | // or disabled into failing or paused. It is sent once per incident, not for | |||
| 1707 | + | // each failed attempt nor for failing to paused. Servers with feature "mirror" | |||
| 1708 | + | // deliver it on "repo:<name>" and "home", subject to repository visibility. It | |||
| 1709 | + | // carries no URL, reason or error detail; read the status for those. | |||
| 1710 | + | type MirrorFailed struct { | |||
| 1711 | + | state protoimpl.MessageState `protogen:"open.v1"` | |||
| 1712 | + | // Repo is the repository name. | |||
| 1713 | + | Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` | |||
| 1714 | + | // State is the new mirror state. | |||
| 1715 | + | State MirrorState `protobuf:"varint,2,opt,name=state,proto3,enum=ermite.MirrorState" json:"state,omitempty"` | |||
| 1716 | + | // FailureClass is the failure category. | |||
| 1717 | + | FailureClass string `protobuf:"bytes,3,opt,name=failure_class,json=failureClass,proto3" json:"failure_class,omitempty"` | |||
| 1718 | + | unknownFields protoimpl.UnknownFields | |||
| 1719 | + | sizeCache protoimpl.SizeCache | |||
| 1720 | + | } | |||
| 1721 | + | ||||
| 1722 | + | func (x *MirrorFailed) Reset() { | |||
| 1723 | + | *x = MirrorFailed{} | |||
| 1724 | + | mi := &file_ermite_event_proto_msgTypes[24] | |||
| 1725 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 1726 | + | ms.StoreMessageInfo(mi) | |||
| 1727 | + | } | |||
| 1728 | + | ||||
| 1729 | + | func (x *MirrorFailed) String() string { | |||
| 1730 | + | return protoimpl.X.MessageStringOf(x) | |||
| 1731 | + | } | |||
| 1732 | + | ||||
| 1733 | + | func (*MirrorFailed) ProtoMessage() {} | |||
| 1734 | + | ||||
| 1735 | + | func (x *MirrorFailed) ProtoReflect() protoreflect.Message { | |||
| 1736 | + | mi := &file_ermite_event_proto_msgTypes[24] | |||
| 1737 | + | if x != nil { | |||
| 1738 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 1739 | + | if ms.LoadMessageInfo() == nil { | |||
| 1740 | + | ms.StoreMessageInfo(mi) | |||
| 1741 | + | } | |||
| 1742 | + | return ms | |||
| 1743 | + | } | |||
| 1744 | + | return mi.MessageOf(x) | |||
| 1745 | + | } | |||
| 1746 | + | ||||
| 1747 | + | // Deprecated: Use MirrorFailed.ProtoReflect.Descriptor instead. | |||
| 1748 | + | func (*MirrorFailed) Descriptor() ([]byte, []int) { | |||
| 1749 | + | return file_ermite_event_proto_rawDescGZIP(), []int{24} | |||
| 1750 | + | } | |||
| 1751 | + | ||||
| 1752 | + | func (x *MirrorFailed) GetRepo() string { | |||
| 1753 | + | if x != nil { | |||
| 1754 | + | return x.Repo | |||
| 1755 | + | } | |||
| 1756 | + | return "" | |||
| 1757 | + | } | |||
| 1758 | + | ||||
| 1759 | + | func (x *MirrorFailed) GetState() MirrorState { | |||
| 1760 | + | if x != nil { | |||
| 1761 | + | return x.State | |||
| 1762 | + | } | |||
| 1763 | + | return MirrorState_MIRROR_STATE_UNSPECIFIED | |||
| 1764 | + | } | |||
| 1765 | + | ||||
| 1766 | + | func (x *MirrorFailed) GetFailureClass() string { | |||
| 1767 | + | if x != nil { | |||
| 1768 | + | return x.FailureClass | |||
| 1769 | + | } | |||
| 1770 | + | return "" | |||
| 1771 | + | } | |||
| 1772 | + | ||||
| 1773 | + | // MirrorRecovered reports a successful sync after failing or paused. Delivery | |||
| 1774 | + | // follows MirrorFailed. It carries no URL or error detail. | |||
| 1775 | + | type MirrorRecovered struct { | |||
| 1776 | + | state protoimpl.MessageState `protogen:"open.v1"` | |||
| 1777 | + | // Repo is the repository name. | |||
| 1778 | + | Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` | |||
| 1779 | + | unknownFields protoimpl.UnknownFields | |||
| 1780 | + | sizeCache protoimpl.SizeCache | |||
| 1781 | + | } | |||
| 1782 | + | ||||
| 1783 | + | func (x *MirrorRecovered) Reset() { | |||
| 1784 | + | *x = MirrorRecovered{} | |||
| 1785 | + | mi := &file_ermite_event_proto_msgTypes[25] | |||
| 1786 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 1787 | + | ms.StoreMessageInfo(mi) | |||
| 1788 | + | } | |||
| 1789 | + | ||||
| 1790 | + | func (x *MirrorRecovered) String() string { | |||
| 1791 | + | return protoimpl.X.MessageStringOf(x) | |||
| 1792 | + | } | |||
| 1793 | + | ||||
| 1794 | + | func (*MirrorRecovered) ProtoMessage() {} | |||
| 1795 | + | ||||
| 1796 | + | func (x *MirrorRecovered) ProtoReflect() protoreflect.Message { | |||
| 1797 | + | mi := &file_ermite_event_proto_msgTypes[25] | |||
| 1798 | + | if x != nil { | |||
| 1799 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 1800 | + | if ms.LoadMessageInfo() == nil { | |||
| 1801 | + | ms.StoreMessageInfo(mi) | |||
| 1802 | + | } | |||
| 1803 | + | return ms | |||
| 1804 | + | } | |||
| 1805 | + | return mi.MessageOf(x) | |||
| 1806 | + | } | |||
| 1807 | + | ||||
| 1808 | + | // Deprecated: Use MirrorRecovered.ProtoReflect.Descriptor instead. | |||
| 1809 | + | func (*MirrorRecovered) Descriptor() ([]byte, []int) { | |||
| 1810 | + | return file_ermite_event_proto_rawDescGZIP(), []int{25} | |||
| 1811 | + | } | |||
| 1812 | + | ||||
| 1813 | + | func (x *MirrorRecovered) GetRepo() string { | |||
| 1814 | + | if x != nil { | |||
| 1815 | + | return x.Repo | |||
| 1816 | + | } | |||
| 1817 | + | return "" | |||
| 1818 | + | } | |||
| 1819 | + | ||||
| 1671 | var File_ermite_event_proto protoreflect.FileDescriptor | 1820 | var File_ermite_event_proto protoreflect.FileDescriptor | ||
| 1672 | 1821 | ||||
| 1673 | const file_ermite_event_proto_rawDesc = "" + | 1822 | const file_ermite_event_proto_rawDesc = "" + | ||
| 1674 | "\n" + | 1823 | "\n" + | ||
| 1675 | - | "\x12ermite/event.proto\x12\x06ermite\x1a\x12ermite/issue.proto\x1a\x1aermite/merge_request.proto\x1a\x11ermite/repo.proto\x1a\x10ermite/run.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"I\n" + | 1824 | + | "\x12ermite/event.proto\x12\x06ermite\x1a\x12ermite/issue.proto\x1a\x1aermite/merge_request.proto\x1a\x13ermite/mirror.proto\x1a\x11ermite/repo.proto\x1a\x10ermite/run.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"I\n" + |
| 1676 | "\fWatchRequest\x12\x16\n" + | 1825 | "\fWatchRequest\x12\x16\n" + | ||
| 1677 | "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" + | 1826 | "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" + | ||
| 1678 | "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" + | 1827 | "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" + | ||
| 1679 | "\rWatchResponse\x12#\n" + | 1828 | "\rWatchResponse\x12#\n" + | ||
| 1680 | - | "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xc8\n" + | 1829 | + | "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xcb\v\n" + |
| 1681 | - | "\n" + | |||
| 1682 | "\x05Event\x12\x0e\n" + | 1830 | "\x05Event\x12\x0e\n" + | ||
| 1683 | "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" + | 1831 | "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" + | ||
| 1684 | "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" + | 1832 | "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" + | ||
| @@ -1704,7 +1852,9 @@ const file_ermite_event_proto_rawDesc = "" + | |||||
| 1704 | "\x0eissue_reopened\x18\x13 \x01(\v2\x15.ermite.IssueReopenedH\x00R\rissueReopened\x12A\n" + | 1852 | "\x0eissue_reopened\x18\x13 \x01(\v2\x15.ermite.IssueReopenedH\x00R\rissueReopened\x12A\n" + | ||
| 1705 | "\x0fissue_commented\x18\x14 \x01(\v2\x16.ermite.IssueCommentedH\x00R\x0eissueCommented\x12A\n" + | 1853 | "\x0fissue_commented\x18\x14 \x01(\v2\x16.ermite.IssueCommentedH\x00R\x0eissueCommented\x12A\n" + | ||
| 1706 | "\x0fissue_submitted\x18\x15 \x01(\v2\x16.ermite.IssueSubmittedH\x00R\x0eissueSubmitted\x12`\n" + | 1854 | "\x0fissue_submitted\x18\x15 \x01(\v2\x16.ermite.IssueSubmittedH\x00R\x0eissueSubmitted\x12`\n" + | ||
| 1707 | - | "\x1amerge_request_mergeability\x18\x16 \x01(\v2 .ermite.MergeRequestMergeabilityH\x00R\x18mergeRequestMergeabilityB\x06\n" + | 1855 | + | "\x1amerge_request_mergeability\x18\x16 \x01(\v2 .ermite.MergeRequestMergeabilityH\x00R\x18mergeRequestMergeability\x12;\n" + |
| 1856 | + | "\rmirror_failed\x18\x17 \x01(\v2\x14.ermite.MirrorFailedH\x00R\fmirrorFailed\x12D\n" + | |||
| 1857 | + | "\x10mirror_recovered\x18\x18 \x01(\v2\x17.ermite.MirrorRecoveredH\x00R\x0fmirrorRecoveredB\x06\n" + | |||
| 1708 | "\x04kind\"/\n" + | 1858 | "\x04kind\"/\n" + | ||
| 1709 | "\vRepoCreated\x12 \n" + | 1859 | "\vRepoCreated\x12 \n" + | ||
| 1710 | "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" + | 1860 | "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" + | ||
| @@ -1765,7 +1915,13 @@ const file_ermite_event_proto_rawDesc = "" + | |||||
| 1765 | "\x03run\x18\x01 \x01(\v2\v.ermite.RunR\x03run\".\n" + | 1915 | "\x03run\x18\x01 \x01(\v2\v.ermite.RunR\x03run\".\n" + | ||
| 1766 | "\n" + | 1916 | "\n" + | ||
| 1767 | "JobUpdated\x12 \n" + | 1917 | "JobUpdated\x12 \n" + | ||
| 1768 | - | "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job2F\n" + | 1918 | + | "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"\x80\x01\n" + |
| 1919 | + | "\fMirrorFailed\x12\x12\n" + | |||
| 1920 | + | "\x04repo\x18\x01 \x01(\tR\x04repo\x12)\n" + | |||
| 1921 | + | "\x05state\x18\x02 \x01(\x0e2\x13.ermite.MirrorStateR\x05state\x12#\n" + | |||
| 1922 | + | "\rfailure_class\x18\x03 \x01(\tR\ffailureClassJ\x04\b\x04\x10\x05R\x06reason\"%\n" + | |||
| 1923 | + | "\x0fMirrorRecovered\x12\x12\n" + | |||
| 1924 | + | "\x04repo\x18\x01 \x01(\tR\x04repo2F\n" + | |||
| 1769 | "\fEventService\x126\n" + | 1925 | "\fEventService\x126\n" + | ||
| 1770 | "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" + | 1926 | "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" + | ||
| 1771 | "\n" + | 1927 | "\n" + | ||
| @@ -1784,7 +1940,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte { | |||||
| 1784 | return file_ermite_event_proto_rawDescData | 1940 | return file_ermite_event_proto_rawDescData | ||
| 1785 | } | 1941 | } | ||
| 1786 | 1942 | ||||
| 1787 | - | var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 24) | 1943 | + | var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 26) |
| 1788 | var file_ermite_event_proto_goTypes = []any{ | 1944 | var file_ermite_event_proto_goTypes = []any{ | ||
| 1789 | (*WatchRequest)(nil), // 0: ermite.WatchRequest | 1945 | (*WatchRequest)(nil), // 0: ermite.WatchRequest | ||
| 1790 | (*WatchResponse)(nil), // 1: ermite.WatchResponse | 1946 | (*WatchResponse)(nil), // 1: ermite.WatchResponse | ||
| @@ -1810,19 +1966,22 @@ var file_ermite_event_proto_goTypes = []any{ | |||||
| 1810 | (*Gap)(nil), // 21: ermite.Gap | 1966 | (*Gap)(nil), // 21: ermite.Gap | ||
| 1811 | (*RunUpdated)(nil), // 22: ermite.RunUpdated | 1967 | (*RunUpdated)(nil), // 22: ermite.RunUpdated | ||
| 1812 | (*JobUpdated)(nil), // 23: ermite.JobUpdated | 1968 | (*JobUpdated)(nil), // 23: ermite.JobUpdated | ||
| 1813 | - | (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp | 1969 | + | (*MirrorFailed)(nil), // 24: ermite.MirrorFailed |
| 1814 | - | (*Repo)(nil), // 25: ermite.Repo | 1970 | + | (*MirrorRecovered)(nil), // 25: ermite.MirrorRecovered |
| 1815 | - | (*MergeRequest)(nil), // 26: ermite.MergeRequest | 1971 | + | (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp |
| 1816 | - | (*Mergeability)(nil), // 27: ermite.Mergeability | 1972 | + | (*Repo)(nil), // 27: ermite.Repo |
| 1817 | - | (*Comment)(nil), // 28: ermite.Comment | 1973 | + | (*MergeRequest)(nil), // 28: ermite.MergeRequest |
| 1818 | - | (*Issue)(nil), // 29: ermite.Issue | 1974 | + | (*Mergeability)(nil), // 29: ermite.Mergeability |
| 1819 | - | (*IssueComment)(nil), // 30: ermite.IssueComment | 1975 | + | (*Comment)(nil), // 30: ermite.Comment |
| 1820 | - | (*Run)(nil), // 31: ermite.Run | 1976 | + | (*Issue)(nil), // 31: ermite.Issue |
| 1821 | - | (*RunJob)(nil), // 32: ermite.RunJob | 1977 | + | (*IssueComment)(nil), // 32: ermite.IssueComment |
| 1978 | + | (*Run)(nil), // 33: ermite.Run | |||
| 1979 | + | (*RunJob)(nil), // 34: ermite.RunJob | |||
| 1980 | + | (MirrorState)(0), // 35: ermite.MirrorState | |||
| 1822 | } | 1981 | } | ||
| 1823 | var file_ermite_event_proto_depIdxs = []int32{ | 1982 | var file_ermite_event_proto_depIdxs = []int32{ | ||
| 1824 | 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event | 1983 | 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event | ||
| 1825 | - | 24, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp | 1984 | + | 26, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp |
| 1826 | 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated | 1985 | 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated | ||
| 1827 | 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated | 1986 | 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated | ||
| 1828 | 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted | 1987 | 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted | ||
| @@ -1843,30 +2002,33 @@ var file_ermite_event_proto_depIdxs = []int32{ | |||||
| 1843 | 19, // 19: ermite.Event.issue_commented:type_name -> ermite.IssueCommented | 2002 | 19, // 19: ermite.Event.issue_commented:type_name -> ermite.IssueCommented | ||
| 1844 | 20, // 20: ermite.Event.issue_submitted:type_name -> ermite.IssueSubmitted | 2003 | 20, // 20: ermite.Event.issue_submitted:type_name -> ermite.IssueSubmitted | ||
| 1845 | 10, // 21: ermite.Event.merge_request_mergeability:type_name -> ermite.MergeRequestMergeability | 2004 | 10, // 21: ermite.Event.merge_request_mergeability:type_name -> ermite.MergeRequestMergeability | ||
| 1846 | - | 25, // 22: ermite.RepoCreated.repo:type_name -> ermite.Repo | 2005 | + | 24, // 22: ermite.Event.mirror_failed:type_name -> ermite.MirrorFailed |
| 1847 | - | 25, // 23: ermite.RepoUpdated.repo:type_name -> ermite.Repo | 2006 | + | 25, // 23: ermite.Event.mirror_recovered:type_name -> ermite.MirrorRecovered |
| 1848 | - | 7, // 24: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate | 2007 | + | 27, // 24: ermite.RepoCreated.repo:type_name -> ermite.Repo |
| 1849 | - | 26, // 25: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest | 2008 | + | 27, // 25: ermite.RepoUpdated.repo:type_name -> ermite.Repo |
| 1850 | - | 26, // 26: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest | 2009 | + | 7, // 26: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate |
| 1851 | - | 27, // 27: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability | 2010 | + | 28, // 27: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest |
| 1852 | - | 26, // 28: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest | 2011 | + | 28, // 28: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest |
| 1853 | - | 28, // 29: ermite.CommentAdded.comment:type_name -> ermite.Comment | 2012 | + | 29, // 29: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability |
| 1854 | - | 28, // 30: ermite.CommentEdited.comment:type_name -> ermite.Comment | 2013 | + | 28, // 30: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest |
| 1855 | - | 28, // 31: ermite.CommentDeleted.comment:type_name -> ermite.Comment | 2014 | + | 30, // 31: ermite.CommentAdded.comment:type_name -> ermite.Comment |
| 1856 | - | 28, // 32: ermite.CommentResolved.comment:type_name -> ermite.Comment | 2015 | + | 30, // 32: ermite.CommentEdited.comment:type_name -> ermite.Comment |
| 1857 | - | 29, // 33: ermite.IssueOpened.issue:type_name -> ermite.Issue | 2016 | + | 30, // 33: ermite.CommentDeleted.comment:type_name -> ermite.Comment |
| 1858 | - | 29, // 34: ermite.IssueClosed.issue:type_name -> ermite.Issue | 2017 | + | 30, // 34: ermite.CommentResolved.comment:type_name -> ermite.Comment |
| 1859 | - | 29, // 35: ermite.IssueReopened.issue:type_name -> ermite.Issue | 2018 | + | 31, // 35: ermite.IssueOpened.issue:type_name -> ermite.Issue |
| 1860 | - | 30, // 36: ermite.IssueCommented.comment:type_name -> ermite.IssueComment | 2019 | + | 31, // 36: ermite.IssueClosed.issue:type_name -> ermite.Issue |
| 1861 | - | 31, // 37: ermite.RunUpdated.run:type_name -> ermite.Run | 2020 | + | 31, // 37: ermite.IssueReopened.issue:type_name -> ermite.Issue |
| 1862 | - | 32, // 38: ermite.JobUpdated.job:type_name -> ermite.RunJob | 2021 | + | 32, // 38: ermite.IssueCommented.comment:type_name -> ermite.IssueComment |
| 1863 | - | 0, // 39: ermite.EventService.Watch:input_type -> ermite.WatchRequest | 2022 | + | 33, // 39: ermite.RunUpdated.run:type_name -> ermite.Run |
| 1864 | - | 1, // 40: ermite.EventService.Watch:output_type -> ermite.WatchResponse | 2023 | + | 34, // 40: ermite.JobUpdated.job:type_name -> ermite.RunJob |
| 1865 | - | 40, // [40:41] is the sub-list for method output_type | 2024 | + | 35, // 41: ermite.MirrorFailed.state:type_name -> ermite.MirrorState |
| 1866 | - | 39, // [39:40] is the sub-list for method input_type | 2025 | + | 0, // 42: ermite.EventService.Watch:input_type -> ermite.WatchRequest |
| 1867 | - | 39, // [39:39] is the sub-list for extension type_name | 2026 | + | 1, // 43: ermite.EventService.Watch:output_type -> ermite.WatchResponse |
| 1868 | - | 39, // [39:39] is the sub-list for extension extendee | 2027 | + | 43, // [43:44] is the sub-list for method output_type |
| 1869 | - | 0, // [0:39] is the sub-list for field type_name | 2028 | + | 42, // [42:43] is the sub-list for method input_type |
| 2029 | + | 42, // [42:42] is the sub-list for extension type_name | |||
| 2030 | + | 42, // [42:42] is the sub-list for extension extendee | |||
| 2031 | + | 0, // [0:42] is the sub-list for field type_name | |||
| 1870 | } | 2032 | } | ||
| 1871 | 2033 | ||||
| 1872 | func init() { file_ermite_event_proto_init() } | 2034 | func init() { file_ermite_event_proto_init() } | ||
| @@ -1876,6 +2038,7 @@ func file_ermite_event_proto_init() { | |||||
| 1876 | } | 2038 | } | ||
| 1877 | file_ermite_issue_proto_init() | 2039 | file_ermite_issue_proto_init() | ||
| 1878 | file_ermite_merge_request_proto_init() | 2040 | file_ermite_merge_request_proto_init() | ||
| 2041 | + | file_ermite_mirror_proto_init() | |||
| 1879 | file_ermite_repo_proto_init() | 2042 | file_ermite_repo_proto_init() | ||
| 1880 | file_ermite_run_proto_init() | 2043 | file_ermite_run_proto_init() | ||
| 1881 | file_ermite_event_proto_msgTypes[2].OneofWrappers = []any{ | 2044 | file_ermite_event_proto_msgTypes[2].OneofWrappers = []any{ | ||
| @@ -1899,6 +2062,8 @@ func file_ermite_event_proto_init() { | |||||
| 1899 | (*Event_IssueCommented)(nil), | 2062 | (*Event_IssueCommented)(nil), | ||
| 1900 | (*Event_IssueSubmitted)(nil), | 2063 | (*Event_IssueSubmitted)(nil), | ||
| 1901 | (*Event_MergeRequestMergeability)(nil), | 2064 | (*Event_MergeRequestMergeability)(nil), | ||
| 2065 | + | (*Event_MirrorFailed)(nil), | |||
| 2066 | + | (*Event_MirrorRecovered)(nil), | |||
| 1902 | } | 2067 | } | ||
| 1903 | type x struct{} | 2068 | type x struct{} | ||
| 1904 | out := protoimpl.TypeBuilder{ | 2069 | out := protoimpl.TypeBuilder{ | ||
| @@ -1906,7 +2071,7 @@ func file_ermite_event_proto_init() { | |||||
| 1906 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | 2071 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||
| 1907 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)), | 2072 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)), | ||
| 1908 | NumEnums: 0, | 2073 | NumEnums: 0, | ||
| 1909 | - | NumMessages: 24, | 2074 | + | NumMessages: 26, |
| 1910 | NumExtensions: 0, | 2075 | NumExtensions: 0, | ||
| 1911 | NumServices: 1, | 2076 | NumServices: 1, | ||
| 1912 | }, | 2077 | }, | ||
A gen/ermite/mirror.pb.go +1820 -0 generated file: collapsed
M gen_test.go +45 -0
| @@ -19,6 +19,17 @@ import ( | |||
| 19 | 19 | // TestProcedures pins the procedure paths: they are the wire contract. | |
| 20 | 20 | func TestProcedures(t *testing.T) { | |
| 21 | 21 | tests := []struct{ got, want string }{ | |
| 22 | + | {ermiteconnect.MirrorServiceGetMirrorKeyProcedure, "/ermite.MirrorService/GetMirrorKey"}, | |
| 23 | + | {ermiteconnect.MirrorServiceRotateMirrorKeyProcedure, "/ermite.MirrorService/RotateMirrorKey"}, | |
| 24 | + | {ermiteconnect.MirrorServiceGetMirrorConfigProcedure, "/ermite.MirrorService/GetMirrorConfig"}, | |
| 25 | + | {ermiteconnect.MirrorServiceSetMirrorConfigProcedure, "/ermite.MirrorService/SetMirrorConfig"}, | |
| 26 | + | {ermiteconnect.MirrorServiceSetRepoMirrorProcedure, "/ermite.MirrorService/SetRepoMirror"}, | |
| 27 | + | {ermiteconnect.MirrorServiceRemoveRepoMirrorProcedure, "/ermite.MirrorService/RemoveRepoMirror"}, | |
| 28 | + | {ermiteconnect.MirrorServiceSetRepoMirrorExcludedProcedure, "/ermite.MirrorService/SetRepoMirrorExcluded"}, | |
| 29 | + | {ermiteconnect.MirrorServiceGetMirrorStatusProcedure, "/ermite.MirrorService/GetMirrorStatus"}, | |
| 30 | + | {ermiteconnect.MirrorServiceListMirrorStatusProcedure, "/ermite.MirrorService/ListMirrorStatus"}, | |
| 31 | + | {ermiteconnect.MirrorServiceSyncMirrorProcedure, "/ermite.MirrorService/SyncMirror"}, | |
| 32 | + | ||
| 22 | 33 | {ermiteconnect.RepoServiceListReposProcedure, "/ermite.RepoService/ListRepos"}, | |
| 23 | 34 | {ermiteconnect.RepoServiceGetRepoProcedure, "/ermite.RepoService/GetRepo"}, | |
| 24 | 35 | {ermiteconnect.RepoServiceCreateRepoProcedure, "/ermite.RepoService/CreateRepo"}, | |
| @@ -569,3 +580,37 @@ func TestCI3RoundTrip(t *testing.T) { | |||
| 569 | 580 | } | |
| 570 | 581 | } | |
| 571 | 582 | } | |
| 583 | + | ||
| 584 | + | // TestMirrorWire pins event numbers and verifies presence of explicit zero patches. | |
| 585 | + | func TestMirrorWire(t *testing.T) { | |
| 586 | + | fields := (&ermite.Event{}).ProtoReflect().Descriptor().Fields() | |
| 587 | + | for name, number := range map[protoreflect.Name]protoreflect.FieldNumber{"mirror_failed": 23, "mirror_recovered": 24} { | |
| 588 | + | if fd := fields.ByName(name); fd == nil || fd.Number() != number || fd.ContainingOneof().Name() != "kind" { | |
| 589 | + | t.Fatalf("Event.%s: %v, want kind field %d", name, fd, number) | |
| 590 | + | } | |
| 591 | + | } | |
| 592 | + | for _, msg := range []proto.Message{&ermite.MirrorFailed{}, &ermite.MirrorRecovered{}} { | |
| 593 | + | fields := msg.ProtoReflect().Descriptor().Fields() | |
| 594 | + | if fields.ByName("url") != nil || fields.ByName("detail") != nil { | |
| 595 | + | t.Fatalf("%T leaks URL or detail", msg) | |
| 596 | + | } | |
| 597 | + | } | |
| 598 | + | for _, in := range []proto.Message{ | |
| 599 | + | &ermite.SetMirrorConfigRequest{Enabled: proto.Bool(false), UrlTemplate: proto.String(""), Cron: proto.String(""), AllBranches: proto.Bool(false)}, | |
| 600 | + | &ermite.SetRepoMirrorRequest{Repo: "repo", AllBranches: proto.Bool(false)}, | |
| 601 | + | &ermite.Event{Kind: &ermite.Event_MirrorFailed{MirrorFailed: &ermite.MirrorFailed{Repo: "repo", State: ermite.MirrorState_MIRROR_STATE_PAUSED, FailureClass: "diverged"}}}, | |
| 602 | + | &ermite.Event{Kind: &ermite.Event_MirrorRecovered{MirrorRecovered: &ermite.MirrorRecovered{Repo: "repo"}}}, | |
| 603 | + | } { | |
| 604 | + | b, err := proto.Marshal(in) | |
| 605 | + | if err != nil { | |
| 606 | + | t.Fatal(err) | |
| 607 | + | } | |
| 608 | + | out := in.ProtoReflect().New().Interface() | |
| 609 | + | if err := proto.Unmarshal(b, out); err != nil { | |
| 610 | + | t.Fatal(err) | |
| 611 | + | } | |
| 612 | + | if !proto.Equal(in, out) { | |
| 613 | + | t.Errorf("%T: round trip mismatch: %v != %v", in, out, in) | |
| 614 | + | } | |
| 615 | + | } | |
| 616 | + | } | |
| @@ -19,6 +19,17 @@ import ( | |||||
| 19 | // TestProcedures pins the procedure paths: they are the wire contract. | 19 | // TestProcedures pins the procedure paths: they are the wire contract. | ||
| 20 | func TestProcedures(t *testing.T) { | 20 | func TestProcedures(t *testing.T) { | ||
| 21 | tests := []struct{ got, want string }{ | 21 | tests := []struct{ got, want string }{ | ||
| 22 | + | {ermiteconnect.MirrorServiceGetMirrorKeyProcedure, "/ermite.MirrorService/GetMirrorKey"}, | |||
| 23 | + | {ermiteconnect.MirrorServiceRotateMirrorKeyProcedure, "/ermite.MirrorService/RotateMirrorKey"}, | |||
| 24 | + | {ermiteconnect.MirrorServiceGetMirrorConfigProcedure, "/ermite.MirrorService/GetMirrorConfig"}, | |||
| 25 | + | {ermiteconnect.MirrorServiceSetMirrorConfigProcedure, "/ermite.MirrorService/SetMirrorConfig"}, | |||
| 26 | + | {ermiteconnect.MirrorServiceSetRepoMirrorProcedure, "/ermite.MirrorService/SetRepoMirror"}, | |||
| 27 | + | {ermiteconnect.MirrorServiceRemoveRepoMirrorProcedure, "/ermite.MirrorService/RemoveRepoMirror"}, | |||
| 28 | + | {ermiteconnect.MirrorServiceSetRepoMirrorExcludedProcedure, "/ermite.MirrorService/SetRepoMirrorExcluded"}, | |||
| 29 | + | {ermiteconnect.MirrorServiceGetMirrorStatusProcedure, "/ermite.MirrorService/GetMirrorStatus"}, | |||
| 30 | + | {ermiteconnect.MirrorServiceListMirrorStatusProcedure, "/ermite.MirrorService/ListMirrorStatus"}, | |||
| 31 | + | {ermiteconnect.MirrorServiceSyncMirrorProcedure, "/ermite.MirrorService/SyncMirror"}, | |||
| 32 | + | ||||
| 22 | {ermiteconnect.RepoServiceListReposProcedure, "/ermite.RepoService/ListRepos"}, | 33 | {ermiteconnect.RepoServiceListReposProcedure, "/ermite.RepoService/ListRepos"}, | ||
| 23 | {ermiteconnect.RepoServiceGetRepoProcedure, "/ermite.RepoService/GetRepo"}, | 34 | {ermiteconnect.RepoServiceGetRepoProcedure, "/ermite.RepoService/GetRepo"}, | ||
| 24 | {ermiteconnect.RepoServiceCreateRepoProcedure, "/ermite.RepoService/CreateRepo"}, | 35 | {ermiteconnect.RepoServiceCreateRepoProcedure, "/ermite.RepoService/CreateRepo"}, | ||
| @@ -569,3 +580,37 @@ func TestCI3RoundTrip(t *testing.T) { | |||||
| 569 | } | 580 | } | ||
| 570 | } | 581 | } | ||
| 571 | } | 582 | } | ||
| 583 | + | ||||
| 584 | + | // TestMirrorWire pins event numbers and verifies presence of explicit zero patches. | |||
| 585 | + | func TestMirrorWire(t *testing.T) { | |||
| 586 | + | fields := (&ermite.Event{}).ProtoReflect().Descriptor().Fields() | |||
| 587 | + | for name, number := range map[protoreflect.Name]protoreflect.FieldNumber{"mirror_failed": 23, "mirror_recovered": 24} { | |||
| 588 | + | if fd := fields.ByName(name); fd == nil || fd.Number() != number || fd.ContainingOneof().Name() != "kind" { | |||
| 589 | + | t.Fatalf("Event.%s: %v, want kind field %d", name, fd, number) | |||
| 590 | + | } | |||
| 591 | + | } | |||
| 592 | + | for _, msg := range []proto.Message{&ermite.MirrorFailed{}, &ermite.MirrorRecovered{}} { | |||
| 593 | + | fields := msg.ProtoReflect().Descriptor().Fields() | |||
| 594 | + | if fields.ByName("url") != nil || fields.ByName("detail") != nil { | |||
| 595 | + | t.Fatalf("%T leaks URL or detail", msg) | |||
| 596 | + | } | |||
| 597 | + | } | |||
| 598 | + | for _, in := range []proto.Message{ | |||
| 599 | + | &ermite.SetMirrorConfigRequest{Enabled: proto.Bool(false), UrlTemplate: proto.String(""), Cron: proto.String(""), AllBranches: proto.Bool(false)}, | |||
| 600 | + | &ermite.SetRepoMirrorRequest{Repo: "repo", AllBranches: proto.Bool(false)}, | |||
| 601 | + | &ermite.Event{Kind: &ermite.Event_MirrorFailed{MirrorFailed: &ermite.MirrorFailed{Repo: "repo", State: ermite.MirrorState_MIRROR_STATE_PAUSED, FailureClass: "diverged"}}}, | |||
| 602 | + | &ermite.Event{Kind: &ermite.Event_MirrorRecovered{MirrorRecovered: &ermite.MirrorRecovered{Repo: "repo"}}}, | |||
| 603 | + | } { | |||
| 604 | + | b, err := proto.Marshal(in) | |||
| 605 | + | if err != nil { | |||
| 606 | + | t.Fatal(err) | |||
| 607 | + | } | |||
| 608 | + | out := in.ProtoReflect().New().Interface() | |||
| 609 | + | if err := proto.Unmarshal(b, out); err != nil { | |||
| 610 | + | t.Fatal(err) | |||
| 611 | + | } | |||
| 612 | + | if !proto.Equal(in, out) { | |||
| 613 | + | t.Errorf("%T: round trip mismatch: %v != %v", in, out, in) | |||
| 614 | + | } | |||
| 615 | + | } | |||
| 616 | + | } | |||
M proto/ermite/event.proto +29 -0
| @@ -6,6 +6,7 @@ package ermite; | |||
| 6 | 6 | ||
| 7 | 7 | import "ermite/issue.proto"; | |
| 8 | 8 | import "ermite/merge_request.proto"; | |
| 9 | + | import "ermite/mirror.proto"; | |
| 9 | 10 | import "ermite/repo.proto"; | |
| 10 | 11 | import "ermite/run.proto"; | |
| 11 | 12 | import "google/protobuf/timestamp.proto"; | |
| @@ -135,6 +136,10 @@ message Event { | |||
| 135 | 136 | // MergeRequestMergeability: the mergeability of an open merge request | |
| 136 | 137 | // changed. | |
| 137 | 138 | MergeRequestMergeability merge_request_mergeability = 22; | |
| 139 | + | // MirrorFailed: a mirror entered failing or paused. | |
| 140 | + | MirrorFailed mirror_failed = 23; | |
| 141 | + | // MirrorRecovered: a failing or paused mirror succeeded again. | |
| 142 | + | MirrorRecovered mirror_recovered = 24; | |
| 138 | 143 | } | |
| 139 | 144 | } | |
| 140 | 145 | ||
| @@ -306,3 +311,27 @@ message JobUpdated { | |||
| 306 | 311 | // Job is the job after the change, with its steps. | |
| 307 | 312 | RunJob job = 1; | |
| 308 | 313 | } | |
| 314 | + | ||
| 315 | + | // MirrorFailed reports the start of a failure incident: a transition from ok | |
| 316 | + | // or disabled into failing or paused. It is sent once per incident, not for | |
| 317 | + | // each failed attempt nor for failing to paused. Servers with feature "mirror" | |
| 318 | + | // deliver it on "repo:<name>" and "home", subject to repository visibility. It | |
| 319 | + | // carries no URL, reason or error detail; read the status for those. | |
| 320 | + | message MirrorFailed { | |
| 321 | + | // Repo is the repository name. | |
| 322 | + | string repo = 1; | |
| 323 | + | // State is the new mirror state. | |
| 324 | + | MirrorState state = 2; | |
| 325 | + | // FailureClass is the failure category. | |
| 326 | + | string failure_class = 3; | |
| 327 | + | ||
| 328 | + | reserved 4; | |
| 329 | + | reserved "reason"; | |
| 330 | + | } | |
| 331 | + | ||
| 332 | + | // MirrorRecovered reports a successful sync after failing or paused. Delivery | |
| 333 | + | // follows MirrorFailed. It carries no URL or error detail. | |
| 334 | + | message MirrorRecovered { | |
| 335 | + | // Repo is the repository name. | |
| 336 | + | string repo = 1; | |
| 337 | + | } | |
| @@ -6,6 +6,7 @@ package ermite; | |||||
| 6 | 6 | ||||
| 7 | import "ermite/issue.proto"; | 7 | import "ermite/issue.proto"; | ||
| 8 | import "ermite/merge_request.proto"; | 8 | import "ermite/merge_request.proto"; | ||
| 9 | + | import "ermite/mirror.proto"; | |||
| 9 | import "ermite/repo.proto"; | 10 | import "ermite/repo.proto"; | ||
| 10 | import "ermite/run.proto"; | 11 | import "ermite/run.proto"; | ||
| 11 | import "google/protobuf/timestamp.proto"; | 12 | import "google/protobuf/timestamp.proto"; | ||
| @@ -135,6 +136,10 @@ message Event { | |||||
| 135 | // MergeRequestMergeability: the mergeability of an open merge request | 136 | // MergeRequestMergeability: the mergeability of an open merge request | ||
| 136 | // changed. | 137 | // changed. | ||
| 137 | MergeRequestMergeability merge_request_mergeability = 22; | 138 | MergeRequestMergeability merge_request_mergeability = 22; | ||
| 139 | + | // MirrorFailed: a mirror entered failing or paused. | |||
| 140 | + | MirrorFailed mirror_failed = 23; | |||
| 141 | + | // MirrorRecovered: a failing or paused mirror succeeded again. | |||
| 142 | + | MirrorRecovered mirror_recovered = 24; | |||
| 138 | } | 143 | } | ||
| 139 | } | 144 | } | ||
| 140 | 145 | ||||
| @@ -306,3 +311,27 @@ message JobUpdated { | |||||
| 306 | // Job is the job after the change, with its steps. | 311 | // Job is the job after the change, with its steps. | ||
| 307 | RunJob job = 1; | 312 | RunJob job = 1; | ||
| 308 | } | 313 | } | ||
| 314 | + | ||||
| 315 | + | // MirrorFailed reports the start of a failure incident: a transition from ok | |||
| 316 | + | // or disabled into failing or paused. It is sent once per incident, not for | |||
| 317 | + | // each failed attempt nor for failing to paused. Servers with feature "mirror" | |||
| 318 | + | // deliver it on "repo:<name>" and "home", subject to repository visibility. It | |||
| 319 | + | // carries no URL, reason or error detail; read the status for those. | |||
| 320 | + | message MirrorFailed { | |||
| 321 | + | // Repo is the repository name. | |||
| 322 | + | string repo = 1; | |||
| 323 | + | // State is the new mirror state. | |||
| 324 | + | MirrorState state = 2; | |||
| 325 | + | // FailureClass is the failure category. | |||
| 326 | + | string failure_class = 3; | |||
| 327 | + | ||||
| 328 | + | reserved 4; | |||
| 329 | + | reserved "reason"; | |||
| 330 | + | } | |||
| 331 | + | ||||
| 332 | + | // MirrorRecovered reports a successful sync after failing or paused. Delivery | |||
| 333 | + | // follows MirrorFailed. It carries no URL or error detail. | |||
| 334 | + | message MirrorRecovered { | |||
| 335 | + | // Repo is the repository name. | |||
| 336 | + | string repo = 1; | |||
| 337 | + | } | |||
A proto/ermite/mirror.proto +289 -0
| @@ -0,0 +1,289 @@ | |||
| 1 | + | // SPDX-License-Identifier: MIT | |
| 2 | + | ||
| 3 | + | syntax = "proto3"; | |
| 4 | + | ||
| 5 | + | package ermite; | |
| 6 | + | ||
| 7 | + | import "google/protobuf/timestamp.proto"; | |
| 8 | + | ||
| 9 | + | // MirrorService configures the push mirrors of the server. Global settings and | |
| 10 | + | // key rotation need the admin token or a token with every scope and no | |
| 11 | + | // repository or branch limits; per-repository settings and SyncMirror need | |
| 12 | + | // repo:admin on the repository; status needs read access. GetMirrorKey needs a | |
| 13 | + | // non-anonymous caller. ListMirrorStatus and SyncMirror with All need owner | |
| 14 | + | // rights. No new token scope is required. Servers implementing this service | |
| 15 | + | // list "mirror" in GetVersionResponse.features. | |
| 16 | + | service MirrorService { | |
| 17 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |
| 18 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |
| 19 | + | // ERMITE_SECRETS_KEY. | |
| 20 | + | rpc GetMirrorKey(GetMirrorKeyRequest) returns (GetMirrorKeyResponse); | |
| 21 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |
| 22 | + | // and sync with force to recover from authentication failures. | |
| 23 | + | rpc RotateMirrorKey(RotateMirrorKeyRequest) returns (RotateMirrorKeyResponse); | |
| 24 | + | // GetMirrorConfig returns the global mirror policy. | |
| 25 | + | rpc GetMirrorConfig(GetMirrorConfigRequest) returns (GetMirrorConfigResponse); | |
| 26 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |
| 27 | + | // Invalid fields give invalid_argument with field violations. | |
| 28 | + | rpc SetMirrorConfig(SetMirrorConfigRequest) returns (SetMirrorConfigResponse); | |
| 29 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |
| 30 | + | rpc SetRepoMirror(SetRepoMirrorRequest) returns (SetRepoMirrorResponse); | |
| 31 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |
| 32 | + | rpc RemoveRepoMirror(RemoveRepoMirrorRequest) returns (RemoveRepoMirrorResponse); | |
| 33 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |
| 34 | + | // policy. An explicit URL override takes precedence. | |
| 35 | + | rpc SetRepoMirrorExcluded(SetRepoMirrorExcludedRequest) returns (SetRepoMirrorExcludedResponse); | |
| 36 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |
| 37 | + | rpc GetMirrorStatus(GetMirrorStatusRequest) returns (GetMirrorStatusResponse); | |
| 38 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |
| 39 | + | rpc ListMirrorStatus(ListMirrorStatusRequest) returns (ListMirrorStatusResponse); | |
| 40 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |
| 41 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |
| 42 | + | rpc SyncMirror(SyncMirrorRequest) returns (SyncMirrorResponse); | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | // MirrorKey is the public SSH key used for push mirrors. Private key material | |
| 46 | + | // is never returned. | |
| 47 | + | message MirrorKey { | |
| 48 | + | // AuthorizedKey is the SSH authorized_keys line. | |
| 49 | + | string authorized_key = 1; | |
| 50 | + | // Fingerprint is the SHA256 fingerprint of the public key. | |
| 51 | + | string fingerprint = 2; | |
| 52 | + | // CreatedAt is when the key was created. | |
| 53 | + | google.protobuf.Timestamp created_at = 3; | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | // GetMirrorKeyRequest selects the input of GetMirrorKey. | |
| 57 | + | message GetMirrorKeyRequest {} | |
| 58 | + | ||
| 59 | + | // GetMirrorKeyResponse holds the result of GetMirrorKey. | |
| 60 | + | message GetMirrorKeyResponse { | |
| 61 | + | // Key is the public mirror key. | |
| 62 | + | MirrorKey key = 1; | |
| 63 | + | } | |
| 64 | + | ||
| 65 | + | // RotateMirrorKeyRequest selects the input of RotateMirrorKey. | |
| 66 | + | message RotateMirrorKeyRequest {} | |
| 67 | + | ||
| 68 | + | // RotateMirrorKeyResponse holds the result of RotateMirrorKey. | |
| 69 | + | message RotateMirrorKeyResponse { | |
| 70 | + | // Key is the public mirror key. | |
| 71 | + | MirrorKey key = 1; | |
| 72 | + | // PreviousFingerprint is the fingerprint of the replaced key. | |
| 73 | + | string previous_fingerprint = 2; | |
| 74 | + | } | |
| 75 | + | ||
| 76 | + | // MirrorConfig is the server-wide push mirror policy. | |
| 77 | + | message MirrorConfig { | |
| 78 | + | // Enabled says whether mirroring is enabled. | |
| 79 | + | bool enabled = 1; | |
| 80 | + | // URLTemplate is an SSH URL containing "{repo}", replaced with the | |
| 81 | + | // repository name. | |
| 82 | + | string url_template = 2; | |
| 83 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |
| 84 | + | // five minutes. | |
| 85 | + | string cron = 3; | |
| 86 | + | // AllBranches includes every branch rather than only the default branch. | |
| 87 | + | // Tags are always included. | |
| 88 | + | bool all_branches = 4; | |
| 89 | + | // UpdatedAt is when the configuration was last changed. | |
| 90 | + | google.protobuf.Timestamp updated_at = 5; | |
| 91 | + | } | |
| 92 | + | ||
| 93 | + | // GetMirrorConfigRequest selects the input of GetMirrorConfig. | |
| 94 | + | message GetMirrorConfigRequest {} | |
| 95 | + | ||
| 96 | + | // GetMirrorConfigResponse holds the result of GetMirrorConfig. | |
| 97 | + | message GetMirrorConfigResponse { | |
| 98 | + | // Config is the global mirror policy. | |
| 99 | + | MirrorConfig config = 1; | |
| 100 | + | } | |
| 101 | + | ||
| 102 | + | // SetMirrorConfigRequest selects the input of SetMirrorConfig. | |
| 103 | + | message SetMirrorConfigRequest { | |
| 104 | + | // Enabled says whether mirroring is enabled. Unset means unchanged. | |
| 105 | + | optional bool enabled = 1; | |
| 106 | + | // URLTemplate is an SSH URL containing "{repo}", replaced with the | |
| 107 | + | // repository name. Unset means unchanged. | |
| 108 | + | optional string url_template = 2; | |
| 109 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |
| 110 | + | // five minutes. Unset means unchanged. | |
| 111 | + | optional string cron = 3; | |
| 112 | + | // AllBranches includes every branch rather than only the default branch. | |
| 113 | + | // Tags are always included. Unset means unchanged. | |
| 114 | + | optional bool all_branches = 4; | |
| 115 | + | } | |
| 116 | + | ||
| 117 | + | // SetMirrorConfigResponse holds the result of SetMirrorConfig. | |
| 118 | + | message SetMirrorConfigResponse { | |
| 119 | + | // Config is the global mirror policy. | |
| 120 | + | MirrorConfig config = 1; | |
| 121 | + | } | |
| 122 | + | ||
| 123 | + | // MirrorSource says which configuration applies to a repository. | |
| 124 | + | enum MirrorSource { | |
| 125 | + | // MIRROR_SOURCE_DISABLED: nothing applies; MIRROR_SOURCE_GLOBAL: the global | |
| 126 | + | // template; MIRROR_SOURCE_OVERRIDE: a per-repository URL; | |
| 127 | + | // MIRROR_SOURCE_EXCLUDED: opted out of the global template. | |
| 128 | + | MIRROR_SOURCE_UNSPECIFIED = 0; | |
| 129 | + | MIRROR_SOURCE_DISABLED = 1; | |
| 130 | + | MIRROR_SOURCE_GLOBAL = 2; | |
| 131 | + | MIRROR_SOURCE_OVERRIDE = 3; | |
| 132 | + | MIRROR_SOURCE_EXCLUDED = 4; | |
| 133 | + | } | |
| 134 | + | ||
| 135 | + | // MirrorTarget is the resolved push mirror target of a repository. | |
| 136 | + | message MirrorTarget { | |
| 137 | + | // Repo is the repository name. | |
| 138 | + | string repo = 1; | |
| 139 | + | // Enabled says whether mirroring is enabled. | |
| 140 | + | bool enabled = 2; | |
| 141 | + | // URL is the SSH destination of the mirror. | |
| 142 | + | string url = 3; | |
| 143 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |
| 144 | + | // five minutes. | |
| 145 | + | string cron = 4; | |
| 146 | + | // AllBranches includes every branch rather than only the default branch. | |
| 147 | + | // Tags are always included. | |
| 148 | + | bool all_branches = 5; | |
| 149 | + | // Source is the configuration used to resolve the target. | |
| 150 | + | MirrorSource source = 6; | |
| 151 | + | } | |
| 152 | + | ||
| 153 | + | // SetRepoMirrorRequest selects the input of SetRepoMirror. | |
| 154 | + | message SetRepoMirrorRequest { | |
| 155 | + | // Repo is the repository name. | |
| 156 | + | string repo = 1; | |
| 157 | + | // URL is the SSH destination of the mirror. | |
| 158 | + | string url = 2; | |
| 159 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |
| 160 | + | // five minutes. | |
| 161 | + | // Empty means inherit the global cron. | |
| 162 | + | string cron = 3; | |
| 163 | + | // AllBranches includes every branch rather than only the default branch. | |
| 164 | + | // Tags are always included. Unset means inherit the global setting. | |
| 165 | + | optional bool all_branches = 4; | |
| 166 | + | } | |
| 167 | + | ||
| 168 | + | // SetRepoMirrorResponse holds the result of SetRepoMirror. | |
| 169 | + | message SetRepoMirrorResponse { | |
| 170 | + | // Target is the resolved mirror target. | |
| 171 | + | MirrorTarget target = 1; | |
| 172 | + | } | |
| 173 | + | ||
| 174 | + | // RemoveRepoMirrorRequest selects the input of RemoveRepoMirror. | |
| 175 | + | message RemoveRepoMirrorRequest { | |
| 176 | + | // Repo is the repository name. | |
| 177 | + | string repo = 1; | |
| 178 | + | } | |
| 179 | + | ||
| 180 | + | // RemoveRepoMirrorResponse holds the result of RemoveRepoMirror. | |
| 181 | + | message RemoveRepoMirrorResponse {} | |
| 182 | + | ||
| 183 | + | // SetRepoMirrorExcludedRequest selects the input of SetRepoMirrorExcluded. | |
| 184 | + | message SetRepoMirrorExcludedRequest { | |
| 185 | + | // Repo is the repository name. | |
| 186 | + | string repo = 1; | |
| 187 | + | // Excluded opts out of the global template, unless a URL override exists. | |
| 188 | + | bool excluded = 2; | |
| 189 | + | } | |
| 190 | + | ||
| 191 | + | // SetRepoMirrorExcludedResponse holds the result of SetRepoMirrorExcluded. | |
| 192 | + | message SetRepoMirrorExcludedResponse { | |
| 193 | + | // Target is the resolved mirror target. | |
| 194 | + | MirrorTarget target = 1; | |
| 195 | + | } | |
| 196 | + | ||
| 197 | + | // MirrorState is the current state of a push mirror. | |
| 198 | + | enum MirrorState { | |
| 199 | + | // MIRROR_STATE_OK: last sync succeeded; MIRROR_STATE_FAILING: retrying with | |
| 200 | + | // backoff; MIRROR_STATE_PAUSED: stopped until a forced sync or a config change. | |
| 201 | + | MIRROR_STATE_UNSPECIFIED = 0; | |
| 202 | + | MIRROR_STATE_DISABLED = 1; | |
| 203 | + | MIRROR_STATE_OK = 2; | |
| 204 | + | MIRROR_STATE_FAILING = 3; | |
| 205 | + | MIRROR_STATE_PAUSED = 4; | |
| 206 | + | } | |
| 207 | + | ||
| 208 | + | // MirrorStatus describes a repository mirror and its last attempts. | |
| 209 | + | message MirrorStatus { | |
| 210 | + | // Target is the resolved mirror target. | |
| 211 | + | MirrorTarget target = 1; | |
| 212 | + | // State is the current mirror state. | |
| 213 | + | MirrorState state = 2; | |
| 214 | + | // FailureClass is the failure category, empty when there is no failure. | |
| 215 | + | string failure_class = 3; | |
| 216 | + | // Reason explains the current state. | |
| 217 | + | string reason = 4; | |
| 218 | + | // Detail is the last error detail, returned only to callers with repo:admin | |
| 219 | + | // on the repository. | |
| 220 | + | string detail = 5; | |
| 221 | + | // ConsecutiveFailures counts failed attempts since the last success or | |
| 222 | + | // reset. | |
| 223 | + | int32 consecutive_failures = 6; | |
| 224 | + | // LastAttemptAt is when the last sync was attempted. | |
| 225 | + | google.protobuf.Timestamp last_attempt_at = 7; | |
| 226 | + | // LastSuccessAt is when the last sync succeeded, including a no-op. | |
| 227 | + | google.protobuf.Timestamp last_success_at = 8; | |
| 228 | + | // NextRetryAt is the next retry time while failing; otherwise unset. | |
| 229 | + | google.protobuf.Timestamp next_retry_at = 9; | |
| 230 | + | // NextRunAt is the next scheduled sync time, or the retry time while | |
| 231 | + | // failing. | |
| 232 | + | google.protobuf.Timestamp next_run_at = 10; | |
| 233 | + | // PausedAt is when the mirror was paused; otherwise unset. | |
| 234 | + | google.protobuf.Timestamp paused_at = 11; | |
| 235 | + | } | |
| 236 | + | ||
| 237 | + | // GetMirrorStatusRequest selects the input of GetMirrorStatus. | |
| 238 | + | message GetMirrorStatusRequest { | |
| 239 | + | // Repo is the repository name. | |
| 240 | + | string repo = 1; | |
| 241 | + | } | |
| 242 | + | ||
| 243 | + | // GetMirrorStatusResponse holds the result of GetMirrorStatus. | |
| 244 | + | message GetMirrorStatusResponse { | |
| 245 | + | // Status is the current mirror status. | |
| 246 | + | MirrorStatus status = 1; | |
| 247 | + | } | |
| 248 | + | ||
| 249 | + | // ListMirrorStatusRequest selects the input of ListMirrorStatus. | |
| 250 | + | message ListMirrorStatusRequest {} | |
| 251 | + | ||
| 252 | + | // ListMirrorStatusResponse holds the result of ListMirrorStatus. | |
| 253 | + | message ListMirrorStatusResponse { | |
| 254 | + | // Statuses are the mirror statuses. | |
| 255 | + | repeated MirrorStatus statuses = 1; | |
| 256 | + | } | |
| 257 | + | ||
| 258 | + | // SyncMirrorRequest selects the input of SyncMirror. | |
| 259 | + | message SyncMirrorRequest { | |
| 260 | + | // Repo is the repository name. | |
| 261 | + | string repo = 1; | |
| 262 | + | // All selects every repository and needs owner rights. Repo must be empty | |
| 263 | + | // when true. | |
| 264 | + | bool all = 2; | |
| 265 | + | // Force lifts a pause and skips the no-op check and the 60-second manual | |
| 266 | + | // throttle. It never forces a Git push. | |
| 267 | + | bool force = 3; | |
| 268 | + | } | |
| 269 | + | ||
| 270 | + | // SyncMirrorResult is the result of a sync request for one repository. | |
| 271 | + | message SyncMirrorResult { | |
| 272 | + | // Repo is the repository name. | |
| 273 | + | string repo = 1; | |
| 274 | + | // Queued says another sync is running and this request was queued. | |
| 275 | + | bool queued = 2; | |
| 276 | + | // NoOp says the refs already matched the last successful snapshot. | |
| 277 | + | bool no_op = 3; | |
| 278 | + | // Status is the current mirror status. | |
| 279 | + | MirrorStatus status = 4; | |
| 280 | + | // Error is a human-readable failure of this repository's sync, empty on | |
| 281 | + | // success. It never contains the mirror URL. | |
| 282 | + | string error = 5; | |
| 283 | + | } | |
| 284 | + | ||
| 285 | + | // SyncMirrorResponse holds the result of SyncMirror. | |
| 286 | + | message SyncMirrorResponse { | |
| 287 | + | // Results are the per-repository sync results. | |
| 288 | + | repeated SyncMirrorResult results = 1; | |
| 289 | + | } | |
| @@ -0,0 +1,289 @@ | |||||
| 1 | + | // SPDX-License-Identifier: MIT | |||
| 2 | + | ||||
| 3 | + | syntax = "proto3"; | |||
| 4 | + | ||||
| 5 | + | package ermite; | |||
| 6 | + | ||||
| 7 | + | import "google/protobuf/timestamp.proto"; | |||
| 8 | + | ||||
| 9 | + | // MirrorService configures the push mirrors of the server. Global settings and | |||
| 10 | + | // key rotation need the admin token or a token with every scope and no | |||
| 11 | + | // repository or branch limits; per-repository settings and SyncMirror need | |||
| 12 | + | // repo:admin on the repository; status needs read access. GetMirrorKey needs a | |||
| 13 | + | // non-anonymous caller. ListMirrorStatus and SyncMirror with All need owner | |||
| 14 | + | // rights. No new token scope is required. Servers implementing this service | |||
| 15 | + | // list "mirror" in GetVersionResponse.features. | |||
| 16 | + | service MirrorService { | |||
| 17 | + | // GetMirrorKey returns the public mirror key, generating it on first use. | |||
| 18 | + | // Needs a non-anonymous caller. Fails with failed_precondition without | |||
| 19 | + | // ERMITE_SECRETS_KEY. | |||
| 20 | + | rpc GetMirrorKey(GetMirrorKeyRequest) returns (GetMirrorKeyResponse); | |||
| 21 | + | // RotateMirrorKey replaces the key immediately. Add the new key to remotes | |||
| 22 | + | // and sync with force to recover from authentication failures. | |||
| 23 | + | rpc RotateMirrorKey(RotateMirrorKeyRequest) returns (RotateMirrorKeyResponse); | |||
| 24 | + | // GetMirrorConfig returns the global mirror policy. | |||
| 25 | + | rpc GetMirrorConfig(GetMirrorConfigRequest) returns (GetMirrorConfigResponse); | |||
| 26 | + | // SetMirrorConfig patches the global policy. Unset fields are unchanged. | |||
| 27 | + | // Invalid fields give invalid_argument with field violations. | |||
| 28 | + | rpc SetMirrorConfig(SetMirrorConfigRequest) returns (SetMirrorConfigResponse); | |||
| 29 | + | // SetRepoMirror sets an override, even when global mirroring is disabled. | |||
| 30 | + | rpc SetRepoMirror(SetRepoMirrorRequest) returns (SetRepoMirrorResponse); | |||
| 31 | + | // RemoveRepoMirror removes the override so the global policy applies again. | |||
| 32 | + | rpc RemoveRepoMirror(RemoveRepoMirrorRequest) returns (RemoveRepoMirrorResponse); | |||
| 33 | + | // SetRepoMirrorExcluded excludes or includes a repository in the global | |||
| 34 | + | // policy. An explicit URL override takes precedence. | |||
| 35 | + | rpc SetRepoMirrorExcluded(SetRepoMirrorExcludedRequest) returns (SetRepoMirrorExcludedResponse); | |||
| 36 | + | // GetMirrorStatus returns the resolved target and status of one repository. | |||
| 37 | + | rpc GetMirrorStatus(GetMirrorStatusRequest) returns (GetMirrorStatusResponse); | |||
| 38 | + | // ListMirrorStatus lists mirror statuses and needs owner rights. | |||
| 39 | + | rpc ListMirrorStatus(ListMirrorStatusRequest) returns (ListMirrorStatusResponse); | |||
| 40 | + | // SyncMirror syncs Repo or, with All, every repository. Paused mirrors need | |||
| 41 | + | // Force. Manual requests without Force are at least 60 seconds apart. | |||
| 42 | + | rpc SyncMirror(SyncMirrorRequest) returns (SyncMirrorResponse); | |||
| 43 | + | } | |||
| 44 | + | ||||
| 45 | + | // MirrorKey is the public SSH key used for push mirrors. Private key material | |||
| 46 | + | // is never returned. | |||
| 47 | + | message MirrorKey { | |||
| 48 | + | // AuthorizedKey is the SSH authorized_keys line. | |||
| 49 | + | string authorized_key = 1; | |||
| 50 | + | // Fingerprint is the SHA256 fingerprint of the public key. | |||
| 51 | + | string fingerprint = 2; | |||
| 52 | + | // CreatedAt is when the key was created. | |||
| 53 | + | google.protobuf.Timestamp created_at = 3; | |||
| 54 | + | } | |||
| 55 | + | ||||
| 56 | + | // GetMirrorKeyRequest selects the input of GetMirrorKey. | |||
| 57 | + | message GetMirrorKeyRequest {} | |||
| 58 | + | ||||
| 59 | + | // GetMirrorKeyResponse holds the result of GetMirrorKey. | |||
| 60 | + | message GetMirrorKeyResponse { | |||
| 61 | + | // Key is the public mirror key. | |||
| 62 | + | MirrorKey key = 1; | |||
| 63 | + | } | |||
| 64 | + | ||||
| 65 | + | // RotateMirrorKeyRequest selects the input of RotateMirrorKey. | |||
| 66 | + | message RotateMirrorKeyRequest {} | |||
| 67 | + | ||||
| 68 | + | // RotateMirrorKeyResponse holds the result of RotateMirrorKey. | |||
| 69 | + | message RotateMirrorKeyResponse { | |||
| 70 | + | // Key is the public mirror key. | |||
| 71 | + | MirrorKey key = 1; | |||
| 72 | + | // PreviousFingerprint is the fingerprint of the replaced key. | |||
| 73 | + | string previous_fingerprint = 2; | |||
| 74 | + | } | |||
| 75 | + | ||||
| 76 | + | // MirrorConfig is the server-wide push mirror policy. | |||
| 77 | + | message MirrorConfig { | |||
| 78 | + | // Enabled says whether mirroring is enabled. | |||
| 79 | + | bool enabled = 1; | |||
| 80 | + | // URLTemplate is an SSH URL containing "{repo}", replaced with the | |||
| 81 | + | // repository name. | |||
| 82 | + | string url_template = 2; | |||
| 83 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |||
| 84 | + | // five minutes. | |||
| 85 | + | string cron = 3; | |||
| 86 | + | // AllBranches includes every branch rather than only the default branch. | |||
| 87 | + | // Tags are always included. | |||
| 88 | + | bool all_branches = 4; | |||
| 89 | + | // UpdatedAt is when the configuration was last changed. | |||
| 90 | + | google.protobuf.Timestamp updated_at = 5; | |||
| 91 | + | } | |||
| 92 | + | ||||
| 93 | + | // GetMirrorConfigRequest selects the input of GetMirrorConfig. | |||
| 94 | + | message GetMirrorConfigRequest {} | |||
| 95 | + | ||||
| 96 | + | // GetMirrorConfigResponse holds the result of GetMirrorConfig. | |||
| 97 | + | message GetMirrorConfigResponse { | |||
| 98 | + | // Config is the global mirror policy. | |||
| 99 | + | MirrorConfig config = 1; | |||
| 100 | + | } | |||
| 101 | + | ||||
| 102 | + | // SetMirrorConfigRequest selects the input of SetMirrorConfig. | |||
| 103 | + | message SetMirrorConfigRequest { | |||
| 104 | + | // Enabled says whether mirroring is enabled. Unset means unchanged. | |||
| 105 | + | optional bool enabled = 1; | |||
| 106 | + | // URLTemplate is an SSH URL containing "{repo}", replaced with the | |||
| 107 | + | // repository name. Unset means unchanged. | |||
| 108 | + | optional string url_template = 2; | |||
| 109 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |||
| 110 | + | // five minutes. Unset means unchanged. | |||
| 111 | + | optional string cron = 3; | |||
| 112 | + | // AllBranches includes every branch rather than only the default branch. | |||
| 113 | + | // Tags are always included. Unset means unchanged. | |||
| 114 | + | optional bool all_branches = 4; | |||
| 115 | + | } | |||
| 116 | + | ||||
| 117 | + | // SetMirrorConfigResponse holds the result of SetMirrorConfig. | |||
| 118 | + | message SetMirrorConfigResponse { | |||
| 119 | + | // Config is the global mirror policy. | |||
| 120 | + | MirrorConfig config = 1; | |||
| 121 | + | } | |||
| 122 | + | ||||
| 123 | + | // MirrorSource says which configuration applies to a repository. | |||
| 124 | + | enum MirrorSource { | |||
| 125 | + | // MIRROR_SOURCE_DISABLED: nothing applies; MIRROR_SOURCE_GLOBAL: the global | |||
| 126 | + | // template; MIRROR_SOURCE_OVERRIDE: a per-repository URL; | |||
| 127 | + | // MIRROR_SOURCE_EXCLUDED: opted out of the global template. | |||
| 128 | + | MIRROR_SOURCE_UNSPECIFIED = 0; | |||
| 129 | + | MIRROR_SOURCE_DISABLED = 1; | |||
| 130 | + | MIRROR_SOURCE_GLOBAL = 2; | |||
| 131 | + | MIRROR_SOURCE_OVERRIDE = 3; | |||
| 132 | + | MIRROR_SOURCE_EXCLUDED = 4; | |||
| 133 | + | } | |||
| 134 | + | ||||
| 135 | + | // MirrorTarget is the resolved push mirror target of a repository. | |||
| 136 | + | message MirrorTarget { | |||
| 137 | + | // Repo is the repository name. | |||
| 138 | + | string repo = 1; | |||
| 139 | + | // Enabled says whether mirroring is enabled. | |||
| 140 | + | bool enabled = 2; | |||
| 141 | + | // URL is the SSH destination of the mirror. | |||
| 142 | + | string url = 3; | |||
| 143 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |||
| 144 | + | // five minutes. | |||
| 145 | + | string cron = 4; | |||
| 146 | + | // AllBranches includes every branch rather than only the default branch. | |||
| 147 | + | // Tags are always included. | |||
| 148 | + | bool all_branches = 5; | |||
| 149 | + | // Source is the configuration used to resolve the target. | |||
| 150 | + | MirrorSource source = 6; | |||
| 151 | + | } | |||
| 152 | + | ||||
| 153 | + | // SetRepoMirrorRequest selects the input of SetRepoMirror. | |||
| 154 | + | message SetRepoMirrorRequest { | |||
| 155 | + | // Repo is the repository name. | |||
| 156 | + | string repo = 1; | |||
| 157 | + | // URL is the SSH destination of the mirror. | |||
| 158 | + | string url = 2; | |||
| 159 | + | // Cron is a five-field cron expression in UTC, no more frequent than every | |||
| 160 | + | // five minutes. | |||
| 161 | + | // Empty means inherit the global cron. | |||
| 162 | + | string cron = 3; | |||
| 163 | + | // AllBranches includes every branch rather than only the default branch. | |||
| 164 | + | // Tags are always included. Unset means inherit the global setting. | |||
| 165 | + | optional bool all_branches = 4; | |||
| 166 | + | } | |||
| 167 | + | ||||
| 168 | + | // SetRepoMirrorResponse holds the result of SetRepoMirror. | |||
| 169 | + | message SetRepoMirrorResponse { | |||
| 170 | + | // Target is the resolved mirror target. | |||
| 171 | + | MirrorTarget target = 1; | |||
| 172 | + | } | |||
| 173 | + | ||||
| 174 | + | // RemoveRepoMirrorRequest selects the input of RemoveRepoMirror. | |||
| 175 | + | message RemoveRepoMirrorRequest { | |||
| 176 | + | // Repo is the repository name. | |||
| 177 | + | string repo = 1; | |||
| 178 | + | } | |||
| 179 | + | ||||
| 180 | + | // RemoveRepoMirrorResponse holds the result of RemoveRepoMirror. | |||
| 181 | + | message RemoveRepoMirrorResponse {} | |||
| 182 | + | ||||
| 183 | + | // SetRepoMirrorExcludedRequest selects the input of SetRepoMirrorExcluded. | |||
| 184 | + | message SetRepoMirrorExcludedRequest { | |||
| 185 | + | // Repo is the repository name. | |||
| 186 | + | string repo = 1; | |||
| 187 | + | // Excluded opts out of the global template, unless a URL override exists. | |||
| 188 | + | bool excluded = 2; | |||
| 189 | + | } | |||
| 190 | + | ||||
| 191 | + | // SetRepoMirrorExcludedResponse holds the result of SetRepoMirrorExcluded. | |||
| 192 | + | message SetRepoMirrorExcludedResponse { | |||
| 193 | + | // Target is the resolved mirror target. | |||
| 194 | + | MirrorTarget target = 1; | |||
| 195 | + | } | |||
| 196 | + | ||||
| 197 | + | // MirrorState is the current state of a push mirror. | |||
| 198 | + | enum MirrorState { | |||
| 199 | + | // MIRROR_STATE_OK: last sync succeeded; MIRROR_STATE_FAILING: retrying with | |||
| 200 | + | // backoff; MIRROR_STATE_PAUSED: stopped until a forced sync or a config change. | |||
| 201 | + | MIRROR_STATE_UNSPECIFIED = 0; | |||
| 202 | + | MIRROR_STATE_DISABLED = 1; | |||
| 203 | + | MIRROR_STATE_OK = 2; | |||
| 204 | + | MIRROR_STATE_FAILING = 3; | |||
| 205 | + | MIRROR_STATE_PAUSED = 4; | |||
| 206 | + | } | |||
| 207 | + | ||||
| 208 | + | // MirrorStatus describes a repository mirror and its last attempts. | |||
| 209 | + | message MirrorStatus { | |||
| 210 | + | // Target is the resolved mirror target. | |||
| 211 | + | MirrorTarget target = 1; | |||
| 212 | + | // State is the current mirror state. | |||
| 213 | + | MirrorState state = 2; | |||
| 214 | + | // FailureClass is the failure category, empty when there is no failure. | |||
| 215 | + | string failure_class = 3; | |||
| 216 | + | // Reason explains the current state. | |||
| 217 | + | string reason = 4; | |||
| 218 | + | // Detail is the last error detail, returned only to callers with repo:admin | |||
| 219 | + | // on the repository. | |||
| 220 | + | string detail = 5; | |||
| 221 | + | // ConsecutiveFailures counts failed attempts since the last success or | |||
| 222 | + | // reset. | |||
| 223 | + | int32 consecutive_failures = 6; | |||
| 224 | + | // LastAttemptAt is when the last sync was attempted. | |||
| 225 | + | google.protobuf.Timestamp last_attempt_at = 7; | |||
| 226 | + | // LastSuccessAt is when the last sync succeeded, including a no-op. | |||
| 227 | + | google.protobuf.Timestamp last_success_at = 8; | |||
| 228 | + | // NextRetryAt is the next retry time while failing; otherwise unset. | |||
| 229 | + | google.protobuf.Timestamp next_retry_at = 9; | |||
| 230 | + | // NextRunAt is the next scheduled sync time, or the retry time while | |||
| 231 | + | // failing. | |||
| 232 | + | google.protobuf.Timestamp next_run_at = 10; | |||
| 233 | + | // PausedAt is when the mirror was paused; otherwise unset. | |||
| 234 | + | google.protobuf.Timestamp paused_at = 11; | |||
| 235 | + | } | |||
| 236 | + | ||||
| 237 | + | // GetMirrorStatusRequest selects the input of GetMirrorStatus. | |||
| 238 | + | message GetMirrorStatusRequest { | |||
| 239 | + | // Repo is the repository name. | |||
| 240 | + | string repo = 1; | |||
| 241 | + | } | |||
| 242 | + | ||||
| 243 | + | // GetMirrorStatusResponse holds the result of GetMirrorStatus. | |||
| 244 | + | message GetMirrorStatusResponse { | |||
| 245 | + | // Status is the current mirror status. | |||
| 246 | + | MirrorStatus status = 1; | |||
| 247 | + | } | |||
| 248 | + | ||||
| 249 | + | // ListMirrorStatusRequest selects the input of ListMirrorStatus. | |||
| 250 | + | message ListMirrorStatusRequest {} | |||
| 251 | + | ||||
| 252 | + | // ListMirrorStatusResponse holds the result of ListMirrorStatus. | |||
| 253 | + | message ListMirrorStatusResponse { | |||
| 254 | + | // Statuses are the mirror statuses. | |||
| 255 | + | repeated MirrorStatus statuses = 1; | |||
| 256 | + | } | |||
| 257 | + | ||||
| 258 | + | // SyncMirrorRequest selects the input of SyncMirror. | |||
| 259 | + | message SyncMirrorRequest { | |||
| 260 | + | // Repo is the repository name. | |||
| 261 | + | string repo = 1; | |||
| 262 | + | // All selects every repository and needs owner rights. Repo must be empty | |||
| 263 | + | // when true. | |||
| 264 | + | bool all = 2; | |||
| 265 | + | // Force lifts a pause and skips the no-op check and the 60-second manual | |||
| 266 | + | // throttle. It never forces a Git push. | |||
| 267 | + | bool force = 3; | |||
| 268 | + | } | |||
| 269 | + | ||||
| 270 | + | // SyncMirrorResult is the result of a sync request for one repository. | |||
| 271 | + | message SyncMirrorResult { | |||
| 272 | + | // Repo is the repository name. | |||
| 273 | + | string repo = 1; | |||
| 274 | + | // Queued says another sync is running and this request was queued. | |||
| 275 | + | bool queued = 2; | |||
| 276 | + | // NoOp says the refs already matched the last successful snapshot. | |||
| 277 | + | bool no_op = 3; | |||
| 278 | + | // Status is the current mirror status. | |||
| 279 | + | MirrorStatus status = 4; | |||
| 280 | + | // Error is a human-readable failure of this repository's sync, empty on | |||
| 281 | + | // success. It never contains the mirror URL. | |||
| 282 | + | string error = 5; | |||
| 283 | + | } | |||
| 284 | + | ||||
| 285 | + | // SyncMirrorResponse holds the result of SyncMirror. | |||
| 286 | + | message SyncMirrorResponse { | |||
| 287 | + | // Results are the per-repository sync results. | |||
| 288 | + | repeated SyncMirrorResult results = 1; | |||
| 289 | + | } | |||
Comments0 open / 0
no comments yet.