1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "ermite/issue.proto";
8import "ermite/merge_request.proto";
9import "ermite/repo.proto";
10import "ermite/run.proto";
11import "google/protobuf/timestamp.proto";
12
13// EventService streams what happens on the forge.
14service EventService {
15 // Watch streams events until the client cancels the call or the server shuts
16 // down. Events are filtered by the caller's access: events of a private
17 // repository are only sent to callers that may read it.
18 //
19 // The events are repo_created, repo_updated, repo_deleted, pushed, gap and,
20 // for merge requests, merge_request_opened, merge_request_merged,
21 // merge_request_closed, comment_added, comment_edited, comment_deleted and
22 // comment_resolved (a thread resolved or reopened); for issues, issue_opened,
23 // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each
24 // one is delivered on the "repo:<name>" topic of its repository and on
25 // "home", subject to the visibility of the repository, except
26 // issue_submitted: it is delivered only on the "owner" topic, never on
27 // "home" or "repo:<name>", and carries no content (see IssueSubmitted).
28 //
29 // Servers with the feature "ci.runs" also publish run_updated and
30 // job_updated, only on the "repo:<name>" topic of their repository (never on
31 // "home"), subject to the same visibility. They carry the state after the
32 // change and are published when a run or a job is created, changes status
33 // or conclusion, or when one of its steps starts or ends (never per log
34 // line: follow a log with RunService.GetJobLog). The order of these events
35 // is not guaranteed, between jobs and runs or between two updates of the same
36 // one: a client keeps the copy with the higher Run.version or
37 // RunJob.version and drops the other. There is no event for a change of title or
38 // description: after a gap, or to see such changes, clients read the merge
39 // request again. A merge publishes
40 // merge_request_merged, then pushed for the target branch.
41 //
42 // The server keeps a bounded buffer of recent events. With resume_after set,
43 // buffered events after that id are replayed first, then live events follow.
44 // When resume_after is no longer buffered (or unknown), the stream begins
45 // with a Gap event, then continues with the oldest buffered event: the client
46 // must reload its state. Without resume_after, only new events are sent.
47 //
48 // The access of the caller is checked again for every event: the stream ends
49 // with unauthenticated when the token was revoked or has expired (the server
50 // may take a few seconds to notice). A repository that becomes private
51 // sends one last repo_updated to the callers who could read it before, with
52 // the new visibility and nothing else about it; no later event of it
53 // reaches them. The server limits the watchers: more than 64 topics is
54 // invalid_argument, and too many concurrent streams, in total or from one
55 // client, is resource_exhausted.
56 rpc Watch(WatchRequest) returns (stream WatchResponse);
57}
58
59// WatchRequest selects the events to receive.
60message WatchRequest {
61 // Topics are the subjects to follow: "home" for every repository visible to
62 // the caller, "repo:<name>" for one repository, or "owner". Empty means
63 // "home". Unknown topics are invalid_argument. A "repo:<name>" topic for a
64 // repository that does not exist or is not visible is not_found.
65 //
66 // The "owner" topic needs owner rights: root, an owner session, or a token
67 // that holds every scope with no repository or branch limit. Anyone else
68 // gets the same invalid_argument as for an unknown topic, so the topic is
69 // not revealed. It carries the merge request and issue events of every
70 // repository (merge_request_opened, merge_request_merged,
71 // merge_request_closed, comment_added, and the issue events), repo_updated
72 // and repo_deleted, plus issue_submitted, which is delivered nowhere else.
73 repeated string topics = 1;
74 // ResumeAfter is the Event.id of the last event the client has seen. Empty
75 // to receive only new events.
76 string resume_after = 2;
77}
78
79// WatchResponse carries one event of the stream.
80message WatchResponse {
81 // Event is the event.
82 Event event = 1;
83}
84
85// Event is something that happened on the forge.
86message Event {
87 // Id identifies the event and is passed as resume_after to resume a stream.
88 // It is opaque and only comparable for equality; clients must not parse it.
89 // Empty on a Gap event.
90 string id = 1;
91 // Time is when the event happened.
92 google.protobuf.Timestamp time = 2;
93 // Kind is the type and payload of the event. New kinds may be added; clients
94 // must ignore kinds they do not know.
95 oneof kind {
96 // RepoCreated: a repository was created.
97 RepoCreated repo_created = 3;
98 // RepoUpdated: repository metadata changed.
99 RepoUpdated repo_updated = 4;
100 // RepoDeleted: a repository was deleted.
101 RepoDeleted repo_deleted = 5;
102 // Pushed: refs of a repository were updated by a push.
103 Pushed pushed = 6;
104 // Gap: events were lost, reload state.
105 Gap gap = 7;
106 // MergeRequestOpened: a merge request was opened.
107 MergeRequestOpened merge_request_opened = 8;
108 // MergeRequestMerged: a merge request was merged.
109 MergeRequestMerged merge_request_merged = 9;
110 // MergeRequestClosed: a merge request was closed without merging.
111 MergeRequestClosed merge_request_closed = 10;
112 // CommentAdded: a comment was added to a merge request.
113 CommentAdded comment_added = 11;
114 // RunUpdated: a CI run was created or changed.
115 RunUpdated run_updated = 12;
116 // JobUpdated: a CI job was created or changed.
117 JobUpdated job_updated = 13;
118 // CommentEdited: the text of a merge request comment was changed.
119 CommentEdited comment_edited = 14;
120 // CommentDeleted: a merge request comment was deleted.
121 CommentDeleted comment_deleted = 15;
122 // CommentResolved: a merge request comment was resolved or unresolved.
123 CommentResolved comment_resolved = 16;
124 // IssueOpened: an issue was opened.
125 IssueOpened issue_opened = 17;
126 // IssueClosed: an issue was closed.
127 IssueClosed issue_closed = 18;
128 // IssueReopened: an issue was reopened.
129 IssueReopened issue_reopened = 19;
130 // IssueCommented: a comment was added to an issue.
131 IssueCommented issue_commented = 20;
132 // IssueSubmitted: an issue is awaiting moderation. Delivered only on the
133 // "owner" topic, never on "home" or "repo:<name>", and carries no content.
134 IssueSubmitted issue_submitted = 21;
135 }
136}
137
138// RepoCreated reports a new repository.
139message RepoCreated {
140 // Repo is the new repository.
141 Repo repo = 1;
142}
143
144// RepoUpdated reports a metadata change.
145message RepoUpdated {
146 // Repo is the repository after the change.
147 Repo repo = 1;
148}
149
150// RepoDeleted reports a deleted repository.
151message RepoDeleted {
152 // Repo is the name of the deleted repository.
153 string repo = 1;
154}
155
156// Pushed reports the ref updates of one push.
157message Pushed {
158 // Repo is the name of the repository.
159 string repo = 1;
160 // RefUpdates are the refs changed by the push.
161 repeated RefUpdate ref_updates = 2;
162}
163
164// RefUpdate is the change of one ref.
165message RefUpdate {
166 // Ref is the full ref name, for example "refs/heads/main".
167 string ref = 1;
168 // OldId is the object id before the update. Empty when the ref was created.
169 string old_id = 2;
170 // NewId is the object id after the update. Empty when the ref was deleted.
171 string new_id = 3;
172}
173
174// MergeRequestOpened reports a new merge request.
175message MergeRequestOpened {
176 // MergeRequest is the new merge request.
177 MergeRequest merge_request = 1;
178}
179
180// MergeRequestMerged reports a merged merge request. It is published before
181// the Pushed event of the target branch.
182message MergeRequestMerged {
183 // MergeRequest is the merge request after the merge.
184 MergeRequest merge_request = 1;
185}
186
187// MergeRequestClosed reports a merge request closed without merging.
188message MergeRequestClosed {
189 // MergeRequest is the merge request after closing.
190 MergeRequest merge_request = 1;
191}
192
193// CommentAdded reports a new comment on a merge request.
194message CommentAdded {
195 // Repo is the name of the repository.
196 string repo = 1;
197 // Number is the number of the merge request.
198 int64 number = 2;
199 // Comment is the new comment.
200 Comment comment = 3;
201}
202
203// CommentEdited reports a comment of a merge request whose text was changed.
204message CommentEdited {
205 // Repo is the name of the repository.
206 string repo = 1;
207 // Number is the number of the merge request.
208 int64 number = 2;
209 // Comment is the comment after the edit.
210 Comment comment = 3;
211}
212
213// CommentDeleted reports a comment of a merge request that was deleted. The
214// comment stays in the thread with deleted set and an empty text.
215message CommentDeleted {
216 // Repo is the name of the repository.
217 string repo = 1;
218 // Number is the number of the merge request.
219 int64 number = 2;
220 // Comment is the comment after the deletion.
221 Comment comment = 3;
222}
223
224// CommentResolved reports a comment of a merge request whose resolved state
225// changed.
226message CommentResolved {
227 // Repo is the name of the repository.
228 string repo = 1;
229 // Number is the number of the merge request.
230 int64 number = 2;
231 // Comment is the comment after the change.
232 Comment comment = 3;
233}
234
235// IssueOpened reports a new issue.
236message IssueOpened {
237 // Issue is the new issue, including its repository and number.
238 Issue issue = 1;
239}
240
241// IssueClosed reports a closed issue.
242message IssueClosed {
243 // Issue is the issue after closing, including its repository and number.
244 Issue issue = 1;
245}
246
247// IssueReopened reports a reopened issue.
248message IssueReopened {
249 // Issue is the issue after reopening, including its repository and number.
250 Issue issue = 1;
251}
252
253// IssueCommented reports a new comment on an issue.
254message IssueCommented {
255 // Repo is the name of the repository.
256 string repo = 1;
257 // Number is the number of the issue.
258 int64 number = 2;
259 // Comment is the new comment.
260 IssueComment comment = 3;
261}
262
263// IssueSubmitted reports an issue awaiting moderation. It is delivered only
264// on the "owner" topic, never on "home" or "repo:<name>". It carries no title or body: content never travels in
265// events, read it with IssueService.ListPendingIssues.
266message IssueSubmitted {
267 // Repo is the name of the repository.
268 string repo = 1;
269 // Id is the PendingIssue.id.
270 string id = 2;
271}
272
273// Gap tells the client that events were lost: the requested resume point is
274// older than the server's buffer. It has no fields. The client should reload
275// the state it displays (repositories, refs, merge requests and their
276// comments, issues and their comments, CI runs and their jobs) and carry on
277// with the next events.
278message Gap {}
279
280// RunUpdated reports a CI run that was created or whose status, conclusion or
281// timestamps changed. It is delivered on the "repo:<name>" topic only.
282message RunUpdated {
283 // Run is the run after the change, as of its latest attempt, without jobs.
284 Run run = 1;
285}
286
287// JobUpdated reports a CI job that was created or whose status, conclusion,
288// runner or steps changed. It is delivered on the "repo:<name>" topic only.
289message JobUpdated {
290 // Job is the job after the change, with its steps.
291 RunJob job = 1;
292}