detached 3130756

feat(api): add issue service, issues repo setting and issue:write scope

commit
31307565591ef7f7a6d4ec73137f80611c88bd55
author
brice · · 2026-10-19 05:15 UTC
committer
brice · · 2026-10-19 08:28 UTC
parent
11411cf
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
11 files · +2205 -115
M gen/ermite/ermiteconnect/event.connect.go +4 -2
@@ -48,7 +48,8 @@ type EventServiceClient interface {
4848 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
4949 // for merge requests, merge_request_opened, merge_request_merged,
5050 // merge_request_closed, comment_added, comment_edited, comment_deleted and
51- // comment_resolved (a thread resolved or reopened). Each one is delivered on the
51+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
52+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
5253 // "repo:<name>" topic of its repository and on "home", subject to the
5354 // visibility of the repository.
5455 //
@@ -121,7 +122,8 @@ type EventServiceHandler interface {
121122 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
122123 // for merge requests, merge_request_opened, merge_request_merged,
123124 // merge_request_closed, comment_added, comment_edited, comment_deleted and
124- // comment_resolved (a thread resolved or reopened). Each one is delivered on the
125+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
126+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
125127 // "repo:<name>" topic of its repository and on "home", subject to the
126128 // visibility of the repository.
127129 //
@@ -48,7 +48,8 @@ type EventServiceClient interface {
48 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,48 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
49 // for merge requests, merge_request_opened, merge_request_merged,49 // for merge requests, merge_request_opened, merge_request_merged,
50 // merge_request_closed, comment_added, comment_edited, comment_deleted and50 // merge_request_closed, comment_added, comment_edited, comment_deleted and
51- // comment_resolved (a thread resolved or reopened). Each one is delivered on the51+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
52+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
52 // "repo:<name>" topic of its repository and on "home", subject to the53 // "repo:<name>" topic of its repository and on "home", subject to the
53 // visibility of the repository.54 // visibility of the repository.
54 //55 //
@@ -121,7 +122,8 @@ type EventServiceHandler interface {
121 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,122 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
122 // for merge requests, merge_request_opened, merge_request_merged,123 // for merge requests, merge_request_opened, merge_request_merged,
123 // merge_request_closed, comment_added, comment_edited, comment_deleted and124 // merge_request_closed, comment_added, comment_edited, comment_deleted and
124- // comment_resolved (a thread resolved or reopened). Each one is delivered on the125+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
126+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
125 // "repo:<name>" topic of its repository and on "home", subject to the127 // "repo:<name>" topic of its repository and on "home", subject to the
126 // visibility of the repository.128 // visibility of the repository.
127 //129 //
A gen/ermite/ermiteconnect/issue.connect.go +265 -0
@@ -0,0 +1,265 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
4+//
5+// Source: ermite/issue.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+ // IssueServiceName is the fully-qualified name of the IssueService service.
27+ IssueServiceName = "ermite.IssueService"
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+ // IssueServiceCreateIssueProcedure is the fully-qualified name of the IssueService's CreateIssue
39+ // RPC.
40+ IssueServiceCreateIssueProcedure = "/ermite.IssueService/CreateIssue"
41+ // IssueServiceListIssuesProcedure is the fully-qualified name of the IssueService's ListIssues RPC.
42+ IssueServiceListIssuesProcedure = "/ermite.IssueService/ListIssues"
43+ // IssueServiceGetIssueProcedure is the fully-qualified name of the IssueService's GetIssue RPC.
44+ IssueServiceGetIssueProcedure = "/ermite.IssueService/GetIssue"
45+ // IssueServiceAddIssueCommentProcedure is the fully-qualified name of the IssueService's
46+ // AddIssueComment RPC.
47+ IssueServiceAddIssueCommentProcedure = "/ermite.IssueService/AddIssueComment"
48+ // IssueServiceCloseIssueProcedure is the fully-qualified name of the IssueService's CloseIssue RPC.
49+ IssueServiceCloseIssueProcedure = "/ermite.IssueService/CloseIssue"
50+ // IssueServiceReopenIssueProcedure is the fully-qualified name of the IssueService's ReopenIssue
51+ // RPC.
52+ IssueServiceReopenIssueProcedure = "/ermite.IssueService/ReopenIssue"
53+)
54+
55+// IssueServiceClient is a client for the ermite.IssueService service.
56+type IssueServiceClient interface {
57+ // CreateIssue opens an issue. Needs the issue:write scope.
58+ CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error)
59+ // ListIssues lists issues, highest number first, optionally in one state.
60+ ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error)
61+ // GetIssue returns an issue with its comments.
62+ GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error)
63+ // AddIssueComment adds a comment. Needs the issue:write scope.
64+ AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error)
65+ // CloseIssue closes an issue. Needs the issue:write scope.
66+ CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error)
67+ // ReopenIssue reopens an issue. Needs the issue:write scope.
68+ ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error)
69+}
70+
71+// NewIssueServiceClient constructs a client for the ermite.IssueService service. By default, it
72+// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
73+// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
74+// connect.WithGRPCWeb() options.
75+//
76+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
77+// http://api.acme.com or https://acme.com/grpc).
78+func NewIssueServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) IssueServiceClient {
79+ baseURL = strings.TrimRight(baseURL, "/")
80+ issueServiceMethods := ermite.File_ermite_issue_proto.Services().ByName("IssueService").Methods()
81+ return &issueServiceClient{
82+ createIssue: connect.NewClient[ermite.CreateIssueRequest, ermite.CreateIssueResponse](
83+ httpClient,
84+ baseURL+IssueServiceCreateIssueProcedure,
85+ connect.WithSchema(issueServiceMethods.ByName("CreateIssue")),
86+ connect.WithClientOptions(opts...),
87+ ),
88+ listIssues: connect.NewClient[ermite.ListIssuesRequest, ermite.ListIssuesResponse](
89+ httpClient,
90+ baseURL+IssueServiceListIssuesProcedure,
91+ connect.WithSchema(issueServiceMethods.ByName("ListIssues")),
92+ connect.WithClientOptions(opts...),
93+ ),
94+ getIssue: connect.NewClient[ermite.GetIssueRequest, ermite.GetIssueResponse](
95+ httpClient,
96+ baseURL+IssueServiceGetIssueProcedure,
97+ connect.WithSchema(issueServiceMethods.ByName("GetIssue")),
98+ connect.WithClientOptions(opts...),
99+ ),
100+ addIssueComment: connect.NewClient[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse](
101+ httpClient,
102+ baseURL+IssueServiceAddIssueCommentProcedure,
103+ connect.WithSchema(issueServiceMethods.ByName("AddIssueComment")),
104+ connect.WithClientOptions(opts...),
105+ ),
106+ closeIssue: connect.NewClient[ermite.CloseIssueRequest, ermite.CloseIssueResponse](
107+ httpClient,
108+ baseURL+IssueServiceCloseIssueProcedure,
109+ connect.WithSchema(issueServiceMethods.ByName("CloseIssue")),
110+ connect.WithClientOptions(opts...),
111+ ),
112+ reopenIssue: connect.NewClient[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse](
113+ httpClient,
114+ baseURL+IssueServiceReopenIssueProcedure,
115+ connect.WithSchema(issueServiceMethods.ByName("ReopenIssue")),
116+ connect.WithClientOptions(opts...),
117+ ),
118+ }
119+}
120+
121+// issueServiceClient implements IssueServiceClient.
122+type issueServiceClient struct {
123+ createIssue *connect.Client[ermite.CreateIssueRequest, ermite.CreateIssueResponse]
124+ listIssues *connect.Client[ermite.ListIssuesRequest, ermite.ListIssuesResponse]
125+ getIssue *connect.Client[ermite.GetIssueRequest, ermite.GetIssueResponse]
126+ addIssueComment *connect.Client[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse]
127+ closeIssue *connect.Client[ermite.CloseIssueRequest, ermite.CloseIssueResponse]
128+ reopenIssue *connect.Client[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse]
129+}
130+
131+// CreateIssue calls ermite.IssueService.CreateIssue.
132+func (c *issueServiceClient) CreateIssue(ctx context.Context, req *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error) {
133+ return c.createIssue.CallUnary(ctx, req)
134+}
135+
136+// ListIssues calls ermite.IssueService.ListIssues.
137+func (c *issueServiceClient) ListIssues(ctx context.Context, req *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error) {
138+ return c.listIssues.CallUnary(ctx, req)
139+}
140+
141+// GetIssue calls ermite.IssueService.GetIssue.
142+func (c *issueServiceClient) GetIssue(ctx context.Context, req *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error) {
143+ return c.getIssue.CallUnary(ctx, req)
144+}
145+
146+// AddIssueComment calls ermite.IssueService.AddIssueComment.
147+func (c *issueServiceClient) AddIssueComment(ctx context.Context, req *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) {
148+ return c.addIssueComment.CallUnary(ctx, req)
149+}
150+
151+// CloseIssue calls ermite.IssueService.CloseIssue.
152+func (c *issueServiceClient) CloseIssue(ctx context.Context, req *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) {
153+ return c.closeIssue.CallUnary(ctx, req)
154+}
155+
156+// ReopenIssue calls ermite.IssueService.ReopenIssue.
157+func (c *issueServiceClient) ReopenIssue(ctx context.Context, req *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) {
158+ return c.reopenIssue.CallUnary(ctx, req)
159+}
160+
161+// IssueServiceHandler is an implementation of the ermite.IssueService service.
162+type IssueServiceHandler interface {
163+ // CreateIssue opens an issue. Needs the issue:write scope.
164+ CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error)
165+ // ListIssues lists issues, highest number first, optionally in one state.
166+ ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error)
167+ // GetIssue returns an issue with its comments.
168+ GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error)
169+ // AddIssueComment adds a comment. Needs the issue:write scope.
170+ AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error)
171+ // CloseIssue closes an issue. Needs the issue:write scope.
172+ CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error)
173+ // ReopenIssue reopens an issue. Needs the issue:write scope.
174+ ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error)
175+}
176+
177+// NewIssueServiceHandler builds an HTTP handler from the service implementation. It returns the
178+// path on which to mount the handler and the handler itself.
179+//
180+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
181+// and JSON codecs. They also support gzip compression.
182+func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
183+ issueServiceMethods := ermite.File_ermite_issue_proto.Services().ByName("IssueService").Methods()
184+ issueServiceCreateIssueHandler := connect.NewUnaryHandler(
185+ IssueServiceCreateIssueProcedure,
186+ svc.CreateIssue,
187+ connect.WithSchema(issueServiceMethods.ByName("CreateIssue")),
188+ connect.WithHandlerOptions(opts...),
189+ )
190+ issueServiceListIssuesHandler := connect.NewUnaryHandler(
191+ IssueServiceListIssuesProcedure,
192+ svc.ListIssues,
193+ connect.WithSchema(issueServiceMethods.ByName("ListIssues")),
194+ connect.WithHandlerOptions(opts...),
195+ )
196+ issueServiceGetIssueHandler := connect.NewUnaryHandler(
197+ IssueServiceGetIssueProcedure,
198+ svc.GetIssue,
199+ connect.WithSchema(issueServiceMethods.ByName("GetIssue")),
200+ connect.WithHandlerOptions(opts...),
201+ )
202+ issueServiceAddIssueCommentHandler := connect.NewUnaryHandler(
203+ IssueServiceAddIssueCommentProcedure,
204+ svc.AddIssueComment,
205+ connect.WithSchema(issueServiceMethods.ByName("AddIssueComment")),
206+ connect.WithHandlerOptions(opts...),
207+ )
208+ issueServiceCloseIssueHandler := connect.NewUnaryHandler(
209+ IssueServiceCloseIssueProcedure,
210+ svc.CloseIssue,
211+ connect.WithSchema(issueServiceMethods.ByName("CloseIssue")),
212+ connect.WithHandlerOptions(opts...),
213+ )
214+ issueServiceReopenIssueHandler := connect.NewUnaryHandler(
215+ IssueServiceReopenIssueProcedure,
216+ svc.ReopenIssue,
217+ connect.WithSchema(issueServiceMethods.ByName("ReopenIssue")),
218+ connect.WithHandlerOptions(opts...),
219+ )
220+ return "/ermite.IssueService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
221+ switch r.URL.Path {
222+ case IssueServiceCreateIssueProcedure:
223+ issueServiceCreateIssueHandler.ServeHTTP(w, r)
224+ case IssueServiceListIssuesProcedure:
225+ issueServiceListIssuesHandler.ServeHTTP(w, r)
226+ case IssueServiceGetIssueProcedure:
227+ issueServiceGetIssueHandler.ServeHTTP(w, r)
228+ case IssueServiceAddIssueCommentProcedure:
229+ issueServiceAddIssueCommentHandler.ServeHTTP(w, r)
230+ case IssueServiceCloseIssueProcedure:
231+ issueServiceCloseIssueHandler.ServeHTTP(w, r)
232+ case IssueServiceReopenIssueProcedure:
233+ issueServiceReopenIssueHandler.ServeHTTP(w, r)
234+ default:
235+ http.NotFound(w, r)
236+ }
237+ })
238+}
239+
240+// UnimplementedIssueServiceHandler returns CodeUnimplemented from all methods.
241+type UnimplementedIssueServiceHandler struct{}
242+
243+func (UnimplementedIssueServiceHandler) CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error) {
244+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CreateIssue is not implemented"))
245+}
246+
247+func (UnimplementedIssueServiceHandler) ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error) {
248+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ListIssues is not implemented"))
249+}
250+
251+func (UnimplementedIssueServiceHandler) GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error) {
252+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.GetIssue is not implemented"))
253+}
254+
255+func (UnimplementedIssueServiceHandler) AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) {
256+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.AddIssueComment is not implemented"))
257+}
258+
259+func (UnimplementedIssueServiceHandler) CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) {
260+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CloseIssue is not implemented"))
261+}
262+
263+func (UnimplementedIssueServiceHandler) ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) {
264+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ReopenIssue is not implemented"))
265+}
@@ -0,0 +1,265 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-connect-go. DO NOT EDIT.
4+//
5+// Source: ermite/issue.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+ // IssueServiceName is the fully-qualified name of the IssueService service.
27+ IssueServiceName = "ermite.IssueService"
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+ // IssueServiceCreateIssueProcedure is the fully-qualified name of the IssueService's CreateIssue
39+ // RPC.
40+ IssueServiceCreateIssueProcedure = "/ermite.IssueService/CreateIssue"
41+ // IssueServiceListIssuesProcedure is the fully-qualified name of the IssueService's ListIssues RPC.
42+ IssueServiceListIssuesProcedure = "/ermite.IssueService/ListIssues"
43+ // IssueServiceGetIssueProcedure is the fully-qualified name of the IssueService's GetIssue RPC.
44+ IssueServiceGetIssueProcedure = "/ermite.IssueService/GetIssue"
45+ // IssueServiceAddIssueCommentProcedure is the fully-qualified name of the IssueService's
46+ // AddIssueComment RPC.
47+ IssueServiceAddIssueCommentProcedure = "/ermite.IssueService/AddIssueComment"
48+ // IssueServiceCloseIssueProcedure is the fully-qualified name of the IssueService's CloseIssue RPC.
49+ IssueServiceCloseIssueProcedure = "/ermite.IssueService/CloseIssue"
50+ // IssueServiceReopenIssueProcedure is the fully-qualified name of the IssueService's ReopenIssue
51+ // RPC.
52+ IssueServiceReopenIssueProcedure = "/ermite.IssueService/ReopenIssue"
53+)
54+
55+// IssueServiceClient is a client for the ermite.IssueService service.
56+type IssueServiceClient interface {
57+ // CreateIssue opens an issue. Needs the issue:write scope.
58+ CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error)
59+ // ListIssues lists issues, highest number first, optionally in one state.
60+ ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error)
61+ // GetIssue returns an issue with its comments.
62+ GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error)
63+ // AddIssueComment adds a comment. Needs the issue:write scope.
64+ AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error)
65+ // CloseIssue closes an issue. Needs the issue:write scope.
66+ CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error)
67+ // ReopenIssue reopens an issue. Needs the issue:write scope.
68+ ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error)
69+}
70+
71+// NewIssueServiceClient constructs a client for the ermite.IssueService service. By default, it
72+// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
73+// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
74+// connect.WithGRPCWeb() options.
75+//
76+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
77+// http://api.acme.com or https://acme.com/grpc).
78+func NewIssueServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) IssueServiceClient {
79+ baseURL = strings.TrimRight(baseURL, "/")
80+ issueServiceMethods := ermite.File_ermite_issue_proto.Services().ByName("IssueService").Methods()
81+ return &issueServiceClient{
82+ createIssue: connect.NewClient[ermite.CreateIssueRequest, ermite.CreateIssueResponse](
83+ httpClient,
84+ baseURL+IssueServiceCreateIssueProcedure,
85+ connect.WithSchema(issueServiceMethods.ByName("CreateIssue")),
86+ connect.WithClientOptions(opts...),
87+ ),
88+ listIssues: connect.NewClient[ermite.ListIssuesRequest, ermite.ListIssuesResponse](
89+ httpClient,
90+ baseURL+IssueServiceListIssuesProcedure,
91+ connect.WithSchema(issueServiceMethods.ByName("ListIssues")),
92+ connect.WithClientOptions(opts...),
93+ ),
94+ getIssue: connect.NewClient[ermite.GetIssueRequest, ermite.GetIssueResponse](
95+ httpClient,
96+ baseURL+IssueServiceGetIssueProcedure,
97+ connect.WithSchema(issueServiceMethods.ByName("GetIssue")),
98+ connect.WithClientOptions(opts...),
99+ ),
100+ addIssueComment: connect.NewClient[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse](
101+ httpClient,
102+ baseURL+IssueServiceAddIssueCommentProcedure,
103+ connect.WithSchema(issueServiceMethods.ByName("AddIssueComment")),
104+ connect.WithClientOptions(opts...),
105+ ),
106+ closeIssue: connect.NewClient[ermite.CloseIssueRequest, ermite.CloseIssueResponse](
107+ httpClient,
108+ baseURL+IssueServiceCloseIssueProcedure,
109+ connect.WithSchema(issueServiceMethods.ByName("CloseIssue")),
110+ connect.WithClientOptions(opts...),
111+ ),
112+ reopenIssue: connect.NewClient[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse](
113+ httpClient,
114+ baseURL+IssueServiceReopenIssueProcedure,
115+ connect.WithSchema(issueServiceMethods.ByName("ReopenIssue")),
116+ connect.WithClientOptions(opts...),
117+ ),
118+ }
119+}
120+
121+// issueServiceClient implements IssueServiceClient.
122+type issueServiceClient struct {
123+ createIssue *connect.Client[ermite.CreateIssueRequest, ermite.CreateIssueResponse]
124+ listIssues *connect.Client[ermite.ListIssuesRequest, ermite.ListIssuesResponse]
125+ getIssue *connect.Client[ermite.GetIssueRequest, ermite.GetIssueResponse]
126+ addIssueComment *connect.Client[ermite.AddIssueCommentRequest, ermite.AddIssueCommentResponse]
127+ closeIssue *connect.Client[ermite.CloseIssueRequest, ermite.CloseIssueResponse]
128+ reopenIssue *connect.Client[ermite.ReopenIssueRequest, ermite.ReopenIssueResponse]
129+}
130+
131+// CreateIssue calls ermite.IssueService.CreateIssue.
132+func (c *issueServiceClient) CreateIssue(ctx context.Context, req *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error) {
133+ return c.createIssue.CallUnary(ctx, req)
134+}
135+
136+// ListIssues calls ermite.IssueService.ListIssues.
137+func (c *issueServiceClient) ListIssues(ctx context.Context, req *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error) {
138+ return c.listIssues.CallUnary(ctx, req)
139+}
140+
141+// GetIssue calls ermite.IssueService.GetIssue.
142+func (c *issueServiceClient) GetIssue(ctx context.Context, req *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error) {
143+ return c.getIssue.CallUnary(ctx, req)
144+}
145+
146+// AddIssueComment calls ermite.IssueService.AddIssueComment.
147+func (c *issueServiceClient) AddIssueComment(ctx context.Context, req *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) {
148+ return c.addIssueComment.CallUnary(ctx, req)
149+}
150+
151+// CloseIssue calls ermite.IssueService.CloseIssue.
152+func (c *issueServiceClient) CloseIssue(ctx context.Context, req *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) {
153+ return c.closeIssue.CallUnary(ctx, req)
154+}
155+
156+// ReopenIssue calls ermite.IssueService.ReopenIssue.
157+func (c *issueServiceClient) ReopenIssue(ctx context.Context, req *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) {
158+ return c.reopenIssue.CallUnary(ctx, req)
159+}
160+
161+// IssueServiceHandler is an implementation of the ermite.IssueService service.
162+type IssueServiceHandler interface {
163+ // CreateIssue opens an issue. Needs the issue:write scope.
164+ CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error)
165+ // ListIssues lists issues, highest number first, optionally in one state.
166+ ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error)
167+ // GetIssue returns an issue with its comments.
168+ GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error)
169+ // AddIssueComment adds a comment. Needs the issue:write scope.
170+ AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error)
171+ // CloseIssue closes an issue. Needs the issue:write scope.
172+ CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error)
173+ // ReopenIssue reopens an issue. Needs the issue:write scope.
174+ ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error)
175+}
176+
177+// NewIssueServiceHandler builds an HTTP handler from the service implementation. It returns the
178+// path on which to mount the handler and the handler itself.
179+//
180+// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
181+// and JSON codecs. They also support gzip compression.
182+func NewIssueServiceHandler(svc IssueServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
183+ issueServiceMethods := ermite.File_ermite_issue_proto.Services().ByName("IssueService").Methods()
184+ issueServiceCreateIssueHandler := connect.NewUnaryHandler(
185+ IssueServiceCreateIssueProcedure,
186+ svc.CreateIssue,
187+ connect.WithSchema(issueServiceMethods.ByName("CreateIssue")),
188+ connect.WithHandlerOptions(opts...),
189+ )
190+ issueServiceListIssuesHandler := connect.NewUnaryHandler(
191+ IssueServiceListIssuesProcedure,
192+ svc.ListIssues,
193+ connect.WithSchema(issueServiceMethods.ByName("ListIssues")),
194+ connect.WithHandlerOptions(opts...),
195+ )
196+ issueServiceGetIssueHandler := connect.NewUnaryHandler(
197+ IssueServiceGetIssueProcedure,
198+ svc.GetIssue,
199+ connect.WithSchema(issueServiceMethods.ByName("GetIssue")),
200+ connect.WithHandlerOptions(opts...),
201+ )
202+ issueServiceAddIssueCommentHandler := connect.NewUnaryHandler(
203+ IssueServiceAddIssueCommentProcedure,
204+ svc.AddIssueComment,
205+ connect.WithSchema(issueServiceMethods.ByName("AddIssueComment")),
206+ connect.WithHandlerOptions(opts...),
207+ )
208+ issueServiceCloseIssueHandler := connect.NewUnaryHandler(
209+ IssueServiceCloseIssueProcedure,
210+ svc.CloseIssue,
211+ connect.WithSchema(issueServiceMethods.ByName("CloseIssue")),
212+ connect.WithHandlerOptions(opts...),
213+ )
214+ issueServiceReopenIssueHandler := connect.NewUnaryHandler(
215+ IssueServiceReopenIssueProcedure,
216+ svc.ReopenIssue,
217+ connect.WithSchema(issueServiceMethods.ByName("ReopenIssue")),
218+ connect.WithHandlerOptions(opts...),
219+ )
220+ return "/ermite.IssueService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
221+ switch r.URL.Path {
222+ case IssueServiceCreateIssueProcedure:
223+ issueServiceCreateIssueHandler.ServeHTTP(w, r)
224+ case IssueServiceListIssuesProcedure:
225+ issueServiceListIssuesHandler.ServeHTTP(w, r)
226+ case IssueServiceGetIssueProcedure:
227+ issueServiceGetIssueHandler.ServeHTTP(w, r)
228+ case IssueServiceAddIssueCommentProcedure:
229+ issueServiceAddIssueCommentHandler.ServeHTTP(w, r)
230+ case IssueServiceCloseIssueProcedure:
231+ issueServiceCloseIssueHandler.ServeHTTP(w, r)
232+ case IssueServiceReopenIssueProcedure:
233+ issueServiceReopenIssueHandler.ServeHTTP(w, r)
234+ default:
235+ http.NotFound(w, r)
236+ }
237+ })
238+}
239+
240+// UnimplementedIssueServiceHandler returns CodeUnimplemented from all methods.
241+type UnimplementedIssueServiceHandler struct{}
242+
243+func (UnimplementedIssueServiceHandler) CreateIssue(context.Context, *connect.Request[ermite.CreateIssueRequest]) (*connect.Response[ermite.CreateIssueResponse], error) {
244+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CreateIssue is not implemented"))
245+}
246+
247+func (UnimplementedIssueServiceHandler) ListIssues(context.Context, *connect.Request[ermite.ListIssuesRequest]) (*connect.Response[ermite.ListIssuesResponse], error) {
248+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ListIssues is not implemented"))
249+}
250+
251+func (UnimplementedIssueServiceHandler) GetIssue(context.Context, *connect.Request[ermite.GetIssueRequest]) (*connect.Response[ermite.GetIssueResponse], error) {
252+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.GetIssue is not implemented"))
253+}
254+
255+func (UnimplementedIssueServiceHandler) AddIssueComment(context.Context, *connect.Request[ermite.AddIssueCommentRequest]) (*connect.Response[ermite.AddIssueCommentResponse], error) {
256+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.AddIssueComment is not implemented"))
257+}
258+
259+func (UnimplementedIssueServiceHandler) CloseIssue(context.Context, *connect.Request[ermite.CloseIssueRequest]) (*connect.Response[ermite.CloseIssueResponse], error) {
260+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.CloseIssue is not implemented"))
261+}
262+
263+func (UnimplementedIssueServiceHandler) ReopenIssue(context.Context, *connect.Request[ermite.ReopenIssueRequest]) (*connect.Response[ermite.ReopenIssueResponse], error) {
264+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.IssueService.ReopenIssue is not implemented"))
265+}
M gen/ermite/event.pb.go +352 -48 generated file: collapsed
A gen/ermite/issue.pb.go +1108 -0
@@ -0,0 +1,1108 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-go. DO NOT EDIT.
4+// versions:
5+// protoc-gen-go v1.36.12
6+// protoc (unknown)
7+// source: ermite/issue.proto
8+
9+package ermite
10+
11+import (
12+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
13+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
14+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
15+ reflect "reflect"
16+ sync "sync"
17+ unsafe "unsafe"
18+)
19+
20+const (
21+ // Verify that this generated code is sufficiently up-to-date.
22+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
23+ // Verify that runtime/protoimpl is sufficiently up-to-date.
24+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
25+)
26+
27+// IssueState is where an issue is in its life.
28+type IssueState int32
29+
30+const (
31+ // Not set. In ListIssuesRequest.state it means every state. Never returned
32+ // by the server.
33+ IssueState_ISSUE_STATE_UNSPECIFIED IssueState = 0
34+ // The issue is open.
35+ IssueState_ISSUE_STATE_OPEN IssueState = 1
36+ // The issue is closed.
37+ IssueState_ISSUE_STATE_CLOSED IssueState = 2
38+ // Reserved for later use: awaiting moderation, owner-only.
39+ IssueState_ISSUE_STATE_PENDING IssueState = 3
40+)
41+
42+// Enum value maps for IssueState.
43+var (
44+ IssueState_name = map[int32]string{
45+ 0: "ISSUE_STATE_UNSPECIFIED",
46+ 1: "ISSUE_STATE_OPEN",
47+ 2: "ISSUE_STATE_CLOSED",
48+ 3: "ISSUE_STATE_PENDING",
49+ }
50+ IssueState_value = map[string]int32{
51+ "ISSUE_STATE_UNSPECIFIED": 0,
52+ "ISSUE_STATE_OPEN": 1,
53+ "ISSUE_STATE_CLOSED": 2,
54+ "ISSUE_STATE_PENDING": 3,
55+ }
56+)
57+
58+func (x IssueState) Enum() *IssueState {
59+ p := new(IssueState)
60+ *p = x
61+ return p
62+}
63+
64+func (x IssueState) String() string {
65+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
66+}
67+
68+func (IssueState) Descriptor() protoreflect.EnumDescriptor {
69+ return file_ermite_issue_proto_enumTypes[0].Descriptor()
70+}
71+
72+func (IssueState) Type() protoreflect.EnumType {
73+ return &file_ermite_issue_proto_enumTypes[0]
74+}
75+
76+func (x IssueState) Number() protoreflect.EnumNumber {
77+ return protoreflect.EnumNumber(x)
78+}
79+
80+// Deprecated: Use IssueState.Descriptor instead.
81+func (IssueState) EnumDescriptor() ([]byte, []int) {
82+ return file_ermite_issue_proto_rawDescGZIP(), []int{0}
83+}
84+
85+// Issue is a discussion in a repository.
86+type Issue struct {
87+ state protoimpl.MessageState `protogen:"open.v1"`
88+ // Repo is the name of the repository.
89+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
90+ // Number identifies the issue within its repository.
91+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
92+ // Title is the one-line title.
93+ Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"`
94+ // Body is the content of the issue. It may be empty.
95+ Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
96+ // State is where the issue is in its life.
97+ State IssueState `protobuf:"varint,5,opt,name=state,proto3,enum=ermite.IssueState" json:"state,omitempty"`
98+ // Author names who created the issue: the label of the token that was used,
99+ // "root" for the root token, or "owner" for a web session. It is
100+ // informational: labels are not unique and the token may be gone.
101+ Author string `protobuf:"bytes,6,opt,name=author,proto3" json:"author,omitempty"`
102+ // CreatedAt is when the issue was created.
103+ CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
104+ // UpdatedAt is when the issue last changed.
105+ UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
106+ // CommentCount is the number of comments on the issue.
107+ CommentCount int32 `protobuf:"varint,9,opt,name=comment_count,json=commentCount,proto3" json:"comment_count,omitempty"`
108+ unknownFields protoimpl.UnknownFields
109+ sizeCache protoimpl.SizeCache
110+}
111+
112+func (x *Issue) Reset() {
113+ *x = Issue{}
114+ mi := &file_ermite_issue_proto_msgTypes[0]
115+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
116+ ms.StoreMessageInfo(mi)
117+}
118+
119+func (x *Issue) String() string {
120+ return protoimpl.X.MessageStringOf(x)
121+}
122+
123+func (*Issue) ProtoMessage() {}
124+
125+func (x *Issue) ProtoReflect() protoreflect.Message {
126+ mi := &file_ermite_issue_proto_msgTypes[0]
127+ if x != nil {
128+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
129+ if ms.LoadMessageInfo() == nil {
130+ ms.StoreMessageInfo(mi)
131+ }
132+ return ms
133+ }
134+ return mi.MessageOf(x)
135+}
136+
137+// Deprecated: Use Issue.ProtoReflect.Descriptor instead.
138+func (*Issue) Descriptor() ([]byte, []int) {
139+ return file_ermite_issue_proto_rawDescGZIP(), []int{0}
140+}
141+
142+func (x *Issue) GetRepo() string {
143+ if x != nil {
144+ return x.Repo
145+ }
146+ return ""
147+}
148+
149+func (x *Issue) GetNumber() int64 {
150+ if x != nil {
151+ return x.Number
152+ }
153+ return 0
154+}
155+
156+func (x *Issue) GetTitle() string {
157+ if x != nil {
158+ return x.Title
159+ }
160+ return ""
161+}
162+
163+func (x *Issue) GetBody() string {
164+ if x != nil {
165+ return x.Body
166+ }
167+ return ""
168+}
169+
170+func (x *Issue) GetState() IssueState {
171+ if x != nil {
172+ return x.State
173+ }
174+ return IssueState_ISSUE_STATE_UNSPECIFIED
175+}
176+
177+func (x *Issue) GetAuthor() string {
178+ if x != nil {
179+ return x.Author
180+ }
181+ return ""
182+}
183+
184+func (x *Issue) GetCreatedAt() *timestamppb.Timestamp {
185+ if x != nil {
186+ return x.CreatedAt
187+ }
188+ return nil
189+}
190+
191+func (x *Issue) GetUpdatedAt() *timestamppb.Timestamp {
192+ if x != nil {
193+ return x.UpdatedAt
194+ }
195+ return nil
196+}
197+
198+func (x *Issue) GetCommentCount() int32 {
199+ if x != nil {
200+ return x.CommentCount
201+ }
202+ return 0
203+}
204+
205+// IssueComment is a note on an issue.
206+type IssueComment struct {
207+ state protoimpl.MessageState `protogen:"open.v1"`
208+ // Id identifies the comment within its issue. Opaque.
209+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
210+ // Author names who wrote the comment, like Issue.author.
211+ Author string `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"`
212+ // Text is the content of the comment.
213+ Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
214+ // CreatedAt is when the comment was written.
215+ CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
216+ unknownFields protoimpl.UnknownFields
217+ sizeCache protoimpl.SizeCache
218+}
219+
220+func (x *IssueComment) Reset() {
221+ *x = IssueComment{}
222+ mi := &file_ermite_issue_proto_msgTypes[1]
223+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
224+ ms.StoreMessageInfo(mi)
225+}
226+
227+func (x *IssueComment) String() string {
228+ return protoimpl.X.MessageStringOf(x)
229+}
230+
231+func (*IssueComment) ProtoMessage() {}
232+
233+func (x *IssueComment) ProtoReflect() protoreflect.Message {
234+ mi := &file_ermite_issue_proto_msgTypes[1]
235+ if x != nil {
236+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
237+ if ms.LoadMessageInfo() == nil {
238+ ms.StoreMessageInfo(mi)
239+ }
240+ return ms
241+ }
242+ return mi.MessageOf(x)
243+}
244+
245+// Deprecated: Use IssueComment.ProtoReflect.Descriptor instead.
246+func (*IssueComment) Descriptor() ([]byte, []int) {
247+ return file_ermite_issue_proto_rawDescGZIP(), []int{1}
248+}
249+
250+func (x *IssueComment) GetId() string {
251+ if x != nil {
252+ return x.Id
253+ }
254+ return ""
255+}
256+
257+func (x *IssueComment) GetAuthor() string {
258+ if x != nil {
259+ return x.Author
260+ }
261+ return ""
262+}
263+
264+func (x *IssueComment) GetText() string {
265+ if x != nil {
266+ return x.Text
267+ }
268+ return ""
269+}
270+
271+func (x *IssueComment) GetCreatedAt() *timestamppb.Timestamp {
272+ if x != nil {
273+ return x.CreatedAt
274+ }
275+ return nil
276+}
277+
278+// CreateIssueRequest describes the issue to open.
279+type CreateIssueRequest struct {
280+ state protoimpl.MessageState `protogen:"open.v1"`
281+ // Repo is the repository name.
282+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
283+ // Title is the one-line title. Required.
284+ Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
285+ // Body is the optional content.
286+ Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
287+ unknownFields protoimpl.UnknownFields
288+ sizeCache protoimpl.SizeCache
289+}
290+
291+func (x *CreateIssueRequest) Reset() {
292+ *x = CreateIssueRequest{}
293+ mi := &file_ermite_issue_proto_msgTypes[2]
294+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
295+ ms.StoreMessageInfo(mi)
296+}
297+
298+func (x *CreateIssueRequest) String() string {
299+ return protoimpl.X.MessageStringOf(x)
300+}
301+
302+func (*CreateIssueRequest) ProtoMessage() {}
303+
304+func (x *CreateIssueRequest) ProtoReflect() protoreflect.Message {
305+ mi := &file_ermite_issue_proto_msgTypes[2]
306+ if x != nil {
307+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
308+ if ms.LoadMessageInfo() == nil {
309+ ms.StoreMessageInfo(mi)
310+ }
311+ return ms
312+ }
313+ return mi.MessageOf(x)
314+}
315+
316+// Deprecated: Use CreateIssueRequest.ProtoReflect.Descriptor instead.
317+func (*CreateIssueRequest) Descriptor() ([]byte, []int) {
318+ return file_ermite_issue_proto_rawDescGZIP(), []int{2}
319+}
320+
321+func (x *CreateIssueRequest) GetRepo() string {
322+ if x != nil {
323+ return x.Repo
324+ }
325+ return ""
326+}
327+
328+func (x *CreateIssueRequest) GetTitle() string {
329+ if x != nil {
330+ return x.Title
331+ }
332+ return ""
333+}
334+
335+func (x *CreateIssueRequest) GetBody() string {
336+ if x != nil {
337+ return x.Body
338+ }
339+ return ""
340+}
341+
342+// CreateIssueResponse holds the new issue.
343+type CreateIssueResponse struct {
344+ state protoimpl.MessageState `protogen:"open.v1"`
345+ // Issue is the created issue.
346+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
347+ unknownFields protoimpl.UnknownFields
348+ sizeCache protoimpl.SizeCache
349+}
350+
351+func (x *CreateIssueResponse) Reset() {
352+ *x = CreateIssueResponse{}
353+ mi := &file_ermite_issue_proto_msgTypes[3]
354+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
355+ ms.StoreMessageInfo(mi)
356+}
357+
358+func (x *CreateIssueResponse) String() string {
359+ return protoimpl.X.MessageStringOf(x)
360+}
361+
362+func (*CreateIssueResponse) ProtoMessage() {}
363+
364+func (x *CreateIssueResponse) ProtoReflect() protoreflect.Message {
365+ mi := &file_ermite_issue_proto_msgTypes[3]
366+ if x != nil {
367+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
368+ if ms.LoadMessageInfo() == nil {
369+ ms.StoreMessageInfo(mi)
370+ }
371+ return ms
372+ }
373+ return mi.MessageOf(x)
374+}
375+
376+// Deprecated: Use CreateIssueResponse.ProtoReflect.Descriptor instead.
377+func (*CreateIssueResponse) Descriptor() ([]byte, []int) {
378+ return file_ermite_issue_proto_rawDescGZIP(), []int{3}
379+}
380+
381+func (x *CreateIssueResponse) GetIssue() *Issue {
382+ if x != nil {
383+ return x.Issue
384+ }
385+ return nil
386+}
387+
388+// ListIssuesRequest selects a page of issues.
389+type ListIssuesRequest struct {
390+ state protoimpl.MessageState `protogen:"open.v1"`
391+ // Repo is the repository name.
392+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
393+ // State restricts the result to one state. ISSUE_STATE_UNSPECIFIED means
394+ // every state.
395+ State IssueState `protobuf:"varint,2,opt,name=state,proto3,enum=ermite.IssueState" json:"state,omitempty"`
396+ // PageSize is the maximum number of issues to return. 0 means the server
397+ // default; values above the server maximum are lowered to it.
398+ PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
399+ // PageToken is the next_page_token of a previous response, to continue the
400+ // same listing. Empty for the first page. Other fields must be unchanged.
401+ PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"`
402+ unknownFields protoimpl.UnknownFields
403+ sizeCache protoimpl.SizeCache
404+}
405+
406+func (x *ListIssuesRequest) Reset() {
407+ *x = ListIssuesRequest{}
408+ mi := &file_ermite_issue_proto_msgTypes[4]
409+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
410+ ms.StoreMessageInfo(mi)
411+}
412+
413+func (x *ListIssuesRequest) String() string {
414+ return protoimpl.X.MessageStringOf(x)
415+}
416+
417+func (*ListIssuesRequest) ProtoMessage() {}
418+
419+func (x *ListIssuesRequest) ProtoReflect() protoreflect.Message {
420+ mi := &file_ermite_issue_proto_msgTypes[4]
421+ if x != nil {
422+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
423+ if ms.LoadMessageInfo() == nil {
424+ ms.StoreMessageInfo(mi)
425+ }
426+ return ms
427+ }
428+ return mi.MessageOf(x)
429+}
430+
431+// Deprecated: Use ListIssuesRequest.ProtoReflect.Descriptor instead.
432+func (*ListIssuesRequest) Descriptor() ([]byte, []int) {
433+ return file_ermite_issue_proto_rawDescGZIP(), []int{4}
434+}
435+
436+func (x *ListIssuesRequest) GetRepo() string {
437+ if x != nil {
438+ return x.Repo
439+ }
440+ return ""
441+}
442+
443+func (x *ListIssuesRequest) GetState() IssueState {
444+ if x != nil {
445+ return x.State
446+ }
447+ return IssueState_ISSUE_STATE_UNSPECIFIED
448+}
449+
450+func (x *ListIssuesRequest) GetPageSize() int32 {
451+ if x != nil {
452+ return x.PageSize
453+ }
454+ return 0
455+}
456+
457+func (x *ListIssuesRequest) GetPageToken() string {
458+ if x != nil {
459+ return x.PageToken
460+ }
461+ return ""
462+}
463+
464+// ListIssuesResponse is one page of issues.
465+type ListIssuesResponse struct {
466+ state protoimpl.MessageState `protogen:"open.v1"`
467+ // Issues are the issues of this page, highest number first.
468+ Issues []*Issue `protobuf:"bytes,1,rep,name=issues,proto3" json:"issues,omitempty"`
469+ // NextPageToken is passed as page_token to get the next page. Empty when
470+ // there is no next page.
471+ NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
472+ unknownFields protoimpl.UnknownFields
473+ sizeCache protoimpl.SizeCache
474+}
475+
476+func (x *ListIssuesResponse) Reset() {
477+ *x = ListIssuesResponse{}
478+ mi := &file_ermite_issue_proto_msgTypes[5]
479+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
480+ ms.StoreMessageInfo(mi)
481+}
482+
483+func (x *ListIssuesResponse) String() string {
484+ return protoimpl.X.MessageStringOf(x)
485+}
486+
487+func (*ListIssuesResponse) ProtoMessage() {}
488+
489+func (x *ListIssuesResponse) ProtoReflect() protoreflect.Message {
490+ mi := &file_ermite_issue_proto_msgTypes[5]
491+ if x != nil {
492+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
493+ if ms.LoadMessageInfo() == nil {
494+ ms.StoreMessageInfo(mi)
495+ }
496+ return ms
497+ }
498+ return mi.MessageOf(x)
499+}
500+
501+// Deprecated: Use ListIssuesResponse.ProtoReflect.Descriptor instead.
502+func (*ListIssuesResponse) Descriptor() ([]byte, []int) {
503+ return file_ermite_issue_proto_rawDescGZIP(), []int{5}
504+}
505+
506+func (x *ListIssuesResponse) GetIssues() []*Issue {
507+ if x != nil {
508+ return x.Issues
509+ }
510+ return nil
511+}
512+
513+func (x *ListIssuesResponse) GetNextPageToken() string {
514+ if x != nil {
515+ return x.NextPageToken
516+ }
517+ return ""
518+}
519+
520+// GetIssueRequest selects an issue.
521+type GetIssueRequest struct {
522+ state protoimpl.MessageState `protogen:"open.v1"`
523+ // Repo is the repository name.
524+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
525+ // Number is the issue number.
526+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
527+ unknownFields protoimpl.UnknownFields
528+ sizeCache protoimpl.SizeCache
529+}
530+
531+func (x *GetIssueRequest) Reset() {
532+ *x = GetIssueRequest{}
533+ mi := &file_ermite_issue_proto_msgTypes[6]
534+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
535+ ms.StoreMessageInfo(mi)
536+}
537+
538+func (x *GetIssueRequest) String() string {
539+ return protoimpl.X.MessageStringOf(x)
540+}
541+
542+func (*GetIssueRequest) ProtoMessage() {}
543+
544+func (x *GetIssueRequest) ProtoReflect() protoreflect.Message {
545+ mi := &file_ermite_issue_proto_msgTypes[6]
546+ if x != nil {
547+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
548+ if ms.LoadMessageInfo() == nil {
549+ ms.StoreMessageInfo(mi)
550+ }
551+ return ms
552+ }
553+ return mi.MessageOf(x)
554+}
555+
556+// Deprecated: Use GetIssueRequest.ProtoReflect.Descriptor instead.
557+func (*GetIssueRequest) Descriptor() ([]byte, []int) {
558+ return file_ermite_issue_proto_rawDescGZIP(), []int{6}
559+}
560+
561+func (x *GetIssueRequest) GetRepo() string {
562+ if x != nil {
563+ return x.Repo
564+ }
565+ return ""
566+}
567+
568+func (x *GetIssueRequest) GetNumber() int64 {
569+ if x != nil {
570+ return x.Number
571+ }
572+ return 0
573+}
574+
575+// GetIssueResponse holds an issue with its comments.
576+type GetIssueResponse struct {
577+ state protoimpl.MessageState `protogen:"open.v1"`
578+ // Issue is the issue.
579+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
580+ // Comments are every comment of the issue, oldest first.
581+ Comments []*IssueComment `protobuf:"bytes,2,rep,name=comments,proto3" json:"comments,omitempty"`
582+ unknownFields protoimpl.UnknownFields
583+ sizeCache protoimpl.SizeCache
584+}
585+
586+func (x *GetIssueResponse) Reset() {
587+ *x = GetIssueResponse{}
588+ mi := &file_ermite_issue_proto_msgTypes[7]
589+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
590+ ms.StoreMessageInfo(mi)
591+}
592+
593+func (x *GetIssueResponse) String() string {
594+ return protoimpl.X.MessageStringOf(x)
595+}
596+
597+func (*GetIssueResponse) ProtoMessage() {}
598+
599+func (x *GetIssueResponse) ProtoReflect() protoreflect.Message {
600+ mi := &file_ermite_issue_proto_msgTypes[7]
601+ if x != nil {
602+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
603+ if ms.LoadMessageInfo() == nil {
604+ ms.StoreMessageInfo(mi)
605+ }
606+ return ms
607+ }
608+ return mi.MessageOf(x)
609+}
610+
611+// Deprecated: Use GetIssueResponse.ProtoReflect.Descriptor instead.
612+func (*GetIssueResponse) Descriptor() ([]byte, []int) {
613+ return file_ermite_issue_proto_rawDescGZIP(), []int{7}
614+}
615+
616+func (x *GetIssueResponse) GetIssue() *Issue {
617+ if x != nil {
618+ return x.Issue
619+ }
620+ return nil
621+}
622+
623+func (x *GetIssueResponse) GetComments() []*IssueComment {
624+ if x != nil {
625+ return x.Comments
626+ }
627+ return nil
628+}
629+
630+// AddIssueCommentRequest describes the comment to add.
631+type AddIssueCommentRequest struct {
632+ state protoimpl.MessageState `protogen:"open.v1"`
633+ // Repo is the repository name.
634+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
635+ // Number is the issue number.
636+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
637+ // Text is the content. Required.
638+ Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
639+ unknownFields protoimpl.UnknownFields
640+ sizeCache protoimpl.SizeCache
641+}
642+
643+func (x *AddIssueCommentRequest) Reset() {
644+ *x = AddIssueCommentRequest{}
645+ mi := &file_ermite_issue_proto_msgTypes[8]
646+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
647+ ms.StoreMessageInfo(mi)
648+}
649+
650+func (x *AddIssueCommentRequest) String() string {
651+ return protoimpl.X.MessageStringOf(x)
652+}
653+
654+func (*AddIssueCommentRequest) ProtoMessage() {}
655+
656+func (x *AddIssueCommentRequest) ProtoReflect() protoreflect.Message {
657+ mi := &file_ermite_issue_proto_msgTypes[8]
658+ if x != nil {
659+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
660+ if ms.LoadMessageInfo() == nil {
661+ ms.StoreMessageInfo(mi)
662+ }
663+ return ms
664+ }
665+ return mi.MessageOf(x)
666+}
667+
668+// Deprecated: Use AddIssueCommentRequest.ProtoReflect.Descriptor instead.
669+func (*AddIssueCommentRequest) Descriptor() ([]byte, []int) {
670+ return file_ermite_issue_proto_rawDescGZIP(), []int{8}
671+}
672+
673+func (x *AddIssueCommentRequest) GetRepo() string {
674+ if x != nil {
675+ return x.Repo
676+ }
677+ return ""
678+}
679+
680+func (x *AddIssueCommentRequest) GetNumber() int64 {
681+ if x != nil {
682+ return x.Number
683+ }
684+ return 0
685+}
686+
687+func (x *AddIssueCommentRequest) GetText() string {
688+ if x != nil {
689+ return x.Text
690+ }
691+ return ""
692+}
693+
694+// AddIssueCommentResponse holds the new comment.
695+type AddIssueCommentResponse struct {
696+ state protoimpl.MessageState `protogen:"open.v1"`
697+ // Comment is the created comment.
698+ Comment *IssueComment `protobuf:"bytes,1,opt,name=comment,proto3" json:"comment,omitempty"`
699+ unknownFields protoimpl.UnknownFields
700+ sizeCache protoimpl.SizeCache
701+}
702+
703+func (x *AddIssueCommentResponse) Reset() {
704+ *x = AddIssueCommentResponse{}
705+ mi := &file_ermite_issue_proto_msgTypes[9]
706+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
707+ ms.StoreMessageInfo(mi)
708+}
709+
710+func (x *AddIssueCommentResponse) String() string {
711+ return protoimpl.X.MessageStringOf(x)
712+}
713+
714+func (*AddIssueCommentResponse) ProtoMessage() {}
715+
716+func (x *AddIssueCommentResponse) ProtoReflect() protoreflect.Message {
717+ mi := &file_ermite_issue_proto_msgTypes[9]
718+ if x != nil {
719+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
720+ if ms.LoadMessageInfo() == nil {
721+ ms.StoreMessageInfo(mi)
722+ }
723+ return ms
724+ }
725+ return mi.MessageOf(x)
726+}
727+
728+// Deprecated: Use AddIssueCommentResponse.ProtoReflect.Descriptor instead.
729+func (*AddIssueCommentResponse) Descriptor() ([]byte, []int) {
730+ return file_ermite_issue_proto_rawDescGZIP(), []int{9}
731+}
732+
733+func (x *AddIssueCommentResponse) GetComment() *IssueComment {
734+ if x != nil {
735+ return x.Comment
736+ }
737+ return nil
738+}
739+
740+// CloseIssueRequest names the issue to close.
741+type CloseIssueRequest struct {
742+ state protoimpl.MessageState `protogen:"open.v1"`
743+ // Repo is the repository name.
744+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
745+ // Number is the issue number.
746+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
747+ unknownFields protoimpl.UnknownFields
748+ sizeCache protoimpl.SizeCache
749+}
750+
751+func (x *CloseIssueRequest) Reset() {
752+ *x = CloseIssueRequest{}
753+ mi := &file_ermite_issue_proto_msgTypes[10]
754+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
755+ ms.StoreMessageInfo(mi)
756+}
757+
758+func (x *CloseIssueRequest) String() string {
759+ return protoimpl.X.MessageStringOf(x)
760+}
761+
762+func (*CloseIssueRequest) ProtoMessage() {}
763+
764+func (x *CloseIssueRequest) ProtoReflect() protoreflect.Message {
765+ mi := &file_ermite_issue_proto_msgTypes[10]
766+ if x != nil {
767+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
768+ if ms.LoadMessageInfo() == nil {
769+ ms.StoreMessageInfo(mi)
770+ }
771+ return ms
772+ }
773+ return mi.MessageOf(x)
774+}
775+
776+// Deprecated: Use CloseIssueRequest.ProtoReflect.Descriptor instead.
777+func (*CloseIssueRequest) Descriptor() ([]byte, []int) {
778+ return file_ermite_issue_proto_rawDescGZIP(), []int{10}
779+}
780+
781+func (x *CloseIssueRequest) GetRepo() string {
782+ if x != nil {
783+ return x.Repo
784+ }
785+ return ""
786+}
787+
788+func (x *CloseIssueRequest) GetNumber() int64 {
789+ if x != nil {
790+ return x.Number
791+ }
792+ return 0
793+}
794+
795+// CloseIssueResponse holds the issue after closing.
796+type CloseIssueResponse struct {
797+ state protoimpl.MessageState `protogen:"open.v1"`
798+ // Issue is the closed issue.
799+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
800+ unknownFields protoimpl.UnknownFields
801+ sizeCache protoimpl.SizeCache
802+}
803+
804+func (x *CloseIssueResponse) Reset() {
805+ *x = CloseIssueResponse{}
806+ mi := &file_ermite_issue_proto_msgTypes[11]
807+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
808+ ms.StoreMessageInfo(mi)
809+}
810+
811+func (x *CloseIssueResponse) String() string {
812+ return protoimpl.X.MessageStringOf(x)
813+}
814+
815+func (*CloseIssueResponse) ProtoMessage() {}
816+
817+func (x *CloseIssueResponse) ProtoReflect() protoreflect.Message {
818+ mi := &file_ermite_issue_proto_msgTypes[11]
819+ if x != nil {
820+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
821+ if ms.LoadMessageInfo() == nil {
822+ ms.StoreMessageInfo(mi)
823+ }
824+ return ms
825+ }
826+ return mi.MessageOf(x)
827+}
828+
829+// Deprecated: Use CloseIssueResponse.ProtoReflect.Descriptor instead.
830+func (*CloseIssueResponse) Descriptor() ([]byte, []int) {
831+ return file_ermite_issue_proto_rawDescGZIP(), []int{11}
832+}
833+
834+func (x *CloseIssueResponse) GetIssue() *Issue {
835+ if x != nil {
836+ return x.Issue
837+ }
838+ return nil
839+}
840+
841+// ReopenIssueRequest names the issue to reopen.
842+type ReopenIssueRequest struct {
843+ state protoimpl.MessageState `protogen:"open.v1"`
844+ // Repo is the repository name.
845+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
846+ // Number is the issue number.
847+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
848+ unknownFields protoimpl.UnknownFields
849+ sizeCache protoimpl.SizeCache
850+}
851+
852+func (x *ReopenIssueRequest) Reset() {
853+ *x = ReopenIssueRequest{}
854+ mi := &file_ermite_issue_proto_msgTypes[12]
855+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
856+ ms.StoreMessageInfo(mi)
857+}
858+
859+func (x *ReopenIssueRequest) String() string {
860+ return protoimpl.X.MessageStringOf(x)
861+}
862+
863+func (*ReopenIssueRequest) ProtoMessage() {}
864+
865+func (x *ReopenIssueRequest) ProtoReflect() protoreflect.Message {
866+ mi := &file_ermite_issue_proto_msgTypes[12]
867+ if x != nil {
868+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
869+ if ms.LoadMessageInfo() == nil {
870+ ms.StoreMessageInfo(mi)
871+ }
872+ return ms
873+ }
874+ return mi.MessageOf(x)
875+}
876+
877+// Deprecated: Use ReopenIssueRequest.ProtoReflect.Descriptor instead.
878+func (*ReopenIssueRequest) Descriptor() ([]byte, []int) {
879+ return file_ermite_issue_proto_rawDescGZIP(), []int{12}
880+}
881+
882+func (x *ReopenIssueRequest) GetRepo() string {
883+ if x != nil {
884+ return x.Repo
885+ }
886+ return ""
887+}
888+
889+func (x *ReopenIssueRequest) GetNumber() int64 {
890+ if x != nil {
891+ return x.Number
892+ }
893+ return 0
894+}
895+
896+// ReopenIssueResponse holds the issue after reopening.
897+type ReopenIssueResponse struct {
898+ state protoimpl.MessageState `protogen:"open.v1"`
899+ // Issue is the reopened issue.
900+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
901+ unknownFields protoimpl.UnknownFields
902+ sizeCache protoimpl.SizeCache
903+}
904+
905+func (x *ReopenIssueResponse) Reset() {
906+ *x = ReopenIssueResponse{}
907+ mi := &file_ermite_issue_proto_msgTypes[13]
908+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
909+ ms.StoreMessageInfo(mi)
910+}
911+
912+func (x *ReopenIssueResponse) String() string {
913+ return protoimpl.X.MessageStringOf(x)
914+}
915+
916+func (*ReopenIssueResponse) ProtoMessage() {}
917+
918+func (x *ReopenIssueResponse) ProtoReflect() protoreflect.Message {
919+ mi := &file_ermite_issue_proto_msgTypes[13]
920+ if x != nil {
921+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
922+ if ms.LoadMessageInfo() == nil {
923+ ms.StoreMessageInfo(mi)
924+ }
925+ return ms
926+ }
927+ return mi.MessageOf(x)
928+}
929+
930+// Deprecated: Use ReopenIssueResponse.ProtoReflect.Descriptor instead.
931+func (*ReopenIssueResponse) Descriptor() ([]byte, []int) {
932+ return file_ermite_issue_proto_rawDescGZIP(), []int{13}
933+}
934+
935+func (x *ReopenIssueResponse) GetIssue() *Issue {
936+ if x != nil {
937+ return x.Issue
938+ }
939+ return nil
940+}
941+
942+var File_ermite_issue_proto protoreflect.FileDescriptor
943+
944+const file_ermite_issue_proto_rawDesc = "" +
945+ "\n" +
946+ "\x12ermite/issue.proto\x12\x06ermite\x1a\x1fgoogle/protobuf/timestamp.proto\"\xba\x02\n" +
947+ "\x05Issue\x12\x12\n" +
948+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
949+ "\x06number\x18\x02 \x01(\x03R\x06number\x12\x14\n" +
950+ "\x05title\x18\x03 \x01(\tR\x05title\x12\x12\n" +
951+ "\x04body\x18\x04 \x01(\tR\x04body\x12(\n" +
952+ "\x05state\x18\x05 \x01(\x0e2\x12.ermite.IssueStateR\x05state\x12\x16\n" +
953+ "\x06author\x18\x06 \x01(\tR\x06author\x129\n" +
954+ "\n" +
955+ "created_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
956+ "\n" +
957+ "updated_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12#\n" +
958+ "\rcomment_count\x18\t \x01(\x05R\fcommentCount\"\x85\x01\n" +
959+ "\fIssueComment\x12\x0e\n" +
960+ "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" +
961+ "\x06author\x18\x02 \x01(\tR\x06author\x12\x12\n" +
962+ "\x04text\x18\x03 \x01(\tR\x04text\x129\n" +
963+ "\n" +
964+ "created_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"R\n" +
965+ "\x12CreateIssueRequest\x12\x12\n" +
966+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x14\n" +
967+ "\x05title\x18\x02 \x01(\tR\x05title\x12\x12\n" +
968+ "\x04body\x18\x03 \x01(\tR\x04body\":\n" +
969+ "\x13CreateIssueResponse\x12#\n" +
970+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\"\x8d\x01\n" +
971+ "\x11ListIssuesRequest\x12\x12\n" +
972+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12(\n" +
973+ "\x05state\x18\x02 \x01(\x0e2\x12.ermite.IssueStateR\x05state\x12\x1b\n" +
974+ "\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x1d\n" +
975+ "\n" +
976+ "page_token\x18\x04 \x01(\tR\tpageToken\"c\n" +
977+ "\x12ListIssuesResponse\x12%\n" +
978+ "\x06issues\x18\x01 \x03(\v2\r.ermite.IssueR\x06issues\x12&\n" +
979+ "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"=\n" +
980+ "\x0fGetIssueRequest\x12\x12\n" +
981+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
982+ "\x06number\x18\x02 \x01(\x03R\x06number\"i\n" +
983+ "\x10GetIssueResponse\x12#\n" +
984+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\x120\n" +
985+ "\bcomments\x18\x02 \x03(\v2\x14.ermite.IssueCommentR\bcomments\"X\n" +
986+ "\x16AddIssueCommentRequest\x12\x12\n" +
987+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
988+ "\x06number\x18\x02 \x01(\x03R\x06number\x12\x12\n" +
989+ "\x04text\x18\x03 \x01(\tR\x04text\"I\n" +
990+ "\x17AddIssueCommentResponse\x12.\n" +
991+ "\acomment\x18\x01 \x01(\v2\x14.ermite.IssueCommentR\acomment\"?\n" +
992+ "\x11CloseIssueRequest\x12\x12\n" +
993+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
994+ "\x06number\x18\x02 \x01(\x03R\x06number\"9\n" +
995+ "\x12CloseIssueResponse\x12#\n" +
996+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\"@\n" +
997+ "\x12ReopenIssueRequest\x12\x12\n" +
998+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
999+ "\x06number\x18\x02 \x01(\x03R\x06number\":\n" +
1000+ "\x13ReopenIssueResponse\x12#\n" +
1001+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue*p\n" +
1002+ "\n" +
1003+ "IssueState\x12\x1b\n" +
1004+ "\x17ISSUE_STATE_UNSPECIFIED\x10\x00\x12\x14\n" +
1005+ "\x10ISSUE_STATE_OPEN\x10\x01\x12\x16\n" +
1006+ "\x12ISSUE_STATE_CLOSED\x10\x02\x12\x17\n" +
1007+ "\x13ISSUE_STATE_PENDING\x10\x032\xbb\x03\n" +
1008+ "\fIssueService\x12F\n" +
1009+ "\vCreateIssue\x12\x1a.ermite.CreateIssueRequest\x1a\x1b.ermite.CreateIssueResponse\x12C\n" +
1010+ "\n" +
1011+ "ListIssues\x12\x19.ermite.ListIssuesRequest\x1a\x1a.ermite.ListIssuesResponse\x12=\n" +
1012+ "\bGetIssue\x12\x17.ermite.GetIssueRequest\x1a\x18.ermite.GetIssueResponse\x12R\n" +
1013+ "\x0fAddIssueComment\x12\x1e.ermite.AddIssueCommentRequest\x1a\x1f.ermite.AddIssueCommentResponse\x12C\n" +
1014+ "\n" +
1015+ "CloseIssue\x12\x19.ermite.CloseIssueRequest\x1a\x1a.ermite.CloseIssueResponse\x12F\n" +
1016+ "\vReopenIssue\x12\x1a.ermite.ReopenIssueRequest\x1a\x1b.ermite.ReopenIssueResponseBq\n" +
1017+ "\n" +
1018+ "com.ermiteB\n" +
1019+ "IssueProtoP\x01Z\x1fbnema.dev/ermite-api/gen/ermite\xa2\x02\x03EXX\xaa\x02\x06Ermite\xca\x02\x06Ermite\xe2\x02\x12Ermite\\GPBMetadata\xea\x02\x06Ermiteb\x06proto3"
1020+
1021+var (
1022+ file_ermite_issue_proto_rawDescOnce sync.Once
1023+ file_ermite_issue_proto_rawDescData []byte
1024+)
1025+
1026+func file_ermite_issue_proto_rawDescGZIP() []byte {
1027+ file_ermite_issue_proto_rawDescOnce.Do(func() {
1028+ file_ermite_issue_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ermite_issue_proto_rawDesc), len(file_ermite_issue_proto_rawDesc)))
1029+ })
1030+ return file_ermite_issue_proto_rawDescData
1031+}
1032+
1033+var file_ermite_issue_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
1034+var file_ermite_issue_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
1035+var file_ermite_issue_proto_goTypes = []any{
1036+ (IssueState)(0), // 0: ermite.IssueState
1037+ (*Issue)(nil), // 1: ermite.Issue
1038+ (*IssueComment)(nil), // 2: ermite.IssueComment
1039+ (*CreateIssueRequest)(nil), // 3: ermite.CreateIssueRequest
1040+ (*CreateIssueResponse)(nil), // 4: ermite.CreateIssueResponse
1041+ (*ListIssuesRequest)(nil), // 5: ermite.ListIssuesRequest
1042+ (*ListIssuesResponse)(nil), // 6: ermite.ListIssuesResponse
1043+ (*GetIssueRequest)(nil), // 7: ermite.GetIssueRequest
1044+ (*GetIssueResponse)(nil), // 8: ermite.GetIssueResponse
1045+ (*AddIssueCommentRequest)(nil), // 9: ermite.AddIssueCommentRequest
1046+ (*AddIssueCommentResponse)(nil), // 10: ermite.AddIssueCommentResponse
1047+ (*CloseIssueRequest)(nil), // 11: ermite.CloseIssueRequest
1048+ (*CloseIssueResponse)(nil), // 12: ermite.CloseIssueResponse
1049+ (*ReopenIssueRequest)(nil), // 13: ermite.ReopenIssueRequest
1050+ (*ReopenIssueResponse)(nil), // 14: ermite.ReopenIssueResponse
1051+ (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
1052+}
1053+var file_ermite_issue_proto_depIdxs = []int32{
1054+ 0, // 0: ermite.Issue.state:type_name -> ermite.IssueState
1055+ 15, // 1: ermite.Issue.created_at:type_name -> google.protobuf.Timestamp
1056+ 15, // 2: ermite.Issue.updated_at:type_name -> google.protobuf.Timestamp
1057+ 15, // 3: ermite.IssueComment.created_at:type_name -> google.protobuf.Timestamp
1058+ 1, // 4: ermite.CreateIssueResponse.issue:type_name -> ermite.Issue
1059+ 0, // 5: ermite.ListIssuesRequest.state:type_name -> ermite.IssueState
1060+ 1, // 6: ermite.ListIssuesResponse.issues:type_name -> ermite.Issue
1061+ 1, // 7: ermite.GetIssueResponse.issue:type_name -> ermite.Issue
1062+ 2, // 8: ermite.GetIssueResponse.comments:type_name -> ermite.IssueComment
1063+ 2, // 9: ermite.AddIssueCommentResponse.comment:type_name -> ermite.IssueComment
1064+ 1, // 10: ermite.CloseIssueResponse.issue:type_name -> ermite.Issue
1065+ 1, // 11: ermite.ReopenIssueResponse.issue:type_name -> ermite.Issue
1066+ 3, // 12: ermite.IssueService.CreateIssue:input_type -> ermite.CreateIssueRequest
1067+ 5, // 13: ermite.IssueService.ListIssues:input_type -> ermite.ListIssuesRequest
1068+ 7, // 14: ermite.IssueService.GetIssue:input_type -> ermite.GetIssueRequest
1069+ 9, // 15: ermite.IssueService.AddIssueComment:input_type -> ermite.AddIssueCommentRequest
1070+ 11, // 16: ermite.IssueService.CloseIssue:input_type -> ermite.CloseIssueRequest
1071+ 13, // 17: ermite.IssueService.ReopenIssue:input_type -> ermite.ReopenIssueRequest
1072+ 4, // 18: ermite.IssueService.CreateIssue:output_type -> ermite.CreateIssueResponse
1073+ 6, // 19: ermite.IssueService.ListIssues:output_type -> ermite.ListIssuesResponse
1074+ 8, // 20: ermite.IssueService.GetIssue:output_type -> ermite.GetIssueResponse
1075+ 10, // 21: ermite.IssueService.AddIssueComment:output_type -> ermite.AddIssueCommentResponse
1076+ 12, // 22: ermite.IssueService.CloseIssue:output_type -> ermite.CloseIssueResponse
1077+ 14, // 23: ermite.IssueService.ReopenIssue:output_type -> ermite.ReopenIssueResponse
1078+ 18, // [18:24] is the sub-list for method output_type
1079+ 12, // [12:18] is the sub-list for method input_type
1080+ 12, // [12:12] is the sub-list for extension type_name
1081+ 12, // [12:12] is the sub-list for extension extendee
1082+ 0, // [0:12] is the sub-list for field type_name
1083+}
1084+
1085+func init() { file_ermite_issue_proto_init() }
1086+func file_ermite_issue_proto_init() {
1087+ if File_ermite_issue_proto != nil {
1088+ return
1089+ }
1090+ type x struct{}
1091+ out := protoimpl.TypeBuilder{
1092+ File: protoimpl.DescBuilder{
1093+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1094+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_issue_proto_rawDesc), len(file_ermite_issue_proto_rawDesc)),
1095+ NumEnums: 1,
1096+ NumMessages: 14,
1097+ NumExtensions: 0,
1098+ NumServices: 1,
1099+ },
1100+ GoTypes: file_ermite_issue_proto_goTypes,
1101+ DependencyIndexes: file_ermite_issue_proto_depIdxs,
1102+ EnumInfos: file_ermite_issue_proto_enumTypes,
1103+ MessageInfos: file_ermite_issue_proto_msgTypes,
1104+ }.Build()
1105+ File_ermite_issue_proto = out.File
1106+ file_ermite_issue_proto_goTypes = nil
1107+ file_ermite_issue_proto_depIdxs = nil
1108+}
@@ -0,0 +1,1108 @@
1+// SPDX-License-Identifier: MIT
2+
3+// Code generated by protoc-gen-go. DO NOT EDIT.
4+// versions:
5+// protoc-gen-go v1.36.12
6+// protoc (unknown)
7+// source: ermite/issue.proto
8+
9+package ermite
10+
11+import (
12+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
13+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
14+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
15+ reflect "reflect"
16+ sync "sync"
17+ unsafe "unsafe"
18+)
19+
20+const (
21+ // Verify that this generated code is sufficiently up-to-date.
22+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
23+ // Verify that runtime/protoimpl is sufficiently up-to-date.
24+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
25+)
26+
27+// IssueState is where an issue is in its life.
28+type IssueState int32
29+
30+const (
31+ // Not set. In ListIssuesRequest.state it means every state. Never returned
32+ // by the server.
33+ IssueState_ISSUE_STATE_UNSPECIFIED IssueState = 0
34+ // The issue is open.
35+ IssueState_ISSUE_STATE_OPEN IssueState = 1
36+ // The issue is closed.
37+ IssueState_ISSUE_STATE_CLOSED IssueState = 2
38+ // Reserved for later use: awaiting moderation, owner-only.
39+ IssueState_ISSUE_STATE_PENDING IssueState = 3
40+)
41+
42+// Enum value maps for IssueState.
43+var (
44+ IssueState_name = map[int32]string{
45+ 0: "ISSUE_STATE_UNSPECIFIED",
46+ 1: "ISSUE_STATE_OPEN",
47+ 2: "ISSUE_STATE_CLOSED",
48+ 3: "ISSUE_STATE_PENDING",
49+ }
50+ IssueState_value = map[string]int32{
51+ "ISSUE_STATE_UNSPECIFIED": 0,
52+ "ISSUE_STATE_OPEN": 1,
53+ "ISSUE_STATE_CLOSED": 2,
54+ "ISSUE_STATE_PENDING": 3,
55+ }
56+)
57+
58+func (x IssueState) Enum() *IssueState {
59+ p := new(IssueState)
60+ *p = x
61+ return p
62+}
63+
64+func (x IssueState) String() string {
65+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
66+}
67+
68+func (IssueState) Descriptor() protoreflect.EnumDescriptor {
69+ return file_ermite_issue_proto_enumTypes[0].Descriptor()
70+}
71+
72+func (IssueState) Type() protoreflect.EnumType {
73+ return &file_ermite_issue_proto_enumTypes[0]
74+}
75+
76+func (x IssueState) Number() protoreflect.EnumNumber {
77+ return protoreflect.EnumNumber(x)
78+}
79+
80+// Deprecated: Use IssueState.Descriptor instead.
81+func (IssueState) EnumDescriptor() ([]byte, []int) {
82+ return file_ermite_issue_proto_rawDescGZIP(), []int{0}
83+}
84+
85+// Issue is a discussion in a repository.
86+type Issue struct {
87+ state protoimpl.MessageState `protogen:"open.v1"`
88+ // Repo is the name of the repository.
89+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
90+ // Number identifies the issue within its repository.
91+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
92+ // Title is the one-line title.
93+ Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"`
94+ // Body is the content of the issue. It may be empty.
95+ Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"`
96+ // State is where the issue is in its life.
97+ State IssueState `protobuf:"varint,5,opt,name=state,proto3,enum=ermite.IssueState" json:"state,omitempty"`
98+ // Author names who created the issue: the label of the token that was used,
99+ // "root" for the root token, or "owner" for a web session. It is
100+ // informational: labels are not unique and the token may be gone.
101+ Author string `protobuf:"bytes,6,opt,name=author,proto3" json:"author,omitempty"`
102+ // CreatedAt is when the issue was created.
103+ CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
104+ // UpdatedAt is when the issue last changed.
105+ UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
106+ // CommentCount is the number of comments on the issue.
107+ CommentCount int32 `protobuf:"varint,9,opt,name=comment_count,json=commentCount,proto3" json:"comment_count,omitempty"`
108+ unknownFields protoimpl.UnknownFields
109+ sizeCache protoimpl.SizeCache
110+}
111+
112+func (x *Issue) Reset() {
113+ *x = Issue{}
114+ mi := &file_ermite_issue_proto_msgTypes[0]
115+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
116+ ms.StoreMessageInfo(mi)
117+}
118+
119+func (x *Issue) String() string {
120+ return protoimpl.X.MessageStringOf(x)
121+}
122+
123+func (*Issue) ProtoMessage() {}
124+
125+func (x *Issue) ProtoReflect() protoreflect.Message {
126+ mi := &file_ermite_issue_proto_msgTypes[0]
127+ if x != nil {
128+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
129+ if ms.LoadMessageInfo() == nil {
130+ ms.StoreMessageInfo(mi)
131+ }
132+ return ms
133+ }
134+ return mi.MessageOf(x)
135+}
136+
137+// Deprecated: Use Issue.ProtoReflect.Descriptor instead.
138+func (*Issue) Descriptor() ([]byte, []int) {
139+ return file_ermite_issue_proto_rawDescGZIP(), []int{0}
140+}
141+
142+func (x *Issue) GetRepo() string {
143+ if x != nil {
144+ return x.Repo
145+ }
146+ return ""
147+}
148+
149+func (x *Issue) GetNumber() int64 {
150+ if x != nil {
151+ return x.Number
152+ }
153+ return 0
154+}
155+
156+func (x *Issue) GetTitle() string {
157+ if x != nil {
158+ return x.Title
159+ }
160+ return ""
161+}
162+
163+func (x *Issue) GetBody() string {
164+ if x != nil {
165+ return x.Body
166+ }
167+ return ""
168+}
169+
170+func (x *Issue) GetState() IssueState {
171+ if x != nil {
172+ return x.State
173+ }
174+ return IssueState_ISSUE_STATE_UNSPECIFIED
175+}
176+
177+func (x *Issue) GetAuthor() string {
178+ if x != nil {
179+ return x.Author
180+ }
181+ return ""
182+}
183+
184+func (x *Issue) GetCreatedAt() *timestamppb.Timestamp {
185+ if x != nil {
186+ return x.CreatedAt
187+ }
188+ return nil
189+}
190+
191+func (x *Issue) GetUpdatedAt() *timestamppb.Timestamp {
192+ if x != nil {
193+ return x.UpdatedAt
194+ }
195+ return nil
196+}
197+
198+func (x *Issue) GetCommentCount() int32 {
199+ if x != nil {
200+ return x.CommentCount
201+ }
202+ return 0
203+}
204+
205+// IssueComment is a note on an issue.
206+type IssueComment struct {
207+ state protoimpl.MessageState `protogen:"open.v1"`
208+ // Id identifies the comment within its issue. Opaque.
209+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
210+ // Author names who wrote the comment, like Issue.author.
211+ Author string `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"`
212+ // Text is the content of the comment.
213+ Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
214+ // CreatedAt is when the comment was written.
215+ CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
216+ unknownFields protoimpl.UnknownFields
217+ sizeCache protoimpl.SizeCache
218+}
219+
220+func (x *IssueComment) Reset() {
221+ *x = IssueComment{}
222+ mi := &file_ermite_issue_proto_msgTypes[1]
223+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
224+ ms.StoreMessageInfo(mi)
225+}
226+
227+func (x *IssueComment) String() string {
228+ return protoimpl.X.MessageStringOf(x)
229+}
230+
231+func (*IssueComment) ProtoMessage() {}
232+
233+func (x *IssueComment) ProtoReflect() protoreflect.Message {
234+ mi := &file_ermite_issue_proto_msgTypes[1]
235+ if x != nil {
236+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
237+ if ms.LoadMessageInfo() == nil {
238+ ms.StoreMessageInfo(mi)
239+ }
240+ return ms
241+ }
242+ return mi.MessageOf(x)
243+}
244+
245+// Deprecated: Use IssueComment.ProtoReflect.Descriptor instead.
246+func (*IssueComment) Descriptor() ([]byte, []int) {
247+ return file_ermite_issue_proto_rawDescGZIP(), []int{1}
248+}
249+
250+func (x *IssueComment) GetId() string {
251+ if x != nil {
252+ return x.Id
253+ }
254+ return ""
255+}
256+
257+func (x *IssueComment) GetAuthor() string {
258+ if x != nil {
259+ return x.Author
260+ }
261+ return ""
262+}
263+
264+func (x *IssueComment) GetText() string {
265+ if x != nil {
266+ return x.Text
267+ }
268+ return ""
269+}
270+
271+func (x *IssueComment) GetCreatedAt() *timestamppb.Timestamp {
272+ if x != nil {
273+ return x.CreatedAt
274+ }
275+ return nil
276+}
277+
278+// CreateIssueRequest describes the issue to open.
279+type CreateIssueRequest struct {
280+ state protoimpl.MessageState `protogen:"open.v1"`
281+ // Repo is the repository name.
282+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
283+ // Title is the one-line title. Required.
284+ Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
285+ // Body is the optional content.
286+ Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"`
287+ unknownFields protoimpl.UnknownFields
288+ sizeCache protoimpl.SizeCache
289+}
290+
291+func (x *CreateIssueRequest) Reset() {
292+ *x = CreateIssueRequest{}
293+ mi := &file_ermite_issue_proto_msgTypes[2]
294+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
295+ ms.StoreMessageInfo(mi)
296+}
297+
298+func (x *CreateIssueRequest) String() string {
299+ return protoimpl.X.MessageStringOf(x)
300+}
301+
302+func (*CreateIssueRequest) ProtoMessage() {}
303+
304+func (x *CreateIssueRequest) ProtoReflect() protoreflect.Message {
305+ mi := &file_ermite_issue_proto_msgTypes[2]
306+ if x != nil {
307+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
308+ if ms.LoadMessageInfo() == nil {
309+ ms.StoreMessageInfo(mi)
310+ }
311+ return ms
312+ }
313+ return mi.MessageOf(x)
314+}
315+
316+// Deprecated: Use CreateIssueRequest.ProtoReflect.Descriptor instead.
317+func (*CreateIssueRequest) Descriptor() ([]byte, []int) {
318+ return file_ermite_issue_proto_rawDescGZIP(), []int{2}
319+}
320+
321+func (x *CreateIssueRequest) GetRepo() string {
322+ if x != nil {
323+ return x.Repo
324+ }
325+ return ""
326+}
327+
328+func (x *CreateIssueRequest) GetTitle() string {
329+ if x != nil {
330+ return x.Title
331+ }
332+ return ""
333+}
334+
335+func (x *CreateIssueRequest) GetBody() string {
336+ if x != nil {
337+ return x.Body
338+ }
339+ return ""
340+}
341+
342+// CreateIssueResponse holds the new issue.
343+type CreateIssueResponse struct {
344+ state protoimpl.MessageState `protogen:"open.v1"`
345+ // Issue is the created issue.
346+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
347+ unknownFields protoimpl.UnknownFields
348+ sizeCache protoimpl.SizeCache
349+}
350+
351+func (x *CreateIssueResponse) Reset() {
352+ *x = CreateIssueResponse{}
353+ mi := &file_ermite_issue_proto_msgTypes[3]
354+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
355+ ms.StoreMessageInfo(mi)
356+}
357+
358+func (x *CreateIssueResponse) String() string {
359+ return protoimpl.X.MessageStringOf(x)
360+}
361+
362+func (*CreateIssueResponse) ProtoMessage() {}
363+
364+func (x *CreateIssueResponse) ProtoReflect() protoreflect.Message {
365+ mi := &file_ermite_issue_proto_msgTypes[3]
366+ if x != nil {
367+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
368+ if ms.LoadMessageInfo() == nil {
369+ ms.StoreMessageInfo(mi)
370+ }
371+ return ms
372+ }
373+ return mi.MessageOf(x)
374+}
375+
376+// Deprecated: Use CreateIssueResponse.ProtoReflect.Descriptor instead.
377+func (*CreateIssueResponse) Descriptor() ([]byte, []int) {
378+ return file_ermite_issue_proto_rawDescGZIP(), []int{3}
379+}
380+
381+func (x *CreateIssueResponse) GetIssue() *Issue {
382+ if x != nil {
383+ return x.Issue
384+ }
385+ return nil
386+}
387+
388+// ListIssuesRequest selects a page of issues.
389+type ListIssuesRequest struct {
390+ state protoimpl.MessageState `protogen:"open.v1"`
391+ // Repo is the repository name.
392+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
393+ // State restricts the result to one state. ISSUE_STATE_UNSPECIFIED means
394+ // every state.
395+ State IssueState `protobuf:"varint,2,opt,name=state,proto3,enum=ermite.IssueState" json:"state,omitempty"`
396+ // PageSize is the maximum number of issues to return. 0 means the server
397+ // default; values above the server maximum are lowered to it.
398+ PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
399+ // PageToken is the next_page_token of a previous response, to continue the
400+ // same listing. Empty for the first page. Other fields must be unchanged.
401+ PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"`
402+ unknownFields protoimpl.UnknownFields
403+ sizeCache protoimpl.SizeCache
404+}
405+
406+func (x *ListIssuesRequest) Reset() {
407+ *x = ListIssuesRequest{}
408+ mi := &file_ermite_issue_proto_msgTypes[4]
409+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
410+ ms.StoreMessageInfo(mi)
411+}
412+
413+func (x *ListIssuesRequest) String() string {
414+ return protoimpl.X.MessageStringOf(x)
415+}
416+
417+func (*ListIssuesRequest) ProtoMessage() {}
418+
419+func (x *ListIssuesRequest) ProtoReflect() protoreflect.Message {
420+ mi := &file_ermite_issue_proto_msgTypes[4]
421+ if x != nil {
422+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
423+ if ms.LoadMessageInfo() == nil {
424+ ms.StoreMessageInfo(mi)
425+ }
426+ return ms
427+ }
428+ return mi.MessageOf(x)
429+}
430+
431+// Deprecated: Use ListIssuesRequest.ProtoReflect.Descriptor instead.
432+func (*ListIssuesRequest) Descriptor() ([]byte, []int) {
433+ return file_ermite_issue_proto_rawDescGZIP(), []int{4}
434+}
435+
436+func (x *ListIssuesRequest) GetRepo() string {
437+ if x != nil {
438+ return x.Repo
439+ }
440+ return ""
441+}
442+
443+func (x *ListIssuesRequest) GetState() IssueState {
444+ if x != nil {
445+ return x.State
446+ }
447+ return IssueState_ISSUE_STATE_UNSPECIFIED
448+}
449+
450+func (x *ListIssuesRequest) GetPageSize() int32 {
451+ if x != nil {
452+ return x.PageSize
453+ }
454+ return 0
455+}
456+
457+func (x *ListIssuesRequest) GetPageToken() string {
458+ if x != nil {
459+ return x.PageToken
460+ }
461+ return ""
462+}
463+
464+// ListIssuesResponse is one page of issues.
465+type ListIssuesResponse struct {
466+ state protoimpl.MessageState `protogen:"open.v1"`
467+ // Issues are the issues of this page, highest number first.
468+ Issues []*Issue `protobuf:"bytes,1,rep,name=issues,proto3" json:"issues,omitempty"`
469+ // NextPageToken is passed as page_token to get the next page. Empty when
470+ // there is no next page.
471+ NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
472+ unknownFields protoimpl.UnknownFields
473+ sizeCache protoimpl.SizeCache
474+}
475+
476+func (x *ListIssuesResponse) Reset() {
477+ *x = ListIssuesResponse{}
478+ mi := &file_ermite_issue_proto_msgTypes[5]
479+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
480+ ms.StoreMessageInfo(mi)
481+}
482+
483+func (x *ListIssuesResponse) String() string {
484+ return protoimpl.X.MessageStringOf(x)
485+}
486+
487+func (*ListIssuesResponse) ProtoMessage() {}
488+
489+func (x *ListIssuesResponse) ProtoReflect() protoreflect.Message {
490+ mi := &file_ermite_issue_proto_msgTypes[5]
491+ if x != nil {
492+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
493+ if ms.LoadMessageInfo() == nil {
494+ ms.StoreMessageInfo(mi)
495+ }
496+ return ms
497+ }
498+ return mi.MessageOf(x)
499+}
500+
501+// Deprecated: Use ListIssuesResponse.ProtoReflect.Descriptor instead.
502+func (*ListIssuesResponse) Descriptor() ([]byte, []int) {
503+ return file_ermite_issue_proto_rawDescGZIP(), []int{5}
504+}
505+
506+func (x *ListIssuesResponse) GetIssues() []*Issue {
507+ if x != nil {
508+ return x.Issues
509+ }
510+ return nil
511+}
512+
513+func (x *ListIssuesResponse) GetNextPageToken() string {
514+ if x != nil {
515+ return x.NextPageToken
516+ }
517+ return ""
518+}
519+
520+// GetIssueRequest selects an issue.
521+type GetIssueRequest struct {
522+ state protoimpl.MessageState `protogen:"open.v1"`
523+ // Repo is the repository name.
524+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
525+ // Number is the issue number.
526+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
527+ unknownFields protoimpl.UnknownFields
528+ sizeCache protoimpl.SizeCache
529+}
530+
531+func (x *GetIssueRequest) Reset() {
532+ *x = GetIssueRequest{}
533+ mi := &file_ermite_issue_proto_msgTypes[6]
534+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
535+ ms.StoreMessageInfo(mi)
536+}
537+
538+func (x *GetIssueRequest) String() string {
539+ return protoimpl.X.MessageStringOf(x)
540+}
541+
542+func (*GetIssueRequest) ProtoMessage() {}
543+
544+func (x *GetIssueRequest) ProtoReflect() protoreflect.Message {
545+ mi := &file_ermite_issue_proto_msgTypes[6]
546+ if x != nil {
547+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
548+ if ms.LoadMessageInfo() == nil {
549+ ms.StoreMessageInfo(mi)
550+ }
551+ return ms
552+ }
553+ return mi.MessageOf(x)
554+}
555+
556+// Deprecated: Use GetIssueRequest.ProtoReflect.Descriptor instead.
557+func (*GetIssueRequest) Descriptor() ([]byte, []int) {
558+ return file_ermite_issue_proto_rawDescGZIP(), []int{6}
559+}
560+
561+func (x *GetIssueRequest) GetRepo() string {
562+ if x != nil {
563+ return x.Repo
564+ }
565+ return ""
566+}
567+
568+func (x *GetIssueRequest) GetNumber() int64 {
569+ if x != nil {
570+ return x.Number
571+ }
572+ return 0
573+}
574+
575+// GetIssueResponse holds an issue with its comments.
576+type GetIssueResponse struct {
577+ state protoimpl.MessageState `protogen:"open.v1"`
578+ // Issue is the issue.
579+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
580+ // Comments are every comment of the issue, oldest first.
581+ Comments []*IssueComment `protobuf:"bytes,2,rep,name=comments,proto3" json:"comments,omitempty"`
582+ unknownFields protoimpl.UnknownFields
583+ sizeCache protoimpl.SizeCache
584+}
585+
586+func (x *GetIssueResponse) Reset() {
587+ *x = GetIssueResponse{}
588+ mi := &file_ermite_issue_proto_msgTypes[7]
589+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
590+ ms.StoreMessageInfo(mi)
591+}
592+
593+func (x *GetIssueResponse) String() string {
594+ return protoimpl.X.MessageStringOf(x)
595+}
596+
597+func (*GetIssueResponse) ProtoMessage() {}
598+
599+func (x *GetIssueResponse) ProtoReflect() protoreflect.Message {
600+ mi := &file_ermite_issue_proto_msgTypes[7]
601+ if x != nil {
602+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
603+ if ms.LoadMessageInfo() == nil {
604+ ms.StoreMessageInfo(mi)
605+ }
606+ return ms
607+ }
608+ return mi.MessageOf(x)
609+}
610+
611+// Deprecated: Use GetIssueResponse.ProtoReflect.Descriptor instead.
612+func (*GetIssueResponse) Descriptor() ([]byte, []int) {
613+ return file_ermite_issue_proto_rawDescGZIP(), []int{7}
614+}
615+
616+func (x *GetIssueResponse) GetIssue() *Issue {
617+ if x != nil {
618+ return x.Issue
619+ }
620+ return nil
621+}
622+
623+func (x *GetIssueResponse) GetComments() []*IssueComment {
624+ if x != nil {
625+ return x.Comments
626+ }
627+ return nil
628+}
629+
630+// AddIssueCommentRequest describes the comment to add.
631+type AddIssueCommentRequest struct {
632+ state protoimpl.MessageState `protogen:"open.v1"`
633+ // Repo is the repository name.
634+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
635+ // Number is the issue number.
636+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
637+ // Text is the content. Required.
638+ Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"`
639+ unknownFields protoimpl.UnknownFields
640+ sizeCache protoimpl.SizeCache
641+}
642+
643+func (x *AddIssueCommentRequest) Reset() {
644+ *x = AddIssueCommentRequest{}
645+ mi := &file_ermite_issue_proto_msgTypes[8]
646+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
647+ ms.StoreMessageInfo(mi)
648+}
649+
650+func (x *AddIssueCommentRequest) String() string {
651+ return protoimpl.X.MessageStringOf(x)
652+}
653+
654+func (*AddIssueCommentRequest) ProtoMessage() {}
655+
656+func (x *AddIssueCommentRequest) ProtoReflect() protoreflect.Message {
657+ mi := &file_ermite_issue_proto_msgTypes[8]
658+ if x != nil {
659+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
660+ if ms.LoadMessageInfo() == nil {
661+ ms.StoreMessageInfo(mi)
662+ }
663+ return ms
664+ }
665+ return mi.MessageOf(x)
666+}
667+
668+// Deprecated: Use AddIssueCommentRequest.ProtoReflect.Descriptor instead.
669+func (*AddIssueCommentRequest) Descriptor() ([]byte, []int) {
670+ return file_ermite_issue_proto_rawDescGZIP(), []int{8}
671+}
672+
673+func (x *AddIssueCommentRequest) GetRepo() string {
674+ if x != nil {
675+ return x.Repo
676+ }
677+ return ""
678+}
679+
680+func (x *AddIssueCommentRequest) GetNumber() int64 {
681+ if x != nil {
682+ return x.Number
683+ }
684+ return 0
685+}
686+
687+func (x *AddIssueCommentRequest) GetText() string {
688+ if x != nil {
689+ return x.Text
690+ }
691+ return ""
692+}
693+
694+// AddIssueCommentResponse holds the new comment.
695+type AddIssueCommentResponse struct {
696+ state protoimpl.MessageState `protogen:"open.v1"`
697+ // Comment is the created comment.
698+ Comment *IssueComment `protobuf:"bytes,1,opt,name=comment,proto3" json:"comment,omitempty"`
699+ unknownFields protoimpl.UnknownFields
700+ sizeCache protoimpl.SizeCache
701+}
702+
703+func (x *AddIssueCommentResponse) Reset() {
704+ *x = AddIssueCommentResponse{}
705+ mi := &file_ermite_issue_proto_msgTypes[9]
706+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
707+ ms.StoreMessageInfo(mi)
708+}
709+
710+func (x *AddIssueCommentResponse) String() string {
711+ return protoimpl.X.MessageStringOf(x)
712+}
713+
714+func (*AddIssueCommentResponse) ProtoMessage() {}
715+
716+func (x *AddIssueCommentResponse) ProtoReflect() protoreflect.Message {
717+ mi := &file_ermite_issue_proto_msgTypes[9]
718+ if x != nil {
719+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
720+ if ms.LoadMessageInfo() == nil {
721+ ms.StoreMessageInfo(mi)
722+ }
723+ return ms
724+ }
725+ return mi.MessageOf(x)
726+}
727+
728+// Deprecated: Use AddIssueCommentResponse.ProtoReflect.Descriptor instead.
729+func (*AddIssueCommentResponse) Descriptor() ([]byte, []int) {
730+ return file_ermite_issue_proto_rawDescGZIP(), []int{9}
731+}
732+
733+func (x *AddIssueCommentResponse) GetComment() *IssueComment {
734+ if x != nil {
735+ return x.Comment
736+ }
737+ return nil
738+}
739+
740+// CloseIssueRequest names the issue to close.
741+type CloseIssueRequest struct {
742+ state protoimpl.MessageState `protogen:"open.v1"`
743+ // Repo is the repository name.
744+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
745+ // Number is the issue number.
746+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
747+ unknownFields protoimpl.UnknownFields
748+ sizeCache protoimpl.SizeCache
749+}
750+
751+func (x *CloseIssueRequest) Reset() {
752+ *x = CloseIssueRequest{}
753+ mi := &file_ermite_issue_proto_msgTypes[10]
754+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
755+ ms.StoreMessageInfo(mi)
756+}
757+
758+func (x *CloseIssueRequest) String() string {
759+ return protoimpl.X.MessageStringOf(x)
760+}
761+
762+func (*CloseIssueRequest) ProtoMessage() {}
763+
764+func (x *CloseIssueRequest) ProtoReflect() protoreflect.Message {
765+ mi := &file_ermite_issue_proto_msgTypes[10]
766+ if x != nil {
767+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
768+ if ms.LoadMessageInfo() == nil {
769+ ms.StoreMessageInfo(mi)
770+ }
771+ return ms
772+ }
773+ return mi.MessageOf(x)
774+}
775+
776+// Deprecated: Use CloseIssueRequest.ProtoReflect.Descriptor instead.
777+func (*CloseIssueRequest) Descriptor() ([]byte, []int) {
778+ return file_ermite_issue_proto_rawDescGZIP(), []int{10}
779+}
780+
781+func (x *CloseIssueRequest) GetRepo() string {
782+ if x != nil {
783+ return x.Repo
784+ }
785+ return ""
786+}
787+
788+func (x *CloseIssueRequest) GetNumber() int64 {
789+ if x != nil {
790+ return x.Number
791+ }
792+ return 0
793+}
794+
795+// CloseIssueResponse holds the issue after closing.
796+type CloseIssueResponse struct {
797+ state protoimpl.MessageState `protogen:"open.v1"`
798+ // Issue is the closed issue.
799+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
800+ unknownFields protoimpl.UnknownFields
801+ sizeCache protoimpl.SizeCache
802+}
803+
804+func (x *CloseIssueResponse) Reset() {
805+ *x = CloseIssueResponse{}
806+ mi := &file_ermite_issue_proto_msgTypes[11]
807+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
808+ ms.StoreMessageInfo(mi)
809+}
810+
811+func (x *CloseIssueResponse) String() string {
812+ return protoimpl.X.MessageStringOf(x)
813+}
814+
815+func (*CloseIssueResponse) ProtoMessage() {}
816+
817+func (x *CloseIssueResponse) ProtoReflect() protoreflect.Message {
818+ mi := &file_ermite_issue_proto_msgTypes[11]
819+ if x != nil {
820+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
821+ if ms.LoadMessageInfo() == nil {
822+ ms.StoreMessageInfo(mi)
823+ }
824+ return ms
825+ }
826+ return mi.MessageOf(x)
827+}
828+
829+// Deprecated: Use CloseIssueResponse.ProtoReflect.Descriptor instead.
830+func (*CloseIssueResponse) Descriptor() ([]byte, []int) {
831+ return file_ermite_issue_proto_rawDescGZIP(), []int{11}
832+}
833+
834+func (x *CloseIssueResponse) GetIssue() *Issue {
835+ if x != nil {
836+ return x.Issue
837+ }
838+ return nil
839+}
840+
841+// ReopenIssueRequest names the issue to reopen.
842+type ReopenIssueRequest struct {
843+ state protoimpl.MessageState `protogen:"open.v1"`
844+ // Repo is the repository name.
845+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
846+ // Number is the issue number.
847+ Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
848+ unknownFields protoimpl.UnknownFields
849+ sizeCache protoimpl.SizeCache
850+}
851+
852+func (x *ReopenIssueRequest) Reset() {
853+ *x = ReopenIssueRequest{}
854+ mi := &file_ermite_issue_proto_msgTypes[12]
855+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
856+ ms.StoreMessageInfo(mi)
857+}
858+
859+func (x *ReopenIssueRequest) String() string {
860+ return protoimpl.X.MessageStringOf(x)
861+}
862+
863+func (*ReopenIssueRequest) ProtoMessage() {}
864+
865+func (x *ReopenIssueRequest) ProtoReflect() protoreflect.Message {
866+ mi := &file_ermite_issue_proto_msgTypes[12]
867+ if x != nil {
868+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
869+ if ms.LoadMessageInfo() == nil {
870+ ms.StoreMessageInfo(mi)
871+ }
872+ return ms
873+ }
874+ return mi.MessageOf(x)
875+}
876+
877+// Deprecated: Use ReopenIssueRequest.ProtoReflect.Descriptor instead.
878+func (*ReopenIssueRequest) Descriptor() ([]byte, []int) {
879+ return file_ermite_issue_proto_rawDescGZIP(), []int{12}
880+}
881+
882+func (x *ReopenIssueRequest) GetRepo() string {
883+ if x != nil {
884+ return x.Repo
885+ }
886+ return ""
887+}
888+
889+func (x *ReopenIssueRequest) GetNumber() int64 {
890+ if x != nil {
891+ return x.Number
892+ }
893+ return 0
894+}
895+
896+// ReopenIssueResponse holds the issue after reopening.
897+type ReopenIssueResponse struct {
898+ state protoimpl.MessageState `protogen:"open.v1"`
899+ // Issue is the reopened issue.
900+ Issue *Issue `protobuf:"bytes,1,opt,name=issue,proto3" json:"issue,omitempty"`
901+ unknownFields protoimpl.UnknownFields
902+ sizeCache protoimpl.SizeCache
903+}
904+
905+func (x *ReopenIssueResponse) Reset() {
906+ *x = ReopenIssueResponse{}
907+ mi := &file_ermite_issue_proto_msgTypes[13]
908+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
909+ ms.StoreMessageInfo(mi)
910+}
911+
912+func (x *ReopenIssueResponse) String() string {
913+ return protoimpl.X.MessageStringOf(x)
914+}
915+
916+func (*ReopenIssueResponse) ProtoMessage() {}
917+
918+func (x *ReopenIssueResponse) ProtoReflect() protoreflect.Message {
919+ mi := &file_ermite_issue_proto_msgTypes[13]
920+ if x != nil {
921+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
922+ if ms.LoadMessageInfo() == nil {
923+ ms.StoreMessageInfo(mi)
924+ }
925+ return ms
926+ }
927+ return mi.MessageOf(x)
928+}
929+
930+// Deprecated: Use ReopenIssueResponse.ProtoReflect.Descriptor instead.
931+func (*ReopenIssueResponse) Descriptor() ([]byte, []int) {
932+ return file_ermite_issue_proto_rawDescGZIP(), []int{13}
933+}
934+
935+func (x *ReopenIssueResponse) GetIssue() *Issue {
936+ if x != nil {
937+ return x.Issue
938+ }
939+ return nil
940+}
941+
942+var File_ermite_issue_proto protoreflect.FileDescriptor
943+
944+const file_ermite_issue_proto_rawDesc = "" +
945+ "\n" +
946+ "\x12ermite/issue.proto\x12\x06ermite\x1a\x1fgoogle/protobuf/timestamp.proto\"\xba\x02\n" +
947+ "\x05Issue\x12\x12\n" +
948+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
949+ "\x06number\x18\x02 \x01(\x03R\x06number\x12\x14\n" +
950+ "\x05title\x18\x03 \x01(\tR\x05title\x12\x12\n" +
951+ "\x04body\x18\x04 \x01(\tR\x04body\x12(\n" +
952+ "\x05state\x18\x05 \x01(\x0e2\x12.ermite.IssueStateR\x05state\x12\x16\n" +
953+ "\x06author\x18\x06 \x01(\tR\x06author\x129\n" +
954+ "\n" +
955+ "created_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
956+ "\n" +
957+ "updated_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12#\n" +
958+ "\rcomment_count\x18\t \x01(\x05R\fcommentCount\"\x85\x01\n" +
959+ "\fIssueComment\x12\x0e\n" +
960+ "\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" +
961+ "\x06author\x18\x02 \x01(\tR\x06author\x12\x12\n" +
962+ "\x04text\x18\x03 \x01(\tR\x04text\x129\n" +
963+ "\n" +
964+ "created_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"R\n" +
965+ "\x12CreateIssueRequest\x12\x12\n" +
966+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x14\n" +
967+ "\x05title\x18\x02 \x01(\tR\x05title\x12\x12\n" +
968+ "\x04body\x18\x03 \x01(\tR\x04body\":\n" +
969+ "\x13CreateIssueResponse\x12#\n" +
970+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\"\x8d\x01\n" +
971+ "\x11ListIssuesRequest\x12\x12\n" +
972+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12(\n" +
973+ "\x05state\x18\x02 \x01(\x0e2\x12.ermite.IssueStateR\x05state\x12\x1b\n" +
974+ "\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x1d\n" +
975+ "\n" +
976+ "page_token\x18\x04 \x01(\tR\tpageToken\"c\n" +
977+ "\x12ListIssuesResponse\x12%\n" +
978+ "\x06issues\x18\x01 \x03(\v2\r.ermite.IssueR\x06issues\x12&\n" +
979+ "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"=\n" +
980+ "\x0fGetIssueRequest\x12\x12\n" +
981+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
982+ "\x06number\x18\x02 \x01(\x03R\x06number\"i\n" +
983+ "\x10GetIssueResponse\x12#\n" +
984+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\x120\n" +
985+ "\bcomments\x18\x02 \x03(\v2\x14.ermite.IssueCommentR\bcomments\"X\n" +
986+ "\x16AddIssueCommentRequest\x12\x12\n" +
987+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
988+ "\x06number\x18\x02 \x01(\x03R\x06number\x12\x12\n" +
989+ "\x04text\x18\x03 \x01(\tR\x04text\"I\n" +
990+ "\x17AddIssueCommentResponse\x12.\n" +
991+ "\acomment\x18\x01 \x01(\v2\x14.ermite.IssueCommentR\acomment\"?\n" +
992+ "\x11CloseIssueRequest\x12\x12\n" +
993+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
994+ "\x06number\x18\x02 \x01(\x03R\x06number\"9\n" +
995+ "\x12CloseIssueResponse\x12#\n" +
996+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue\"@\n" +
997+ "\x12ReopenIssueRequest\x12\x12\n" +
998+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" +
999+ "\x06number\x18\x02 \x01(\x03R\x06number\":\n" +
1000+ "\x13ReopenIssueResponse\x12#\n" +
1001+ "\x05issue\x18\x01 \x01(\v2\r.ermite.IssueR\x05issue*p\n" +
1002+ "\n" +
1003+ "IssueState\x12\x1b\n" +
1004+ "\x17ISSUE_STATE_UNSPECIFIED\x10\x00\x12\x14\n" +
1005+ "\x10ISSUE_STATE_OPEN\x10\x01\x12\x16\n" +
1006+ "\x12ISSUE_STATE_CLOSED\x10\x02\x12\x17\n" +
1007+ "\x13ISSUE_STATE_PENDING\x10\x032\xbb\x03\n" +
1008+ "\fIssueService\x12F\n" +
1009+ "\vCreateIssue\x12\x1a.ermite.CreateIssueRequest\x1a\x1b.ermite.CreateIssueResponse\x12C\n" +
1010+ "\n" +
1011+ "ListIssues\x12\x19.ermite.ListIssuesRequest\x1a\x1a.ermite.ListIssuesResponse\x12=\n" +
1012+ "\bGetIssue\x12\x17.ermite.GetIssueRequest\x1a\x18.ermite.GetIssueResponse\x12R\n" +
1013+ "\x0fAddIssueComment\x12\x1e.ermite.AddIssueCommentRequest\x1a\x1f.ermite.AddIssueCommentResponse\x12C\n" +
1014+ "\n" +
1015+ "CloseIssue\x12\x19.ermite.CloseIssueRequest\x1a\x1a.ermite.CloseIssueResponse\x12F\n" +
1016+ "\vReopenIssue\x12\x1a.ermite.ReopenIssueRequest\x1a\x1b.ermite.ReopenIssueResponseBq\n" +
1017+ "\n" +
1018+ "com.ermiteB\n" +
1019+ "IssueProtoP\x01Z\x1fbnema.dev/ermite-api/gen/ermite\xa2\x02\x03EXX\xaa\x02\x06Ermite\xca\x02\x06Ermite\xe2\x02\x12Ermite\\GPBMetadata\xea\x02\x06Ermiteb\x06proto3"
1020+
1021+var (
1022+ file_ermite_issue_proto_rawDescOnce sync.Once
1023+ file_ermite_issue_proto_rawDescData []byte
1024+)
1025+
1026+func file_ermite_issue_proto_rawDescGZIP() []byte {
1027+ file_ermite_issue_proto_rawDescOnce.Do(func() {
1028+ file_ermite_issue_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ermite_issue_proto_rawDesc), len(file_ermite_issue_proto_rawDesc)))
1029+ })
1030+ return file_ermite_issue_proto_rawDescData
1031+}
1032+
1033+var file_ermite_issue_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
1034+var file_ermite_issue_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
1035+var file_ermite_issue_proto_goTypes = []any{
1036+ (IssueState)(0), // 0: ermite.IssueState
1037+ (*Issue)(nil), // 1: ermite.Issue
1038+ (*IssueComment)(nil), // 2: ermite.IssueComment
1039+ (*CreateIssueRequest)(nil), // 3: ermite.CreateIssueRequest
1040+ (*CreateIssueResponse)(nil), // 4: ermite.CreateIssueResponse
1041+ (*ListIssuesRequest)(nil), // 5: ermite.ListIssuesRequest
1042+ (*ListIssuesResponse)(nil), // 6: ermite.ListIssuesResponse
1043+ (*GetIssueRequest)(nil), // 7: ermite.GetIssueRequest
1044+ (*GetIssueResponse)(nil), // 8: ermite.GetIssueResponse
1045+ (*AddIssueCommentRequest)(nil), // 9: ermite.AddIssueCommentRequest
1046+ (*AddIssueCommentResponse)(nil), // 10: ermite.AddIssueCommentResponse
1047+ (*CloseIssueRequest)(nil), // 11: ermite.CloseIssueRequest
1048+ (*CloseIssueResponse)(nil), // 12: ermite.CloseIssueResponse
1049+ (*ReopenIssueRequest)(nil), // 13: ermite.ReopenIssueRequest
1050+ (*ReopenIssueResponse)(nil), // 14: ermite.ReopenIssueResponse
1051+ (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
1052+}
1053+var file_ermite_issue_proto_depIdxs = []int32{
1054+ 0, // 0: ermite.Issue.state:type_name -> ermite.IssueState
1055+ 15, // 1: ermite.Issue.created_at:type_name -> google.protobuf.Timestamp
1056+ 15, // 2: ermite.Issue.updated_at:type_name -> google.protobuf.Timestamp
1057+ 15, // 3: ermite.IssueComment.created_at:type_name -> google.protobuf.Timestamp
1058+ 1, // 4: ermite.CreateIssueResponse.issue:type_name -> ermite.Issue
1059+ 0, // 5: ermite.ListIssuesRequest.state:type_name -> ermite.IssueState
1060+ 1, // 6: ermite.ListIssuesResponse.issues:type_name -> ermite.Issue
1061+ 1, // 7: ermite.GetIssueResponse.issue:type_name -> ermite.Issue
1062+ 2, // 8: ermite.GetIssueResponse.comments:type_name -> ermite.IssueComment
1063+ 2, // 9: ermite.AddIssueCommentResponse.comment:type_name -> ermite.IssueComment
1064+ 1, // 10: ermite.CloseIssueResponse.issue:type_name -> ermite.Issue
1065+ 1, // 11: ermite.ReopenIssueResponse.issue:type_name -> ermite.Issue
1066+ 3, // 12: ermite.IssueService.CreateIssue:input_type -> ermite.CreateIssueRequest
1067+ 5, // 13: ermite.IssueService.ListIssues:input_type -> ermite.ListIssuesRequest
1068+ 7, // 14: ermite.IssueService.GetIssue:input_type -> ermite.GetIssueRequest
1069+ 9, // 15: ermite.IssueService.AddIssueComment:input_type -> ermite.AddIssueCommentRequest
1070+ 11, // 16: ermite.IssueService.CloseIssue:input_type -> ermite.CloseIssueRequest
1071+ 13, // 17: ermite.IssueService.ReopenIssue:input_type -> ermite.ReopenIssueRequest
1072+ 4, // 18: ermite.IssueService.CreateIssue:output_type -> ermite.CreateIssueResponse
1073+ 6, // 19: ermite.IssueService.ListIssues:output_type -> ermite.ListIssuesResponse
1074+ 8, // 20: ermite.IssueService.GetIssue:output_type -> ermite.GetIssueResponse
1075+ 10, // 21: ermite.IssueService.AddIssueComment:output_type -> ermite.AddIssueCommentResponse
1076+ 12, // 22: ermite.IssueService.CloseIssue:output_type -> ermite.CloseIssueResponse
1077+ 14, // 23: ermite.IssueService.ReopenIssue:output_type -> ermite.ReopenIssueResponse
1078+ 18, // [18:24] is the sub-list for method output_type
1079+ 12, // [12:18] is the sub-list for method input_type
1080+ 12, // [12:12] is the sub-list for extension type_name
1081+ 12, // [12:12] is the sub-list for extension extendee
1082+ 0, // [0:12] is the sub-list for field type_name
1083+}
1084+
1085+func init() { file_ermite_issue_proto_init() }
1086+func file_ermite_issue_proto_init() {
1087+ if File_ermite_issue_proto != nil {
1088+ return
1089+ }
1090+ type x struct{}
1091+ out := protoimpl.TypeBuilder{
1092+ File: protoimpl.DescBuilder{
1093+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1094+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_issue_proto_rawDesc), len(file_ermite_issue_proto_rawDesc)),
1095+ NumEnums: 1,
1096+ NumMessages: 14,
1097+ NumExtensions: 0,
1098+ NumServices: 1,
1099+ },
1100+ GoTypes: file_ermite_issue_proto_goTypes,
1101+ DependencyIndexes: file_ermite_issue_proto_depIdxs,
1102+ EnumInfos: file_ermite_issue_proto_enumTypes,
1103+ MessageInfos: file_ermite_issue_proto_msgTypes,
1104+ }.Build()
1105+ File_ermite_issue_proto = out.File
1106+ file_ermite_issue_proto_goTypes = nil
1107+ file_ermite_issue_proto_depIdxs = nil
1108+}
M gen/ermite/repo.pb.go +146 -57 generated file: collapsed
M gen/ermite/token.pb.go +8 -2 generated file: collapsed
A issue_test.go +85 -0
@@ -0,0 +1,85 @@
1+// SPDX-License-Identifier: MIT
2+
3+package api_test
4+
5+import (
6+ "testing"
7+
8+ "bnema.dev/ermite-api/gen/ermite"
9+ "bnema.dev/ermite-api/gen/ermite/ermiteconnect"
10+ "google.golang.org/protobuf/proto"
11+ "google.golang.org/protobuf/reflect/protoreflect"
12+)
13+
14+func TestIssueProcedures(t *testing.T) {
15+ tests := map[string]string{
16+ ermiteconnect.IssueServiceCreateIssueProcedure: "CreateIssue",
17+ ermiteconnect.IssueServiceListIssuesProcedure: "ListIssues",
18+ ermiteconnect.IssueServiceGetIssueProcedure: "GetIssue",
19+ ermiteconnect.IssueServiceAddIssueCommentProcedure: "AddIssueComment",
20+ ermiteconnect.IssueServiceCloseIssueProcedure: "CloseIssue",
21+ ermiteconnect.IssueServiceReopenIssueProcedure: "ReopenIssue",
22+ }
23+ for got, name := range tests {
24+ if want := "/ermite.IssueService/" + name; got != want {
25+ t.Errorf("procedure = %q, want %q", got, want)
26+ }
27+ }
28+}
29+
30+func TestIssueContract(t *testing.T) {
31+ for _, tt := range []struct {
32+ msg proto.Message
33+ fields map[string]int
34+ }{
35+ {&ermite.Issue{}, map[string]int{"repo": 1, "number": 2, "title": 3, "body": 4, "state": 5, "author": 6, "created_at": 7, "updated_at": 8, "comment_count": 9}},
36+ {&ermite.IssueComment{}, map[string]int{"id": 1, "author": 2, "text": 3, "created_at": 4}},
37+ {&ermite.RepoSettings{}, map[string]int{"issues": 3}},
38+ {&ermite.UpdateRepoRequest{}, map[string]int{"issues": 8}},
39+ {&ermite.Event{}, map[string]int{"issue_opened": 17, "issue_closed": 18, "issue_reopened": 19, "issue_commented": 20}},
40+ } {
41+ md := tt.msg.ProtoReflect().Descriptor()
42+ for name, num := range tt.fields {
43+ if fd := md.Fields().ByName(protoreflect.Name(name)); fd == nil || int(fd.Number()) != num {
44+ t.Errorf("%s.%s = %v, want %d", md.Name(), name, fd, num)
45+ }
46+ }
47+ }
48+ if ermite.Scope_SCOPE_ISSUE_WRITE != 11 {
49+ t.Fatal("issue:write scope number changed")
50+ }
51+ for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3} {
52+ if got := ermite.IssueState_value[name]; got != want {
53+ t.Errorf("%s = %d, want %d", name, got, want)
54+ }
55+ }
56+ for name, want := range map[string]int32{"ISSUES_MODE_UNSPECIFIED": 0, "ISSUES_MODE_OFF": 1, "ISSUES_MODE_OWNER": 2, "ISSUES_MODE_PUBLIC": 3} {
57+ if got := ermite.IssuesMode_value[name]; got != want {
58+ t.Errorf("%s = %d, want %d", name, got, want)
59+ }
60+ }
61+ mode := ermite.IssuesMode_ISSUES_MODE_OFF
62+ for _, in := range []proto.Message{
63+ &ermite.UpdateRepoRequest{Repo: "r", Issues: &mode},
64+ &ermite.Event{Kind: &ermite.Event_IssueOpened{IssueOpened: &ermite.IssueOpened{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
65+ &ermite.Event{Kind: &ermite.Event_IssueClosed{IssueClosed: &ermite.IssueClosed{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
66+ &ermite.Event{Kind: &ermite.Event_IssueReopened{IssueReopened: &ermite.IssueReopened{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
67+ &ermite.Event{Kind: &ermite.Event_IssueCommented{IssueCommented: &ermite.IssueCommented{Repo: "r", Number: 1, Comment: &ermite.IssueComment{Id: "c", Text: "hi"}}}},
68+ } {
69+ b, err := proto.Marshal(in)
70+ if err != nil {
71+ t.Fatal(err)
72+ }
73+ out := in.ProtoReflect().New().Interface()
74+ if err := proto.Unmarshal(b, out); err != nil {
75+ t.Fatal(err)
76+ }
77+ if !proto.Equal(in, out) {
78+ t.Errorf("%T: round trip mismatch", in)
79+ }
80+ }
81+ fd := (&ermite.UpdateRepoRequest{}).ProtoReflect().Descriptor().Fields().ByName("issues")
82+ if !fd.HasOptionalKeyword() {
83+ t.Fatal("UpdateRepoRequest.issues must be optional")
84+ }
85+}
@@ -0,0 +1,85 @@
1+// SPDX-License-Identifier: MIT
2+
3+package api_test
4+
5+import (
6+ "testing"
7+
8+ "bnema.dev/ermite-api/gen/ermite"
9+ "bnema.dev/ermite-api/gen/ermite/ermiteconnect"
10+ "google.golang.org/protobuf/proto"
11+ "google.golang.org/protobuf/reflect/protoreflect"
12+)
13+
14+func TestIssueProcedures(t *testing.T) {
15+ tests := map[string]string{
16+ ermiteconnect.IssueServiceCreateIssueProcedure: "CreateIssue",
17+ ermiteconnect.IssueServiceListIssuesProcedure: "ListIssues",
18+ ermiteconnect.IssueServiceGetIssueProcedure: "GetIssue",
19+ ermiteconnect.IssueServiceAddIssueCommentProcedure: "AddIssueComment",
20+ ermiteconnect.IssueServiceCloseIssueProcedure: "CloseIssue",
21+ ermiteconnect.IssueServiceReopenIssueProcedure: "ReopenIssue",
22+ }
23+ for got, name := range tests {
24+ if want := "/ermite.IssueService/" + name; got != want {
25+ t.Errorf("procedure = %q, want %q", got, want)
26+ }
27+ }
28+}
29+
30+func TestIssueContract(t *testing.T) {
31+ for _, tt := range []struct {
32+ msg proto.Message
33+ fields map[string]int
34+ }{
35+ {&ermite.Issue{}, map[string]int{"repo": 1, "number": 2, "title": 3, "body": 4, "state": 5, "author": 6, "created_at": 7, "updated_at": 8, "comment_count": 9}},
36+ {&ermite.IssueComment{}, map[string]int{"id": 1, "author": 2, "text": 3, "created_at": 4}},
37+ {&ermite.RepoSettings{}, map[string]int{"issues": 3}},
38+ {&ermite.UpdateRepoRequest{}, map[string]int{"issues": 8}},
39+ {&ermite.Event{}, map[string]int{"issue_opened": 17, "issue_closed": 18, "issue_reopened": 19, "issue_commented": 20}},
40+ } {
41+ md := tt.msg.ProtoReflect().Descriptor()
42+ for name, num := range tt.fields {
43+ if fd := md.Fields().ByName(protoreflect.Name(name)); fd == nil || int(fd.Number()) != num {
44+ t.Errorf("%s.%s = %v, want %d", md.Name(), name, fd, num)
45+ }
46+ }
47+ }
48+ if ermite.Scope_SCOPE_ISSUE_WRITE != 11 {
49+ t.Fatal("issue:write scope number changed")
50+ }
51+ for name, want := range map[string]int32{"ISSUE_STATE_UNSPECIFIED": 0, "ISSUE_STATE_OPEN": 1, "ISSUE_STATE_CLOSED": 2, "ISSUE_STATE_PENDING": 3} {
52+ if got := ermite.IssueState_value[name]; got != want {
53+ t.Errorf("%s = %d, want %d", name, got, want)
54+ }
55+ }
56+ for name, want := range map[string]int32{"ISSUES_MODE_UNSPECIFIED": 0, "ISSUES_MODE_OFF": 1, "ISSUES_MODE_OWNER": 2, "ISSUES_MODE_PUBLIC": 3} {
57+ if got := ermite.IssuesMode_value[name]; got != want {
58+ t.Errorf("%s = %d, want %d", name, got, want)
59+ }
60+ }
61+ mode := ermite.IssuesMode_ISSUES_MODE_OFF
62+ for _, in := range []proto.Message{
63+ &ermite.UpdateRepoRequest{Repo: "r", Issues: &mode},
64+ &ermite.Event{Kind: &ermite.Event_IssueOpened{IssueOpened: &ermite.IssueOpened{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
65+ &ermite.Event{Kind: &ermite.Event_IssueClosed{IssueClosed: &ermite.IssueClosed{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
66+ &ermite.Event{Kind: &ermite.Event_IssueReopened{IssueReopened: &ermite.IssueReopened{Issue: &ermite.Issue{Repo: "r", Number: 1}}}},
67+ &ermite.Event{Kind: &ermite.Event_IssueCommented{IssueCommented: &ermite.IssueCommented{Repo: "r", Number: 1, Comment: &ermite.IssueComment{Id: "c", Text: "hi"}}}},
68+ } {
69+ b, err := proto.Marshal(in)
70+ if err != nil {
71+ t.Fatal(err)
72+ }
73+ out := in.ProtoReflect().New().Interface()
74+ if err := proto.Unmarshal(b, out); err != nil {
75+ t.Fatal(err)
76+ }
77+ if !proto.Equal(in, out) {
78+ t.Errorf("%T: round trip mismatch", in)
79+ }
80+ }
81+ fd := (&ermite.UpdateRepoRequest{}).ProtoReflect().Descriptor().Fields().ByName("issues")
82+ if !fd.HasOptionalKeyword() {
83+ t.Fatal("UpdateRepoRequest.issues must be optional")
84+ }
85+}
M proto/ermite/event.proto +41 -2
@@ -4,6 +4,7 @@ syntax = "proto3";
44
55 package ermite;
66
7+import "ermite/issue.proto";
78 import "ermite/merge_request.proto";
89 import "ermite/repo.proto";
910 import "ermite/run.proto";
@@ -18,7 +19,8 @@ service EventService {
1819 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
1920 // for merge requests, merge_request_opened, merge_request_merged,
2021 // merge_request_closed, comment_added, comment_edited, comment_deleted and
21- // comment_resolved (a thread resolved or reopened). Each one is delivered on the
22+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
23+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
2224 // "repo:<name>" topic of its repository and on "home", subject to the
2325 // visibility of the repository.
2426 //
@@ -109,6 +111,14 @@ message Event {
109111 CommentDeleted comment_deleted = 15;
110112 // CommentResolved: a merge request comment was resolved or unresolved.
111113 CommentResolved comment_resolved = 16;
114+ // IssueOpened: an issue was opened.
115+ IssueOpened issue_opened = 17;
116+ // IssueClosed: an issue was closed.
117+ IssueClosed issue_closed = 18;
118+ // IssueReopened: an issue was reopened.
119+ IssueReopened issue_reopened = 19;
120+ // IssueCommented: a comment was added to an issue.
121+ IssueCommented issue_commented = 20;
112122 }
113123 }
114124
@@ -209,10 +219,39 @@ message CommentResolved {
209219 Comment comment = 3;
210220 }
211221
222+// IssueOpened reports a new issue.
223+message IssueOpened {
224+ // Issue is the new issue, including its repository and number.
225+ Issue issue = 1;
226+}
227+
228+// IssueClosed reports a closed issue.
229+message IssueClosed {
230+ // Issue is the issue after closing, including its repository and number.
231+ Issue issue = 1;
232+}
233+
234+// IssueReopened reports a reopened issue.
235+message IssueReopened {
236+ // Issue is the issue after reopening, including its repository and number.
237+ Issue issue = 1;
238+}
239+
240+// IssueCommented reports a new comment on an issue.
241+message IssueCommented {
242+ // Repo is the name of the repository.
243+ string repo = 1;
244+ // Number is the number of the issue.
245+ int64 number = 2;
246+ // Comment is the new comment.
247+ IssueComment comment = 3;
248+}
249+
212250 // Gap tells the client that events were lost: the requested resume point is
213251 // older than the server's buffer. It has no fields. The client should reload
214252 // the state it displays (repositories, refs, merge requests and their
215-// comments, CI runs and their jobs) and carry on with the next events.
253+// comments, issues and their comments, CI runs and their jobs) and carry on
254+// with the next events.
216255 message Gap {}
217256
218257 // RunUpdated reports a CI run that was created or whose status, conclusion or
@@ -4,6 +4,7 @@ syntax = "proto3";
4 4
5 package ermite;5 package ermite;
6 6
7+import "ermite/issue.proto";
7 import "ermite/merge_request.proto";8 import "ermite/merge_request.proto";
8 import "ermite/repo.proto";9 import "ermite/repo.proto";
9 import "ermite/run.proto";10 import "ermite/run.proto";
@@ -18,7 +19,8 @@ service EventService {
18 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,19 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
19 // for merge requests, merge_request_opened, merge_request_merged,20 // for merge requests, merge_request_opened, merge_request_merged,
20 // merge_request_closed, comment_added, comment_edited, comment_deleted and21 // merge_request_closed, comment_added, comment_edited, comment_deleted and
21- // comment_resolved (a thread resolved or reopened). Each one is delivered on the22+ // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
23+ // issue_closed, issue_reopened and issue_commented. Each one is delivered on the
22 // "repo:<name>" topic of its repository and on "home", subject to the24 // "repo:<name>" topic of its repository and on "home", subject to the
23 // visibility of the repository.25 // visibility of the repository.
24 //26 //
@@ -109,6 +111,14 @@ message Event {
109 CommentDeleted comment_deleted = 15;111 CommentDeleted comment_deleted = 15;
110 // CommentResolved: a merge request comment was resolved or unresolved.112 // CommentResolved: a merge request comment was resolved or unresolved.
111 CommentResolved comment_resolved = 16;113 CommentResolved comment_resolved = 16;
114+ // IssueOpened: an issue was opened.
115+ IssueOpened issue_opened = 17;
116+ // IssueClosed: an issue was closed.
117+ IssueClosed issue_closed = 18;
118+ // IssueReopened: an issue was reopened.
119+ IssueReopened issue_reopened = 19;
120+ // IssueCommented: a comment was added to an issue.
121+ IssueCommented issue_commented = 20;
112 }122 }
113 }123 }
114 124
@@ -209,10 +219,39 @@ message CommentResolved {
209 Comment comment = 3;219 Comment comment = 3;
210 }220 }
211 221
222+// IssueOpened reports a new issue.
223+message IssueOpened {
224+ // Issue is the new issue, including its repository and number.
225+ Issue issue = 1;
226+}
227+
228+// IssueClosed reports a closed issue.
229+message IssueClosed {
230+ // Issue is the issue after closing, including its repository and number.
231+ Issue issue = 1;
232+}
233+
234+// IssueReopened reports a reopened issue.
235+message IssueReopened {
236+ // Issue is the issue after reopening, including its repository and number.
237+ Issue issue = 1;
238+}
239+
240+// IssueCommented reports a new comment on an issue.
241+message IssueCommented {
242+ // Repo is the name of the repository.
243+ string repo = 1;
244+ // Number is the number of the issue.
245+ int64 number = 2;
246+ // Comment is the new comment.
247+ IssueComment comment = 3;
248+}
249+
212 // Gap tells the client that events were lost: the requested resume point is250 // Gap tells the client that events were lost: the requested resume point is
213 // older than the server's buffer. It has no fields. The client should reload251 // older than the server's buffer. It has no fields. The client should reload
214 // the state it displays (repositories, refs, merge requests and their252 // the state it displays (repositories, refs, merge requests and their
215-// comments, CI runs and their jobs) and carry on with the next events.253+// comments, issues and their comments, CI runs and their jobs) and carry on
254+// with the next events.
216 message Gap {}255 message Gap {}
217 256
218 // RunUpdated reports a CI run that was created or whose status, conclusion or257 // RunUpdated reports a CI run that was created or whose status, conclusion or
A proto/ermite/issue.proto +172 -0
@@ -0,0 +1,172 @@
1+// SPDX-License-Identifier: MIT
2+
3+syntax = "proto3";
4+
5+package ermite;
6+
7+import "google/protobuf/timestamp.proto";
8+
9+// IssueState is where an issue is in its life.
10+enum IssueState {
11+ // Not set. In ListIssuesRequest.state it means every state. Never returned
12+ // by the server.
13+ ISSUE_STATE_UNSPECIFIED = 0;
14+ // The issue is open.
15+ ISSUE_STATE_OPEN = 1;
16+ // The issue is closed.
17+ ISSUE_STATE_CLOSED = 2;
18+ // Reserved for later use: awaiting moderation, owner-only.
19+ ISSUE_STATE_PENDING = 3;
20+}
21+
22+// Issue is a discussion in a repository.
23+message Issue {
24+ // Repo is the name of the repository.
25+ string repo = 1;
26+ // Number identifies the issue within its repository.
27+ int64 number = 2;
28+ // Title is the one-line title.
29+ string title = 3;
30+ // Body is the content of the issue. It may be empty.
31+ string body = 4;
32+ // State is where the issue is in its life.
33+ IssueState state = 5;
34+ // Author names who created the issue: the label of the token that was used,
35+ // "root" for the root token, or "owner" for a web session. It is
36+ // informational: labels are not unique and the token may be gone.
37+ string author = 6;
38+ // CreatedAt is when the issue was created.
39+ google.protobuf.Timestamp created_at = 7;
40+ // UpdatedAt is when the issue last changed.
41+ google.protobuf.Timestamp updated_at = 8;
42+ // CommentCount is the number of comments on the issue.
43+ int32 comment_count = 9;
44+}
45+
46+// IssueComment is a note on an issue.
47+message IssueComment {
48+ // Id identifies the comment within its issue. Opaque.
49+ string id = 1;
50+ // Author names who wrote the comment, like Issue.author.
51+ string author = 2;
52+ // Text is the content of the comment.
53+ string text = 3;
54+ // CreatedAt is when the comment was written.
55+ google.protobuf.Timestamp created_at = 4;
56+}
57+
58+// IssueService manages issues and their comments.
59+service IssueService {
60+ // CreateIssue opens an issue. Needs the issue:write scope.
61+ rpc CreateIssue(CreateIssueRequest) returns (CreateIssueResponse);
62+ // ListIssues lists issues, highest number first, optionally in one state.
63+ rpc ListIssues(ListIssuesRequest) returns (ListIssuesResponse);
64+ // GetIssue returns an issue with its comments.
65+ rpc GetIssue(GetIssueRequest) returns (GetIssueResponse);
66+ // AddIssueComment adds a comment. Needs the issue:write scope.
67+ rpc AddIssueComment(AddIssueCommentRequest) returns (AddIssueCommentResponse);
68+ // CloseIssue closes an issue. Needs the issue:write scope.
69+ rpc CloseIssue(CloseIssueRequest) returns (CloseIssueResponse);
70+ // ReopenIssue reopens an issue. Needs the issue:write scope.
71+ rpc ReopenIssue(ReopenIssueRequest) returns (ReopenIssueResponse);
72+}
73+
74+// CreateIssueRequest describes the issue to open.
75+message CreateIssueRequest {
76+ // Repo is the repository name.
77+ string repo = 1;
78+ // Title is the one-line title. Required.
79+ string title = 2;
80+ // Body is the optional content.
81+ string body = 3;
82+}
83+
84+// CreateIssueResponse holds the new issue.
85+message CreateIssueResponse {
86+ // Issue is the created issue.
87+ Issue issue = 1;
88+}
89+
90+// ListIssuesRequest selects a page of issues.
91+message ListIssuesRequest {
92+ // Repo is the repository name.
93+ string repo = 1;
94+ // State restricts the result to one state. ISSUE_STATE_UNSPECIFIED means
95+ // every state.
96+ IssueState state = 2;
97+ // PageSize is the maximum number of issues to return. 0 means the server
98+ // default; values above the server maximum are lowered to it.
99+ int32 page_size = 3;
100+ // PageToken is the next_page_token of a previous response, to continue the
101+ // same listing. Empty for the first page. Other fields must be unchanged.
102+ string page_token = 4;
103+}
104+
105+// ListIssuesResponse is one page of issues.
106+message ListIssuesResponse {
107+ // Issues are the issues of this page, highest number first.
108+ repeated Issue issues = 1;
109+ // NextPageToken is passed as page_token to get the next page. Empty when
110+ // there is no next page.
111+ string next_page_token = 2;
112+}
113+
114+// GetIssueRequest selects an issue.
115+message GetIssueRequest {
116+ // Repo is the repository name.
117+ string repo = 1;
118+ // Number is the issue number.
119+ int64 number = 2;
120+}
121+
122+// GetIssueResponse holds an issue with its comments.
123+message GetIssueResponse {
124+ // Issue is the issue.
125+ Issue issue = 1;
126+ // Comments are every comment of the issue, oldest first.
127+ repeated IssueComment comments = 2;
128+}
129+
130+// AddIssueCommentRequest describes the comment to add.
131+message AddIssueCommentRequest {
132+ // Repo is the repository name.
133+ string repo = 1;
134+ // Number is the issue number.
135+ int64 number = 2;
136+ // Text is the content. Required.
137+ string text = 3;
138+}
139+
140+// AddIssueCommentResponse holds the new comment.
141+message AddIssueCommentResponse {
142+ // Comment is the created comment.
143+ IssueComment comment = 1;
144+}
145+
146+// CloseIssueRequest names the issue to close.
147+message CloseIssueRequest {
148+ // Repo is the repository name.
149+ string repo = 1;
150+ // Number is the issue number.
151+ int64 number = 2;
152+}
153+
154+// CloseIssueResponse holds the issue after closing.
155+message CloseIssueResponse {
156+ // Issue is the closed issue.
157+ Issue issue = 1;
158+}
159+
160+// ReopenIssueRequest names the issue to reopen.
161+message ReopenIssueRequest {
162+ // Repo is the repository name.
163+ string repo = 1;
164+ // Number is the issue number.
165+ int64 number = 2;
166+}
167+
168+// ReopenIssueResponse holds the issue after reopening.
169+message ReopenIssueResponse {
170+ // Issue is the reopened issue.
171+ Issue issue = 1;
172+}
@@ -0,0 +1,172 @@
1+// SPDX-License-Identifier: MIT
2+
3+syntax = "proto3";
4+
5+package ermite;
6+
7+import "google/protobuf/timestamp.proto";
8+
9+// IssueState is where an issue is in its life.
10+enum IssueState {
11+ // Not set. In ListIssuesRequest.state it means every state. Never returned
12+ // by the server.
13+ ISSUE_STATE_UNSPECIFIED = 0;
14+ // The issue is open.
15+ ISSUE_STATE_OPEN = 1;
16+ // The issue is closed.
17+ ISSUE_STATE_CLOSED = 2;
18+ // Reserved for later use: awaiting moderation, owner-only.
19+ ISSUE_STATE_PENDING = 3;
20+}
21+
22+// Issue is a discussion in a repository.
23+message Issue {
24+ // Repo is the name of the repository.
25+ string repo = 1;
26+ // Number identifies the issue within its repository.
27+ int64 number = 2;
28+ // Title is the one-line title.
29+ string title = 3;
30+ // Body is the content of the issue. It may be empty.
31+ string body = 4;
32+ // State is where the issue is in its life.
33+ IssueState state = 5;
34+ // Author names who created the issue: the label of the token that was used,
35+ // "root" for the root token, or "owner" for a web session. It is
36+ // informational: labels are not unique and the token may be gone.
37+ string author = 6;
38+ // CreatedAt is when the issue was created.
39+ google.protobuf.Timestamp created_at = 7;
40+ // UpdatedAt is when the issue last changed.
41+ google.protobuf.Timestamp updated_at = 8;
42+ // CommentCount is the number of comments on the issue.
43+ int32 comment_count = 9;
44+}
45+
46+// IssueComment is a note on an issue.
47+message IssueComment {
48+ // Id identifies the comment within its issue. Opaque.
49+ string id = 1;
50+ // Author names who wrote the comment, like Issue.author.
51+ string author = 2;
52+ // Text is the content of the comment.
53+ string text = 3;
54+ // CreatedAt is when the comment was written.
55+ google.protobuf.Timestamp created_at = 4;
56+}
57+
58+// IssueService manages issues and their comments.
59+service IssueService {
60+ // CreateIssue opens an issue. Needs the issue:write scope.
61+ rpc CreateIssue(CreateIssueRequest) returns (CreateIssueResponse);
62+ // ListIssues lists issues, highest number first, optionally in one state.
63+ rpc ListIssues(ListIssuesRequest) returns (ListIssuesResponse);
64+ // GetIssue returns an issue with its comments.
65+ rpc GetIssue(GetIssueRequest) returns (GetIssueResponse);
66+ // AddIssueComment adds a comment. Needs the issue:write scope.
67+ rpc AddIssueComment(AddIssueCommentRequest) returns (AddIssueCommentResponse);
68+ // CloseIssue closes an issue. Needs the issue:write scope.
69+ rpc CloseIssue(CloseIssueRequest) returns (CloseIssueResponse);
70+ // ReopenIssue reopens an issue. Needs the issue:write scope.
71+ rpc ReopenIssue(ReopenIssueRequest) returns (ReopenIssueResponse);
72+}
73+
74+// CreateIssueRequest describes the issue to open.
75+message CreateIssueRequest {
76+ // Repo is the repository name.
77+ string repo = 1;
78+ // Title is the one-line title. Required.
79+ string title = 2;
80+ // Body is the optional content.
81+ string body = 3;
82+}
83+
84+// CreateIssueResponse holds the new issue.
85+message CreateIssueResponse {
86+ // Issue is the created issue.
87+ Issue issue = 1;
88+}
89+
90+// ListIssuesRequest selects a page of issues.
91+message ListIssuesRequest {
92+ // Repo is the repository name.
93+ string repo = 1;
94+ // State restricts the result to one state. ISSUE_STATE_UNSPECIFIED means
95+ // every state.
96+ IssueState state = 2;
97+ // PageSize is the maximum number of issues to return. 0 means the server
98+ // default; values above the server maximum are lowered to it.
99+ int32 page_size = 3;
100+ // PageToken is the next_page_token of a previous response, to continue the
101+ // same listing. Empty for the first page. Other fields must be unchanged.
102+ string page_token = 4;
103+}
104+
105+// ListIssuesResponse is one page of issues.
106+message ListIssuesResponse {
107+ // Issues are the issues of this page, highest number first.
108+ repeated Issue issues = 1;
109+ // NextPageToken is passed as page_token to get the next page. Empty when
110+ // there is no next page.
111+ string next_page_token = 2;
112+}
113+
114+// GetIssueRequest selects an issue.
115+message GetIssueRequest {
116+ // Repo is the repository name.
117+ string repo = 1;
118+ // Number is the issue number.
119+ int64 number = 2;
120+}
121+
122+// GetIssueResponse holds an issue with its comments.
123+message GetIssueResponse {
124+ // Issue is the issue.
125+ Issue issue = 1;
126+ // Comments are every comment of the issue, oldest first.
127+ repeated IssueComment comments = 2;
128+}
129+
130+// AddIssueCommentRequest describes the comment to add.
131+message AddIssueCommentRequest {
132+ // Repo is the repository name.
133+ string repo = 1;
134+ // Number is the issue number.
135+ int64 number = 2;
136+ // Text is the content. Required.
137+ string text = 3;
138+}
139+
140+// AddIssueCommentResponse holds the new comment.
141+message AddIssueCommentResponse {
142+ // Comment is the created comment.
143+ IssueComment comment = 1;
144+}
145+
146+// CloseIssueRequest names the issue to close.
147+message CloseIssueRequest {
148+ // Repo is the repository name.
149+ string repo = 1;
150+ // Number is the issue number.
151+ int64 number = 2;
152+}
153+
154+// CloseIssueResponse holds the issue after closing.
155+message CloseIssueResponse {
156+ // Issue is the closed issue.
157+ Issue issue = 1;
158+}
159+
160+// ReopenIssueRequest names the issue to reopen.
161+message ReopenIssueRequest {
162+ // Repo is the repository name.
163+ string repo = 1;
164+ // Number is the issue number.
165+ int64 number = 2;
166+}
167+
168+// ReopenIssueResponse holds the issue after reopening.
169+message ReopenIssueResponse {
170+ // Issue is the reopened issue.
171+ Issue issue = 1;
172+}
M proto/ermite/repo.proto +21 -4
@@ -20,8 +20,20 @@ enum Visibility {
2020 VISIBILITY_PRIVATE = 2;
2121 }
2222
23+// IssuesMode says who may write issues in a repository.
24+enum IssuesMode {
25+ // Not set.
26+ ISSUES_MODE_UNSPECIFIED = 0;
27+ // Issues are disabled.
28+ ISSUES_MODE_OFF = 1;
29+ // Only the owner may write issues.
30+ ISSUES_MODE_OWNER = 2;
31+ // Issues are open to public participation.
32+ ISSUES_MODE_PUBLIC = 3;
33+}
34+
2335 // RepoSettings are the settings of a repository that govern its merge
24-// requests.
36+// requests and issues.
2537 message RepoSettings {
2638 // AllowedMergeModes are the modes with which a merge request of the
2739 // repository may be merged. It is never empty in a response and has no
@@ -33,6 +45,8 @@ message RepoSettings {
3345 // explicitly, so a later change of the server default never alters an
3446 // existing repository.
3547 bool failing_checks_block = 2;
48+ // Issues is the issue participation mode of the repository.
49+ IssuesMode issues = 3;
3650 }
3751
3852 // Repo is the metadata of a repository. Git-owned state (refs, trees, history)
@@ -53,7 +67,7 @@ message Repo {
5367 google.protobuf.Timestamp created_at = 5;
5468 // PushedAt is the time of the last push. It is unset until the first push.
5569 google.protobuf.Timestamp pushed_at = 6;
56- // Settings are the merge settings of the repository. Always set in a
70+ // Settings are the settings of the repository. Always set in a
5771 // response, with the defaults for a repository that never changed them.
5872 RepoSettings settings = 7;
5973 // Topics classify the repository, as on GitHub: at most 20, each 1-50
@@ -153,8 +167,9 @@ message UpdateRepoRequest {
153167 string default_branch = 4;
154168 // UpdateMask lists the fields to change: "description", "visibility",
155169 // "default_branch", "topics", "settings.allowed_merge_modes" and/or
156- // "settings.failing_checks_block". "settings" stands for both settings
157- // paths. It must not be empty. Other paths are invalid_argument.
170+ // "settings.failing_checks_block". "settings" stands for both merge settings
171+ // paths. The optional issues field changes the issue mode separately.
172+ // It must not be empty. Other paths are invalid_argument.
158173 google.protobuf.FieldMask update_mask = 5;
159174 // Settings holds the new merge settings. Only the fields named in
160175 // update_mask are used. allowed_merge_modes must then not be empty nor
@@ -165,6 +180,8 @@ message UpdateRepoRequest {
165180 // Topics replace the topics of the repository (see Repo.topics). Used only
166181 // if update_mask contains "topics"; an empty list then clears them.
167182 repeated string topics = 7;
183+ // Issues is the new issue participation mode. When absent it is unchanged.
184+ optional IssuesMode issues = 8;
168185 }
169186
170187 // UpdateRepoResponse holds the repository after the update.
@@ -20,8 +20,20 @@ enum Visibility {
20 VISIBILITY_PRIVATE = 2;20 VISIBILITY_PRIVATE = 2;
21 }21 }
22 22
23+// IssuesMode says who may write issues in a repository.
24+enum IssuesMode {
25+ // Not set.
26+ ISSUES_MODE_UNSPECIFIED = 0;
27+ // Issues are disabled.
28+ ISSUES_MODE_OFF = 1;
29+ // Only the owner may write issues.
30+ ISSUES_MODE_OWNER = 2;
31+ // Issues are open to public participation.
32+ ISSUES_MODE_PUBLIC = 3;
33+}
34+
23 // RepoSettings are the settings of a repository that govern its merge35 // RepoSettings are the settings of a repository that govern its merge
24-// requests.36+// requests and issues.
25 message RepoSettings {37 message RepoSettings {
26 // AllowedMergeModes are the modes with which a merge request of the38 // AllowedMergeModes are the modes with which a merge request of the
27 // repository may be merged. It is never empty in a response and has no39 // repository may be merged. It is never empty in a response and has no
@@ -33,6 +45,8 @@ message RepoSettings {
33 // explicitly, so a later change of the server default never alters an45 // explicitly, so a later change of the server default never alters an
34 // existing repository.46 // existing repository.
35 bool failing_checks_block = 2;47 bool failing_checks_block = 2;
48+ // Issues is the issue participation mode of the repository.
49+ IssuesMode issues = 3;
36 }50 }
37 51
38 // Repo is the metadata of a repository. Git-owned state (refs, trees, history)52 // Repo is the metadata of a repository. Git-owned state (refs, trees, history)
@@ -53,7 +67,7 @@ message Repo {
53 google.protobuf.Timestamp created_at = 5;67 google.protobuf.Timestamp created_at = 5;
54 // PushedAt is the time of the last push. It is unset until the first push.68 // PushedAt is the time of the last push. It is unset until the first push.
55 google.protobuf.Timestamp pushed_at = 6;69 google.protobuf.Timestamp pushed_at = 6;
56- // Settings are the merge settings of the repository. Always set in a70+ // Settings are the settings of the repository. Always set in a
57 // response, with the defaults for a repository that never changed them.71 // response, with the defaults for a repository that never changed them.
58 RepoSettings settings = 7;72 RepoSettings settings = 7;
59 // Topics classify the repository, as on GitHub: at most 20, each 1-5073 // Topics classify the repository, as on GitHub: at most 20, each 1-50
@@ -153,8 +167,9 @@ message UpdateRepoRequest {
153 string default_branch = 4;167 string default_branch = 4;
154 // UpdateMask lists the fields to change: "description", "visibility",168 // UpdateMask lists the fields to change: "description", "visibility",
155 // "default_branch", "topics", "settings.allowed_merge_modes" and/or169 // "default_branch", "topics", "settings.allowed_merge_modes" and/or
156- // "settings.failing_checks_block". "settings" stands for both settings170+ // "settings.failing_checks_block". "settings" stands for both merge settings
157- // paths. It must not be empty. Other paths are invalid_argument.171+ // paths. The optional issues field changes the issue mode separately.
172+ // It must not be empty. Other paths are invalid_argument.
158 google.protobuf.FieldMask update_mask = 5;173 google.protobuf.FieldMask update_mask = 5;
159 // Settings holds the new merge settings. Only the fields named in174 // Settings holds the new merge settings. Only the fields named in
160 // update_mask are used. allowed_merge_modes must then not be empty nor175 // update_mask are used. allowed_merge_modes must then not be empty nor
@@ -165,6 +180,8 @@ message UpdateRepoRequest {
165 // Topics replace the topics of the repository (see Repo.topics). Used only180 // Topics replace the topics of the repository (see Repo.topics). Used only
166 // if update_mask contains "topics"; an empty list then clears them.181 // if update_mask contains "topics"; an empty list then clears them.
167 repeated string topics = 7;182 repeated string topics = 7;
183+ // Issues is the new issue participation mode. When absent it is unchanged.
184+ optional IssuesMode issues = 8;
168 }185 }
169 186
170 // UpdateRepoResponse holds the repository after the update.187 // UpdateRepoResponse holds the repository after the update.
M proto/ermite/token.proto +3 -0
@@ -42,6 +42,9 @@ enum Scope {
4242 // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on
4343 // merge request notes. Wire name: mr:review.
4444 SCOPE_MR_REVIEW = 10;
45+ // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
46+ // issues. Wire name: issue:write.
47+ SCOPE_ISSUE_WRITE = 11;
4548 }
4649
4750 // Token describes a stored token. It never contains the secret nor its hash.
@@ -42,6 +42,9 @@ enum Scope {
42 // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on42 // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on
43 // merge request notes. Wire name: mr:review.43 // merge request notes. Wire name: mr:review.
44 SCOPE_MR_REVIEW = 10;44 SCOPE_MR_REVIEW = 10;
45+ // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
46+ // issues. Wire name: issue:write.
47+ SCOPE_ISSUE_WRITE = 11;
45 }48 }
46 49
47 // Token describes a stored token. It never contains the secret nor its hash.50 // 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