// SPDX-License-Identifier: MIT syntax = "proto3"; package ermite; import "ermite/issue.proto"; import "ermite/merge_request.proto"; import "ermite/repo.proto"; import "ermite/run.proto"; import "google/protobuf/timestamp.proto"; // EventService streams what happens on the forge. service EventService { // Watch streams events until the client cancels the call or the server shuts // down. Events are filtered by the caller's access: events of a private // repository are only sent to callers that may read it. // // The events are repo_created, repo_updated, repo_deleted, pushed, gap and, // for merge requests, merge_request_opened, merge_request_merged, // merge_request_closed, comment_added, comment_edited, comment_deleted and // comment_resolved (a thread resolved or reopened); for issues, issue_opened, // issue_closed, issue_reopened and issue_commented, and issue_submitted. Each // one is delivered on the "repo:" topic of its repository and on // "home", subject to the visibility of the repository, except // issue_submitted: it is delivered only on the "owner" topic, never on // "home" or "repo:", and carries no content (see IssueSubmitted). // // Servers with the feature "ci.runs" also publish run_updated and // job_updated, only on the "repo:" topic of their repository (never on // "home"), subject to the same visibility. They carry the state after the // change and are published when a run or a job is created, changes status // or conclusion, or when one of its steps starts or ends (never per log // line: follow a log with RunService.GetJobLog). The order of these events // is not guaranteed, between jobs and runs or between two updates of the same // one: a client keeps the copy with the higher Run.version or // RunJob.version and drops the other. There is no event for a change of title or // description: after a gap, or to see such changes, clients read the merge // request again. A merge publishes // merge_request_merged, then pushed for the target branch. // // The server keeps a bounded buffer of recent events. With resume_after set, // buffered events after that id are replayed first, then live events follow. // When resume_after is no longer buffered (or unknown), the stream begins // with a Gap event, then continues with the oldest buffered event: the client // must reload its state. Without resume_after, only new events are sent. // // The access of the caller is checked again for every event: the stream ends // with unauthenticated when the token was revoked or has expired (the server // may take a few seconds to notice). A repository that becomes private // sends one last repo_updated to the callers who could read it before, with // the new visibility and nothing else about it; no later event of it // reaches them. The server limits the watchers: more than 64 topics is // invalid_argument, and too many concurrent streams, in total or from one // client, is resource_exhausted. rpc Watch(WatchRequest) returns (stream WatchResponse); } // WatchRequest selects the events to receive. message WatchRequest { // Topics are the subjects to follow: "home" for every repository visible to // the caller, "repo:" for one repository, or "owner". Empty means // "home". Unknown topics are invalid_argument. A "repo:" topic for a // repository that does not exist or is not visible is not_found. // // The "owner" topic needs owner rights: root, an owner session, or a token // that holds every scope with no repository or branch limit. Anyone else // gets the same invalid_argument as for an unknown topic, so the topic is // not revealed. It carries the merge request and issue events of every // repository (merge_request_opened, merge_request_merged, // merge_request_closed, comment_added, and the issue events), repo_updated // and repo_deleted, plus issue_submitted, which is delivered nowhere else. repeated string topics = 1; // ResumeAfter is the Event.id of the last event the client has seen. Empty // to receive only new events. string resume_after = 2; } // WatchResponse carries one event of the stream. message WatchResponse { // Event is the event. Event event = 1; } // Event is something that happened on the forge. message Event { // Id identifies the event and is passed as resume_after to resume a stream. // It is opaque and only comparable for equality; clients must not parse it. // Empty on a Gap event. string id = 1; // Time is when the event happened. google.protobuf.Timestamp time = 2; // Kind is the type and payload of the event. New kinds may be added; clients // must ignore kinds they do not know. oneof kind { // RepoCreated: a repository was created. RepoCreated repo_created = 3; // RepoUpdated: repository metadata changed. RepoUpdated repo_updated = 4; // RepoDeleted: a repository was deleted. RepoDeleted repo_deleted = 5; // Pushed: refs of a repository were updated by a push. Pushed pushed = 6; // Gap: events were lost, reload state. Gap gap = 7; // MergeRequestOpened: a merge request was opened. MergeRequestOpened merge_request_opened = 8; // MergeRequestMerged: a merge request was merged. MergeRequestMerged merge_request_merged = 9; // MergeRequestClosed: a merge request was closed without merging. MergeRequestClosed merge_request_closed = 10; // CommentAdded: a comment was added to a merge request. CommentAdded comment_added = 11; // RunUpdated: a CI run was created or changed. RunUpdated run_updated = 12; // JobUpdated: a CI job was created or changed. JobUpdated job_updated = 13; // CommentEdited: the text of a merge request comment was changed. CommentEdited comment_edited = 14; // CommentDeleted: a merge request comment was deleted. CommentDeleted comment_deleted = 15; // CommentResolved: a merge request comment was resolved or unresolved. CommentResolved comment_resolved = 16; // IssueOpened: an issue was opened. IssueOpened issue_opened = 17; // IssueClosed: an issue was closed. IssueClosed issue_closed = 18; // IssueReopened: an issue was reopened. IssueReopened issue_reopened = 19; // IssueCommented: a comment was added to an issue. IssueCommented issue_commented = 20; // IssueSubmitted: an issue is awaiting moderation. Delivered only on the // "owner" topic, never on "home" or "repo:", and carries no content. IssueSubmitted issue_submitted = 21; } } // RepoCreated reports a new repository. message RepoCreated { // Repo is the new repository. Repo repo = 1; } // RepoUpdated reports a metadata change. message RepoUpdated { // Repo is the repository after the change. Repo repo = 1; } // RepoDeleted reports a deleted repository. message RepoDeleted { // Repo is the name of the deleted repository. string repo = 1; } // Pushed reports the ref updates of one push. message Pushed { // Repo is the name of the repository. string repo = 1; // RefUpdates are the refs changed by the push. repeated RefUpdate ref_updates = 2; } // RefUpdate is the change of one ref. message RefUpdate { // Ref is the full ref name, for example "refs/heads/main". string ref = 1; // OldId is the object id before the update. Empty when the ref was created. string old_id = 2; // NewId is the object id after the update. Empty when the ref was deleted. string new_id = 3; } // MergeRequestOpened reports a new merge request. message MergeRequestOpened { // MergeRequest is the new merge request. MergeRequest merge_request = 1; } // MergeRequestMerged reports a merged merge request. It is published before // the Pushed event of the target branch. message MergeRequestMerged { // MergeRequest is the merge request after the merge. MergeRequest merge_request = 1; } // MergeRequestClosed reports a merge request closed without merging. message MergeRequestClosed { // MergeRequest is the merge request after closing. MergeRequest merge_request = 1; } // CommentAdded reports a new comment on a merge request. message CommentAdded { // Repo is the name of the repository. string repo = 1; // Number is the number of the merge request. int64 number = 2; // Comment is the new comment. Comment comment = 3; } // CommentEdited reports a comment of a merge request whose text was changed. message CommentEdited { // Repo is the name of the repository. string repo = 1; // Number is the number of the merge request. int64 number = 2; // Comment is the comment after the edit. Comment comment = 3; } // CommentDeleted reports a comment of a merge request that was deleted. The // comment stays in the thread with deleted set and an empty text. message CommentDeleted { // Repo is the name of the repository. string repo = 1; // Number is the number of the merge request. int64 number = 2; // Comment is the comment after the deletion. Comment comment = 3; } // CommentResolved reports a comment of a merge request whose resolved state // changed. message CommentResolved { // Repo is the name of the repository. string repo = 1; // Number is the number of the merge request. int64 number = 2; // Comment is the comment after the change. Comment comment = 3; } // IssueOpened reports a new issue. message IssueOpened { // Issue is the new issue, including its repository and number. Issue issue = 1; } // IssueClosed reports a closed issue. message IssueClosed { // Issue is the issue after closing, including its repository and number. Issue issue = 1; } // IssueReopened reports a reopened issue. message IssueReopened { // Issue is the issue after reopening, including its repository and number. Issue issue = 1; } // IssueCommented reports a new comment on an issue. message IssueCommented { // Repo is the name of the repository. string repo = 1; // Number is the number of the issue. int64 number = 2; // Comment is the new comment. IssueComment comment = 3; } // IssueSubmitted reports an issue awaiting moderation. It is delivered only // on the "owner" topic, never on "home" or "repo:". It carries no title or body: content never travels in // events, read it with IssueService.ListPendingIssues. message IssueSubmitted { // Repo is the name of the repository. string repo = 1; // Id is the PendingIssue.id. string id = 2; } // Gap tells the client that events were lost: the requested resume point is // older than the server's buffer. It has no fields. The client should reload // the state it displays (repositories, refs, merge requests and their // comments, issues and their comments, CI runs and their jobs) and carry on // with the next events. message Gap {} // RunUpdated reports a CI run that was created or whose status, conclusion or // timestamps changed. It is delivered on the "repo:" topic only. message RunUpdated { // Run is the run after the change, as of its latest attempt, without jobs. Run run = 1; } // JobUpdated reports a CI job that was created or whose status, conclusion, // runner or steps changed. It is delivered on the "repo:" topic only. message JobUpdated { // Job is the job after the change, with its steps. RunJob job = 1; }