1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "ermite/issue.proto";
8import "ermite/merge_request.proto";
9import "ermite/mirror.proto";
10import "ermite/repo.proto";
11import "ermite/run.proto";
12import "google/protobuf/timestamp.proto";
13
14// EventService streams what happens on the forge.
15service EventService {
16 // Watch streams events until the client cancels the call or the server shuts
17 // down. Events are filtered by the caller's access: events of a private
18 // repository are only sent to callers that may read it.
19 //
20 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
21 // for merge requests, merge_request_opened, merge_request_merged,
22 // merge_request_closed, comment_added, comment_edited, comment_deleted and
23 // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
24 // issue_closed, issue_resolved, issue_reopened and issue_commented, and
25 // issue_submitted. Each one is delivered on the "repo:<name>" topic of its
26 // repository and on "home", subject to the visibility of the repository,
27 // except
28 // issue_submitted: it is delivered only on the "owner" topic, never on
29 // "home" or "repo:<name>", and carries no content (see IssueSubmitted).
30 //
31 // Servers with the feature "ci.runs" also publish run_updated and
32 // job_updated, only on the "repo:<name>" topic of their repository (never on
33 // "home"), subject to the same visibility. They carry the state after the
34 // change and are published when a run or a job is created, changes status
35 // or conclusion, or when one of its steps starts or ends (never per log
36 // line: follow a log with RunService.GetJobLog). The order of these events
37 // is not guaranteed, between jobs and runs or between two updates of the same
38 // one: a client keeps the copy with the higher Run.version or
39 // RunJob.version and drops the other. There is no event for a change of title or
40 // description: after a gap, or to see such changes, clients read the merge
41 // request again. A merge publishes
42 // merge_request_merged, then pushed for the target branch.
43 //
44 // The server keeps a bounded buffer of recent events. With resume_after set,
45 // buffered events after that id are replayed first, then live events follow.
46 // When resume_after is no longer buffered (or unknown), the stream begins
47 // with a Gap event, then continues with the oldest buffered event: the client
48 // must reload its state. Without resume_after, only new events are sent.
49 //
50 // The access of the caller is checked again for every event: the stream ends
51 // with unauthenticated when the token was revoked or has expired (the server
52 // may take a few seconds to notice). A repository that becomes private
53 // sends one last repo_updated to the callers who could read it before, with
54 // the new visibility and nothing else about it; no later event of it
55 // reaches them. The server limits the watchers: more than 64 topics is
56 // invalid_argument, and too many concurrent streams, in total or from one
57 // client, is resource_exhausted.
58 rpc Watch(WatchRequest) returns (stream WatchResponse);
59}
60
61// WatchRequest selects the events to receive.
62message WatchRequest {
63 // Topics are the subjects to follow: "home" for every repository visible to
64 // the caller, "repo:<name>" for one repository, or "owner". Empty means
65 // "home". Unknown topics are invalid_argument. A "repo:<name>" topic for a
66 // repository that does not exist or is not visible is not_found.
67 //
68 // The "owner" topic needs owner rights: root, an owner session, or a token
69 // that holds every scope with no repository or branch limit. Anyone else
70 // gets the same invalid_argument as for an unknown topic, so the topic is
71 // not revealed. It carries the merge request and issue events of every
72 // repository (merge_request_opened, merge_request_merged,
73 // merge_request_closed, comment_added, and the issue events), repo_updated
74 // and repo_deleted, plus issue_submitted, which is delivered nowhere else.
75 repeated string topics = 1;
76 // ResumeAfter is the Event.id of the last event the client has seen. Empty
77 // to receive only new events.
78 string resume_after = 2;
79}
80
81// WatchResponse carries one event of the stream.
82message WatchResponse {
83 // Event is the event.
84 Event event = 1;
85}
86
87// Event is something that happened on the forge.
88message Event {
89 // Id identifies the event and is passed as resume_after to resume a stream.
90 // It is opaque and only comparable for equality; clients must not parse it.
91 // Empty on a Gap event.
92 string id = 1;
93 // Time is when the event happened.
94 google.protobuf.Timestamp time = 2;
95 // Kind is the type and payload of the event. New kinds may be added; clients
96 // must ignore kinds they do not know.
97 oneof kind {
98 // RepoCreated: a repository was created.
99 RepoCreated repo_created = 3;
100 // RepoUpdated: repository metadata changed.
101 RepoUpdated repo_updated = 4;
102 // RepoDeleted: a repository was deleted.
103 RepoDeleted repo_deleted = 5;
104 // Pushed: refs of a repository were updated by a push.
105 Pushed pushed = 6;
106 // Gap: events were lost, reload state.
107 Gap gap = 7;
108 // MergeRequestOpened: a merge request was opened.
109 MergeRequestOpened merge_request_opened = 8;
110 // MergeRequestMerged: a merge request was merged.
111 MergeRequestMerged merge_request_merged = 9;
112 // MergeRequestClosed: a merge request was closed without merging.
113 MergeRequestClosed merge_request_closed = 10;
114 // CommentAdded: a comment was added to a merge request.
115 CommentAdded comment_added = 11;
116 // RunUpdated: a CI run was created or changed.
117 RunUpdated run_updated = 12;
118 // JobUpdated: a CI job was created or changed.
119 JobUpdated job_updated = 13;
120 // CommentEdited: the text of a merge request comment was changed.
121 CommentEdited comment_edited = 14;
122 // CommentDeleted: a merge request comment was deleted.
123 CommentDeleted comment_deleted = 15;
124 // CommentResolved: a merge request comment was resolved or unresolved.
125 CommentResolved comment_resolved = 16;
126 // IssueOpened: an issue was opened.
127 IssueOpened issue_opened = 17;
128 // IssueClosed: an issue was closed.
129 IssueClosed issue_closed = 18;
130 // IssueReopened: an issue was reopened.
131 IssueReopened issue_reopened = 19;
132 // IssueCommented: a comment was added to an issue.
133 IssueCommented issue_commented = 20;
134 // IssueSubmitted: an issue is awaiting moderation. Delivered only on the
135 // "owner" topic, never on "home" or "repo:<name>", and carries no content.
136 IssueSubmitted issue_submitted = 21;
137 // MergeRequestMergeability: the mergeability of an open merge request
138 // changed.
139 MergeRequestMergeability merge_request_mergeability = 22;
140 // MirrorFailed: a mirror entered failing or paused.
141 MirrorFailed mirror_failed = 23;
142 // MirrorRecovered: a failing or paused mirror succeeded again.
143 MirrorRecovered mirror_recovered = 24;
144 // MergeRequestAutoMergeEnabled: auto-merge was enabled on a merge request.
145 MergeRequestAutoMergeEnabled merge_request_auto_merge_enabled = 25;
146 // MergeRequestAutoMergeCancelled: the auto-merge of a merge request was
147 // cancelled.
148 MergeRequestAutoMergeCancelled merge_request_auto_merge_cancelled = 26;
149 // ReleasePublished reports a release published.
150 ReleasePublished release_published = 27;
151 // ReleaseUpdated reports a release updated.
152 ReleaseUpdated release_updated = 28;
153 // ReleaseDeleted reports a release deleted.
154 ReleaseDeleted release_deleted = 29;
155 // ReleaseUnpublished reports a release turned into a draft after tag deletion.
156 ReleaseUnpublished release_unpublished = 30;
157 // IssueResolved: an issue was resolved.
158 IssueResolved issue_resolved = 31;
159 }
160}
161
162// RepoCreated reports a new repository.
163message RepoCreated {
164 // Repo is the new repository.
165 Repo repo = 1;
166}
167
168// RepoUpdated reports a metadata change.
169message RepoUpdated {
170 // Repo is the repository after the change.
171 Repo repo = 1;
172}
173
174// RepoDeleted reports a deleted repository.
175message RepoDeleted {
176 // Repo is the name of the deleted repository.
177 string repo = 1;
178}
179
180// Pushed reports the ref updates of one push.
181message Pushed {
182 // Repo is the name of the repository.
183 string repo = 1;
184 // RefUpdates are the refs changed by the push.
185 repeated RefUpdate ref_updates = 2;
186}
187
188// RefUpdate is the change of one ref.
189message RefUpdate {
190 // Ref is the full ref name, for example "refs/heads/main".
191 string ref = 1;
192 // OldId is the object id before the update. Empty when the ref was created.
193 string old_id = 2;
194 // NewId is the object id after the update. Empty when the ref was deleted.
195 string new_id = 3;
196}
197
198// MergeRequestOpened reports a new merge request.
199message MergeRequestOpened {
200 // MergeRequest is the new merge request.
201 MergeRequest merge_request = 1;
202}
203
204// MergeRequestMerged reports a merged merge request. It is published before
205// the Pushed event of the target branch.
206message MergeRequestMerged {
207 // MergeRequest is the merge request after the merge.
208 MergeRequest merge_request = 1;
209 // Auto is true when the server merged it by auto-merge.
210 bool auto = 2;
211}
212
213// MergeRequestAutoMergeEnabled reports auto-merge enabled on an open merge
214// request. It is published again when auto-merge is enabled again.
215message MergeRequestAutoMergeEnabled {
216 // MergeRequest is the merge request, with auto_merge set.
217 MergeRequest merge_request = 1;
218}
219
220// MergeRequestAutoMergeCancelled reports the auto-merge of a merge request
221// cancelled, by a caller or by the server.
222message MergeRequestAutoMergeCancelled {
223 // MergeRequest is the merge request, with auto_merge unset.
224 MergeRequest merge_request = 1;
225 // Reason says in one line why it was cancelled. For display only.
226 string reason = 2;
227}
228
229// MergeRequestMergeability reports the mergeability of an open merge request.
230// It is published each time the server settles a result for new tips of the
231// source or target branch, so the state may be the same as the previous
232// event's. A push that moves neither branch publishes nothing.
233message MergeRequestMergeability {
234 // Repo is the name of the repository.
235 string repo = 1;
236 // Number is the number of the merge request.
237 int64 number = 2;
238 // Mergeability is the new result.
239 Mergeability mergeability = 3;
240}
241
242// MergeRequestClosed reports a merge request closed without merging.
243message MergeRequestClosed {
244 // MergeRequest is the merge request after closing.
245 MergeRequest merge_request = 1;
246}
247
248// CommentAdded reports a new comment on a merge request.
249message CommentAdded {
250 // Repo is the name of the repository.
251 string repo = 1;
252 // Number is the number of the merge request.
253 int64 number = 2;
254 // Comment is the new comment.
255 Comment comment = 3;
256}
257
258// CommentEdited reports a comment of a merge request whose text was changed.
259message CommentEdited {
260 // Repo is the name of the repository.
261 string repo = 1;
262 // Number is the number of the merge request.
263 int64 number = 2;
264 // Comment is the comment after the edit.
265 Comment comment = 3;
266}
267
268// CommentDeleted reports a comment of a merge request that was deleted. The
269// comment stays in the thread with deleted set and an empty text.
270message CommentDeleted {
271 // Repo is the name of the repository.
272 string repo = 1;
273 // Number is the number of the merge request.
274 int64 number = 2;
275 // Comment is the comment after the deletion.
276 Comment comment = 3;
277}
278
279// CommentResolved reports a comment of a merge request whose resolved state
280// changed.
281message CommentResolved {
282 // Repo is the name of the repository.
283 string repo = 1;
284 // Number is the number of the merge request.
285 int64 number = 2;
286 // Comment is the comment after the change.
287 Comment comment = 3;
288}
289
290// IssueOpened reports a new issue.
291message IssueOpened {
292 // Issue is the new issue, including its repository and number.
293 Issue issue = 1;
294}
295
296// IssueClosed reports a closed issue. A merge that resolves an issue sends
297// issue_resolved, not issue_closed.
298message IssueClosed {
299 // Issue is the issue after closing, including its repository and number.
300 Issue issue = 1;
301}
302
303// IssueResolved reports a resolved issue.
304message IssueResolved {
305 // Issue is the issue after resolving, including its repository, number and
306 // closed_by_merge_request.
307 Issue issue = 1;
308}
309
310// IssueReopened reports a reopened issue.
311message IssueReopened {
312 // Issue is the issue after reopening, including its repository and number.
313 Issue issue = 1;
314}
315
316// IssueCommented reports a new comment on an issue.
317message IssueCommented {
318 // Repo is the name of the repository.
319 string repo = 1;
320 // Number is the number of the issue.
321 int64 number = 2;
322 // Comment is the new comment.
323 IssueComment comment = 3;
324}
325
326// IssueSubmitted reports an issue awaiting moderation. It is delivered only
327// on the "owner" topic, never on "home" or "repo:<name>". It carries no title or body: content never travels in
328// events, read it with IssueService.ListPendingIssues.
329message IssueSubmitted {
330 // Repo is the name of the repository.
331 string repo = 1;
332 // Id is the PendingIssue.id.
333 string id = 2;
334}
335
336// Gap tells the client that events were lost: the requested resume point is
337// older than the server's buffer. It has no fields. The client should reload
338// the state it displays (repositories, refs, merge requests and their
339// comments, issues and their comments, CI runs and their jobs) and carry on
340// with the next events.
341message Gap {}
342
343// RunUpdated reports a CI run that was created or whose status, conclusion or
344// timestamps changed. It is delivered on the "repo:<name>" topic only.
345message RunUpdated {
346 // Run is the run after the change, as of its latest attempt, without jobs.
347 Run run = 1;
348}
349
350// JobUpdated reports a CI job that was created or whose status, conclusion,
351// runner or steps changed. It is delivered on the "repo:<name>" topic only.
352message JobUpdated {
353 // Job is the job after the change, with its steps.
354 RunJob job = 1;
355}
356
357// MirrorFailed reports the start of a failure incident: a transition from ok
358// or disabled into failing or paused. It is sent once per incident, not for
359// each failed attempt nor for failing to paused. Servers with feature "mirror"
360// deliver it on "repo:<name>" and "home", subject to repository visibility. It
361// carries no URL, reason or error detail; read the status for those.
362message MirrorFailed {
363 // Repo is the repository name.
364 string repo = 1;
365 // State is the new mirror state.
366 MirrorState state = 2;
367 // FailureClass is the failure category.
368 string failure_class = 3;
369
370 reserved 4;
371 reserved "reason";
372}
373
374// MirrorRecovered reports a successful sync after failing or paused. Delivery
375// follows MirrorFailed. It carries no URL or error detail.
376message MirrorRecovered {
377 // Repo is the repository name.
378 string repo = 1;
379}
380
381// ReleasePublished reports a release change on repo:<name> and home topics.
382message ReleasePublished {
383 string repo = 1;
384 int64 id = 2;
385 string tag = 3;
386 bool draft = 4;
387 bool prerelease = 5;
388}
389
390// ReleaseUpdated reports a release change on repo:<name> and home topics.
391message ReleaseUpdated {
392 string repo = 1;
393 int64 id = 2;
394 string tag = 3;
395 bool draft = 4;
396 bool prerelease = 5;
397}
398
399// ReleaseDeleted reports a release change on repo:<name> and home topics.
400message ReleaseDeleted {
401 string repo = 1;
402 int64 id = 2;
403 string tag = 3;
404}
405
406// ReleaseUnpublished reports a release change on repo:<name> and home topics.
407message ReleaseUnpublished {
408 string repo = 1;
409 int64 id = 2;
410 string tag = 3;
411 bool draft = 4;
412 bool prerelease = 5;
413}