detached 751d351

feat(proto): ReleaseService, release:write scope and release events

commit
751d3518d858cfece95cd552f798e836e6ba4292
author
brice · · 2026-10-21 14:14 UTC
committer
brice · · 2026-10-21 17:42 UTC
parent
e4b332d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
2/2
refs
tag: v0.16.0
11 files · +3361 -47
M docs/services.md +26 -0
@@ -50,3 +50,29 @@ starts failing (ok or disabled to failing or paused, once per incident), and `mi
5050 These are transition events, not events for every attempt. They are delivered on
5151 `repo:<name>` and `home`, subject to repository visibility. Neither event carries
5252 a URL, reason or error detail (`MirrorFailed` field 4, `reason`, was removed).
53+
54+## ReleaseService
55+
56+Servers advertise `releases` in `GetVersionResponse.features`.
57+
58+| RPC | Behavior |
59+|---|---|
60+| `CreateRelease`, `GetRelease`, `ListReleases`, `UpdateRelease`, `DeleteRelease` | Manage releases; get selects by id, tag or latest. Lists are paginated, newest first. Updates use a field mask |
61+| `UploadReleaseAsset` | Client stream: metadata and nonnegative exact size first, then data in chunks of at most 1 MiB. `replace` replaces a taken name |
62+| `UpdateReleaseAsset`, `DeleteReleaseAsset`, `ListReleaseAssets` | Rename/relabel with a field mask, delete, or list uploaded assets by name |
63+| `DownloadReleaseAsset` | Select by asset id, tag/name or latest/name; metadata first, then chunks of at most 1 MiB. Resume with a byte offset |
64+| `GetReleaseUsage` | Repository usage including reserved uploads, quota, asset size and count limits |
65+
66+Published releases follow repository read access; drafts are visible only to
67+writers. Writes require `release:write` (`SCOPE_RELEASE_WRITE = 13`) or a job
68+token with `contents: write` for that repository. Branch-limited tokens cannot
69+write releases. Unreadable objects return `not_found`. Duplicate tags or asset
70+names return `already_exists`; limits return `resource_exhausted`. Publishing
71+requires an existing tag or `target_commitish` to create it; existing tags never
72+move. `make_latest` is a boolean pin, and updates use mask presence.
73+
74+`EventService.Watch` adds `release_published` (27), `release_updated` (28),
75+`release_deleted` (29) and `release_unpublished` (30), delivered on `repo:<name>`
76+and `home` subject to repository visibility. Payloads carry repository, release
77+id and tag; all except deletion also carry draft and prerelease flags. Tag
78+deletion turns a release into a draft without deleting its assets.
@@ -50,3 +50,29 @@ starts failing (ok or disabled to failing or paused, once per incident), and `mi
50 These are transition events, not events for every attempt. They are delivered on50 These are transition events, not events for every attempt. They are delivered on
51 `repo:<name>` and `home`, subject to repository visibility. Neither event carries51 `repo:<name>` and `home`, subject to repository visibility. Neither event carries
52 a URL, reason or error detail (`MirrorFailed` field 4, `reason`, was removed).52 a URL, reason or error detail (`MirrorFailed` field 4, `reason`, was removed).
53+
54+## ReleaseService
55+
56+Servers advertise `releases` in `GetVersionResponse.features`.
57+
58+| RPC | Behavior |
59+|---|---|
60+| `CreateRelease`, `GetRelease`, `ListReleases`, `UpdateRelease`, `DeleteRelease` | Manage releases; get selects by id, tag or latest. Lists are paginated, newest first. Updates use a field mask |
61+| `UploadReleaseAsset` | Client stream: metadata and nonnegative exact size first, then data in chunks of at most 1 MiB. `replace` replaces a taken name |
62+| `UpdateReleaseAsset`, `DeleteReleaseAsset`, `ListReleaseAssets` | Rename/relabel with a field mask, delete, or list uploaded assets by name |
63+| `DownloadReleaseAsset` | Select by asset id, tag/name or latest/name; metadata first, then chunks of at most 1 MiB. Resume with a byte offset |
64+| `GetReleaseUsage` | Repository usage including reserved uploads, quota, asset size and count limits |
65+
66+Published releases follow repository read access; drafts are visible only to
67+writers. Writes require `release:write` (`SCOPE_RELEASE_WRITE = 13`) or a job
68+token with `contents: write` for that repository. Branch-limited tokens cannot
69+write releases. Unreadable objects return `not_found`. Duplicate tags or asset
70+names return `already_exists`; limits return `resource_exhausted`. Publishing
71+requires an existing tag or `target_commitish` to create it; existing tags never
72+move. `make_latest` is a boolean pin, and updates use mask presence.
73+
74+`EventService.Watch` adds `release_published` (27), `release_updated` (28),
75+`release_deleted` (29) and `release_unpublished` (30), delivered on `repo:<name>`
76+and `home` subject to repository visibility. Payloads carry repository, release
77+id and tag; all except deletion also carry draft and prerelease flags. Tag
78+deletion turns a release into a draft without deleting its assets.
A gen/ermite/ermiteconnect/release.connect.go +441 -0
@@ -0,0 +1,441 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
4+//
5+// Source: ermite/release.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+ // ReleaseServiceName is the fully-qualified name of the ReleaseService service.
27+ ReleaseServiceName = "ermite.ReleaseService"
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+ // ReleaseServiceCreateReleaseProcedure is the fully-qualified name of the ReleaseService's
39+ // CreateRelease RPC.
40+ ReleaseServiceCreateReleaseProcedure = "/ermite.ReleaseService/CreateRelease"
41+ // ReleaseServiceGetReleaseProcedure is the fully-qualified name of the ReleaseService's GetRelease
42+ // RPC.
43+ ReleaseServiceGetReleaseProcedure = "/ermite.ReleaseService/GetRelease"
44+ // ReleaseServiceListReleasesProcedure is the fully-qualified name of the ReleaseService's
45+ // ListReleases RPC.
46+ ReleaseServiceListReleasesProcedure = "/ermite.ReleaseService/ListReleases"
47+ // ReleaseServiceUpdateReleaseProcedure is the fully-qualified name of the ReleaseService's
48+ // UpdateRelease RPC.
49+ ReleaseServiceUpdateReleaseProcedure = "/ermite.ReleaseService/UpdateRelease"
50+ // ReleaseServiceDeleteReleaseProcedure is the fully-qualified name of the ReleaseService's
51+ // DeleteRelease RPC.
52+ ReleaseServiceDeleteReleaseProcedure = "/ermite.ReleaseService/DeleteRelease"
53+ // ReleaseServiceUploadReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
54+ // UploadReleaseAsset RPC.
55+ ReleaseServiceUploadReleaseAssetProcedure = "/ermite.ReleaseService/UploadReleaseAsset"
56+ // ReleaseServiceUpdateReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
57+ // UpdateReleaseAsset RPC.
58+ ReleaseServiceUpdateReleaseAssetProcedure = "/ermite.ReleaseService/UpdateReleaseAsset"
59+ // ReleaseServiceDeleteReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
60+ // DeleteReleaseAsset RPC.
61+ ReleaseServiceDeleteReleaseAssetProcedure = "/ermite.ReleaseService/DeleteReleaseAsset"
62+ // ReleaseServiceDownloadReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
63+ // DownloadReleaseAsset RPC.
64+ ReleaseServiceDownloadReleaseAssetProcedure = "/ermite.ReleaseService/DownloadReleaseAsset"
65+ // ReleaseServiceListReleaseAssetsProcedure is the fully-qualified name of the ReleaseService's
66+ // ListReleaseAssets RPC.
67+ ReleaseServiceListReleaseAssetsProcedure = "/ermite.ReleaseService/ListReleaseAssets"
68+ // ReleaseServiceGetReleaseUsageProcedure is the fully-qualified name of the ReleaseService's
69+ // GetReleaseUsage RPC.
70+ ReleaseServiceGetReleaseUsageProcedure = "/ermite.ReleaseService/GetReleaseUsage"
71+)
72+
73+// ReleaseServiceClient is a client for the ermite.ReleaseService service.
74+type ReleaseServiceClient interface {
75+ // CreateRelease creates one release per tag (already_exists on duplication).
76+ // Publishing without an existing tag is failed_precondition, unless
77+ // target_commitish is supplied to create it; existing tags never move.
78+ CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error)
79+ // GetRelease selects by id, tag or latest (latest must be true).
80+ GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error)
81+ // ListReleases lists newest first, including drafts only for writers.
82+ ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error)
83+ // UpdateRelease changes masked fields. Publishing requires an existing tag
84+ // or target_commitish to create it; otherwise failed_precondition.
85+ UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error)
86+ // DeleteRelease removes a release and its assets.
87+ DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error)
88+ // UploadReleaseAsset reserves size before reading. The first message carries
89+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
90+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
91+ // asset. A taken name gives already_exists unless replace is true. Uploading
92+ // to a release of another repo gives failed_precondition.
93+ UploadReleaseAsset(context.Context) *connect.ClientStreamForClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse]
94+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
95+ UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error)
96+ // DeleteReleaseAsset removes an asset.
97+ DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error)
98+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
99+ // 1 MiB. Resume with the offset after the last byte received. An offset
100+ // beyond the size gives out_of_range.
101+ DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest]) (*connect.ServerStreamForClient[ermite.DownloadReleaseAssetResponse], error)
102+ // ListReleaseAssets lists uploaded assets, ordered by name.
103+ ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error)
104+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
105+ GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error)
106+}
107+
108+// NewReleaseServiceClient constructs a client for the ermite.ReleaseService service. By default, it
109+// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
110+// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
111+// connect.WithGRPCWeb() options.
112+//
113+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
114+// http://api.acme.com or https://acme.com/grpc).
115+func NewReleaseServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ReleaseServiceClient {
116+ baseURL = strings.TrimRight(baseURL, "/")
117+ releaseServiceMethods := ermite.File_ermite_release_proto.Services().ByName("ReleaseService").Methods()
118+ return &releaseServiceClient{
119+ createRelease: connect.NewClient[ermite.CreateReleaseRequest, ermite.CreateReleaseResponse](
120+ httpClient,
121+ baseURL+ReleaseServiceCreateReleaseProcedure,
122+ connect.WithSchema(releaseServiceMethods.ByName("CreateRelease")),
123+ connect.WithClientOptions(opts...),
124+ ),
125+ getRelease: connect.NewClient[ermite.GetReleaseRequest, ermite.GetReleaseResponse](
126+ httpClient,
127+ baseURL+ReleaseServiceGetReleaseProcedure,
128+ connect.WithSchema(releaseServiceMethods.ByName("GetRelease")),
129+ connect.WithClientOptions(opts...),
130+ ),
131+ listReleases: connect.NewClient[ermite.ListReleasesRequest, ermite.ListReleasesResponse](
132+ httpClient,
133+ baseURL+ReleaseServiceListReleasesProcedure,
134+ connect.WithSchema(releaseServiceMethods.ByName("ListReleases")),
135+ connect.WithClientOptions(opts...),
136+ ),
137+ updateRelease: connect.NewClient[ermite.UpdateReleaseRequest, ermite.UpdateReleaseResponse](
138+ httpClient,
139+ baseURL+ReleaseServiceUpdateReleaseProcedure,
140+ connect.WithSchema(releaseServiceMethods.ByName("UpdateRelease")),
141+ connect.WithClientOptions(opts...),
142+ ),
143+ deleteRelease: connect.NewClient[ermite.DeleteReleaseRequest, ermite.DeleteReleaseResponse](
144+ httpClient,
145+ baseURL+ReleaseServiceDeleteReleaseProcedure,
146+ connect.WithSchema(releaseServiceMethods.ByName("DeleteRelease")),
147+ connect.WithClientOptions(opts...),
148+ ),
149+ uploadReleaseAsset: connect.NewClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse](
150+ httpClient,
151+ baseURL+ReleaseServiceUploadReleaseAssetProcedure,
152+ connect.WithSchema(releaseServiceMethods.ByName("UploadReleaseAsset")),
153+ connect.WithClientOptions(opts...),
154+ ),
155+ updateReleaseAsset: connect.NewClient[ermite.UpdateReleaseAssetRequest, ermite.UpdateReleaseAssetResponse](
156+ httpClient,
157+ baseURL+ReleaseServiceUpdateReleaseAssetProcedure,
158+ connect.WithSchema(releaseServiceMethods.ByName("UpdateReleaseAsset")),
159+ connect.WithClientOptions(opts...),
160+ ),
161+ deleteReleaseAsset: connect.NewClient[ermite.DeleteReleaseAssetRequest, ermite.DeleteReleaseAssetResponse](
162+ httpClient,
163+ baseURL+ReleaseServiceDeleteReleaseAssetProcedure,
164+ connect.WithSchema(releaseServiceMethods.ByName("DeleteReleaseAsset")),
165+ connect.WithClientOptions(opts...),
166+ ),
167+ downloadReleaseAsset: connect.NewClient[ermite.DownloadReleaseAssetRequest, ermite.DownloadReleaseAssetResponse](
168+ httpClient,
169+ baseURL+ReleaseServiceDownloadReleaseAssetProcedure,
170+ connect.WithSchema(releaseServiceMethods.ByName("DownloadReleaseAsset")),
171+ connect.WithClientOptions(opts...),
172+ ),
173+ listReleaseAssets: connect.NewClient[ermite.ListReleaseAssetsRequest, ermite.ListReleaseAssetsResponse](
174+ httpClient,
175+ baseURL+ReleaseServiceListReleaseAssetsProcedure,
176+ connect.WithSchema(releaseServiceMethods.ByName("ListReleaseAssets")),
177+ connect.WithClientOptions(opts...),
178+ ),
179+ getReleaseUsage: connect.NewClient[ermite.GetReleaseUsageRequest, ermite.GetReleaseUsageResponse](
180+ httpClient,
181+ baseURL+ReleaseServiceGetReleaseUsageProcedure,
182+ connect.WithSchema(releaseServiceMethods.ByName("GetReleaseUsage")),
183+ connect.WithClientOptions(opts...),
184+ ),
185+ }
186+}
187+
188+// releaseServiceClient implements ReleaseServiceClient.
189+type releaseServiceClient struct {
190+ createRelease *connect.Client[ermite.CreateReleaseRequest, ermite.CreateReleaseResponse]
191+ getRelease *connect.Client[ermite.GetReleaseRequest, ermite.GetReleaseResponse]
192+ listReleases *connect.Client[ermite.ListReleasesRequest, ermite.ListReleasesResponse]
193+ updateRelease *connect.Client[ermite.UpdateReleaseRequest, ermite.UpdateReleaseResponse]
194+ deleteRelease *connect.Client[ermite.DeleteReleaseRequest, ermite.DeleteReleaseResponse]
195+ uploadReleaseAsset *connect.Client[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse]
196+ updateReleaseAsset *connect.Client[ermite.UpdateReleaseAssetRequest, ermite.UpdateReleaseAssetResponse]
197+ deleteReleaseAsset *connect.Client[ermite.DeleteReleaseAssetRequest, ermite.DeleteReleaseAssetResponse]
198+ downloadReleaseAsset *connect.Client[ermite.DownloadReleaseAssetRequest, ermite.DownloadReleaseAssetResponse]
199+ listReleaseAssets *connect.Client[ermite.ListReleaseAssetsRequest, ermite.ListReleaseAssetsResponse]
200+ getReleaseUsage *connect.Client[ermite.GetReleaseUsageRequest, ermite.GetReleaseUsageResponse]
201+}
202+
203+// CreateRelease calls ermite.ReleaseService.CreateRelease.
204+func (c *releaseServiceClient) CreateRelease(ctx context.Context, req *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error) {
205+ return c.createRelease.CallUnary(ctx, req)
206+}
207+
208+// GetRelease calls ermite.ReleaseService.GetRelease.
209+func (c *releaseServiceClient) GetRelease(ctx context.Context, req *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error) {
210+ return c.getRelease.CallUnary(ctx, req)
211+}
212+
213+// ListReleases calls ermite.ReleaseService.ListReleases.
214+func (c *releaseServiceClient) ListReleases(ctx context.Context, req *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error) {
215+ return c.listReleases.CallUnary(ctx, req)
216+}
217+
218+// UpdateRelease calls ermite.ReleaseService.UpdateRelease.
219+func (c *releaseServiceClient) UpdateRelease(ctx context.Context, req *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error) {
220+ return c.updateRelease.CallUnary(ctx, req)
221+}
222+
223+// DeleteRelease calls ermite.ReleaseService.DeleteRelease.
224+func (c *releaseServiceClient) DeleteRelease(ctx context.Context, req *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error) {
225+ return c.deleteRelease.CallUnary(ctx, req)
226+}
227+
228+// UploadReleaseAsset calls ermite.ReleaseService.UploadReleaseAsset.
229+func (c *releaseServiceClient) UploadReleaseAsset(ctx context.Context) *connect.ClientStreamForClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse] {
230+ return c.uploadReleaseAsset.CallClientStream(ctx)
231+}
232+
233+// UpdateReleaseAsset calls ermite.ReleaseService.UpdateReleaseAsset.
234+func (c *releaseServiceClient) UpdateReleaseAsset(ctx context.Context, req *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error) {
235+ return c.updateReleaseAsset.CallUnary(ctx, req)
236+}
237+
238+// DeleteReleaseAsset calls ermite.ReleaseService.DeleteReleaseAsset.
239+func (c *releaseServiceClient) DeleteReleaseAsset(ctx context.Context, req *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error) {
240+ return c.deleteReleaseAsset.CallUnary(ctx, req)
241+}
242+
243+// DownloadReleaseAsset calls ermite.ReleaseService.DownloadReleaseAsset.
244+func (c *releaseServiceClient) DownloadReleaseAsset(ctx context.Context, req *connect.Request[ermite.DownloadReleaseAssetRequest]) (*connect.ServerStreamForClient[ermite.DownloadReleaseAssetResponse], error) {
245+ return c.downloadReleaseAsset.CallServerStream(ctx, req)
246+}
247+
248+// ListReleaseAssets calls ermite.ReleaseService.ListReleaseAssets.
249+func (c *releaseServiceClient) ListReleaseAssets(ctx context.Context, req *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error) {
250+ return c.listReleaseAssets.CallUnary(ctx, req)
251+}
252+
253+// GetReleaseUsage calls ermite.ReleaseService.GetReleaseUsage.
254+func (c *releaseServiceClient) GetReleaseUsage(ctx context.Context, req *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error) {
255+ return c.getReleaseUsage.CallUnary(ctx, req)
256+}
257+
258+// ReleaseServiceHandler is an implementation of the ermite.ReleaseService service.
259+type ReleaseServiceHandler interface {
260+ // CreateRelease creates one release per tag (already_exists on duplication).
261+ // Publishing without an existing tag is failed_precondition, unless
262+ // target_commitish is supplied to create it; existing tags never move.
263+ CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error)
264+ // GetRelease selects by id, tag or latest (latest must be true).
265+ GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error)
266+ // ListReleases lists newest first, including drafts only for writers.
267+ ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error)
268+ // UpdateRelease changes masked fields. Publishing requires an existing tag
269+ // or target_commitish to create it; otherwise failed_precondition.
270+ UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error)
271+ // DeleteRelease removes a release and its assets.
272+ DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error)
273+ // UploadReleaseAsset reserves size before reading. The first message carries
274+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
275+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
276+ // asset. A taken name gives already_exists unless replace is true. Uploading
277+ // to a release of another repo gives failed_precondition.
278+ UploadReleaseAsset(context.Context, *connect.ClientStream[ermite.UploadReleaseAssetRequest]) (*connect.Response[ermite.UploadReleaseAssetResponse], error)
279+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
280+ UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error)
281+ // DeleteReleaseAsset removes an asset.
282+ DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error)
283+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
284+ // 1 MiB. Resume with the offset after the last byte received. An offset
285+ // beyond the size gives out_of_range.
286+ DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest], *connect.ServerStream[ermite.DownloadReleaseAssetResponse]) error
287+ // ListReleaseAssets lists uploaded assets, ordered by name.
288+ ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error)
289+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
290+ GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error)
291+}
292+
293+// NewReleaseServiceHandler builds an HTTP handler from the service implementation. It returns the
294+// path on which to mount the handler and the handler itself.
295+//
296+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
297+// and JSON codecs. They also support gzip compression.
298+func NewReleaseServiceHandler(svc ReleaseServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
299+ releaseServiceMethods := ermite.File_ermite_release_proto.Services().ByName("ReleaseService").Methods()
300+ releaseServiceCreateReleaseHandler := connect.NewUnaryHandler(
301+ ReleaseServiceCreateReleaseProcedure,
302+ svc.CreateRelease,
303+ connect.WithSchema(releaseServiceMethods.ByName("CreateRelease")),
304+ connect.WithHandlerOptions(opts...),
305+ )
306+ releaseServiceGetReleaseHandler := connect.NewUnaryHandler(
307+ ReleaseServiceGetReleaseProcedure,
308+ svc.GetRelease,
309+ connect.WithSchema(releaseServiceMethods.ByName("GetRelease")),
310+ connect.WithHandlerOptions(opts...),
311+ )
312+ releaseServiceListReleasesHandler := connect.NewUnaryHandler(
313+ ReleaseServiceListReleasesProcedure,
314+ svc.ListReleases,
315+ connect.WithSchema(releaseServiceMethods.ByName("ListReleases")),
316+ connect.WithHandlerOptions(opts...),
317+ )
318+ releaseServiceUpdateReleaseHandler := connect.NewUnaryHandler(
319+ ReleaseServiceUpdateReleaseProcedure,
320+ svc.UpdateRelease,
321+ connect.WithSchema(releaseServiceMethods.ByName("UpdateRelease")),
322+ connect.WithHandlerOptions(opts...),
323+ )
324+ releaseServiceDeleteReleaseHandler := connect.NewUnaryHandler(
325+ ReleaseServiceDeleteReleaseProcedure,
326+ svc.DeleteRelease,
327+ connect.WithSchema(releaseServiceMethods.ByName("DeleteRelease")),
328+ connect.WithHandlerOptions(opts...),
329+ )
330+ releaseServiceUploadReleaseAssetHandler := connect.NewClientStreamHandler(
331+ ReleaseServiceUploadReleaseAssetProcedure,
332+ svc.UploadReleaseAsset,
333+ connect.WithSchema(releaseServiceMethods.ByName("UploadReleaseAsset")),
334+ connect.WithHandlerOptions(opts...),
335+ )
336+ releaseServiceUpdateReleaseAssetHandler := connect.NewUnaryHandler(
337+ ReleaseServiceUpdateReleaseAssetProcedure,
338+ svc.UpdateReleaseAsset,
339+ connect.WithSchema(releaseServiceMethods.ByName("UpdateReleaseAsset")),
340+ connect.WithHandlerOptions(opts...),
341+ )
342+ releaseServiceDeleteReleaseAssetHandler := connect.NewUnaryHandler(
343+ ReleaseServiceDeleteReleaseAssetProcedure,
344+ svc.DeleteReleaseAsset,
345+ connect.WithSchema(releaseServiceMethods.ByName("DeleteReleaseAsset")),
346+ connect.WithHandlerOptions(opts...),
347+ )
348+ releaseServiceDownloadReleaseAssetHandler := connect.NewServerStreamHandler(
349+ ReleaseServiceDownloadReleaseAssetProcedure,
350+ svc.DownloadReleaseAsset,
351+ connect.WithSchema(releaseServiceMethods.ByName("DownloadReleaseAsset")),
352+ connect.WithHandlerOptions(opts...),
353+ )
354+ releaseServiceListReleaseAssetsHandler := connect.NewUnaryHandler(
355+ ReleaseServiceListReleaseAssetsProcedure,
356+ svc.ListReleaseAssets,
357+ connect.WithSchema(releaseServiceMethods.ByName("ListReleaseAssets")),
358+ connect.WithHandlerOptions(opts...),
359+ )
360+ releaseServiceGetReleaseUsageHandler := connect.NewUnaryHandler(
361+ ReleaseServiceGetReleaseUsageProcedure,
362+ svc.GetReleaseUsage,
363+ connect.WithSchema(releaseServiceMethods.ByName("GetReleaseUsage")),
364+ connect.WithHandlerOptions(opts...),
365+ )
366+ return "/ermite.ReleaseService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
367+ switch r.URL.Path {
368+ case ReleaseServiceCreateReleaseProcedure:
369+ releaseServiceCreateReleaseHandler.ServeHTTP(w, r)
370+ case ReleaseServiceGetReleaseProcedure:
371+ releaseServiceGetReleaseHandler.ServeHTTP(w, r)
372+ case ReleaseServiceListReleasesProcedure:
373+ releaseServiceListReleasesHandler.ServeHTTP(w, r)
374+ case ReleaseServiceUpdateReleaseProcedure:
375+ releaseServiceUpdateReleaseHandler.ServeHTTP(w, r)
376+ case ReleaseServiceDeleteReleaseProcedure:
377+ releaseServiceDeleteReleaseHandler.ServeHTTP(w, r)
378+ case ReleaseServiceUploadReleaseAssetProcedure:
379+ releaseServiceUploadReleaseAssetHandler.ServeHTTP(w, r)
380+ case ReleaseServiceUpdateReleaseAssetProcedure:
381+ releaseServiceUpdateReleaseAssetHandler.ServeHTTP(w, r)
382+ case ReleaseServiceDeleteReleaseAssetProcedure:
383+ releaseServiceDeleteReleaseAssetHandler.ServeHTTP(w, r)
384+ case ReleaseServiceDownloadReleaseAssetProcedure:
385+ releaseServiceDownloadReleaseAssetHandler.ServeHTTP(w, r)
386+ case ReleaseServiceListReleaseAssetsProcedure:
387+ releaseServiceListReleaseAssetsHandler.ServeHTTP(w, r)
388+ case ReleaseServiceGetReleaseUsageProcedure:
389+ releaseServiceGetReleaseUsageHandler.ServeHTTP(w, r)
390+ default:
391+ http.NotFound(w, r)
392+ }
393+ })
394+}
395+
396+// UnimplementedReleaseServiceHandler returns CodeUnimplemented from all methods.
397+type UnimplementedReleaseServiceHandler struct{}
398+
399+func (UnimplementedReleaseServiceHandler) CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error) {
400+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.CreateRelease is not implemented"))
401+}
402+
403+func (UnimplementedReleaseServiceHandler) GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error) {
404+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.GetRelease is not implemented"))
405+}
406+
407+func (UnimplementedReleaseServiceHandler) ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error) {
408+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.ListReleases is not implemented"))
409+}
410+
411+func (UnimplementedReleaseServiceHandler) UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error) {
412+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UpdateRelease is not implemented"))
413+}
414+
415+func (UnimplementedReleaseServiceHandler) DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error) {
416+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DeleteRelease is not implemented"))
417+}
418+
419+func (UnimplementedReleaseServiceHandler) UploadReleaseAsset(context.Context, *connect.ClientStream[ermite.UploadReleaseAssetRequest]) (*connect.Response[ermite.UploadReleaseAssetResponse], error) {
420+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UploadReleaseAsset is not implemented"))
421+}
422+
423+func (UnimplementedReleaseServiceHandler) UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error) {
424+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UpdateReleaseAsset is not implemented"))
425+}
426+
427+func (UnimplementedReleaseServiceHandler) DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error) {
428+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DeleteReleaseAsset is not implemented"))
429+}
430+
431+func (UnimplementedReleaseServiceHandler) DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest], *connect.ServerStream[ermite.DownloadReleaseAssetResponse]) error {
432+ return connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DownloadReleaseAsset is not implemented"))
433+}
434+
435+func (UnimplementedReleaseServiceHandler) ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error) {
436+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.ListReleaseAssets is not implemented"))
437+}
438+
439+func (UnimplementedReleaseServiceHandler) GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error) {
440+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.GetReleaseUsage is not implemented"))
441+}
@@ -0,0 +1,441 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
4+//
5+// Source: ermite/release.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+ // ReleaseServiceName is the fully-qualified name of the ReleaseService service.
27+ ReleaseServiceName = "ermite.ReleaseService"
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+ // ReleaseServiceCreateReleaseProcedure is the fully-qualified name of the ReleaseService's
39+ // CreateRelease RPC.
40+ ReleaseServiceCreateReleaseProcedure = "/ermite.ReleaseService/CreateRelease"
41+ // ReleaseServiceGetReleaseProcedure is the fully-qualified name of the ReleaseService's GetRelease
42+ // RPC.
43+ ReleaseServiceGetReleaseProcedure = "/ermite.ReleaseService/GetRelease"
44+ // ReleaseServiceListReleasesProcedure is the fully-qualified name of the ReleaseService's
45+ // ListReleases RPC.
46+ ReleaseServiceListReleasesProcedure = "/ermite.ReleaseService/ListReleases"
47+ // ReleaseServiceUpdateReleaseProcedure is the fully-qualified name of the ReleaseService's
48+ // UpdateRelease RPC.
49+ ReleaseServiceUpdateReleaseProcedure = "/ermite.ReleaseService/UpdateRelease"
50+ // ReleaseServiceDeleteReleaseProcedure is the fully-qualified name of the ReleaseService's
51+ // DeleteRelease RPC.
52+ ReleaseServiceDeleteReleaseProcedure = "/ermite.ReleaseService/DeleteRelease"
53+ // ReleaseServiceUploadReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
54+ // UploadReleaseAsset RPC.
55+ ReleaseServiceUploadReleaseAssetProcedure = "/ermite.ReleaseService/UploadReleaseAsset"
56+ // ReleaseServiceUpdateReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
57+ // UpdateReleaseAsset RPC.
58+ ReleaseServiceUpdateReleaseAssetProcedure = "/ermite.ReleaseService/UpdateReleaseAsset"
59+ // ReleaseServiceDeleteReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
60+ // DeleteReleaseAsset RPC.
61+ ReleaseServiceDeleteReleaseAssetProcedure = "/ermite.ReleaseService/DeleteReleaseAsset"
62+ // ReleaseServiceDownloadReleaseAssetProcedure is the fully-qualified name of the ReleaseService's
63+ // DownloadReleaseAsset RPC.
64+ ReleaseServiceDownloadReleaseAssetProcedure = "/ermite.ReleaseService/DownloadReleaseAsset"
65+ // ReleaseServiceListReleaseAssetsProcedure is the fully-qualified name of the ReleaseService's
66+ // ListReleaseAssets RPC.
67+ ReleaseServiceListReleaseAssetsProcedure = "/ermite.ReleaseService/ListReleaseAssets"
68+ // ReleaseServiceGetReleaseUsageProcedure is the fully-qualified name of the ReleaseService's
69+ // GetReleaseUsage RPC.
70+ ReleaseServiceGetReleaseUsageProcedure = "/ermite.ReleaseService/GetReleaseUsage"
71+)
72+
73+// ReleaseServiceClient is a client for the ermite.ReleaseService service.
74+type ReleaseServiceClient interface {
75+ // CreateRelease creates one release per tag (already_exists on duplication).
76+ // Publishing without an existing tag is failed_precondition, unless
77+ // target_commitish is supplied to create it; existing tags never move.
78+ CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error)
79+ // GetRelease selects by id, tag or latest (latest must be true).
80+ GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error)
81+ // ListReleases lists newest first, including drafts only for writers.
82+ ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error)
83+ // UpdateRelease changes masked fields. Publishing requires an existing tag
84+ // or target_commitish to create it; otherwise failed_precondition.
85+ UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error)
86+ // DeleteRelease removes a release and its assets.
87+ DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error)
88+ // UploadReleaseAsset reserves size before reading. The first message carries
89+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
90+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
91+ // asset. A taken name gives already_exists unless replace is true. Uploading
92+ // to a release of another repo gives failed_precondition.
93+ UploadReleaseAsset(context.Context) *connect.ClientStreamForClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse]
94+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
95+ UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error)
96+ // DeleteReleaseAsset removes an asset.
97+ DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error)
98+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
99+ // 1 MiB. Resume with the offset after the last byte received. An offset
100+ // beyond the size gives out_of_range.
101+ DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest]) (*connect.ServerStreamForClient[ermite.DownloadReleaseAssetResponse], error)
102+ // ListReleaseAssets lists uploaded assets, ordered by name.
103+ ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error)
104+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
105+ GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error)
106+}
107+
108+// NewReleaseServiceClient constructs a client for the ermite.ReleaseService service. By default, it
109+// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
110+// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
111+// connect.WithGRPCWeb() options.
112+//
113+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
114+// http://api.acme.com or https://acme.com/grpc).
115+func NewReleaseServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ReleaseServiceClient {
116+ baseURL = strings.TrimRight(baseURL, "/")
117+ releaseServiceMethods := ermite.File_ermite_release_proto.Services().ByName("ReleaseService").Methods()
118+ return &releaseServiceClient{
119+ createRelease: connect.NewClient[ermite.CreateReleaseRequest, ermite.CreateReleaseResponse](
120+ httpClient,
121+ baseURL+ReleaseServiceCreateReleaseProcedure,
122+ connect.WithSchema(releaseServiceMethods.ByName("CreateRelease")),
123+ connect.WithClientOptions(opts...),
124+ ),
125+ getRelease: connect.NewClient[ermite.GetReleaseRequest, ermite.GetReleaseResponse](
126+ httpClient,
127+ baseURL+ReleaseServiceGetReleaseProcedure,
128+ connect.WithSchema(releaseServiceMethods.ByName("GetRelease")),
129+ connect.WithClientOptions(opts...),
130+ ),
131+ listReleases: connect.NewClient[ermite.ListReleasesRequest, ermite.ListReleasesResponse](
132+ httpClient,
133+ baseURL+ReleaseServiceListReleasesProcedure,
134+ connect.WithSchema(releaseServiceMethods.ByName("ListReleases")),
135+ connect.WithClientOptions(opts...),
136+ ),
137+ updateRelease: connect.NewClient[ermite.UpdateReleaseRequest, ermite.UpdateReleaseResponse](
138+ httpClient,
139+ baseURL+ReleaseServiceUpdateReleaseProcedure,
140+ connect.WithSchema(releaseServiceMethods.ByName("UpdateRelease")),
141+ connect.WithClientOptions(opts...),
142+ ),
143+ deleteRelease: connect.NewClient[ermite.DeleteReleaseRequest, ermite.DeleteReleaseResponse](
144+ httpClient,
145+ baseURL+ReleaseServiceDeleteReleaseProcedure,
146+ connect.WithSchema(releaseServiceMethods.ByName("DeleteRelease")),
147+ connect.WithClientOptions(opts...),
148+ ),
149+ uploadReleaseAsset: connect.NewClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse](
150+ httpClient,
151+ baseURL+ReleaseServiceUploadReleaseAssetProcedure,
152+ connect.WithSchema(releaseServiceMethods.ByName("UploadReleaseAsset")),
153+ connect.WithClientOptions(opts...),
154+ ),
155+ updateReleaseAsset: connect.NewClient[ermite.UpdateReleaseAssetRequest, ermite.UpdateReleaseAssetResponse](
156+ httpClient,
157+ baseURL+ReleaseServiceUpdateReleaseAssetProcedure,
158+ connect.WithSchema(releaseServiceMethods.ByName("UpdateReleaseAsset")),
159+ connect.WithClientOptions(opts...),
160+ ),
161+ deleteReleaseAsset: connect.NewClient[ermite.DeleteReleaseAssetRequest, ermite.DeleteReleaseAssetResponse](
162+ httpClient,
163+ baseURL+ReleaseServiceDeleteReleaseAssetProcedure,
164+ connect.WithSchema(releaseServiceMethods.ByName("DeleteReleaseAsset")),
165+ connect.WithClientOptions(opts...),
166+ ),
167+ downloadReleaseAsset: connect.NewClient[ermite.DownloadReleaseAssetRequest, ermite.DownloadReleaseAssetResponse](
168+ httpClient,
169+ baseURL+ReleaseServiceDownloadReleaseAssetProcedure,
170+ connect.WithSchema(releaseServiceMethods.ByName("DownloadReleaseAsset")),
171+ connect.WithClientOptions(opts...),
172+ ),
173+ listReleaseAssets: connect.NewClient[ermite.ListReleaseAssetsRequest, ermite.ListReleaseAssetsResponse](
174+ httpClient,
175+ baseURL+ReleaseServiceListReleaseAssetsProcedure,
176+ connect.WithSchema(releaseServiceMethods.ByName("ListReleaseAssets")),
177+ connect.WithClientOptions(opts...),
178+ ),
179+ getReleaseUsage: connect.NewClient[ermite.GetReleaseUsageRequest, ermite.GetReleaseUsageResponse](
180+ httpClient,
181+ baseURL+ReleaseServiceGetReleaseUsageProcedure,
182+ connect.WithSchema(releaseServiceMethods.ByName("GetReleaseUsage")),
183+ connect.WithClientOptions(opts...),
184+ ),
185+ }
186+}
187+
188+// releaseServiceClient implements ReleaseServiceClient.
189+type releaseServiceClient struct {
190+ createRelease *connect.Client[ermite.CreateReleaseRequest, ermite.CreateReleaseResponse]
191+ getRelease *connect.Client[ermite.GetReleaseRequest, ermite.GetReleaseResponse]
192+ listReleases *connect.Client[ermite.ListReleasesRequest, ermite.ListReleasesResponse]
193+ updateRelease *connect.Client[ermite.UpdateReleaseRequest, ermite.UpdateReleaseResponse]
194+ deleteRelease *connect.Client[ermite.DeleteReleaseRequest, ermite.DeleteReleaseResponse]
195+ uploadReleaseAsset *connect.Client[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse]
196+ updateReleaseAsset *connect.Client[ermite.UpdateReleaseAssetRequest, ermite.UpdateReleaseAssetResponse]
197+ deleteReleaseAsset *connect.Client[ermite.DeleteReleaseAssetRequest, ermite.DeleteReleaseAssetResponse]
198+ downloadReleaseAsset *connect.Client[ermite.DownloadReleaseAssetRequest, ermite.DownloadReleaseAssetResponse]
199+ listReleaseAssets *connect.Client[ermite.ListReleaseAssetsRequest, ermite.ListReleaseAssetsResponse]
200+ getReleaseUsage *connect.Client[ermite.GetReleaseUsageRequest, ermite.GetReleaseUsageResponse]
201+}
202+
203+// CreateRelease calls ermite.ReleaseService.CreateRelease.
204+func (c *releaseServiceClient) CreateRelease(ctx context.Context, req *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error) {
205+ return c.createRelease.CallUnary(ctx, req)
206+}
207+
208+// GetRelease calls ermite.ReleaseService.GetRelease.
209+func (c *releaseServiceClient) GetRelease(ctx context.Context, req *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error) {
210+ return c.getRelease.CallUnary(ctx, req)
211+}
212+
213+// ListReleases calls ermite.ReleaseService.ListReleases.
214+func (c *releaseServiceClient) ListReleases(ctx context.Context, req *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error) {
215+ return c.listReleases.CallUnary(ctx, req)
216+}
217+
218+// UpdateRelease calls ermite.ReleaseService.UpdateRelease.
219+func (c *releaseServiceClient) UpdateRelease(ctx context.Context, req *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error) {
220+ return c.updateRelease.CallUnary(ctx, req)
221+}
222+
223+// DeleteRelease calls ermite.ReleaseService.DeleteRelease.
224+func (c *releaseServiceClient) DeleteRelease(ctx context.Context, req *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error) {
225+ return c.deleteRelease.CallUnary(ctx, req)
226+}
227+
228+// UploadReleaseAsset calls ermite.ReleaseService.UploadReleaseAsset.
229+func (c *releaseServiceClient) UploadReleaseAsset(ctx context.Context) *connect.ClientStreamForClient[ermite.UploadReleaseAssetRequest, ermite.UploadReleaseAssetResponse] {
230+ return c.uploadReleaseAsset.CallClientStream(ctx)
231+}
232+
233+// UpdateReleaseAsset calls ermite.ReleaseService.UpdateReleaseAsset.
234+func (c *releaseServiceClient) UpdateReleaseAsset(ctx context.Context, req *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error) {
235+ return c.updateReleaseAsset.CallUnary(ctx, req)
236+}
237+
238+// DeleteReleaseAsset calls ermite.ReleaseService.DeleteReleaseAsset.
239+func (c *releaseServiceClient) DeleteReleaseAsset(ctx context.Context, req *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error) {
240+ return c.deleteReleaseAsset.CallUnary(ctx, req)
241+}
242+
243+// DownloadReleaseAsset calls ermite.ReleaseService.DownloadReleaseAsset.
244+func (c *releaseServiceClient) DownloadReleaseAsset(ctx context.Context, req *connect.Request[ermite.DownloadReleaseAssetRequest]) (*connect.ServerStreamForClient[ermite.DownloadReleaseAssetResponse], error) {
245+ return c.downloadReleaseAsset.CallServerStream(ctx, req)
246+}
247+
248+// ListReleaseAssets calls ermite.ReleaseService.ListReleaseAssets.
249+func (c *releaseServiceClient) ListReleaseAssets(ctx context.Context, req *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error) {
250+ return c.listReleaseAssets.CallUnary(ctx, req)
251+}
252+
253+// GetReleaseUsage calls ermite.ReleaseService.GetReleaseUsage.
254+func (c *releaseServiceClient) GetReleaseUsage(ctx context.Context, req *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error) {
255+ return c.getReleaseUsage.CallUnary(ctx, req)
256+}
257+
258+// ReleaseServiceHandler is an implementation of the ermite.ReleaseService service.
259+type ReleaseServiceHandler interface {
260+ // CreateRelease creates one release per tag (already_exists on duplication).
261+ // Publishing without an existing tag is failed_precondition, unless
262+ // target_commitish is supplied to create it; existing tags never move.
263+ CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error)
264+ // GetRelease selects by id, tag or latest (latest must be true).
265+ GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error)
266+ // ListReleases lists newest first, including drafts only for writers.
267+ ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error)
268+ // UpdateRelease changes masked fields. Publishing requires an existing tag
269+ // or target_commitish to create it; otherwise failed_precondition.
270+ UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error)
271+ // DeleteRelease removes a release and its assets.
272+ DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error)
273+ // UploadReleaseAsset reserves size before reading. The first message carries
274+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
275+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
276+ // asset. A taken name gives already_exists unless replace is true. Uploading
277+ // to a release of another repo gives failed_precondition.
278+ UploadReleaseAsset(context.Context, *connect.ClientStream[ermite.UploadReleaseAssetRequest]) (*connect.Response[ermite.UploadReleaseAssetResponse], error)
279+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
280+ UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error)
281+ // DeleteReleaseAsset removes an asset.
282+ DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error)
283+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
284+ // 1 MiB. Resume with the offset after the last byte received. An offset
285+ // beyond the size gives out_of_range.
286+ DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest], *connect.ServerStream[ermite.DownloadReleaseAssetResponse]) error
287+ // ListReleaseAssets lists uploaded assets, ordered by name.
288+ ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error)
289+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
290+ GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error)
291+}
292+
293+// NewReleaseServiceHandler builds an HTTP handler from the service implementation. It returns the
294+// path on which to mount the handler and the handler itself.
295+//
296+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
297+// and JSON codecs. They also support gzip compression.
298+func NewReleaseServiceHandler(svc ReleaseServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
299+ releaseServiceMethods := ermite.File_ermite_release_proto.Services().ByName("ReleaseService").Methods()
300+ releaseServiceCreateReleaseHandler := connect.NewUnaryHandler(
301+ ReleaseServiceCreateReleaseProcedure,
302+ svc.CreateRelease,
303+ connect.WithSchema(releaseServiceMethods.ByName("CreateRelease")),
304+ connect.WithHandlerOptions(opts...),
305+ )
306+ releaseServiceGetReleaseHandler := connect.NewUnaryHandler(
307+ ReleaseServiceGetReleaseProcedure,
308+ svc.GetRelease,
309+ connect.WithSchema(releaseServiceMethods.ByName("GetRelease")),
310+ connect.WithHandlerOptions(opts...),
311+ )
312+ releaseServiceListReleasesHandler := connect.NewUnaryHandler(
313+ ReleaseServiceListReleasesProcedure,
314+ svc.ListReleases,
315+ connect.WithSchema(releaseServiceMethods.ByName("ListReleases")),
316+ connect.WithHandlerOptions(opts...),
317+ )
318+ releaseServiceUpdateReleaseHandler := connect.NewUnaryHandler(
319+ ReleaseServiceUpdateReleaseProcedure,
320+ svc.UpdateRelease,
321+ connect.WithSchema(releaseServiceMethods.ByName("UpdateRelease")),
322+ connect.WithHandlerOptions(opts...),
323+ )
324+ releaseServiceDeleteReleaseHandler := connect.NewUnaryHandler(
325+ ReleaseServiceDeleteReleaseProcedure,
326+ svc.DeleteRelease,
327+ connect.WithSchema(releaseServiceMethods.ByName("DeleteRelease")),
328+ connect.WithHandlerOptions(opts...),
329+ )
330+ releaseServiceUploadReleaseAssetHandler := connect.NewClientStreamHandler(
331+ ReleaseServiceUploadReleaseAssetProcedure,
332+ svc.UploadReleaseAsset,
333+ connect.WithSchema(releaseServiceMethods.ByName("UploadReleaseAsset")),
334+ connect.WithHandlerOptions(opts...),
335+ )
336+ releaseServiceUpdateReleaseAssetHandler := connect.NewUnaryHandler(
337+ ReleaseServiceUpdateReleaseAssetProcedure,
338+ svc.UpdateReleaseAsset,
339+ connect.WithSchema(releaseServiceMethods.ByName("UpdateReleaseAsset")),
340+ connect.WithHandlerOptions(opts...),
341+ )
342+ releaseServiceDeleteReleaseAssetHandler := connect.NewUnaryHandler(
343+ ReleaseServiceDeleteReleaseAssetProcedure,
344+ svc.DeleteReleaseAsset,
345+ connect.WithSchema(releaseServiceMethods.ByName("DeleteReleaseAsset")),
346+ connect.WithHandlerOptions(opts...),
347+ )
348+ releaseServiceDownloadReleaseAssetHandler := connect.NewServerStreamHandler(
349+ ReleaseServiceDownloadReleaseAssetProcedure,
350+ svc.DownloadReleaseAsset,
351+ connect.WithSchema(releaseServiceMethods.ByName("DownloadReleaseAsset")),
352+ connect.WithHandlerOptions(opts...),
353+ )
354+ releaseServiceListReleaseAssetsHandler := connect.NewUnaryHandler(
355+ ReleaseServiceListReleaseAssetsProcedure,
356+ svc.ListReleaseAssets,
357+ connect.WithSchema(releaseServiceMethods.ByName("ListReleaseAssets")),
358+ connect.WithHandlerOptions(opts...),
359+ )
360+ releaseServiceGetReleaseUsageHandler := connect.NewUnaryHandler(
361+ ReleaseServiceGetReleaseUsageProcedure,
362+ svc.GetReleaseUsage,
363+ connect.WithSchema(releaseServiceMethods.ByName("GetReleaseUsage")),
364+ connect.WithHandlerOptions(opts...),
365+ )
366+ return "/ermite.ReleaseService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
367+ switch r.URL.Path {
368+ case ReleaseServiceCreateReleaseProcedure:
369+ releaseServiceCreateReleaseHandler.ServeHTTP(w, r)
370+ case ReleaseServiceGetReleaseProcedure:
371+ releaseServiceGetReleaseHandler.ServeHTTP(w, r)
372+ case ReleaseServiceListReleasesProcedure:
373+ releaseServiceListReleasesHandler.ServeHTTP(w, r)
374+ case ReleaseServiceUpdateReleaseProcedure:
375+ releaseServiceUpdateReleaseHandler.ServeHTTP(w, r)
376+ case ReleaseServiceDeleteReleaseProcedure:
377+ releaseServiceDeleteReleaseHandler.ServeHTTP(w, r)
378+ case ReleaseServiceUploadReleaseAssetProcedure:
379+ releaseServiceUploadReleaseAssetHandler.ServeHTTP(w, r)
380+ case ReleaseServiceUpdateReleaseAssetProcedure:
381+ releaseServiceUpdateReleaseAssetHandler.ServeHTTP(w, r)
382+ case ReleaseServiceDeleteReleaseAssetProcedure:
383+ releaseServiceDeleteReleaseAssetHandler.ServeHTTP(w, r)
384+ case ReleaseServiceDownloadReleaseAssetProcedure:
385+ releaseServiceDownloadReleaseAssetHandler.ServeHTTP(w, r)
386+ case ReleaseServiceListReleaseAssetsProcedure:
387+ releaseServiceListReleaseAssetsHandler.ServeHTTP(w, r)
388+ case ReleaseServiceGetReleaseUsageProcedure:
389+ releaseServiceGetReleaseUsageHandler.ServeHTTP(w, r)
390+ default:
391+ http.NotFound(w, r)
392+ }
393+ })
394+}
395+
396+// UnimplementedReleaseServiceHandler returns CodeUnimplemented from all methods.
397+type UnimplementedReleaseServiceHandler struct{}
398+
399+func (UnimplementedReleaseServiceHandler) CreateRelease(context.Context, *connect.Request[ermite.CreateReleaseRequest]) (*connect.Response[ermite.CreateReleaseResponse], error) {
400+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.CreateRelease is not implemented"))
401+}
402+
403+func (UnimplementedReleaseServiceHandler) GetRelease(context.Context, *connect.Request[ermite.GetReleaseRequest]) (*connect.Response[ermite.GetReleaseResponse], error) {
404+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.GetRelease is not implemented"))
405+}
406+
407+func (UnimplementedReleaseServiceHandler) ListReleases(context.Context, *connect.Request[ermite.ListReleasesRequest]) (*connect.Response[ermite.ListReleasesResponse], error) {
408+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.ListReleases is not implemented"))
409+}
410+
411+func (UnimplementedReleaseServiceHandler) UpdateRelease(context.Context, *connect.Request[ermite.UpdateReleaseRequest]) (*connect.Response[ermite.UpdateReleaseResponse], error) {
412+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UpdateRelease is not implemented"))
413+}
414+
415+func (UnimplementedReleaseServiceHandler) DeleteRelease(context.Context, *connect.Request[ermite.DeleteReleaseRequest]) (*connect.Response[ermite.DeleteReleaseResponse], error) {
416+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DeleteRelease is not implemented"))
417+}
418+
419+func (UnimplementedReleaseServiceHandler) UploadReleaseAsset(context.Context, *connect.ClientStream[ermite.UploadReleaseAssetRequest]) (*connect.Response[ermite.UploadReleaseAssetResponse], error) {
420+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UploadReleaseAsset is not implemented"))
421+}
422+
423+func (UnimplementedReleaseServiceHandler) UpdateReleaseAsset(context.Context, *connect.Request[ermite.UpdateReleaseAssetRequest]) (*connect.Response[ermite.UpdateReleaseAssetResponse], error) {
424+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.UpdateReleaseAsset is not implemented"))
425+}
426+
427+func (UnimplementedReleaseServiceHandler) DeleteReleaseAsset(context.Context, *connect.Request[ermite.DeleteReleaseAssetRequest]) (*connect.Response[ermite.DeleteReleaseAssetResponse], error) {
428+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DeleteReleaseAsset is not implemented"))
429+}
430+
431+func (UnimplementedReleaseServiceHandler) DownloadReleaseAsset(context.Context, *connect.Request[ermite.DownloadReleaseAssetRequest], *connect.ServerStream[ermite.DownloadReleaseAssetResponse]) error {
432+ return connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.DownloadReleaseAsset is not implemented"))
433+}
434+
435+func (UnimplementedReleaseServiceHandler) ListReleaseAssets(context.Context, *connect.Request[ermite.ListReleaseAssetsRequest]) (*connect.Response[ermite.ListReleaseAssetsResponse], error) {
436+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.ListReleaseAssets is not implemented"))
437+}
438+
439+func (UnimplementedReleaseServiceHandler) GetReleaseUsage(context.Context, *connect.Request[ermite.GetReleaseUsageRequest]) (*connect.Response[ermite.GetReleaseUsageResponse], error) {
440+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.ReleaseService.GetReleaseUsage is not implemented"))
441+}
M gen/ermite/event.pb.go +447 -43
@@ -175,6 +175,10 @@ type Event struct {
175175 // *Event_MirrorRecovered
176176 // *Event_MergeRequestAutoMergeEnabled
177177 // *Event_MergeRequestAutoMergeCancelled
178+ // *Event_ReleasePublished
179+ // *Event_ReleaseUpdated
180+ // *Event_ReleaseDeleted
181+ // *Event_ReleaseUnpublished
178182 Kind isEvent_Kind `protobuf_oneof:"kind"`
179183 unknownFields protoimpl.UnknownFields
180184 sizeCache protoimpl.SizeCache
@@ -447,6 +451,42 @@ func (x *Event) GetMergeRequestAutoMergeCancelled() *MergeRequestAutoMergeCancel
447451 return nil
448452 }
449453
454+func (x *Event) GetReleasePublished() *ReleasePublished {
455+ if x != nil {
456+ if x, ok := x.Kind.(*Event_ReleasePublished); ok {
457+ return x.ReleasePublished
458+ }
459+ }
460+ return nil
461+}
462+
463+func (x *Event) GetReleaseUpdated() *ReleaseUpdated {
464+ if x != nil {
465+ if x, ok := x.Kind.(*Event_ReleaseUpdated); ok {
466+ return x.ReleaseUpdated
467+ }
468+ }
469+ return nil
470+}
471+
472+func (x *Event) GetReleaseDeleted() *ReleaseDeleted {
473+ if x != nil {
474+ if x, ok := x.Kind.(*Event_ReleaseDeleted); ok {
475+ return x.ReleaseDeleted
476+ }
477+ }
478+ return nil
479+}
480+
481+func (x *Event) GetReleaseUnpublished() *ReleaseUnpublished {
482+ if x != nil {
483+ if x, ok := x.Kind.(*Event_ReleaseUnpublished); ok {
484+ return x.ReleaseUnpublished
485+ }
486+ }
487+ return nil
488+}
489+
450490 type isEvent_Kind interface {
451491 isEvent_Kind()
452492 }
@@ -574,6 +614,26 @@ type Event_MergeRequestAutoMergeCancelled struct {
574614 MergeRequestAutoMergeCancelled *MergeRequestAutoMergeCancelled `protobuf:"bytes,26,opt,name=merge_request_auto_merge_cancelled,json=mergeRequestAutoMergeCancelled,proto3,oneof"`
575615 }
576616
617+type Event_ReleasePublished struct {
618+ // ReleasePublished reports a release published.
619+ ReleasePublished *ReleasePublished `protobuf:"bytes,27,opt,name=release_published,json=releasePublished,proto3,oneof"`
620+}
621+
622+type Event_ReleaseUpdated struct {
623+ // ReleaseUpdated reports a release updated.
624+ ReleaseUpdated *ReleaseUpdated `protobuf:"bytes,28,opt,name=release_updated,json=releaseUpdated,proto3,oneof"`
625+}
626+
627+type Event_ReleaseDeleted struct {
628+ // ReleaseDeleted reports a release deleted.
629+ ReleaseDeleted *ReleaseDeleted `protobuf:"bytes,29,opt,name=release_deleted,json=releaseDeleted,proto3,oneof"`
630+}
631+
632+type Event_ReleaseUnpublished struct {
633+ // ReleaseUnpublished reports a release turned into a draft after tag deletion.
634+ ReleaseUnpublished *ReleaseUnpublished `protobuf:"bytes,30,opt,name=release_unpublished,json=releaseUnpublished,proto3,oneof"`
635+}
636+
577637 func (*Event_RepoCreated) isEvent_Kind() {}
578638
579639 func (*Event_RepoUpdated) isEvent_Kind() {}
@@ -622,6 +682,14 @@ func (*Event_MergeRequestAutoMergeEnabled) isEvent_Kind() {}
622682
623683 func (*Event_MergeRequestAutoMergeCancelled) isEvent_Kind() {}
624684
685+func (*Event_ReleasePublished) isEvent_Kind() {}
686+
687+func (*Event_ReleaseUpdated) isEvent_Kind() {}
688+
689+func (*Event_ReleaseDeleted) isEvent_Kind() {}
690+
691+func (*Event_ReleaseUnpublished) isEvent_Kind() {}
692+
625693 // RepoCreated reports a new repository.
626694 type RepoCreated struct {
627695 state protoimpl.MessageState `protogen:"open.v1"`
@@ -1964,6 +2032,298 @@ func (x *MirrorRecovered) GetRepo() string {
19642032 return ""
19652033 }
19662034
2035+// ReleasePublished reports a release change on repo:<name> and home topics.
2036+type ReleasePublished struct {
2037+ state protoimpl.MessageState `protogen:"open.v1"`
2038+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2039+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2040+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2041+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2042+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2043+ unknownFields protoimpl.UnknownFields
2044+ sizeCache protoimpl.SizeCache
2045+}
2046+
2047+func (x *ReleasePublished) Reset() {
2048+ *x = ReleasePublished{}
2049+ mi := &file_ermite_event_proto_msgTypes[28]
2050+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2051+ ms.StoreMessageInfo(mi)
2052+}
2053+
2054+func (x *ReleasePublished) String() string {
2055+ return protoimpl.X.MessageStringOf(x)
2056+}
2057+
2058+func (*ReleasePublished) ProtoMessage() {}
2059+
2060+func (x *ReleasePublished) ProtoReflect() protoreflect.Message {
2061+ mi := &file_ermite_event_proto_msgTypes[28]
2062+ if x != nil {
2063+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2064+ if ms.LoadMessageInfo() == nil {
2065+ ms.StoreMessageInfo(mi)
2066+ }
2067+ return ms
2068+ }
2069+ return mi.MessageOf(x)
2070+}
2071+
2072+// Deprecated: Use ReleasePublished.ProtoReflect.Descriptor instead.
2073+func (*ReleasePublished) Descriptor() ([]byte, []int) {
2074+ return file_ermite_event_proto_rawDescGZIP(), []int{28}
2075+}
2076+
2077+func (x *ReleasePublished) GetRepo() string {
2078+ if x != nil {
2079+ return x.Repo
2080+ }
2081+ return ""
2082+}
2083+
2084+func (x *ReleasePublished) GetId() int64 {
2085+ if x != nil {
2086+ return x.Id
2087+ }
2088+ return 0
2089+}
2090+
2091+func (x *ReleasePublished) GetTag() string {
2092+ if x != nil {
2093+ return x.Tag
2094+ }
2095+ return ""
2096+}
2097+
2098+func (x *ReleasePublished) GetDraft() bool {
2099+ if x != nil {
2100+ return x.Draft
2101+ }
2102+ return false
2103+}
2104+
2105+func (x *ReleasePublished) GetPrerelease() bool {
2106+ if x != nil {
2107+ return x.Prerelease
2108+ }
2109+ return false
2110+}
2111+
2112+// ReleaseUpdated reports a release change on repo:<name> and home topics.
2113+type ReleaseUpdated struct {
2114+ state protoimpl.MessageState `protogen:"open.v1"`
2115+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2116+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2117+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2118+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2119+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2120+ unknownFields protoimpl.UnknownFields
2121+ sizeCache protoimpl.SizeCache
2122+}
2123+
2124+func (x *ReleaseUpdated) Reset() {
2125+ *x = ReleaseUpdated{}
2126+ mi := &file_ermite_event_proto_msgTypes[29]
2127+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2128+ ms.StoreMessageInfo(mi)
2129+}
2130+
2131+func (x *ReleaseUpdated) String() string {
2132+ return protoimpl.X.MessageStringOf(x)
2133+}
2134+
2135+func (*ReleaseUpdated) ProtoMessage() {}
2136+
2137+func (x *ReleaseUpdated) ProtoReflect() protoreflect.Message {
2138+ mi := &file_ermite_event_proto_msgTypes[29]
2139+ if x != nil {
2140+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2141+ if ms.LoadMessageInfo() == nil {
2142+ ms.StoreMessageInfo(mi)
2143+ }
2144+ return ms
2145+ }
2146+ return mi.MessageOf(x)
2147+}
2148+
2149+// Deprecated: Use ReleaseUpdated.ProtoReflect.Descriptor instead.
2150+func (*ReleaseUpdated) Descriptor() ([]byte, []int) {
2151+ return file_ermite_event_proto_rawDescGZIP(), []int{29}
2152+}
2153+
2154+func (x *ReleaseUpdated) GetRepo() string {
2155+ if x != nil {
2156+ return x.Repo
2157+ }
2158+ return ""
2159+}
2160+
2161+func (x *ReleaseUpdated) GetId() int64 {
2162+ if x != nil {
2163+ return x.Id
2164+ }
2165+ return 0
2166+}
2167+
2168+func (x *ReleaseUpdated) GetTag() string {
2169+ if x != nil {
2170+ return x.Tag
2171+ }
2172+ return ""
2173+}
2174+
2175+func (x *ReleaseUpdated) GetDraft() bool {
2176+ if x != nil {
2177+ return x.Draft
2178+ }
2179+ return false
2180+}
2181+
2182+func (x *ReleaseUpdated) GetPrerelease() bool {
2183+ if x != nil {
2184+ return x.Prerelease
2185+ }
2186+ return false
2187+}
2188+
2189+// ReleaseDeleted reports a release change on repo:<name> and home topics.
2190+type ReleaseDeleted struct {
2191+ state protoimpl.MessageState `protogen:"open.v1"`
2192+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2193+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2194+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2195+ unknownFields protoimpl.UnknownFields
2196+ sizeCache protoimpl.SizeCache
2197+}
2198+
2199+func (x *ReleaseDeleted) Reset() {
2200+ *x = ReleaseDeleted{}
2201+ mi := &file_ermite_event_proto_msgTypes[30]
2202+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2203+ ms.StoreMessageInfo(mi)
2204+}
2205+
2206+func (x *ReleaseDeleted) String() string {
2207+ return protoimpl.X.MessageStringOf(x)
2208+}
2209+
2210+func (*ReleaseDeleted) ProtoMessage() {}
2211+
2212+func (x *ReleaseDeleted) ProtoReflect() protoreflect.Message {
2213+ mi := &file_ermite_event_proto_msgTypes[30]
2214+ if x != nil {
2215+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2216+ if ms.LoadMessageInfo() == nil {
2217+ ms.StoreMessageInfo(mi)
2218+ }
2219+ return ms
2220+ }
2221+ return mi.MessageOf(x)
2222+}
2223+
2224+// Deprecated: Use ReleaseDeleted.ProtoReflect.Descriptor instead.
2225+func (*ReleaseDeleted) Descriptor() ([]byte, []int) {
2226+ return file_ermite_event_proto_rawDescGZIP(), []int{30}
2227+}
2228+
2229+func (x *ReleaseDeleted) GetRepo() string {
2230+ if x != nil {
2231+ return x.Repo
2232+ }
2233+ return ""
2234+}
2235+
2236+func (x *ReleaseDeleted) GetId() int64 {
2237+ if x != nil {
2238+ return x.Id
2239+ }
2240+ return 0
2241+}
2242+
2243+func (x *ReleaseDeleted) GetTag() string {
2244+ if x != nil {
2245+ return x.Tag
2246+ }
2247+ return ""
2248+}
2249+
2250+// ReleaseUnpublished reports a release change on repo:<name> and home topics.
2251+type ReleaseUnpublished struct {
2252+ state protoimpl.MessageState `protogen:"open.v1"`
2253+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2254+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2255+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2256+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2257+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2258+ unknownFields protoimpl.UnknownFields
2259+ sizeCache protoimpl.SizeCache
2260+}
2261+
2262+func (x *ReleaseUnpublished) Reset() {
2263+ *x = ReleaseUnpublished{}
2264+ mi := &file_ermite_event_proto_msgTypes[31]
2265+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2266+ ms.StoreMessageInfo(mi)
2267+}
2268+
2269+func (x *ReleaseUnpublished) String() string {
2270+ return protoimpl.X.MessageStringOf(x)
2271+}
2272+
2273+func (*ReleaseUnpublished) ProtoMessage() {}
2274+
2275+func (x *ReleaseUnpublished) ProtoReflect() protoreflect.Message {
2276+ mi := &file_ermite_event_proto_msgTypes[31]
2277+ if x != nil {
2278+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2279+ if ms.LoadMessageInfo() == nil {
2280+ ms.StoreMessageInfo(mi)
2281+ }
2282+ return ms
2283+ }
2284+ return mi.MessageOf(x)
2285+}
2286+
2287+// Deprecated: Use ReleaseUnpublished.ProtoReflect.Descriptor instead.
2288+func (*ReleaseUnpublished) Descriptor() ([]byte, []int) {
2289+ return file_ermite_event_proto_rawDescGZIP(), []int{31}
2290+}
2291+
2292+func (x *ReleaseUnpublished) GetRepo() string {
2293+ if x != nil {
2294+ return x.Repo
2295+ }
2296+ return ""
2297+}
2298+
2299+func (x *ReleaseUnpublished) GetId() int64 {
2300+ if x != nil {
2301+ return x.Id
2302+ }
2303+ return 0
2304+}
2305+
2306+func (x *ReleaseUnpublished) GetTag() string {
2307+ if x != nil {
2308+ return x.Tag
2309+ }
2310+ return ""
2311+}
2312+
2313+func (x *ReleaseUnpublished) GetDraft() bool {
2314+ if x != nil {
2315+ return x.Draft
2316+ }
2317+ return false
2318+}
2319+
2320+func (x *ReleaseUnpublished) GetPrerelease() bool {
2321+ if x != nil {
2322+ return x.Prerelease
2323+ }
2324+ return false
2325+}
2326+
19672327 var File_ermite_event_proto protoreflect.FileDescriptor
19682328
19692329 const file_ermite_event_proto_rawDesc = "" +
@@ -1973,7 +2333,7 @@ const file_ermite_event_proto_rawDesc = "" +
19732333 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +
19742334 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +
19752335 "\rWatchResponse\x12#\n" +
1976- "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xb1\r\n" +
2336+ "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xcf\x0f\n" +
19772337 "\x05Event\x12\x0e\n" +
19782338 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +
19792339 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +
@@ -2003,7 +2363,11 @@ const file_ermite_event_proto_rawDesc = "" +
20032363 "\rmirror_failed\x18\x17 \x01(\v2\x14.ermite.MirrorFailedH\x00R\fmirrorFailed\x12D\n" +
20042364 "\x10mirror_recovered\x18\x18 \x01(\v2\x17.ermite.MirrorRecoveredH\x00R\x0fmirrorRecovered\x12n\n" +
20052365 " merge_request_auto_merge_enabled\x18\x19 \x01(\v2$.ermite.MergeRequestAutoMergeEnabledH\x00R\x1cmergeRequestAutoMergeEnabled\x12t\n" +
2006- "\"merge_request_auto_merge_cancelled\x18\x1a \x01(\v2&.ermite.MergeRequestAutoMergeCancelledH\x00R\x1emergeRequestAutoMergeCancelledB\x06\n" +
2366+ "\"merge_request_auto_merge_cancelled\x18\x1a \x01(\v2&.ermite.MergeRequestAutoMergeCancelledH\x00R\x1emergeRequestAutoMergeCancelled\x12G\n" +
2367+ "\x11release_published\x18\x1b \x01(\v2\x18.ermite.ReleasePublishedH\x00R\x10releasePublished\x12A\n" +
2368+ "\x0frelease_updated\x18\x1c \x01(\v2\x16.ermite.ReleaseUpdatedH\x00R\x0ereleaseUpdated\x12A\n" +
2369+ "\x0frelease_deleted\x18\x1d \x01(\v2\x16.ermite.ReleaseDeletedH\x00R\x0ereleaseDeleted\x12M\n" +
2370+ "\x13release_unpublished\x18\x1e \x01(\v2\x1a.ermite.ReleaseUnpublishedH\x00R\x12releaseUnpublishedB\x06\n" +
20072371 "\x04kind\"/\n" +
20082372 "\vRepoCreated\x12 \n" +
20092373 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +
@@ -2076,7 +2440,35 @@ const file_ermite_event_proto_rawDesc = "" +
20762440 "\x05state\x18\x02 \x01(\x0e2\x13.ermite.MirrorStateR\x05state\x12#\n" +
20772441 "\rfailure_class\x18\x03 \x01(\tR\ffailureClassJ\x04\b\x04\x10\x05R\x06reason\"%\n" +
20782442 "\x0fMirrorRecovered\x12\x12\n" +
2079- "\x04repo\x18\x01 \x01(\tR\x04repo2F\n" +
2443+ "\x04repo\x18\x01 \x01(\tR\x04repo\"~\n" +
2444+ "\x10ReleasePublished\x12\x12\n" +
2445+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2446+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2447+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2448+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2449+ "\n" +
2450+ "prerelease\x18\x05 \x01(\bR\n" +
2451+ "prerelease\"|\n" +
2452+ "\x0eReleaseUpdated\x12\x12\n" +
2453+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2454+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2455+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2456+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2457+ "\n" +
2458+ "prerelease\x18\x05 \x01(\bR\n" +
2459+ "prerelease\"F\n" +
2460+ "\x0eReleaseDeleted\x12\x12\n" +
2461+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2462+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2463+ "\x03tag\x18\x03 \x01(\tR\x03tag\"\x80\x01\n" +
2464+ "\x12ReleaseUnpublished\x12\x12\n" +
2465+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2466+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2467+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2468+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2469+ "\n" +
2470+ "prerelease\x18\x05 \x01(\bR\n" +
2471+ "prerelease2F\n" +
20802472 "\fEventService\x126\n" +
20812473 "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" +
20822474 "\n" +
@@ -2095,7 +2487,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte {
20952487 return file_ermite_event_proto_rawDescData
20962488 }
20972489
2098-var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
2490+var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 32)
20992491 var file_ermite_event_proto_goTypes = []any{
21002492 (*WatchRequest)(nil), // 0: ermite.WatchRequest
21012493 (*WatchResponse)(nil), // 1: ermite.WatchResponse
@@ -2125,20 +2517,24 @@ var file_ermite_event_proto_goTypes = []any{
21252517 (*JobUpdated)(nil), // 25: ermite.JobUpdated
21262518 (*MirrorFailed)(nil), // 26: ermite.MirrorFailed
21272519 (*MirrorRecovered)(nil), // 27: ermite.MirrorRecovered
2128- (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp
2129- (*Repo)(nil), // 29: ermite.Repo
2130- (*MergeRequest)(nil), // 30: ermite.MergeRequest
2131- (*Mergeability)(nil), // 31: ermite.Mergeability
2132- (*Comment)(nil), // 32: ermite.Comment
2133- (*Issue)(nil), // 33: ermite.Issue
2134- (*IssueComment)(nil), // 34: ermite.IssueComment
2135- (*Run)(nil), // 35: ermite.Run
2136- (*RunJob)(nil), // 36: ermite.RunJob
2137- (MirrorState)(0), // 37: ermite.MirrorState
2520+ (*ReleasePublished)(nil), // 28: ermite.ReleasePublished
2521+ (*ReleaseUpdated)(nil), // 29: ermite.ReleaseUpdated
2522+ (*ReleaseDeleted)(nil), // 30: ermite.ReleaseDeleted
2523+ (*ReleaseUnpublished)(nil), // 31: ermite.ReleaseUnpublished
2524+ (*timestamppb.Timestamp)(nil), // 32: google.protobuf.Timestamp
2525+ (*Repo)(nil), // 33: ermite.Repo
2526+ (*MergeRequest)(nil), // 34: ermite.MergeRequest
2527+ (*Mergeability)(nil), // 35: ermite.Mergeability
2528+ (*Comment)(nil), // 36: ermite.Comment
2529+ (*Issue)(nil), // 37: ermite.Issue
2530+ (*IssueComment)(nil), // 38: ermite.IssueComment
2531+ (*Run)(nil), // 39: ermite.Run
2532+ (*RunJob)(nil), // 40: ermite.RunJob
2533+ (MirrorState)(0), // 41: ermite.MirrorState
21382534 }
21392535 var file_ermite_event_proto_depIdxs = []int32{
21402536 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event
2141- 28, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
2537+ 32, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
21422538 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated
21432539 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated
21442540 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted
@@ -2163,33 +2559,37 @@ var file_ermite_event_proto_depIdxs = []int32{
21632559 27, // 23: ermite.Event.mirror_recovered:type_name -> ermite.MirrorRecovered
21642560 10, // 24: ermite.Event.merge_request_auto_merge_enabled:type_name -> ermite.MergeRequestAutoMergeEnabled
21652561 11, // 25: ermite.Event.merge_request_auto_merge_cancelled:type_name -> ermite.MergeRequestAutoMergeCancelled
2166- 29, // 26: ermite.RepoCreated.repo:type_name -> ermite.Repo
2167- 29, // 27: ermite.RepoUpdated.repo:type_name -> ermite.Repo
2168- 7, // 28: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
2169- 30, // 29: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
2170- 30, // 30: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
2171- 30, // 31: ermite.MergeRequestAutoMergeEnabled.merge_request:type_name -> ermite.MergeRequest
2172- 30, // 32: ermite.MergeRequestAutoMergeCancelled.merge_request:type_name -> ermite.MergeRequest
2173- 31, // 33: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability
2174- 30, // 34: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
2175- 32, // 35: ermite.CommentAdded.comment:type_name -> ermite.Comment
2176- 32, // 36: ermite.CommentEdited.comment:type_name -> ermite.Comment
2177- 32, // 37: ermite.CommentDeleted.comment:type_name -> ermite.Comment
2178- 32, // 38: ermite.CommentResolved.comment:type_name -> ermite.Comment
2179- 33, // 39: ermite.IssueOpened.issue:type_name -> ermite.Issue
2180- 33, // 40: ermite.IssueClosed.issue:type_name -> ermite.Issue
2181- 33, // 41: ermite.IssueReopened.issue:type_name -> ermite.Issue
2182- 34, // 42: ermite.IssueCommented.comment:type_name -> ermite.IssueComment
2183- 35, // 43: ermite.RunUpdated.run:type_name -> ermite.Run
2184- 36, // 44: ermite.JobUpdated.job:type_name -> ermite.RunJob
2185- 37, // 45: ermite.MirrorFailed.state:type_name -> ermite.MirrorState
2186- 0, // 46: ermite.EventService.Watch:input_type -> ermite.WatchRequest
2187- 1, // 47: ermite.EventService.Watch:output_type -> ermite.WatchResponse
2188- 47, // [47:48] is the sub-list for method output_type
2189- 46, // [46:47] is the sub-list for method input_type
2190- 46, // [46:46] is the sub-list for extension type_name
2191- 46, // [46:46] is the sub-list for extension extendee
2192- 0, // [0:46] is the sub-list for field type_name
2562+ 28, // 26: ermite.Event.release_published:type_name -> ermite.ReleasePublished
2563+ 29, // 27: ermite.Event.release_updated:type_name -> ermite.ReleaseUpdated
2564+ 30, // 28: ermite.Event.release_deleted:type_name -> ermite.ReleaseDeleted
2565+ 31, // 29: ermite.Event.release_unpublished:type_name -> ermite.ReleaseUnpublished
2566+ 33, // 30: ermite.RepoCreated.repo:type_name -> ermite.Repo
2567+ 33, // 31: ermite.RepoUpdated.repo:type_name -> ermite.Repo
2568+ 7, // 32: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
2569+ 34, // 33: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
2570+ 34, // 34: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
2571+ 34, // 35: ermite.MergeRequestAutoMergeEnabled.merge_request:type_name -> ermite.MergeRequest
2572+ 34, // 36: ermite.MergeRequestAutoMergeCancelled.merge_request:type_name -> ermite.MergeRequest
2573+ 35, // 37: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability
2574+ 34, // 38: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
2575+ 36, // 39: ermite.CommentAdded.comment:type_name -> ermite.Comment
2576+ 36, // 40: ermite.CommentEdited.comment:type_name -> ermite.Comment
2577+ 36, // 41: ermite.CommentDeleted.comment:type_name -> ermite.Comment
2578+ 36, // 42: ermite.CommentResolved.comment:type_name -> ermite.Comment
2579+ 37, // 43: ermite.IssueOpened.issue:type_name -> ermite.Issue
2580+ 37, // 44: ermite.IssueClosed.issue:type_name -> ermite.Issue
2581+ 37, // 45: ermite.IssueReopened.issue:type_name -> ermite.Issue
2582+ 38, // 46: ermite.IssueCommented.comment:type_name -> ermite.IssueComment
2583+ 39, // 47: ermite.RunUpdated.run:type_name -> ermite.Run
2584+ 40, // 48: ermite.JobUpdated.job:type_name -> ermite.RunJob
2585+ 41, // 49: ermite.MirrorFailed.state:type_name -> ermite.MirrorState
2586+ 0, // 50: ermite.EventService.Watch:input_type -> ermite.WatchRequest
2587+ 1, // 51: ermite.EventService.Watch:output_type -> ermite.WatchResponse
2588+ 51, // [51:52] is the sub-list for method output_type
2589+ 50, // [50:51] is the sub-list for method input_type
2590+ 50, // [50:50] is the sub-list for extension type_name
2591+ 50, // [50:50] is the sub-list for extension extendee
2592+ 0, // [0:50] is the sub-list for field type_name
21932593 }
21942594
21952595 func init() { file_ermite_event_proto_init() }
@@ -2227,6 +2627,10 @@ func file_ermite_event_proto_init() {
22272627 (*Event_MirrorRecovered)(nil),
22282628 (*Event_MergeRequestAutoMergeEnabled)(nil),
22292629 (*Event_MergeRequestAutoMergeCancelled)(nil),
2630+ (*Event_ReleasePublished)(nil),
2631+ (*Event_ReleaseUpdated)(nil),
2632+ (*Event_ReleaseDeleted)(nil),
2633+ (*Event_ReleaseUnpublished)(nil),
22302634 }
22312635 type x struct{}
22322636 out := protoimpl.TypeBuilder{
@@ -2234,7 +2638,7 @@ func file_ermite_event_proto_init() {
22342638 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
22352639 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),
22362640 NumEnums: 0,
2237- NumMessages: 28,
2641+ NumMessages: 32,
22382642 NumExtensions: 0,
22392643 NumServices: 1,
22402644 },
@@ -175,6 +175,10 @@ type Event struct {
175 // *Event_MirrorRecovered175 // *Event_MirrorRecovered
176 // *Event_MergeRequestAutoMergeEnabled176 // *Event_MergeRequestAutoMergeEnabled
177 // *Event_MergeRequestAutoMergeCancelled177 // *Event_MergeRequestAutoMergeCancelled
178+ // *Event_ReleasePublished
179+ // *Event_ReleaseUpdated
180+ // *Event_ReleaseDeleted
181+ // *Event_ReleaseUnpublished
178 Kind isEvent_Kind `protobuf_oneof:"kind"`182 Kind isEvent_Kind `protobuf_oneof:"kind"`
179 unknownFields protoimpl.UnknownFields183 unknownFields protoimpl.UnknownFields
180 sizeCache protoimpl.SizeCache184 sizeCache protoimpl.SizeCache
@@ -447,6 +451,42 @@ func (x *Event) GetMergeRequestAutoMergeCancelled() *MergeRequestAutoMergeCancel
447 return nil451 return nil
448 }452 }
449 453
454+func (x *Event) GetReleasePublished() *ReleasePublished {
455+ if x != nil {
456+ if x, ok := x.Kind.(*Event_ReleasePublished); ok {
457+ return x.ReleasePublished
458+ }
459+ }
460+ return nil
461+}
462+
463+func (x *Event) GetReleaseUpdated() *ReleaseUpdated {
464+ if x != nil {
465+ if x, ok := x.Kind.(*Event_ReleaseUpdated); ok {
466+ return x.ReleaseUpdated
467+ }
468+ }
469+ return nil
470+}
471+
472+func (x *Event) GetReleaseDeleted() *ReleaseDeleted {
473+ if x != nil {
474+ if x, ok := x.Kind.(*Event_ReleaseDeleted); ok {
475+ return x.ReleaseDeleted
476+ }
477+ }
478+ return nil
479+}
480+
481+func (x *Event) GetReleaseUnpublished() *ReleaseUnpublished {
482+ if x != nil {
483+ if x, ok := x.Kind.(*Event_ReleaseUnpublished); ok {
484+ return x.ReleaseUnpublished
485+ }
486+ }
487+ return nil
488+}
489+
450 type isEvent_Kind interface {490 type isEvent_Kind interface {
451 isEvent_Kind()491 isEvent_Kind()
452 }492 }
@@ -574,6 +614,26 @@ type Event_MergeRequestAutoMergeCancelled struct {
574 MergeRequestAutoMergeCancelled *MergeRequestAutoMergeCancelled `protobuf:"bytes,26,opt,name=merge_request_auto_merge_cancelled,json=mergeRequestAutoMergeCancelled,proto3,oneof"`614 MergeRequestAutoMergeCancelled *MergeRequestAutoMergeCancelled `protobuf:"bytes,26,opt,name=merge_request_auto_merge_cancelled,json=mergeRequestAutoMergeCancelled,proto3,oneof"`
575 }615 }
576 616
617+type Event_ReleasePublished struct {
618+ // ReleasePublished reports a release published.
619+ ReleasePublished *ReleasePublished `protobuf:"bytes,27,opt,name=release_published,json=releasePublished,proto3,oneof"`
620+}
621+
622+type Event_ReleaseUpdated struct {
623+ // ReleaseUpdated reports a release updated.
624+ ReleaseUpdated *ReleaseUpdated `protobuf:"bytes,28,opt,name=release_updated,json=releaseUpdated,proto3,oneof"`
625+}
626+
627+type Event_ReleaseDeleted struct {
628+ // ReleaseDeleted reports a release deleted.
629+ ReleaseDeleted *ReleaseDeleted `protobuf:"bytes,29,opt,name=release_deleted,json=releaseDeleted,proto3,oneof"`
630+}
631+
632+type Event_ReleaseUnpublished struct {
633+ // ReleaseUnpublished reports a release turned into a draft after tag deletion.
634+ ReleaseUnpublished *ReleaseUnpublished `protobuf:"bytes,30,opt,name=release_unpublished,json=releaseUnpublished,proto3,oneof"`
635+}
636+
577 func (*Event_RepoCreated) isEvent_Kind() {}637 func (*Event_RepoCreated) isEvent_Kind() {}
578 638
579 func (*Event_RepoUpdated) isEvent_Kind() {}639 func (*Event_RepoUpdated) isEvent_Kind() {}
@@ -622,6 +682,14 @@ func (*Event_MergeRequestAutoMergeEnabled) isEvent_Kind() {}
622 682
623 func (*Event_MergeRequestAutoMergeCancelled) isEvent_Kind() {}683 func (*Event_MergeRequestAutoMergeCancelled) isEvent_Kind() {}
624 684
685+func (*Event_ReleasePublished) isEvent_Kind() {}
686+
687+func (*Event_ReleaseUpdated) isEvent_Kind() {}
688+
689+func (*Event_ReleaseDeleted) isEvent_Kind() {}
690+
691+func (*Event_ReleaseUnpublished) isEvent_Kind() {}
692+
625 // RepoCreated reports a new repository.693 // RepoCreated reports a new repository.
626 type RepoCreated struct {694 type RepoCreated struct {
627 state protoimpl.MessageState `protogen:"open.v1"`695 state protoimpl.MessageState `protogen:"open.v1"`
@@ -1964,6 +2032,298 @@ func (x *MirrorRecovered) GetRepo() string {
1964 return ""2032 return ""
1965 }2033 }
1966 2034
2035+// ReleasePublished reports a release change on repo:<name> and home topics.
2036+type ReleasePublished struct {
2037+ state protoimpl.MessageState `protogen:"open.v1"`
2038+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2039+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2040+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2041+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2042+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2043+ unknownFields protoimpl.UnknownFields
2044+ sizeCache protoimpl.SizeCache
2045+}
2046+
2047+func (x *ReleasePublished) Reset() {
2048+ *x = ReleasePublished{}
2049+ mi := &file_ermite_event_proto_msgTypes[28]
2050+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2051+ ms.StoreMessageInfo(mi)
2052+}
2053+
2054+func (x *ReleasePublished) String() string {
2055+ return protoimpl.X.MessageStringOf(x)
2056+}
2057+
2058+func (*ReleasePublished) ProtoMessage() {}
2059+
2060+func (x *ReleasePublished) ProtoReflect() protoreflect.Message {
2061+ mi := &file_ermite_event_proto_msgTypes[28]
2062+ if x != nil {
2063+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2064+ if ms.LoadMessageInfo() == nil {
2065+ ms.StoreMessageInfo(mi)
2066+ }
2067+ return ms
2068+ }
2069+ return mi.MessageOf(x)
2070+}
2071+
2072+// Deprecated: Use ReleasePublished.ProtoReflect.Descriptor instead.
2073+func (*ReleasePublished) Descriptor() ([]byte, []int) {
2074+ return file_ermite_event_proto_rawDescGZIP(), []int{28}
2075+}
2076+
2077+func (x *ReleasePublished) GetRepo() string {
2078+ if x != nil {
2079+ return x.Repo
2080+ }
2081+ return ""
2082+}
2083+
2084+func (x *ReleasePublished) GetId() int64 {
2085+ if x != nil {
2086+ return x.Id
2087+ }
2088+ return 0
2089+}
2090+
2091+func (x *ReleasePublished) GetTag() string {
2092+ if x != nil {
2093+ return x.Tag
2094+ }
2095+ return ""
2096+}
2097+
2098+func (x *ReleasePublished) GetDraft() bool {
2099+ if x != nil {
2100+ return x.Draft
2101+ }
2102+ return false
2103+}
2104+
2105+func (x *ReleasePublished) GetPrerelease() bool {
2106+ if x != nil {
2107+ return x.Prerelease
2108+ }
2109+ return false
2110+}
2111+
2112+// ReleaseUpdated reports a release change on repo:<name> and home topics.
2113+type ReleaseUpdated struct {
2114+ state protoimpl.MessageState `protogen:"open.v1"`
2115+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2116+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2117+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2118+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2119+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2120+ unknownFields protoimpl.UnknownFields
2121+ sizeCache protoimpl.SizeCache
2122+}
2123+
2124+func (x *ReleaseUpdated) Reset() {
2125+ *x = ReleaseUpdated{}
2126+ mi := &file_ermite_event_proto_msgTypes[29]
2127+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2128+ ms.StoreMessageInfo(mi)
2129+}
2130+
2131+func (x *ReleaseUpdated) String() string {
2132+ return protoimpl.X.MessageStringOf(x)
2133+}
2134+
2135+func (*ReleaseUpdated) ProtoMessage() {}
2136+
2137+func (x *ReleaseUpdated) ProtoReflect() protoreflect.Message {
2138+ mi := &file_ermite_event_proto_msgTypes[29]
2139+ if x != nil {
2140+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2141+ if ms.LoadMessageInfo() == nil {
2142+ ms.StoreMessageInfo(mi)
2143+ }
2144+ return ms
2145+ }
2146+ return mi.MessageOf(x)
2147+}
2148+
2149+// Deprecated: Use ReleaseUpdated.ProtoReflect.Descriptor instead.
2150+func (*ReleaseUpdated) Descriptor() ([]byte, []int) {
2151+ return file_ermite_event_proto_rawDescGZIP(), []int{29}
2152+}
2153+
2154+func (x *ReleaseUpdated) GetRepo() string {
2155+ if x != nil {
2156+ return x.Repo
2157+ }
2158+ return ""
2159+}
2160+
2161+func (x *ReleaseUpdated) GetId() int64 {
2162+ if x != nil {
2163+ return x.Id
2164+ }
2165+ return 0
2166+}
2167+
2168+func (x *ReleaseUpdated) GetTag() string {
2169+ if x != nil {
2170+ return x.Tag
2171+ }
2172+ return ""
2173+}
2174+
2175+func (x *ReleaseUpdated) GetDraft() bool {
2176+ if x != nil {
2177+ return x.Draft
2178+ }
2179+ return false
2180+}
2181+
2182+func (x *ReleaseUpdated) GetPrerelease() bool {
2183+ if x != nil {
2184+ return x.Prerelease
2185+ }
2186+ return false
2187+}
2188+
2189+// ReleaseDeleted reports a release change on repo:<name> and home topics.
2190+type ReleaseDeleted struct {
2191+ state protoimpl.MessageState `protogen:"open.v1"`
2192+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2193+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2194+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2195+ unknownFields protoimpl.UnknownFields
2196+ sizeCache protoimpl.SizeCache
2197+}
2198+
2199+func (x *ReleaseDeleted) Reset() {
2200+ *x = ReleaseDeleted{}
2201+ mi := &file_ermite_event_proto_msgTypes[30]
2202+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2203+ ms.StoreMessageInfo(mi)
2204+}
2205+
2206+func (x *ReleaseDeleted) String() string {
2207+ return protoimpl.X.MessageStringOf(x)
2208+}
2209+
2210+func (*ReleaseDeleted) ProtoMessage() {}
2211+
2212+func (x *ReleaseDeleted) ProtoReflect() protoreflect.Message {
2213+ mi := &file_ermite_event_proto_msgTypes[30]
2214+ if x != nil {
2215+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2216+ if ms.LoadMessageInfo() == nil {
2217+ ms.StoreMessageInfo(mi)
2218+ }
2219+ return ms
2220+ }
2221+ return mi.MessageOf(x)
2222+}
2223+
2224+// Deprecated: Use ReleaseDeleted.ProtoReflect.Descriptor instead.
2225+func (*ReleaseDeleted) Descriptor() ([]byte, []int) {
2226+ return file_ermite_event_proto_rawDescGZIP(), []int{30}
2227+}
2228+
2229+func (x *ReleaseDeleted) GetRepo() string {
2230+ if x != nil {
2231+ return x.Repo
2232+ }
2233+ return ""
2234+}
2235+
2236+func (x *ReleaseDeleted) GetId() int64 {
2237+ if x != nil {
2238+ return x.Id
2239+ }
2240+ return 0
2241+}
2242+
2243+func (x *ReleaseDeleted) GetTag() string {
2244+ if x != nil {
2245+ return x.Tag
2246+ }
2247+ return ""
2248+}
2249+
2250+// ReleaseUnpublished reports a release change on repo:<name> and home topics.
2251+type ReleaseUnpublished struct {
2252+ state protoimpl.MessageState `protogen:"open.v1"`
2253+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
2254+ Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
2255+ Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"`
2256+ Draft bool `protobuf:"varint,4,opt,name=draft,proto3" json:"draft,omitempty"`
2257+ Prerelease bool `protobuf:"varint,5,opt,name=prerelease,proto3" json:"prerelease,omitempty"`
2258+ unknownFields protoimpl.UnknownFields
2259+ sizeCache protoimpl.SizeCache
2260+}
2261+
2262+func (x *ReleaseUnpublished) Reset() {
2263+ *x = ReleaseUnpublished{}
2264+ mi := &file_ermite_event_proto_msgTypes[31]
2265+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2266+ ms.StoreMessageInfo(mi)
2267+}
2268+
2269+func (x *ReleaseUnpublished) String() string {
2270+ return protoimpl.X.MessageStringOf(x)
2271+}
2272+
2273+func (*ReleaseUnpublished) ProtoMessage() {}
2274+
2275+func (x *ReleaseUnpublished) ProtoReflect() protoreflect.Message {
2276+ mi := &file_ermite_event_proto_msgTypes[31]
2277+ if x != nil {
2278+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2279+ if ms.LoadMessageInfo() == nil {
2280+ ms.StoreMessageInfo(mi)
2281+ }
2282+ return ms
2283+ }
2284+ return mi.MessageOf(x)
2285+}
2286+
2287+// Deprecated: Use ReleaseUnpublished.ProtoReflect.Descriptor instead.
2288+func (*ReleaseUnpublished) Descriptor() ([]byte, []int) {
2289+ return file_ermite_event_proto_rawDescGZIP(), []int{31}
2290+}
2291+
2292+func (x *ReleaseUnpublished) GetRepo() string {
2293+ if x != nil {
2294+ return x.Repo
2295+ }
2296+ return ""
2297+}
2298+
2299+func (x *ReleaseUnpublished) GetId() int64 {
2300+ if x != nil {
2301+ return x.Id
2302+ }
2303+ return 0
2304+}
2305+
2306+func (x *ReleaseUnpublished) GetTag() string {
2307+ if x != nil {
2308+ return x.Tag
2309+ }
2310+ return ""
2311+}
2312+
2313+func (x *ReleaseUnpublished) GetDraft() bool {
2314+ if x != nil {
2315+ return x.Draft
2316+ }
2317+ return false
2318+}
2319+
2320+func (x *ReleaseUnpublished) GetPrerelease() bool {
2321+ if x != nil {
2322+ return x.Prerelease
2323+ }
2324+ return false
2325+}
2326+
1967 var File_ermite_event_proto protoreflect.FileDescriptor2327 var File_ermite_event_proto protoreflect.FileDescriptor
1968 2328
1969 const file_ermite_event_proto_rawDesc = "" +2329 const file_ermite_event_proto_rawDesc = "" +
@@ -1973,7 +2333,7 @@ const file_ermite_event_proto_rawDesc = "" +
1973 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +2333 "\x06topics\x18\x01 \x03(\tR\x06topics\x12!\n" +
1974 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +2334 "\fresume_after\x18\x02 \x01(\tR\vresumeAfter\"4\n" +
1975 "\rWatchResponse\x12#\n" +2335 "\rWatchResponse\x12#\n" +
1976- "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xb1\r\n" +2336+ "\x05event\x18\x01 \x01(\v2\r.ermite.EventR\x05event\"\xcf\x0f\n" +
1977 "\x05Event\x12\x0e\n" +2337 "\x05Event\x12\x0e\n" +
1978 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +2338 "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" +
1979 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +2339 "\x04time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x04time\x128\n" +
@@ -2003,7 +2363,11 @@ const file_ermite_event_proto_rawDesc = "" +
2003 "\rmirror_failed\x18\x17 \x01(\v2\x14.ermite.MirrorFailedH\x00R\fmirrorFailed\x12D\n" +2363 "\rmirror_failed\x18\x17 \x01(\v2\x14.ermite.MirrorFailedH\x00R\fmirrorFailed\x12D\n" +
2004 "\x10mirror_recovered\x18\x18 \x01(\v2\x17.ermite.MirrorRecoveredH\x00R\x0fmirrorRecovered\x12n\n" +2364 "\x10mirror_recovered\x18\x18 \x01(\v2\x17.ermite.MirrorRecoveredH\x00R\x0fmirrorRecovered\x12n\n" +
2005 " merge_request_auto_merge_enabled\x18\x19 \x01(\v2$.ermite.MergeRequestAutoMergeEnabledH\x00R\x1cmergeRequestAutoMergeEnabled\x12t\n" +2365 " merge_request_auto_merge_enabled\x18\x19 \x01(\v2$.ermite.MergeRequestAutoMergeEnabledH\x00R\x1cmergeRequestAutoMergeEnabled\x12t\n" +
2006- "\"merge_request_auto_merge_cancelled\x18\x1a \x01(\v2&.ermite.MergeRequestAutoMergeCancelledH\x00R\x1emergeRequestAutoMergeCancelledB\x06\n" +2366+ "\"merge_request_auto_merge_cancelled\x18\x1a \x01(\v2&.ermite.MergeRequestAutoMergeCancelledH\x00R\x1emergeRequestAutoMergeCancelled\x12G\n" +
2367+ "\x11release_published\x18\x1b \x01(\v2\x18.ermite.ReleasePublishedH\x00R\x10releasePublished\x12A\n" +
2368+ "\x0frelease_updated\x18\x1c \x01(\v2\x16.ermite.ReleaseUpdatedH\x00R\x0ereleaseUpdated\x12A\n" +
2369+ "\x0frelease_deleted\x18\x1d \x01(\v2\x16.ermite.ReleaseDeletedH\x00R\x0ereleaseDeleted\x12M\n" +
2370+ "\x13release_unpublished\x18\x1e \x01(\v2\x1a.ermite.ReleaseUnpublishedH\x00R\x12releaseUnpublishedB\x06\n" +
2007 "\x04kind\"/\n" +2371 "\x04kind\"/\n" +
2008 "\vRepoCreated\x12 \n" +2372 "\vRepoCreated\x12 \n" +
2009 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +2373 "\x04repo\x18\x01 \x01(\v2\f.ermite.RepoR\x04repo\"/\n" +
@@ -2076,7 +2440,35 @@ const file_ermite_event_proto_rawDesc = "" +
2076 "\x05state\x18\x02 \x01(\x0e2\x13.ermite.MirrorStateR\x05state\x12#\n" +2440 "\x05state\x18\x02 \x01(\x0e2\x13.ermite.MirrorStateR\x05state\x12#\n" +
2077 "\rfailure_class\x18\x03 \x01(\tR\ffailureClassJ\x04\b\x04\x10\x05R\x06reason\"%\n" +2441 "\rfailure_class\x18\x03 \x01(\tR\ffailureClassJ\x04\b\x04\x10\x05R\x06reason\"%\n" +
2078 "\x0fMirrorRecovered\x12\x12\n" +2442 "\x0fMirrorRecovered\x12\x12\n" +
2079- "\x04repo\x18\x01 \x01(\tR\x04repo2F\n" +2443+ "\x04repo\x18\x01 \x01(\tR\x04repo\"~\n" +
2444+ "\x10ReleasePublished\x12\x12\n" +
2445+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2446+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2447+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2448+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2449+ "\n" +
2450+ "prerelease\x18\x05 \x01(\bR\n" +
2451+ "prerelease\"|\n" +
2452+ "\x0eReleaseUpdated\x12\x12\n" +
2453+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2454+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2455+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2456+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2457+ "\n" +
2458+ "prerelease\x18\x05 \x01(\bR\n" +
2459+ "prerelease\"F\n" +
2460+ "\x0eReleaseDeleted\x12\x12\n" +
2461+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2462+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2463+ "\x03tag\x18\x03 \x01(\tR\x03tag\"\x80\x01\n" +
2464+ "\x12ReleaseUnpublished\x12\x12\n" +
2465+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x0e\n" +
2466+ "\x02id\x18\x02 \x01(\x03R\x02id\x12\x10\n" +
2467+ "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x14\n" +
2468+ "\x05draft\x18\x04 \x01(\bR\x05draft\x12\x1e\n" +
2469+ "\n" +
2470+ "prerelease\x18\x05 \x01(\bR\n" +
2471+ "prerelease2F\n" +
2080 "\fEventService\x126\n" +2472 "\fEventService\x126\n" +
2081 "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" +2473 "\x05Watch\x12\x14.ermite.WatchRequest\x1a\x15.ermite.WatchResponse0\x01Bq\n" +
2082 "\n" +2474 "\n" +
@@ -2095,7 +2487,7 @@ func file_ermite_event_proto_rawDescGZIP() []byte {
2095 return file_ermite_event_proto_rawDescData2487 return file_ermite_event_proto_rawDescData
2096 }2488 }
2097 2489
2098-var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 28)2490+var file_ermite_event_proto_msgTypes = make([]protoimpl.MessageInfo, 32)
2099 var file_ermite_event_proto_goTypes = []any{2491 var file_ermite_event_proto_goTypes = []any{
2100 (*WatchRequest)(nil), // 0: ermite.WatchRequest2492 (*WatchRequest)(nil), // 0: ermite.WatchRequest
2101 (*WatchResponse)(nil), // 1: ermite.WatchResponse2493 (*WatchResponse)(nil), // 1: ermite.WatchResponse
@@ -2125,20 +2517,24 @@ var file_ermite_event_proto_goTypes = []any{
2125 (*JobUpdated)(nil), // 25: ermite.JobUpdated2517 (*JobUpdated)(nil), // 25: ermite.JobUpdated
2126 (*MirrorFailed)(nil), // 26: ermite.MirrorFailed2518 (*MirrorFailed)(nil), // 26: ermite.MirrorFailed
2127 (*MirrorRecovered)(nil), // 27: ermite.MirrorRecovered2519 (*MirrorRecovered)(nil), // 27: ermite.MirrorRecovered
2128- (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp2520+ (*ReleasePublished)(nil), // 28: ermite.ReleasePublished
2129- (*Repo)(nil), // 29: ermite.Repo2521+ (*ReleaseUpdated)(nil), // 29: ermite.ReleaseUpdated
2130- (*MergeRequest)(nil), // 30: ermite.MergeRequest2522+ (*ReleaseDeleted)(nil), // 30: ermite.ReleaseDeleted
2131- (*Mergeability)(nil), // 31: ermite.Mergeability2523+ (*ReleaseUnpublished)(nil), // 31: ermite.ReleaseUnpublished
2132- (*Comment)(nil), // 32: ermite.Comment2524+ (*timestamppb.Timestamp)(nil), // 32: google.protobuf.Timestamp
2133- (*Issue)(nil), // 33: ermite.Issue2525+ (*Repo)(nil), // 33: ermite.Repo
2134- (*IssueComment)(nil), // 34: ermite.IssueComment2526+ (*MergeRequest)(nil), // 34: ermite.MergeRequest
2135- (*Run)(nil), // 35: ermite.Run2527+ (*Mergeability)(nil), // 35: ermite.Mergeability
2136- (*RunJob)(nil), // 36: ermite.RunJob2528+ (*Comment)(nil), // 36: ermite.Comment
2137- (MirrorState)(0), // 37: ermite.MirrorState2529+ (*Issue)(nil), // 37: ermite.Issue
2530+ (*IssueComment)(nil), // 38: ermite.IssueComment
2531+ (*Run)(nil), // 39: ermite.Run
2532+ (*RunJob)(nil), // 40: ermite.RunJob
2533+ (MirrorState)(0), // 41: ermite.MirrorState
2138 }2534 }
2139 var file_ermite_event_proto_depIdxs = []int32{2535 var file_ermite_event_proto_depIdxs = []int32{
2140 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event2536 2, // 0: ermite.WatchResponse.event:type_name -> ermite.Event
2141- 28, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp2537+ 32, // 1: ermite.Event.time:type_name -> google.protobuf.Timestamp
2142 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated2538 3, // 2: ermite.Event.repo_created:type_name -> ermite.RepoCreated
2143 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated2539 4, // 3: ermite.Event.repo_updated:type_name -> ermite.RepoUpdated
2144 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted2540 5, // 4: ermite.Event.repo_deleted:type_name -> ermite.RepoDeleted
@@ -2163,33 +2559,37 @@ var file_ermite_event_proto_depIdxs = []int32{
2163 27, // 23: ermite.Event.mirror_recovered:type_name -> ermite.MirrorRecovered2559 27, // 23: ermite.Event.mirror_recovered:type_name -> ermite.MirrorRecovered
2164 10, // 24: ermite.Event.merge_request_auto_merge_enabled:type_name -> ermite.MergeRequestAutoMergeEnabled2560 10, // 24: ermite.Event.merge_request_auto_merge_enabled:type_name -> ermite.MergeRequestAutoMergeEnabled
2165 11, // 25: ermite.Event.merge_request_auto_merge_cancelled:type_name -> ermite.MergeRequestAutoMergeCancelled2561 11, // 25: ermite.Event.merge_request_auto_merge_cancelled:type_name -> ermite.MergeRequestAutoMergeCancelled
2166- 29, // 26: ermite.RepoCreated.repo:type_name -> ermite.Repo2562+ 28, // 26: ermite.Event.release_published:type_name -> ermite.ReleasePublished
2167- 29, // 27: ermite.RepoUpdated.repo:type_name -> ermite.Repo2563+ 29, // 27: ermite.Event.release_updated:type_name -> ermite.ReleaseUpdated
2168- 7, // 28: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate2564+ 30, // 28: ermite.Event.release_deleted:type_name -> ermite.ReleaseDeleted
2169- 30, // 29: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest2565+ 31, // 29: ermite.Event.release_unpublished:type_name -> ermite.ReleaseUnpublished
2170- 30, // 30: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest2566+ 33, // 30: ermite.RepoCreated.repo:type_name -> ermite.Repo
2171- 30, // 31: ermite.MergeRequestAutoMergeEnabled.merge_request:type_name -> ermite.MergeRequest2567+ 33, // 31: ermite.RepoUpdated.repo:type_name -> ermite.Repo
2172- 30, // 32: ermite.MergeRequestAutoMergeCancelled.merge_request:type_name -> ermite.MergeRequest2568+ 7, // 32: ermite.Pushed.ref_updates:type_name -> ermite.RefUpdate
2173- 31, // 33: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability2569+ 34, // 33: ermite.MergeRequestOpened.merge_request:type_name -> ermite.MergeRequest
2174- 30, // 34: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest2570+ 34, // 34: ermite.MergeRequestMerged.merge_request:type_name -> ermite.MergeRequest
2175- 32, // 35: ermite.CommentAdded.comment:type_name -> ermite.Comment2571+ 34, // 35: ermite.MergeRequestAutoMergeEnabled.merge_request:type_name -> ermite.MergeRequest
2176- 32, // 36: ermite.CommentEdited.comment:type_name -> ermite.Comment2572+ 34, // 36: ermite.MergeRequestAutoMergeCancelled.merge_request:type_name -> ermite.MergeRequest
2177- 32, // 37: ermite.CommentDeleted.comment:type_name -> ermite.Comment2573+ 35, // 37: ermite.MergeRequestMergeability.mergeability:type_name -> ermite.Mergeability
2178- 32, // 38: ermite.CommentResolved.comment:type_name -> ermite.Comment2574+ 34, // 38: ermite.MergeRequestClosed.merge_request:type_name -> ermite.MergeRequest
2179- 33, // 39: ermite.IssueOpened.issue:type_name -> ermite.Issue2575+ 36, // 39: ermite.CommentAdded.comment:type_name -> ermite.Comment
2180- 33, // 40: ermite.IssueClosed.issue:type_name -> ermite.Issue2576+ 36, // 40: ermite.CommentEdited.comment:type_name -> ermite.Comment
2181- 33, // 41: ermite.IssueReopened.issue:type_name -> ermite.Issue2577+ 36, // 41: ermite.CommentDeleted.comment:type_name -> ermite.Comment
2182- 34, // 42: ermite.IssueCommented.comment:type_name -> ermite.IssueComment2578+ 36, // 42: ermite.CommentResolved.comment:type_name -> ermite.Comment
2183- 35, // 43: ermite.RunUpdated.run:type_name -> ermite.Run2579+ 37, // 43: ermite.IssueOpened.issue:type_name -> ermite.Issue
2184- 36, // 44: ermite.JobUpdated.job:type_name -> ermite.RunJob2580+ 37, // 44: ermite.IssueClosed.issue:type_name -> ermite.Issue
2185- 37, // 45: ermite.MirrorFailed.state:type_name -> ermite.MirrorState2581+ 37, // 45: ermite.IssueReopened.issue:type_name -> ermite.Issue
2186- 0, // 46: ermite.EventService.Watch:input_type -> ermite.WatchRequest2582+ 38, // 46: ermite.IssueCommented.comment:type_name -> ermite.IssueComment
2187- 1, // 47: ermite.EventService.Watch:output_type -> ermite.WatchResponse2583+ 39, // 47: ermite.RunUpdated.run:type_name -> ermite.Run
2188- 47, // [47:48] is the sub-list for method output_type2584+ 40, // 48: ermite.JobUpdated.job:type_name -> ermite.RunJob
2189- 46, // [46:47] is the sub-list for method input_type2585+ 41, // 49: ermite.MirrorFailed.state:type_name -> ermite.MirrorState
2190- 46, // [46:46] is the sub-list for extension type_name2586+ 0, // 50: ermite.EventService.Watch:input_type -> ermite.WatchRequest
2191- 46, // [46:46] is the sub-list for extension extendee2587+ 1, // 51: ermite.EventService.Watch:output_type -> ermite.WatchResponse
2192- 0, // [0:46] is the sub-list for field type_name2588+ 51, // [51:52] is the sub-list for method output_type
2589+ 50, // [50:51] is the sub-list for method input_type
2590+ 50, // [50:50] is the sub-list for extension type_name
2591+ 50, // [50:50] is the sub-list for extension extendee
2592+ 0, // [0:50] is the sub-list for field type_name
2193 }2593 }
2194 2594
2195 func init() { file_ermite_event_proto_init() }2595 func init() { file_ermite_event_proto_init() }
@@ -2227,6 +2627,10 @@ func file_ermite_event_proto_init() {
2227 (*Event_MirrorRecovered)(nil),2627 (*Event_MirrorRecovered)(nil),
2228 (*Event_MergeRequestAutoMergeEnabled)(nil),2628 (*Event_MergeRequestAutoMergeEnabled)(nil),
2229 (*Event_MergeRequestAutoMergeCancelled)(nil),2629 (*Event_MergeRequestAutoMergeCancelled)(nil),
2630+ (*Event_ReleasePublished)(nil),
2631+ (*Event_ReleaseUpdated)(nil),
2632+ (*Event_ReleaseDeleted)(nil),
2633+ (*Event_ReleaseUnpublished)(nil),
2230 }2634 }
2231 type x struct{}2635 type x struct{}
2232 out := protoimpl.TypeBuilder{2636 out := protoimpl.TypeBuilder{
@@ -2234,7 +2638,7 @@ func file_ermite_event_proto_init() {
2234 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),2638 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
2235 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),2639 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_event_proto_rawDesc), len(file_ermite_event_proto_rawDesc)),
2236 NumEnums: 0,2640 NumEnums: 0,
2237- NumMessages: 28,2641+ NumMessages: 32,
2238 NumExtensions: 0,2642 NumExtensions: 0,
2239 NumServices: 1,2643 NumServices: 1,
2240 },2644 },
A gen/ermite/release.pb.go +2106 -0 generated file: collapsed
M gen/ermite/server.pb.go +2 -1 generated file: collapsed
M gen/ermite/token.pb.go +8 -2 generated file: collapsed
M gen_test.go +20 -0
@@ -19,6 +19,18 @@ import (
1919 // TestProcedures pins the procedure paths: they are the wire contract.
2020 func TestProcedures(t *testing.T) {
2121 tests := []struct{ got, want string }{
22+ {ermiteconnect.ReleaseServiceCreateReleaseProcedure, "/ermite.ReleaseService/CreateRelease"},
23+ {ermiteconnect.ReleaseServiceGetReleaseProcedure, "/ermite.ReleaseService/GetRelease"},
24+ {ermiteconnect.ReleaseServiceListReleasesProcedure, "/ermite.ReleaseService/ListReleases"},
25+ {ermiteconnect.ReleaseServiceUpdateReleaseProcedure, "/ermite.ReleaseService/UpdateRelease"},
26+ {ermiteconnect.ReleaseServiceDeleteReleaseProcedure, "/ermite.ReleaseService/DeleteRelease"},
27+ {ermiteconnect.ReleaseServiceUploadReleaseAssetProcedure, "/ermite.ReleaseService/UploadReleaseAsset"},
28+ {ermiteconnect.ReleaseServiceUpdateReleaseAssetProcedure, "/ermite.ReleaseService/UpdateReleaseAsset"},
29+ {ermiteconnect.ReleaseServiceDeleteReleaseAssetProcedure, "/ermite.ReleaseService/DeleteReleaseAsset"},
30+ {ermiteconnect.ReleaseServiceDownloadReleaseAssetProcedure, "/ermite.ReleaseService/DownloadReleaseAsset"},
31+ {ermiteconnect.ReleaseServiceListReleaseAssetsProcedure, "/ermite.ReleaseService/ListReleaseAssets"},
32+ {ermiteconnect.ReleaseServiceGetReleaseUsageProcedure, "/ermite.ReleaseService/GetReleaseUsage"},
33+
2234 {ermiteconnect.MirrorServiceGetMirrorKeyProcedure, "/ermite.MirrorService/GetMirrorKey"},
2335 {ermiteconnect.MirrorServiceRotateMirrorKeyProcedure, "/ermite.MirrorService/RotateMirrorKey"},
2436 {ermiteconnect.MirrorServiceGetMirrorConfigProcedure, "/ermite.MirrorService/GetMirrorConfig"},
@@ -615,3 +627,11 @@ func TestMirrorWire(t *testing.T) {
615627 }
616628 }
617629 }
630+
631+// TestReleaseSymbols pins the scope and event wrapper exports used by callers.
632+func TestReleaseSymbols(t *testing.T) {
633+ if ermite.Scope_SCOPE_RELEASE_WRITE != 13 {
634+ t.Fatal("release scope wire value changed")
635+ }
636+ var _ proto.Message = &ermite.Event{Kind: &ermite.Event_ReleasePublished{ReleasePublished: &ermite.ReleasePublished{}}}
637+}
@@ -19,6 +19,18 @@ 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.ReleaseServiceCreateReleaseProcedure, "/ermite.ReleaseService/CreateRelease"},
23+ {ermiteconnect.ReleaseServiceGetReleaseProcedure, "/ermite.ReleaseService/GetRelease"},
24+ {ermiteconnect.ReleaseServiceListReleasesProcedure, "/ermite.ReleaseService/ListReleases"},
25+ {ermiteconnect.ReleaseServiceUpdateReleaseProcedure, "/ermite.ReleaseService/UpdateRelease"},
26+ {ermiteconnect.ReleaseServiceDeleteReleaseProcedure, "/ermite.ReleaseService/DeleteRelease"},
27+ {ermiteconnect.ReleaseServiceUploadReleaseAssetProcedure, "/ermite.ReleaseService/UploadReleaseAsset"},
28+ {ermiteconnect.ReleaseServiceUpdateReleaseAssetProcedure, "/ermite.ReleaseService/UpdateReleaseAsset"},
29+ {ermiteconnect.ReleaseServiceDeleteReleaseAssetProcedure, "/ermite.ReleaseService/DeleteReleaseAsset"},
30+ {ermiteconnect.ReleaseServiceDownloadReleaseAssetProcedure, "/ermite.ReleaseService/DownloadReleaseAsset"},
31+ {ermiteconnect.ReleaseServiceListReleaseAssetsProcedure, "/ermite.ReleaseService/ListReleaseAssets"},
32+ {ermiteconnect.ReleaseServiceGetReleaseUsageProcedure, "/ermite.ReleaseService/GetReleaseUsage"},
33+
22 {ermiteconnect.MirrorServiceGetMirrorKeyProcedure, "/ermite.MirrorService/GetMirrorKey"},34 {ermiteconnect.MirrorServiceGetMirrorKeyProcedure, "/ermite.MirrorService/GetMirrorKey"},
23 {ermiteconnect.MirrorServiceRotateMirrorKeyProcedure, "/ermite.MirrorService/RotateMirrorKey"},35 {ermiteconnect.MirrorServiceRotateMirrorKeyProcedure, "/ermite.MirrorService/RotateMirrorKey"},
24 {ermiteconnect.MirrorServiceGetMirrorConfigProcedure, "/ermite.MirrorService/GetMirrorConfig"},36 {ermiteconnect.MirrorServiceGetMirrorConfigProcedure, "/ermite.MirrorService/GetMirrorConfig"},
@@ -615,3 +627,11 @@ func TestMirrorWire(t *testing.T) {
615 }627 }
616 }628 }
617 }629 }
630+
631+// TestReleaseSymbols pins the scope and event wrapper exports used by callers.
632+func TestReleaseSymbols(t *testing.T) {
633+ if ermite.Scope_SCOPE_RELEASE_WRITE != 13 {
634+ t.Fatal("release scope wire value changed")
635+ }
636+ var _ proto.Message = &ermite.Event{Kind: &ermite.Event_ReleasePublished{ReleasePublished: &ermite.ReleasePublished{}}}
637+}
M proto/ermite/event.proto +42 -0
@@ -145,6 +145,14 @@ message Event {
145145 // MergeRequestAutoMergeCancelled: the auto-merge of a merge request was
146146 // cancelled.
147147 MergeRequestAutoMergeCancelled merge_request_auto_merge_cancelled = 26;
148+ // ReleasePublished reports a release published.
149+ ReleasePublished release_published = 27;
150+ // ReleaseUpdated reports a release updated.
151+ ReleaseUpdated release_updated = 28;
152+ // ReleaseDeleted reports a release deleted.
153+ ReleaseDeleted release_deleted = 29;
154+ // ReleaseUnpublished reports a release turned into a draft after tag deletion.
155+ ReleaseUnpublished release_unpublished = 30;
148156 }
149157 }
150158
@@ -358,3 +366,37 @@ message MirrorRecovered {
358366 // Repo is the repository name.
359367 string repo = 1;
360368 }
369+
370+// ReleasePublished reports a release change on repo:<name> and home topics.
371+message ReleasePublished {
372+ string repo = 1;
373+ int64 id = 2;
374+ string tag = 3;
375+ bool draft = 4;
376+ bool prerelease = 5;
377+}
378+
379+// ReleaseUpdated reports a release change on repo:<name> and home topics.
380+message ReleaseUpdated {
381+ string repo = 1;
382+ int64 id = 2;
383+ string tag = 3;
384+ bool draft = 4;
385+ bool prerelease = 5;
386+}
387+
388+// ReleaseDeleted reports a release change on repo:<name> and home topics.
389+message ReleaseDeleted {
390+ string repo = 1;
391+ int64 id = 2;
392+ string tag = 3;
393+}
394+
395+// ReleaseUnpublished reports a release change on repo:<name> and home topics.
396+message ReleaseUnpublished {
397+ string repo = 1;
398+ int64 id = 2;
399+ string tag = 3;
400+ bool draft = 4;
401+ bool prerelease = 5;
402+}
@@ -145,6 +145,14 @@ message Event {
145 // MergeRequestAutoMergeCancelled: the auto-merge of a merge request was145 // MergeRequestAutoMergeCancelled: the auto-merge of a merge request was
146 // cancelled.146 // cancelled.
147 MergeRequestAutoMergeCancelled merge_request_auto_merge_cancelled = 26;147 MergeRequestAutoMergeCancelled merge_request_auto_merge_cancelled = 26;
148+ // ReleasePublished reports a release published.
149+ ReleasePublished release_published = 27;
150+ // ReleaseUpdated reports a release updated.
151+ ReleaseUpdated release_updated = 28;
152+ // ReleaseDeleted reports a release deleted.
153+ ReleaseDeleted release_deleted = 29;
154+ // ReleaseUnpublished reports a release turned into a draft after tag deletion.
155+ ReleaseUnpublished release_unpublished = 30;
148 }156 }
149 }157 }
150 158
@@ -358,3 +366,37 @@ message MirrorRecovered {
358 // Repo is the repository name.366 // Repo is the repository name.
359 string repo = 1;367 string repo = 1;
360 }368 }
369+
370+// ReleasePublished reports a release change on repo:<name> and home topics.
371+message ReleasePublished {
372+ string repo = 1;
373+ int64 id = 2;
374+ string tag = 3;
375+ bool draft = 4;
376+ bool prerelease = 5;
377+}
378+
379+// ReleaseUpdated reports a release change on repo:<name> and home topics.
380+message ReleaseUpdated {
381+ string repo = 1;
382+ int64 id = 2;
383+ string tag = 3;
384+ bool draft = 4;
385+ bool prerelease = 5;
386+}
387+
388+// ReleaseDeleted reports a release change on repo:<name> and home topics.
389+message ReleaseDeleted {
390+ string repo = 1;
391+ int64 id = 2;
392+ string tag = 3;
393+}
394+
395+// ReleaseUnpublished reports a release change on repo:<name> and home topics.
396+message ReleaseUnpublished {
397+ string repo = 1;
398+ int64 id = 2;
399+ string tag = 3;
400+ bool draft = 4;
401+ bool prerelease = 5;
402+}
A proto/ermite/release.proto +264 -0
@@ -0,0 +1,264 @@
1+// SPDX-License-Identifier: MIT
2+
3+syntax = "proto3";
4+
5+package ermite;
6+
7+import "google/protobuf/field_mask.proto";
8+import "google/protobuf/timestamp.proto";
9+
10+// Release describes a tag and its notes. Drafts are visible only to writers.
11+message Release {
12+ int64 id = 1;
13+ string repo = 2;
14+ string tag = 3;
15+ string title = 4;
16+ string notes = 5;
17+ bool draft = 6;
18+ bool prerelease = 7;
19+ // Latest identifies the release returned by the latest selector, computed or pinned.
20+ bool latest = 8;
21+ // TargetCommitish is the tag's commit; empty for a draft without a tag.
22+ string target_commitish = 9;
23+ // Author is the label of the principal that created the release.
24+ string author = 10;
25+ google.protobuf.Timestamp created_at = 11;
26+ // PublishedAt is unset while draft.
27+ google.protobuf.Timestamp published_at = 12;
28+ google.protobuf.Timestamp updated_at = 13;
29+ // Assets contains uploaded assets only, ordered by name.
30+ repeated ReleaseAsset assets = 14;
31+}
32+
33+// ReleaseAsset describes an uploaded file, with a sha256:<hex> digest.
34+message ReleaseAsset {
35+ int64 id = 1;
36+ int64 release_id = 2;
37+ // Name is unique within the release, 1–255 characters, without slashes or controls.
38+ string name = 3;
39+ string label = 4;
40+ // ContentType defaults to application/octet-stream.
41+ string content_type = 5;
42+ int64 size = 6;
43+ string digest = 7;
44+ string uploader = 8;
45+ google.protobuf.Timestamp created_at = 9;
46+ google.protobuf.Timestamp updated_at = 10;
47+}
48+
49+// ReleaseService manages releases and their assets. Servers list "releases" in
50+// GetVersionResponse.features; other servers answer unimplemented.
51+// Published releases follow repository read access; drafts require write access.
52+// Unknown or unreadable repositories, releases and assets give not_found.
53+// Writes require release:write or a job token with contents: write for the repo;
54+// readers and branch-limited tokens receive permission_denied.
55+// Invalid names, media types or masks give invalid_argument. Size, asset count
56+// and repository quota limits give resource_exhausted and leave no stored upload.
57+service ReleaseService {
58+ // CreateRelease creates one release per tag (already_exists on duplication).
59+ // Publishing without an existing tag is failed_precondition, unless
60+ // target_commitish is supplied to create it; existing tags never move.
61+ rpc CreateRelease(CreateReleaseRequest) returns (CreateReleaseResponse);
62+ // GetRelease selects by id, tag or latest (latest must be true).
63+ rpc GetRelease(GetReleaseRequest) returns (GetReleaseResponse);
64+ // ListReleases lists newest first, including drafts only for writers.
65+ rpc ListReleases(ListReleasesRequest) returns (ListReleasesResponse);
66+ // UpdateRelease changes masked fields. Publishing requires an existing tag
67+ // or target_commitish to create it; otherwise failed_precondition.
68+ rpc UpdateRelease(UpdateReleaseRequest) returns (UpdateReleaseResponse);
69+ // DeleteRelease removes a release and its assets.
70+ rpc DeleteRelease(DeleteReleaseRequest) returns (DeleteReleaseResponse);
71+ // UploadReleaseAsset reserves size before reading. The first message carries
72+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
73+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
74+ // asset. A taken name gives already_exists unless replace is true. Uploading
75+ // to a release of another repo gives failed_precondition.
76+ rpc UploadReleaseAsset(stream UploadReleaseAssetRequest) returns (UploadReleaseAssetResponse);
77+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
78+ rpc UpdateReleaseAsset(UpdateReleaseAssetRequest) returns (UpdateReleaseAssetResponse);
79+ // DeleteReleaseAsset removes an asset.
80+ rpc DeleteReleaseAsset(DeleteReleaseAssetRequest) returns (DeleteReleaseAssetResponse);
81+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
82+ // 1 MiB. Resume with the offset after the last byte received. An offset
83+ // beyond the size gives out_of_range.
84+ rpc DownloadReleaseAsset(DownloadReleaseAssetRequest) returns (stream DownloadReleaseAssetResponse);
85+ // ListReleaseAssets lists uploaded assets, ordered by name.
86+ rpc ListReleaseAssets(ListReleaseAssetsRequest) returns (ListReleaseAssetsResponse);
87+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
88+ rpc GetReleaseUsage(GetReleaseUsageRequest) returns (GetReleaseUsageResponse);
89+}
90+
91+// CreateReleaseRequest is the request of ReleaseService.CreateRelease.
92+message CreateReleaseRequest {
93+ string repo = 1;
94+ string tag = 2;
95+ string target_commitish = 3;
96+ string title = 4;
97+ string notes = 5;
98+ bool draft = 6;
99+ bool prerelease = 7;
100+ // MakeLatest pins this published non-prerelease as latest. False does not pin the release.
101+ bool make_latest = 8;
102+}
103+
104+// CreateReleaseResponse is the response of ReleaseService.CreateRelease.
105+message CreateReleaseResponse {
106+ Release release = 1;
107+}
108+
109+// ListReleasesRequest is the request of ReleaseService.ListReleases.
110+message ListReleasesRequest {
111+ string repo = 1;
112+ // PageSize is the maximum count; zero uses the server default.
113+ int32 page_size = 2;
114+ // PageToken is next_page_token from the preceding page, or empty initially.
115+ string page_token = 3;
116+}
117+
118+// ListReleasesResponse is the response of ReleaseService.ListReleases.
119+message ListReleasesResponse {
120+ repeated Release releases = 1;
121+ string next_page_token = 2;
122+}
123+
124+// UpdateReleaseRequest is the request of ReleaseService.UpdateRelease.
125+message UpdateReleaseRequest {
126+ string repo = 1;
127+ int64 id = 2;
128+ string tag = 3;
129+ string target_commitish = 4;
130+ string title = 5;
131+ string notes = 6;
132+ bool draft = 7;
133+ bool prerelease = 8;
134+ // MakeLatest pins this published non-prerelease as latest. False does not pin the release.
135+ bool make_latest = 9;
136+ // UpdateMask names the fields to change; unknown paths are invalid_argument.
137+ google.protobuf.FieldMask update_mask = 10;
138+}
139+
140+// UpdateReleaseResponse is the response of ReleaseService.UpdateRelease.
141+message UpdateReleaseResponse {
142+ Release release = 1;
143+}
144+
145+// DeleteReleaseRequest is the request of ReleaseService.DeleteRelease.
146+message DeleteReleaseRequest {
147+ string repo = 1;
148+ int64 id = 2;
149+}
150+
151+// DeleteReleaseResponse is the response of ReleaseService.DeleteRelease.
152+message DeleteReleaseResponse {
153+}
154+
155+// UploadReleaseAssetRequest is the request of ReleaseService.UploadReleaseAsset.
156+message UploadReleaseAssetRequest {
157+ string repo = 1;
158+ int64 release_id = 2;
159+ string name = 3;
160+ string label = 4;
161+ string content_type = 5;
162+ int64 size = 6;
163+ bool replace = 7;
164+ bytes data = 8;
165+}
166+
167+// UploadReleaseAssetResponse is the response of ReleaseService.UploadReleaseAsset.
168+message UploadReleaseAssetResponse {
169+ ReleaseAsset asset = 1;
170+}
171+
172+// UpdateReleaseAssetRequest is the request of ReleaseService.UpdateReleaseAsset.
173+message UpdateReleaseAssetRequest {
174+ string repo = 1;
175+ int64 asset_id = 2;
176+ string name = 3;
177+ string label = 4;
178+ // UpdateMask names the fields to change; unknown paths are invalid_argument.
179+ google.protobuf.FieldMask update_mask = 5;
180+}
181+
182+// UpdateReleaseAssetResponse is the response of ReleaseService.UpdateReleaseAsset.
183+message UpdateReleaseAssetResponse {
184+ ReleaseAsset asset = 1;
185+}
186+
187+// DeleteReleaseAssetRequest is the request of ReleaseService.DeleteReleaseAsset.
188+message DeleteReleaseAssetRequest {
189+ string repo = 1;
190+ int64 asset_id = 2;
191+}
192+
193+// DeleteReleaseAssetResponse is the response of ReleaseService.DeleteReleaseAsset.
194+message DeleteReleaseAssetResponse {
195+}
196+
197+// DownloadReleaseAssetResponse is the response of ReleaseService.DownloadReleaseAsset.
198+message DownloadReleaseAssetResponse {
199+ ReleaseAsset asset = 1;
200+ bytes chunk = 2;
201+}
202+
203+// ListReleaseAssetsRequest is the request of ReleaseService.ListReleaseAssets.
204+message ListReleaseAssetsRequest {
205+ string repo = 1;
206+ int64 release_id = 2;
207+}
208+
209+// ListReleaseAssetsResponse is the response of ReleaseService.ListReleaseAssets.
210+message ListReleaseAssetsResponse {
211+ repeated ReleaseAsset assets = 1;
212+}
213+
214+// GetReleaseUsageRequest is the request of ReleaseService.GetReleaseUsage.
215+message GetReleaseUsageRequest {
216+ string repo = 1;
217+}
218+
219+// GetReleaseUsageResponse is the response of ReleaseService.GetReleaseUsage.
220+message GetReleaseUsageResponse {
221+ int64 used_bytes = 1;
222+ int64 quota_bytes = 2;
223+ int64 asset_max_bytes = 3;
224+ int32 assets_max = 4;
225+}
226+
227+// GetReleaseRequest selects exactly one release.
228+message GetReleaseRequest {
229+ string repo = 1;
230+ oneof selector {
231+ int64 id = 2;
232+ string tag = 3;
233+ bool latest = 4;
234+ }
235+}
236+
237+// ReleaseAssetTag selects a named asset of a tag.
238+message ReleaseAssetTag {
239+ string tag = 1;
240+ string name = 2;
241+}
242+
243+// ReleaseAssetLatest selects a named asset of the latest release.
244+message ReleaseAssetLatest {
245+ // Latest must be true.
246+ bool latest = 1;
247+ string name = 2;
248+}
249+
250+// DownloadReleaseAssetRequest selects an asset and a resume offset.
251+message DownloadReleaseAssetRequest {
252+ string repo = 1;
253+ oneof selector {
254+ int64 asset_id = 2;
255+ ReleaseAssetTag tag = 3;
256+ ReleaseAssetLatest latest = 4;
257+ }
258+ int64 offset = 5;
259+}
260+
261+// GetReleaseResponse contains the selected release.
262+message GetReleaseResponse {
263+ Release release = 1;
264+}
@@ -0,0 +1,264 @@
1+// SPDX-License-Identifier: MIT
2+
3+syntax = "proto3";
4+
5+package ermite;
6+
7+import "google/protobuf/field_mask.proto";
8+import "google/protobuf/timestamp.proto";
9+
10+// Release describes a tag and its notes. Drafts are visible only to writers.
11+message Release {
12+ int64 id = 1;
13+ string repo = 2;
14+ string tag = 3;
15+ string title = 4;
16+ string notes = 5;
17+ bool draft = 6;
18+ bool prerelease = 7;
19+ // Latest identifies the release returned by the latest selector, computed or pinned.
20+ bool latest = 8;
21+ // TargetCommitish is the tag's commit; empty for a draft without a tag.
22+ string target_commitish = 9;
23+ // Author is the label of the principal that created the release.
24+ string author = 10;
25+ google.protobuf.Timestamp created_at = 11;
26+ // PublishedAt is unset while draft.
27+ google.protobuf.Timestamp published_at = 12;
28+ google.protobuf.Timestamp updated_at = 13;
29+ // Assets contains uploaded assets only, ordered by name.
30+ repeated ReleaseAsset assets = 14;
31+}
32+
33+// ReleaseAsset describes an uploaded file, with a sha256:<hex> digest.
34+message ReleaseAsset {
35+ int64 id = 1;
36+ int64 release_id = 2;
37+ // Name is unique within the release, 1–255 characters, without slashes or controls.
38+ string name = 3;
39+ string label = 4;
40+ // ContentType defaults to application/octet-stream.
41+ string content_type = 5;
42+ int64 size = 6;
43+ string digest = 7;
44+ string uploader = 8;
45+ google.protobuf.Timestamp created_at = 9;
46+ google.protobuf.Timestamp updated_at = 10;
47+}
48+
49+// ReleaseService manages releases and their assets. Servers list "releases" in
50+// GetVersionResponse.features; other servers answer unimplemented.
51+// Published releases follow repository read access; drafts require write access.
52+// Unknown or unreadable repositories, releases and assets give not_found.
53+// Writes require release:write or a job token with contents: write for the repo;
54+// readers and branch-limited tokens receive permission_denied.
55+// Invalid names, media types or masks give invalid_argument. Size, asset count
56+// and repository quota limits give resource_exhausted and leave no stored upload.
57+service ReleaseService {
58+ // CreateRelease creates one release per tag (already_exists on duplication).
59+ // Publishing without an existing tag is failed_precondition, unless
60+ // target_commitish is supplied to create it; existing tags never move.
61+ rpc CreateRelease(CreateReleaseRequest) returns (CreateReleaseResponse);
62+ // GetRelease selects by id, tag or latest (latest must be true).
63+ rpc GetRelease(GetReleaseRequest) returns (GetReleaseResponse);
64+ // ListReleases lists newest first, including drafts only for writers.
65+ rpc ListReleases(ListReleasesRequest) returns (ListReleasesResponse);
66+ // UpdateRelease changes masked fields. Publishing requires an existing tag
67+ // or target_commitish to create it; otherwise failed_precondition.
68+ rpc UpdateRelease(UpdateReleaseRequest) returns (UpdateReleaseResponse);
69+ // DeleteRelease removes a release and its assets.
70+ rpc DeleteRelease(DeleteReleaseRequest) returns (DeleteReleaseResponse);
71+ // UploadReleaseAsset reserves size before reading. The first message carries
72+ // metadata; subsequent messages carry only data, at most 1 MiB per message.
73+ // Size must be nonnegative (-1 is refused). An interrupted stream stores no
74+ // asset. A taken name gives already_exists unless replace is true. Uploading
75+ // to a release of another repo gives failed_precondition.
76+ rpc UploadReleaseAsset(stream UploadReleaseAssetRequest) returns (UploadReleaseAssetResponse);
77+ // UpdateReleaseAsset changes masked name and label; a taken name gives already_exists.
78+ rpc UpdateReleaseAsset(UpdateReleaseAssetRequest) returns (UpdateReleaseAssetResponse);
79+ // DeleteReleaseAsset removes an asset.
80+ rpc DeleteReleaseAsset(DeleteReleaseAssetRequest) returns (DeleteReleaseAssetResponse);
81+ // DownloadReleaseAsset sends asset metadata first, then chunks of at most
82+ // 1 MiB. Resume with the offset after the last byte received. An offset
83+ // beyond the size gives out_of_range.
84+ rpc DownloadReleaseAsset(DownloadReleaseAssetRequest) returns (stream DownloadReleaseAssetResponse);
85+ // ListReleaseAssets lists uploaded assets, ordered by name.
86+ rpc ListReleaseAssets(ListReleaseAssetsRequest) returns (ListReleaseAssetsResponse);
87+ // GetReleaseUsage returns usage (including reserved uploads) and limits.
88+ rpc GetReleaseUsage(GetReleaseUsageRequest) returns (GetReleaseUsageResponse);
89+}
90+
91+// CreateReleaseRequest is the request of ReleaseService.CreateRelease.
92+message CreateReleaseRequest {
93+ string repo = 1;
94+ string tag = 2;
95+ string target_commitish = 3;
96+ string title = 4;
97+ string notes = 5;
98+ bool draft = 6;
99+ bool prerelease = 7;
100+ // MakeLatest pins this published non-prerelease as latest. False does not pin the release.
101+ bool make_latest = 8;
102+}
103+
104+// CreateReleaseResponse is the response of ReleaseService.CreateRelease.
105+message CreateReleaseResponse {
106+ Release release = 1;
107+}
108+
109+// ListReleasesRequest is the request of ReleaseService.ListReleases.
110+message ListReleasesRequest {
111+ string repo = 1;
112+ // PageSize is the maximum count; zero uses the server default.
113+ int32 page_size = 2;
114+ // PageToken is next_page_token from the preceding page, or empty initially.
115+ string page_token = 3;
116+}
117+
118+// ListReleasesResponse is the response of ReleaseService.ListReleases.
119+message ListReleasesResponse {
120+ repeated Release releases = 1;
121+ string next_page_token = 2;
122+}
123+
124+// UpdateReleaseRequest is the request of ReleaseService.UpdateRelease.
125+message UpdateReleaseRequest {
126+ string repo = 1;
127+ int64 id = 2;
128+ string tag = 3;
129+ string target_commitish = 4;
130+ string title = 5;
131+ string notes = 6;
132+ bool draft = 7;
133+ bool prerelease = 8;
134+ // MakeLatest pins this published non-prerelease as latest. False does not pin the release.
135+ bool make_latest = 9;
136+ // UpdateMask names the fields to change; unknown paths are invalid_argument.
137+ google.protobuf.FieldMask update_mask = 10;
138+}
139+
140+// UpdateReleaseResponse is the response of ReleaseService.UpdateRelease.
141+message UpdateReleaseResponse {
142+ Release release = 1;
143+}
144+
145+// DeleteReleaseRequest is the request of ReleaseService.DeleteRelease.
146+message DeleteReleaseRequest {
147+ string repo = 1;
148+ int64 id = 2;
149+}
150+
151+// DeleteReleaseResponse is the response of ReleaseService.DeleteRelease.
152+message DeleteReleaseResponse {
153+}
154+
155+// UploadReleaseAssetRequest is the request of ReleaseService.UploadReleaseAsset.
156+message UploadReleaseAssetRequest {
157+ string repo = 1;
158+ int64 release_id = 2;
159+ string name = 3;
160+ string label = 4;
161+ string content_type = 5;
162+ int64 size = 6;
163+ bool replace = 7;
164+ bytes data = 8;
165+}
166+
167+// UploadReleaseAssetResponse is the response of ReleaseService.UploadReleaseAsset.
168+message UploadReleaseAssetResponse {
169+ ReleaseAsset asset = 1;
170+}
171+
172+// UpdateReleaseAssetRequest is the request of ReleaseService.UpdateReleaseAsset.
173+message UpdateReleaseAssetRequest {
174+ string repo = 1;
175+ int64 asset_id = 2;
176+ string name = 3;
177+ string label = 4;
178+ // UpdateMask names the fields to change; unknown paths are invalid_argument.
179+ google.protobuf.FieldMask update_mask = 5;
180+}
181+
182+// UpdateReleaseAssetResponse is the response of ReleaseService.UpdateReleaseAsset.
183+message UpdateReleaseAssetResponse {
184+ ReleaseAsset asset = 1;
185+}
186+
187+// DeleteReleaseAssetRequest is the request of ReleaseService.DeleteReleaseAsset.
188+message DeleteReleaseAssetRequest {
189+ string repo = 1;
190+ int64 asset_id = 2;
191+}
192+
193+// DeleteReleaseAssetResponse is the response of ReleaseService.DeleteReleaseAsset.
194+message DeleteReleaseAssetResponse {
195+}
196+
197+// DownloadReleaseAssetResponse is the response of ReleaseService.DownloadReleaseAsset.
198+message DownloadReleaseAssetResponse {
199+ ReleaseAsset asset = 1;
200+ bytes chunk = 2;
201+}
202+
203+// ListReleaseAssetsRequest is the request of ReleaseService.ListReleaseAssets.
204+message ListReleaseAssetsRequest {
205+ string repo = 1;
206+ int64 release_id = 2;
207+}
208+
209+// ListReleaseAssetsResponse is the response of ReleaseService.ListReleaseAssets.
210+message ListReleaseAssetsResponse {
211+ repeated ReleaseAsset assets = 1;
212+}
213+
214+// GetReleaseUsageRequest is the request of ReleaseService.GetReleaseUsage.
215+message GetReleaseUsageRequest {
216+ string repo = 1;
217+}
218+
219+// GetReleaseUsageResponse is the response of ReleaseService.GetReleaseUsage.
220+message GetReleaseUsageResponse {
221+ int64 used_bytes = 1;
222+ int64 quota_bytes = 2;
223+ int64 asset_max_bytes = 3;
224+ int32 assets_max = 4;
225+}
226+
227+// GetReleaseRequest selects exactly one release.
228+message GetReleaseRequest {
229+ string repo = 1;
230+ oneof selector {
231+ int64 id = 2;
232+ string tag = 3;
233+ bool latest = 4;
234+ }
235+}
236+
237+// ReleaseAssetTag selects a named asset of a tag.
238+message ReleaseAssetTag {
239+ string tag = 1;
240+ string name = 2;
241+}
242+
243+// ReleaseAssetLatest selects a named asset of the latest release.
244+message ReleaseAssetLatest {
245+ // Latest must be true.
246+ bool latest = 1;
247+ string name = 2;
248+}
249+
250+// DownloadReleaseAssetRequest selects an asset and a resume offset.
251+message DownloadReleaseAssetRequest {
252+ string repo = 1;
253+ oneof selector {
254+ int64 asset_id = 2;
255+ ReleaseAssetTag tag = 3;
256+ ReleaseAssetLatest latest = 4;
257+ }
258+ int64 offset = 5;
259+}
260+
261+// GetReleaseResponse contains the selected release.
262+message GetReleaseResponse {
263+ Release release = 1;
264+}
M proto/ermite/server.proto +2 -1
@@ -64,7 +64,8 @@ message GetVersionResponse {
6464 // RepoSettings.allow_auto_merge, MergeRequest.auto_merge and auto_merged,
6565 // the EnableAutoMerge and CancelAutoMerge RPCs, the
6666 // MergeRequestAutoMergeEnabled and MergeRequestAutoMergeCancelled events
67- // and MergeRequestMerged.auto.
67+ // and MergeRequestMerged.auto. "releases" covers ReleaseService and the
68+ // release_published, release_updated, release_deleted and release_unpublished events.
6869 repeated string features = 2;
6970 }
7071
@@ -64,7 +64,8 @@ message GetVersionResponse {
64 // RepoSettings.allow_auto_merge, MergeRequest.auto_merge and auto_merged,64 // RepoSettings.allow_auto_merge, MergeRequest.auto_merge and auto_merged,
65 // the EnableAutoMerge and CancelAutoMerge RPCs, the65 // the EnableAutoMerge and CancelAutoMerge RPCs, the
66 // MergeRequestAutoMergeEnabled and MergeRequestAutoMergeCancelled events66 // MergeRequestAutoMergeEnabled and MergeRequestAutoMergeCancelled events
67- // and MergeRequestMerged.auto.67+ // and MergeRequestMerged.auto. "releases" covers ReleaseService and the
68+ // release_published, release_updated, release_deleted and release_unpublished events.
68 repeated string features = 2;69 repeated string features = 2;
69 }70 }
70 71
M proto/ermite/token.proto +3 -0
@@ -49,6 +49,9 @@ enum Scope {
4949 // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
5050 // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
5151 SCOPE_MR_FORCE_MERGE = 12;
52+ // SCOPE_RELEASE_WRITE allows creating, editing and deleting releases and their assets.
53+ // Wire name: release:write.
54+ SCOPE_RELEASE_WRITE = 13;
5255 }
5356
5457 // Token describes a stored token. It never contains the secret nor its hash.
@@ -49,6 +49,9 @@ enum Scope {
49 // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks49 // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
50 // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.50 // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
51 SCOPE_MR_FORCE_MERGE = 12;51 SCOPE_MR_FORCE_MERGE = 12;
52+ // SCOPE_RELEASE_WRITE allows creating, editing and deleting releases and their assets.
53+ // Wire name: release:write.
54+ SCOPE_RELEASE_WRITE = 13;
52 }55 }
53 56
54 // Token describes a stored token. It never contains the secret nor its hash.57 // Token describes a stored token. It never contains the secret nor its hash.

Keyboard shortcuts

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

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

Branches 2

Tags 18

↑↓ moveenter openesc close