1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "ermite/runner.proto";
8import "google/protobuf/timestamp.proto";
9
10// Run is one execution of one workflow file for one event, like a GitHub
11// workflow run. A re-run keeps the run and adds an attempt.
12message Run {
13 // Repo is the name of the repository.
14 string repo = 1;
15 // Id identifies the run on the whole server: it is the "github.run_id".
16 // Increasing, never reused.
17 int64 id = 2;
18 // Number counts the runs of the same workflow file in the repository,
19 // starting at 1, never reused: it is the "github.run_number". It does not
20 // change on a re-run.
21 int64 number = 3;
22 // Attempt is the attempt this message describes: 1 for the first, one more
23 // after each RerunRun. ListRuns and events describe the latest attempt;
24 // GetRun can ask for another one.
25 int32 attempt = 4;
26 // WorkflowPath is the path of the workflow file at sha, for example
27 // ".github/workflows/ci.yml".
28 string workflow_path = 5;
29 // WorkflowName is the "name" of the workflow, or workflow_path when it has
30 // none (as GitHub does). It is the "github.workflow" of the run and the
31 // workflow name of its checks. See name for the name of the run itself.
32 string workflow_name = 6;
33 // Title is GitHub's display title, at most 256 characters: the evaluated
34 // "run-name" of the workflow when it has one, else for a push to a branch
35 // the first line of the message of the commit sha, and for a push of a tag
36 // the name of the workflow registered for workflow_path (the "name" of that
37 // file on the default branch, else workflow_name).
38 string title = 7;
39 // Event is the event that triggered the run, in GitHub's name: "push" (push
40 // to a branch or a tag, and merge of a merge request), and from servers with
41 // the matching trigger "pull_request", "workflow_dispatch", "schedule" and
42 // "workflow_run". New values may be added; clients show the ones they do not
43 // know as they are.
44 string event = 8;
45 // Ref is the full ref name that was pushed, for example "refs/heads/main"
46 // or "refs/tags/v1.0.0".
47 string ref = 9;
48 // Sha is the full id of the commit the run is for.
49 string sha = 10;
50 // Actor names who triggered the run: the label of the token that pushed, or
51 // "root", or "owner" (a web session, a merge of the web UI), as
52 // MergeRequest.author. It is informational.
53 string actor = 11;
54 // Status is where this attempt is: QUEUED until a job starts, IN_PROGRESS
55 // while jobs run or wait, COMPLETED when every job is over.
56 CiStatus status = 12;
57 // Conclusion is how this attempt ended, from its jobs' conclusions like
58 // GitHub: CANCELLED if it was cancelled, else FAILURE if a job failed or
59 // timed out, else SUCCESS (also when jobs were skipped). Unset until
60 // status is COMPLETED.
61 CiConclusion conclusion = 13;
62 // Error is set when the run failed without running a job because the
63 // workflow could not be used: an invalid workflow file (the run then has
64 // no jobs and conclusion FAILURE), as GitHub's "Invalid workflow file".
65 // It holds the errors with their positions, one per line, at most 8 KiB.
66 // Empty otherwise.
67 string error = 14;
68 // CreatedAt is when this attempt was created: for attempt 1 when the
69 // trigger was planned, for later ones when RerunRun was called.
70 google.protobuf.Timestamp created_at = 15;
71 // StartedAt is when the first job of this attempt was given to a runner.
72 // Unset until then.
73 google.protobuf.Timestamp started_at = 16;
74 // CompletedAt is when this attempt completed. Unset until then.
75 google.protobuf.Timestamp completed_at = 17;
76 // Version counts the changes of this run on the server: it grows by at least
77 // one at every change and never goes back, also across attempts. Events are
78 // not delivered in order, and a client that holds two copies of a run keeps
79 // the one with the higher version and drops the other.
80 int64 version = 18;
81 // Name is the name of the run, GitHub's "name" of a workflow run: the
82 // evaluated "run-name" of the workflow when it has one, else the same value
83 // as workflow_name. It is what GitHub lists as the run's name, whereas
84 // workflow_name stays the name of the workflow ("github.workflow") even when
85 // the workflow has a "run-name". A run stored before this field existed
86 // reads as workflow_name.
87 string name = 19;
88 // Trusted is true when the run may use secrets and a job token with write
89 // permissions: its actor is the owner, a "workflow_run" inherits it from the
90 // run that triggered it, and a re-run keeps it only if the original run had
91 // it and the caller of the re-run is the owner. It is false when the actor
92 // is a token limited to branches (see Job.trusted). It never goes from false
93 // to true. False for a run stored before this field existed and from servers
94 // without the feature "ci.secrets".
95 bool trusted = 20;
96}
97
98// RunJob is a job of a run as people see it: the state of one job instance
99// (one matrix combination is one job) in one attempt. It is not Job, which is
100// what a runner receives.
101message RunJob {
102 // Id is the Job.job_id. It is the same in every attempt.
103 string id = 1;
104 // RunId is the run the job belongs to.
105 int64 run_id = 2;
106 // Attempt is the attempt of the run in which this job executed. It is lower
107 // than the attempt of the run when the job was kept from an earlier attempt
108 // by a re-run of the failed jobs only; the log and steps are then those of
109 // that earlier attempt. Pass it to GetJob and GetJobLog.
110 int32 attempt = 3;
111 // Repo is the name of the repository.
112 string repo = 4;
113 // Key is the key of the job under "jobs:" in the workflow (the
114 // "github.job"). Matrix instances of one job share it.
115 string key = 5;
116 // Name is the display name of the job, evaluated, with the matrix suffix as
117 // GitHub names them, for example "build (linux, 1.27)". It is also the
118 // name of the job's check.
119 string name = 6;
120 // Status is where the job is. A job waits QUEUED for a runner and for the
121 // jobs it needs, and PENDING for its concurrency group.
122 CiStatus status = 7;
123 // Conclusion is how the job ended. Unset until status is COMPLETED.
124 CiConclusion conclusion = 8;
125 // Error explains a FAILURE, CANCELLED or TIMED_OUT that no step explains, in
126 // GitHub's words where it has them: the runner was lost ("The self-hosted
127 // runner: <name> lost communication with the server..."), it received a
128 // shutdown signal, no runner took the job within 24 hours, the log limit
129 // was reached, the workflow uses a feature that is not supported yet
130 // ("not supported yet: <feature>"). At most 4 KiB. Empty otherwise.
131 string error = 9;
132 // Labels are the runs-on labels of the job, evaluated. Empty while the job
133 // is not planned yet.
134 repeated string labels = 10;
135 // Needs are the keys of the jobs this job needs, for drawing the graph.
136 repeated string needs = 11;
137 // RunnerId is the id of the runner that executed or is executing the job.
138 // Empty while queued, and when the runner has since been removed (runner_name
139 // and isolation are kept).
140 string runner_id = 12;
141 // RunnerName is the name of that runner. Empty while queued.
142 string runner_name = 13;
143 // Isolation is how that runner isolated the job. UNSPECIFIED while queued.
144 RunnerIsolation isolation = 14;
145 // Steps are the steps reported so far, ordered by number, including the
146 // implicit "Set up job" and "Complete job". Empty while queued. Always
147 // set, including in JobUpdated events.
148 repeated Step steps = 15;
149 // CreatedAt is when the job was created (planned).
150 google.protobuf.Timestamp created_at = 16;
151 // StartedAt is when the job was given to a runner. Unset until then.
152 google.protobuf.Timestamp started_at = 17;
153 // CompletedAt is when the job completed. Unset until then.
154 google.protobuf.Timestamp completed_at = 18;
155 // Version counts the changes of this job on the server (status, conclusion,
156 // runner, steps, with any attempt): it grows by at least one at every change
157 // and never goes back. A client that holds two copies of a job keeps the
158 // one with the higher version and drops the other, as for Run.version.
159 int64 version = 19;
160 // ConcurrencyGroup is the evaluated concurrency group of the job (its
161 // "concurrency:", or the one of its workflow), compared without regard to
162 // case within the repository. Empty when the job has none and from servers
163 // without the feature "ci.concurrency". The job is PENDING while another job
164 // of the group runs or a newer one is waiting.
165 string concurrency_group = 20;
166}
167
168// Step is one step of a job, with where its lines are in the job log.
169message Step {
170 // Number is the 1-based number of the step in the job, the one the runner
171 // uses in UpdateJob and AppendLog.
172 int32 number = 1;
173 // Name is the display name of the step.
174 string name = 2;
175 // State is where the step is.
176 StepState state = 3;
177 // Conclusion is how the step ended. Unset until state is COMPLETED.
178 CiConclusion conclusion = 4;
179 // StartedAt is when the step started. Unset while PENDING.
180 google.protobuf.Timestamp started_at = 5;
181 // CompletedAt is when the step ended. Unset until COMPLETED.
182 google.protobuf.Timestamp completed_at = 6;
183 // LogStart is the number of the first line of the step in the job log (the
184 // offset of GetJobLogRequest and AppendLogRequest), counted from 0.
185 int64 log_start = 7;
186 // LogEnd is the number of the line after the last one of the step. For an
187 // IN_PROGRESS step it is the number of lines held at the time of the
188 // call and grows; for a step without a line it equals log_start.
189 int64 log_end = 8;
190 // Outcome is how the step ended before continue-on-error was applied, as
191 // StepUpdate.outcome: it differs from conclusion only for a failed step with
192 // continue-on-error. Unset until state is COMPLETED, and for a step stored
193 // by a server or runner before this field existed (read it as conclusion).
194 CiConclusion outcome = 9;
195}
196
197// Check is the result of one job on one commit, the unit shown next to a
198// commit or a merge request and counted by the merge rules. There is one per
199// job instance, named like GitHub's checks.
200message Check {
201 // Id identifies the check. It is opaque and stable across attempts.
202 string id = 1;
203 // Repo is the name of the repository.
204 string repo = 2;
205 // Sha is the full id of the commit.
206 string sha = 3;
207 // Name is the name of the check: the RunJob.name of the job.
208 string name = 4;
209 // Status is where the check is.
210 CiStatus status = 5;
211 // Conclusion is how the check ended. Unset until status is COMPLETED. The
212 // value "stale" of GitHub is never used.
213 CiConclusion conclusion = 6;
214 // RunId is the run of the job.
215 int64 run_id = 7;
216 // JobId is the RunJob.id of the job, to open its page and log.
217 string job_id = 8;
218 // Attempt is the attempt the check describes: the latest attempt of the run.
219 int32 attempt = 9;
220 // WorkflowName is the Run.workflow_name of the run.
221 string workflow_name = 10;
222 // StartedAt is when the job was given to a runner. Unset while queued.
223 google.protobuf.Timestamp started_at = 11;
224 // CompletedAt is when the job completed. Unset until then.
225 google.protobuf.Timestamp completed_at = 12;
226}
227
228// Runner is a registered CI runner. It never contains the runner token nor its
229// hash.
230message Runner {
231 // Id identifies the runner in RemoveRunner. It is not a secret.
232 string id = 1;
233 // Name is the unique name chosen at registration.
234 string name = 2;
235 // Labels are all the labels the runner can match: the ones chosen at
236 // registration plus the implicit ones ("self-hosted", the os and the arch),
237 // lowercase, sorted.
238 repeated string labels = 3;
239 // Isolation is how the runner isolates jobs.
240 RunnerIsolation isolation = 4;
241 // Version is the version of the runner software.
242 string version = 5;
243 // Arch is "x64" or "arm64".
244 string arch = 6;
245 // Os is "linux".
246 string os = 7;
247 // RegisteredAt is when the runner was registered.
248 google.protobuf.Timestamp registered_at = 8;
249 // LastSeen is when the server last heard from the runner: a FetchJob poll or
250 // a heartbeat of one of its jobs. Unset if never. It may lag behind the real
251 // time by a short delay. A runner not seen for more than about 2 minutes is
252 // offline.
253 google.protobuf.Timestamp last_seen = 9;
254 // Busy is true while the runner has a job in progress.
255 bool busy = 10;
256 // Online is true when the server heard from the runner (see last_seen) less
257 // than 2 minutes ago, by the server's own clock at the time of the answer.
258 // Clients show this instead of comparing last_seen with their clock, which
259 // may be minutes off. A server that predates the field leaves it false:
260 // clients that need to tell can fall back to last_seen.
261 bool online = 11;
262}
263
264// RunService reads and controls CI runs, like `gh run` does on GitHub. It is for
265// owners and their tools; runners use RunnerService.
266//
267// Runs, jobs, checks, logs, annotations and summaries belong to a repository,
268// and reading them needs the same access as reading it: nothing for a public
269// repository, the repo:read scope for a private one. A repository that does not exist or that
270// the caller cannot read gives not_found; so does a run or a job that belongs
271// to another repository than the one named (ids are global but are always
272// checked against the repository). Cancelling and re-running need the ci:write
273// scope on the repository (a token restricted to other repositories gets
274// permission_denied). The runner RPCs (ListRunners, RemoveRunner) are not about
275// a repository and need the runner:register scope on a token that is not
276// restricted to repositories, or the root token. A caller without the needed
277// scope gets permission_denied.
278//
279// Page sizes and page tokens work as in the other services: page_size 0 is the
280// server default, larger values are lowered to the server maximum, and a
281// page_token is the next_page_token of a previous response for the same
282// request (other fields must be unchanged).
283//
284// Servers that implement the runs side (every RPC but ListRunners,
285// RemoveRunner, ListAnnotations, GetStepSummaries, DispatchWorkflow and the
286// workflow state RPCs) list
287// "ci.runs" in
288// GetVersionResponse.features; those that
289// implement the runners side list "ci.runners", as RunnerService does. A server
290// that honours the filters of ListRunsRequest also lists "ci.runs.filters".
291// ListAnnotations needs "ci.annotations" and GetStepSummaries "ci.summaries",
292// which are also the features of the runner side of each. DispatchWorkflow
293// needs "ci.dispatch". ListWorkflows, DisableWorkflow and EnableWorkflow need
294// "ci.workflows". RunJob.concurrency_group and CI_STATUS_PENDING belong
295// to "ci.concurrency", Run.trusted to "ci.secrets".
296service RunService {
297 // ListRuns lists the runs of a repository, highest id (newest) first. Each
298 // run is described by its latest attempt. The filters narrow the result; a
299 // server without the feature "ci.runs.filters" ignores them and returns
300 // every run, so a client that needs them checks the feature. Fails with
301 // invalid_argument if a filter is malformed.
302 rpc ListRuns(ListRunsRequest) returns (ListRunsResponse);
303 // GetRun returns a run with its jobs and their steps, for the latest attempt
304 // or for the one asked. Fails with not_found if the run or the attempt does
305 // not exist.
306 rpc GetRun(GetRunRequest) returns (GetRunResponse);
307 // GetJob returns one job with its steps. Fails with not_found if the job
308 // or the attempt does not exist.
309 rpc GetJob(GetJobRequest) returns (GetJobResponse);
310 // ListAnnotations lists the annotations of a run attempt, optionally of one
311 // job, ordered by job (as in GetRun), step number, then the order in which
312 // the step produced them. For each job it gives the annotations of the
313 // attempt in which that job executed (RunJob.attempt), which is lower than
314 // the attempt of the run for a job kept by a re-run of failed jobs only. Needs the same access as GetRun. Returns at most
315 // 1,000 annotations (truncated tells). A run without annotations gives an
316 // empty list. Only servers with the feature "ci.annotations" implement it
317 // (unimplemented otherwise). Fails with not_found if the run, the attempt or
318 // the job does not exist, or if the job is not a job of the run.
319 rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse);
320 // GetStepSummaries returns the job summaries (the Markdown written to
321 // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
322 // number. Like GitHub, it returns at most 20 summaries per job: the first 20
323 // steps that have one, in step order; truncated says there are more. Needs
324 // the same access as GetJob. Only servers with the feature
325 // "ci.summaries" implement it (unimplemented otherwise). A job without
326 // summaries gives an empty list. Fails with not_found if the job or the
327 // attempt does not exist.
328 rpc GetStepSummaries(GetStepSummariesRequest) returns (GetStepSummariesResponse);
329 // GetJobLog streams the lines of the log of a job, from a line number. The
330 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
331 // text each.
332 //
333 // Without follow, the stream ends after the last line stored when the call
334 // was made. With follow, it goes on as lines arrive, with at most 1 second of
335 // delay after the runner's AppendLog, and ends without error once the job has
336 // completed and all its lines were sent; on a completed job follow changes
337 // nothing. A client that loses the stream calls again with the offset after
338 // the last line it received. The client may cancel at any time.
339 //
340 // Fails with not_found if the job, the attempt or its log does not exist (the
341 // log is removed by the retention sweep, and a queued job has none: with
342 // follow, the call waits for the first line instead), with out_of_range if
343 // offset is beyond the end of the log of a job without follow, and with
344 // resource_exhausted when there are too many concurrent log streams, in
345 // total or from one client. Like Watch, a stream ends with unauthenticated
346 // when the token was revoked or expired.
347 rpc GetJobLog(GetJobLogRequest) returns (stream GetJobLogResponse);
348 // CancelRun asks to cancel the latest attempt of a run. Needs the ci:write
349 // scope. Jobs that have not started are cancelled at once; jobs in progress
350 // get a CANCEL_REASON_USER request through WatchJob, and the run completes
351 // when they have ended, so the returned run may still be IN_PROGRESS.
352 // Cancelling a run that already has a cancellation requested succeeds and
353 // changes nothing. Fails with failed_precondition if the run has completed.
354 rpc CancelRun(CancelRunRequest) returns (CancelRunResponse);
355 // RerunRun starts a new attempt of a completed run: same run id and number,
356 // attempt + 1, same commit and same workflow file as at the original run (the
357 // file of the repository is not read again). Needs the ci:write scope. Fails
358 // with failed_precondition if the latest attempt has not completed, or if
359 // failed_only is set and no job failed. The new attempt is returned QUEUED.
360 rpc RerunRun(RerunRunRequest) returns (RerunRunResponse);
361 // DispatchWorkflow starts a run of a workflow file by hand, like `gh
362 // workflow run` and GitHub's "workflow_dispatch" event. Needs the ci:write
363 // scope on the repository. The workflow is read at ref and must have
364 // "workflow_dispatch" among its events. The run has event
365 // "workflow_dispatch", ref and the commit ref points to, and the caller as
366 // actor; it is trusted when the caller is the owner and not trusted when the
367 // caller is a token limited to branches. The run is returned QUEUED, before
368 // any job has been given to a runner. Only servers with the feature
369 // "ci.dispatch" implement it (unimplemented otherwise). Fails with
370 // not_found if the repository, the workflow file or ref does not exist,
371 // with failed_precondition if the workflow does not declare
372 // "workflow_dispatch", and with invalid_argument if an input is unknown, is
373 // missing while required without default, or has a value of the wrong type
374 // or outside its choices, or if the workflow file is not valid.
375 rpc DispatchWorkflow(DispatchWorkflowRequest) returns (DispatchWorkflowResponse);
376 // ListWorkflows lists the workflow files of a repository with their state,
377 // like `gh workflow list --all`, ordered by path: the files of
378 // .github/workflows at the tip of the default branch, and the files that are
379 // disabled even if the default branch has no such file (a repository that
380 // is empty, or a file not pushed yet). Needs the same access as reading the
381 // repository. A repository without a default branch lists only its disabled
382 // files. Only servers with the feature "ci.workflows" implement it
383 // (unimplemented otherwise). Fails with not_found if the repository does not
384 // exist or cannot be read.
385 rpc ListWorkflows(ListWorkflowsRequest) returns (ListWorkflowsResponse);
386 // DisableWorkflow disables a workflow file of a repository, like `gh
387 // workflow disable`: no event starts a run of it any more (push,
388 // pull_request, pull_request_target, schedule, workflow_run, create,
389 // delete, and workflow_dispatch). Runs already started are not affected.
390 // The state belongs to the repository and to the file path, not to a
391 // commit or a branch, and the file does not have to exist: it can be set on
392 // an empty repository, before the first push. Disabling a disabled workflow
393 // succeeds and changes nothing. Needs the repo:admin scope on the
394 // repository, and a token that is not limited to branch prefixes. Only
395 // servers with the feature "ci.workflows" implement it (unimplemented
396 // otherwise). Fails with not_found if the repository does not exist or the
397 // caller cannot read it, permission_denied without the scope, and
398 // invalid_argument if the workflow is not a file name or a path of
399 // .github/workflows ending in .yml or .yaml.
400 rpc DisableWorkflow(DisableWorkflowRequest) returns (DisableWorkflowResponse);
401 // EnableWorkflow undoes DisableWorkflow, like `gh workflow enable`. Enabling
402 // a workflow that is not disabled succeeds and changes nothing. Same access
403 // and errors as DisableWorkflow. Events that happened while the workflow was
404 // disabled are not replayed.
405 rpc EnableWorkflow(EnableWorkflowRequest) returns (EnableWorkflowResponse);
406 // ListChecks lists the checks of a commit: for each job of each run on that
407 // sha, the one of the latest attempt, ordered by creation time then name.
408 // A commit without a run has no check: the list is empty, which is not an
409 // error, and the server does not verify that the commit exists. Returns at
410 // most 1,000 checks (truncated tells).
411 rpc ListChecks(ListChecksRequest) returns (ListChecksResponse);
412 // ListRunners lists the registered runners, ordered by name. Needs the
413 // runner:register scope.
414 rpc ListRunners(ListRunnersRequest) returns (ListRunnersResponse);
415 // RemoveRunner removes a runner: its runner token stops working at once (a
416 // FetchJob in progress ends with unauthenticated) and it no longer gets
417 // jobs. A job it is running is not affected: it ends normally, or fails as
418 // a lost runner without heartbeats. Needs the runner:register scope. Fails
419 // with not_found if the id is unknown.
420 rpc RemoveRunner(RemoveRunnerRequest) returns (RemoveRunnerResponse);
421}
422
423// ListRunsRequest selects a page of runs.
424message ListRunsRequest {
425 // Repo is the repository name.
426 string repo = 1;
427 // PageSize is the maximum number of runs to return.
428 int32 page_size = 2;
429 // PageToken is the next_page_token of a previous response. Empty for the
430 // first page.
431 string page_token = 3;
432 // Workflow restricts the result to one workflow file: its path
433 // (".github/workflows/ci.yml") or its file name ("ci.yml"). Empty means
434 // every workflow. Ignored by servers without "ci.runs.filters".
435 string workflow = 4;
436 // Branch restricts the result to the runs whose ref is this branch, by
437 // short name ("main"). Empty means every ref. Ignored by servers without
438 // "ci.runs.filters".
439 string branch = 5;
440 // Status restricts the result to the runs whose latest attempt has this
441 // status. CI_STATUS_UNSPECIFIED means every status. Ignored by servers
442 // without "ci.runs.filters".
443 CiStatus status = 6;
444}
445
446// ListRunsResponse is one page of runs.
447message ListRunsResponse {
448 // Runs are the runs of this page, highest id first, without jobs.
449 repeated Run runs = 1;
450 // NextPageToken is passed as page_token to get the next page. Empty when
451 // there is no next page.
452 string next_page_token = 2;
453}
454
455// GetRunRequest selects a run.
456message GetRunRequest {
457 // Repo is the repository name.
458 string repo = 1;
459 // RunId is the Run.id.
460 int64 run_id = 2;
461 // Attempt is the attempt to read. 0 means the latest.
462 int32 attempt = 3;
463}
464
465// GetRunResponse holds a run with its jobs.
466message GetRunResponse {
467 // Run is the run, as of the attempt asked.
468 Run run = 1;
469 // Jobs are the jobs of that attempt, with their steps, in the order of the
470 // workflow file (matrix instances in the order of the matrix). Jobs kept from
471 // an earlier attempt by a re-run of failed jobs are included, with their own
472 // RunJob.attempt. Empty for a run that failed on an invalid workflow file.
473 repeated RunJob jobs = 2;
474 // LatestAttempt is the latest attempt of the run, to offer the other ones.
475 int32 latest_attempt = 3;
476}
477
478// GetJobRequest selects a job.
479message GetJobRequest {
480 // Repo is the repository name.
481 string repo = 1;
482 // JobId is the RunJob.id.
483 string job_id = 2;
484 // Attempt is the RunJob.attempt to read. 0 means the latest.
485 int32 attempt = 3;
486}
487
488// GetJobResponse holds a job.
489message GetJobResponse {
490 // Job is the job with its steps.
491 RunJob job = 1;
492}
493
494// ListAnnotationsRequest selects the annotations of a run.
495message ListAnnotationsRequest {
496 // Repo is the repository name.
497 string repo = 1;
498 // RunId is the Run.id.
499 int64 run_id = 2;
500 // Attempt is the attempt to read. 0 means the latest, and then each job
501 // contributes the annotations of its own RunJob.attempt (not necessarily the
502 // latest attempt of the run, see ListAnnotations).
503 int32 attempt = 3;
504 // JobId restricts the result to one job (RunJob.id). Empty means every job
505 // of the run.
506 string job_id = 4;
507}
508
509// ListAnnotationsResponse holds the annotations of a run.
510message ListAnnotationsResponse {
511 // Annotations are the annotations, at most 1,000.
512 repeated JobAnnotation annotations = 1;
513 // Truncated is true when there are more annotations than annotations holds.
514 bool truncated = 2;
515}
516
517// JobAnnotation is an annotation with the job it belongs to.
518message JobAnnotation {
519 // JobId is the RunJob.id of the job.
520 string job_id = 1;
521 // Annotation is the annotation as the runner sent it, after the server
522 // checked it. Its step_number is the step of the job.
523 Annotation annotation = 2;
524}
525
526// GetStepSummariesRequest selects a job.
527message GetStepSummariesRequest {
528 // Repo is the repository name.
529 string repo = 1;
530 // JobId is the RunJob.id.
531 string job_id = 2;
532 // Attempt is the RunJob.attempt to read. 0 means the latest.
533 int32 attempt = 3;
534}
535
536// GetStepSummariesResponse holds the summaries of a job.
537message GetStepSummariesResponse {
538 // Summaries are the summaries of the steps that have one, ordered by step
539 // number: at most 20, the first 20 steps having one.
540 repeated StepSummary summaries = 1;
541 // Truncated is true when the job has more than 20 steps with a summary and
542 // summaries holds only the first 20.
543 bool truncated = 2;
544}
545
546// StepSummary is the job summary of one step.
547message StepSummary {
548 // StepNumber is the number of the step (see Step.number).
549 int32 step_number = 1;
550 // Markdown is the summary as uploaded, at most 1 MiB. Clients render it
551 // safely: it is untrusted content (raw HTML and script URLs must not run).
552 string markdown = 2;
553}
554
555// GetJobLogRequest selects the lines to stream.
556message GetJobLogRequest {
557 // Repo is the repository name.
558 string repo = 1;
559 // JobId is the RunJob.id.
560 string job_id = 2;
561 // Attempt is the RunJob.attempt whose log to read. 0 means the latest.
562 int32 attempt = 3;
563 // Offset is the number of the first line to send, counted from 0 across all
564 // steps (see Step.log_start). Negative is invalid_argument.
565 int64 offset = 4;
566 // Follow keeps the stream open while the job runs. See GetJobLog.
567 bool follow = 5;
568}
569
570// GetJobLogResponse is one message of the log stream.
571message GetJobLogResponse {
572 // Offset is the number of the first line of lines.
573 int64 offset = 1;
574 // Lines are consecutive lines of the log, at most 1,000, at most 64 KiB of
575 // text in total. Never empty.
576 repeated JobLogLine lines = 2;
577}
578
579// JobLogLine is one line of a job log, as the runner sent it.
580message JobLogLine {
581 // Step is the number of the step the line belongs to.
582 int32 step = 1;
583 // Time is when the runner produced the line, with nanosecond precision.
584 google.protobuf.Timestamp time = 2;
585 // Text is the line without its terminator, as in LogLine.text, including the
586 // "##[group]" and "##[endgroup]" markers. Clients show it escaped.
587 string text = 3;
588 // Continued is true when the line continues the line before it, which was
589 // too long for the runner to send whole (see LogLine.continued). Pieces keep
590 // their own line numbers, so offsets are the same as the runner's; a client
591 // that shows lines joins a continued line to the previous one. The raw log
592 // file already has them joined.
593 bool continued = 4;
594}
595
596// CancelRunRequest names the run to cancel.
597message CancelRunRequest {
598 // Repo is the repository name.
599 string repo = 1;
600 // RunId is the Run.id.
601 int64 run_id = 2;
602}
603
604// CancelRunResponse holds the run after the request.
605message CancelRunResponse {
606 // Run is the latest attempt of the run.
607 Run run = 1;
608}
609
610// RerunRunRequest names the run to run again.
611message RerunRunRequest {
612 // Repo is the repository name.
613 string repo = 1;
614 // RunId is the Run.id.
615 int64 run_id = 2;
616 // FailedOnly runs again only the jobs of the latest attempt that did not
617 // succeed (conclusion FAILURE, CANCELLED, TIMED_OUT or ACTION_REQUIRED) and
618 // the jobs that need them, directly or not, even if they were skipped. The
619 // other jobs keep their result, steps and log from the earlier attempt. When
620 // false, every job runs again.
621 bool failed_only = 3;
622}
623
624// RerunRunResponse holds the new attempt.
625message RerunRunResponse {
626 // Run is the run as of the new attempt, QUEUED.
627 Run run = 1;
628}
629
630// DispatchWorkflowRequest names the workflow to run and its inputs.
631message DispatchWorkflowRequest {
632 // Repo is the repository name.
633 string repo = 1;
634 // WorkflowPath is the path of the workflow file at ref, for example
635 // ".github/workflows/ci.yml", or its file name ("ci.yml").
636 string workflow_path = 2;
637 // Ref is the branch or tag to run on, by short name ("main") or full name
638 // ("refs/heads/main"). Empty means the default branch of the repository.
639 string ref = 3;
640 // Inputs are the values of the "inputs" of the workflow's
641 // "workflow_dispatch" by name, as strings: a boolean is "true" or "false", a
642 // number its decimal text. An input left out takes its default.
643 map<string, string> inputs = 4;
644}
645
646// DispatchWorkflowResponse holds the new run.
647message DispatchWorkflowResponse {
648 // Run is the new run, QUEUED, attempt 1.
649 Run run = 1;
650}
651
652// ListChecksRequest names the commit.
653message ListChecksRequest {
654 // Repo is the repository name.
655 string repo = 1;
656 // Sha is the full commit id (40 lowercase hexadecimal characters for SHA-1).
657 // Abbreviations and names are invalid_argument.
658 string sha = 2;
659}
660
661// ListChecksResponse holds the checks of a commit.
662message ListChecksResponse {
663 // Checks are the checks of the commit, one per job of the latest attempt of
664 // each run, ordered by creation time then name.
665 repeated Check checks = 1;
666 // Truncated is true when the commit has more checks than checks holds.
667 bool truncated = 2;
668}
669
670// ListRunnersRequest selects a page of runners.
671message ListRunnersRequest {
672 // PageSize is the maximum number of runners to return.
673 int32 page_size = 1;
674 // PageToken is the next_page_token of a previous response. Empty for the
675 // first page.
676 string page_token = 2;
677}
678
679// ListRunnersResponse is one page of runners.
680message ListRunnersResponse {
681 // Runners are the runners of this page, ordered by name.
682 repeated Runner runners = 1;
683 // NextPageToken is passed as page_token to get the next page. Empty when
684 // there is no next page.
685 string next_page_token = 2;
686}
687
688// RemoveRunnerRequest names the runner to remove.
689message RemoveRunnerRequest {
690 // RunnerId is the Runner.id.
691 string runner_id = 1;
692}
693
694// RemoveRunnerResponse is empty.
695message RemoveRunnerResponse {}
696
697// WorkflowState tells whether a workflow file starts runs.
698enum WorkflowState {
699 WORKFLOW_STATE_UNSPECIFIED = 0;
700 // The workflow starts runs for the events it declares.
701 WORKFLOW_STATE_ENABLED = 1;
702 // The workflow starts no run for any event (DisableWorkflow).
703 WORKFLOW_STATE_DISABLED = 2;
704}
705
706// Workflow is a workflow file of a repository and its state.
707message Workflow {
708 // Path is the path of the file, always ".github/workflows/<file>".
709 string path = 1;
710 // Name is the "name:" of the workflow at the tip of the default branch, the
711 // path when the file has none. Empty when the default branch has no such file
712 // or it cannot be read as a workflow.
713 string name = 2;
714 // State is ENABLED or DISABLED.
715 WorkflowState state = 3;
716}
717
718// ListWorkflowsRequest names the repository.
719message ListWorkflowsRequest {
720 // Repo is the repository name.
721 string repo = 1;
722}
723
724// ListWorkflowsResponse holds the workflows of a repository, ordered by path.
725message ListWorkflowsResponse {
726 repeated Workflow workflows = 1;
727}
728
729// DisableWorkflowRequest names the workflow to disable.
730message DisableWorkflowRequest {
731 // Repo is the repository name.
732 string repo = 1;
733 // Workflow is the path of the file (".github/workflows/release.yml") or its
734 // file name ("release.yml"). The file does not have to exist.
735 string workflow = 2;
736}
737
738// DisableWorkflowResponse holds the workflow after the change.
739message DisableWorkflowResponse {
740 // Workflow has the normalized path and state DISABLED.
741 Workflow workflow = 1;
742}
743
744// EnableWorkflowRequest names the workflow to enable.
745message EnableWorkflowRequest {
746 // Repo is the repository name.
747 string repo = 1;
748 // Workflow is the path of the file or its file name, as in
749 // DisableWorkflowRequest.
750 string workflow = 2;
751}
752
753// EnableWorkflowResponse holds the workflow after the change.
754message EnableWorkflowResponse {
755 // Workflow has the normalized path and state ENABLED.
756 Workflow workflow = 1;
757}