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