1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "google/protobuf/field_mask.proto";
8import "ermite/types.proto";
9import "google/protobuf/timestamp.proto";
10
11// Visibility says who may read a repository.
12enum Visibility {
13 // Not set. In requests, the server applies its default (private on create,
14 // unchanged on update). Never returned by the server.
15 VISIBILITY_UNSPECIFIED = 0;
16 // Anyone, including anonymous callers, may read the repository.
17 VISIBILITY_PUBLIC = 1;
18 // Only callers holding the repo:read scope on the repository may read it.
19 // Everyone else gets not_found, never permission_denied.
20 VISIBILITY_PRIVATE = 2;
21}
22
23// IssuesMode says who may write issues in a repository.
24enum 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
35// RepoSettings are the settings of a repository that govern its merge
36// requests and issues.
37message RepoSettings {
38 // AllowedMergeModes are the modes with which a merge request of the
39 // repository may be merged. It is never empty in a response and has no
40 // duplicate. Every mode is allowed by default. MERGE_MODE_UNSPECIFIED is
41 // rejected.
42 repeated MergeMode allowed_merge_modes = 1;
43 // FailingChecksBlock says whether a merge request whose checks fail cannot be
44 // merged. It is true at creation of the repository and always stored
45 // explicitly, so a later change of the server default never alters an
46 // existing repository.
47 bool failing_checks_block = 2;
48 // Issues is the issue participation mode of the repository.
49 IssuesMode issues = 3;
50}
51
52// Repo is the metadata of a repository. Git-owned state (refs, trees, history)
53// is read through GitService.
54message Repo {
55 // Name is the unique, lowercase repository name: 1-100 characters from
56 // [a-z0-9._-], without a ".git" suffix. It is also the URL path: /<name>.
57 string name = 1;
58 // Description is a free one-line description. It may be empty.
59 string description = 2;
60 // Visibility is who may read the repository.
61 Visibility visibility = 3;
62 // DefaultBranch is the short name of the branch HEAD points to, for example
63 // "main". It is set even when the branch does not exist yet (empty
64 // repository).
65 string default_branch = 4;
66 // CreatedAt is when the repository was created.
67 google.protobuf.Timestamp created_at = 5;
68 // PushedAt is the time of the last push. It is unset until the first push.
69 google.protobuf.Timestamp pushed_at = 6;
70 // Settings are the settings of the repository. Always set in a
71 // response, with the defaults for a repository that never changed them.
72 RepoSettings settings = 7;
73 // Topics classify the repository, as on GitHub: at most 20, each 1-50
74 // characters from [a-z0-9-], starting with a letter or a digit, sorted
75 // and without duplicates.
76 repeated string topics = 8;
77}
78
79// RepoService manages repositories and their metadata.
80//
81// Anonymous callers see public repositories only. A private repository that the
82// caller cannot read is reported as not_found.
83service RepoService {
84 // ListRepos lists the repositories the caller may see, ordered by name.
85 rpc ListRepos(ListReposRequest) returns (ListReposResponse);
86 // GetRepo returns one repository. Fails with not_found if it does not exist
87 // or is private and not readable by the caller.
88 rpc GetRepo(GetRepoRequest) returns (GetRepoResponse);
89 // CreateRepo creates an empty repository with the default settings. Needs
90 // the repo:write scope. Fails
91 // with already_exists if the name is taken and invalid_argument if the name
92 // is not valid.
93 rpc CreateRepo(CreateRepoRequest) returns (CreateRepoResponse);
94 // UpdateRepo changes the fields named in update_mask, including the merge
95 // settings. Needs the repo:admin scope.
96 rpc UpdateRepo(UpdateRepoRequest) returns (UpdateRepoResponse);
97 // DeleteRepo deletes a repository. Needs the repo:admin scope. The server
98 // moves the data aside rather than destroying it; there is no undelete RPC.
99 rpc DeleteRepo(DeleteRepoRequest) returns (DeleteRepoResponse);
100}
101
102// ListReposRequest selects a page of repositories.
103message ListReposRequest {
104 // PageSize is the maximum number of repositories to return. 0 means the
105 // server default; values above the server maximum are lowered to it.
106 int32 page_size = 1;
107 // PageToken is the next_page_token of a previous response, to get the page
108 // after it. Empty for the first page.
109 string page_token = 2;
110}
111
112// ListReposResponse is one page of repositories.
113message ListReposResponse {
114 // Repos are the repositories of this page, ordered by name.
115 repeated Repo repos = 1;
116 // NextPageToken is passed as page_token to get the next page. Empty when
117 // there is no next page.
118 string next_page_token = 2;
119}
120
121// GetRepoRequest names the repository to read.
122message GetRepoRequest {
123 // Repo is the repository name.
124 string repo = 1;
125}
126
127// GetRepoResponse holds the repository.
128message GetRepoResponse {
129 // Repo is the repository metadata.
130 Repo repo = 1;
131}
132
133// CreateRepoRequest describes the repository to create.
134message CreateRepoRequest {
135 // Name is the name of the new repository. Names are lowercase; an uppercase
136 // name is rejected with invalid_argument.
137 string name = 1;
138 // Description is an optional one-line description.
139 string description = 2;
140 // Visibility of the new repository. VISIBILITY_UNSPECIFIED means private.
141 Visibility visibility = 3;
142 // Topics are the optional topics of the new repository (see Repo.topics);
143 // they are lowercased, sorted and deduplicated.
144 repeated string topics = 4;
145}
146
147// CreateRepoResponse holds the new repository.
148message CreateRepoResponse {
149 // Repo is the created repository.
150 Repo repo = 1;
151}
152
153// UpdateRepoRequest changes some fields of a repository.
154message UpdateRepoRequest {
155 // Repo is the name of the repository to change. Repositories cannot be
156 // renamed.
157 string repo = 1;
158 // Description is the new description. Used only if update_mask contains
159 // "description"; an empty value then clears it.
160 string description = 2;
161 // Visibility is the new visibility. Used only if update_mask contains
162 // "visibility"; it must not be VISIBILITY_UNSPECIFIED then.
163 Visibility visibility = 3;
164 // DefaultBranch is the short name of the new default branch. Used only if
165 // update_mask contains "default_branch". The branch must exist, otherwise
166 // the call fails with failed_precondition.
167 string default_branch = 4;
168 // UpdateMask lists the fields to change: "description", "visibility",
169 // "default_branch", "topics", "settings.allowed_merge_modes" and/or
170 // "settings.failing_checks_block". "settings" stands for both merge settings
171 // paths. It must not be empty unless issues is set. Other paths are
172 // invalid_argument, including "settings.issues" and "issues": the issues
173 // field is applied outside the mask.
174 google.protobuf.FieldMask update_mask = 5;
175 // Settings holds the new merge settings. Only the fields named in
176 // update_mask are used. allowed_merge_modes must then not be empty nor
177 // contain MERGE_MODE_UNSPECIFIED, otherwise the call fails with
178 // invalid_argument. Changing settings needs the repo:admin scope, like any
179 // other field.
180 RepoSettings settings = 6;
181 // Topics replace the topics of the repository (see Repo.topics). Used only
182 // if update_mask contains "topics"; an empty list then clears them.
183 repeated string topics = 7;
184 // Issues is the new issue participation mode. When absent it is unchanged.
185 // It is applied whatever update_mask contains, and may be the only change
186 // (an empty update_mask is then valid). When present it must not be
187 // ISSUES_MODE_UNSPECIFIED: that is invalid_argument. Changing it needs the
188 // repo:admin scope and a token with no branch limit, like any other field.
189 optional IssuesMode issues = 8;
190}
191
192// UpdateRepoResponse holds the repository after the update.
193message UpdateRepoResponse {
194 // Repo is the updated repository.
195 Repo repo = 1;
196}
197
198// DeleteRepoRequest names the repository to delete.
199message DeleteRepoRequest {
200 // Repo is the repository name.
201 string repo = 1;
202}
203
204// DeleteRepoResponse is empty.
205message DeleteRepoResponse {}