detached 49ac5fd

Merge pull request 'feat(ci): add actions, annotations and summaries to the CI protocol' (#9) from feat/ci2-protocol into main

commit
49ac5fd7a78a04c05aa33c86f7dcec5b6a4a58e7
author
bnema · · 2026-10-13 09:16 UTC
merge of
4db3b8b + b94fede · diff against the first parent
signature
SSH UnverifiedSHA256:VOCA5lYARHcbKDZ7GhTV45VmcjWnJ6ZQIBazj17LivA The key is unknown
refs
tag: v0.2.0
10 files · +2129 -252
M README.md +2 -2
@@ -22,8 +22,8 @@ Handlers are mounted under `/-/api/` by the server. Errors are Connect codes.
2222 | `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |
2323 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |
2424 | `EventService` | `Watch` (streamed, resumable) |
25-| `RunnerService` | `RegisterRunner`, `FetchJob` (long poll), `UpdateJob`, `AppendLog` (offset-idempotent), `Heartbeat`, `WatchJob` (cancel requests, streamed), `CompleteJob` (idempotent); for CI runners |
26-| `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `CancelRun`, `RerunRun`, `ListChecks`, `ListRunners`, `RemoveRunner` |
25+| `RunnerService` | `RegisterRunner`, `FetchJob` (long poll), `UpdateJob` (steps, annotations), `AppendLog` (offset-idempotent), `Heartbeat`, `WatchJob` (cancel requests, streamed), `CompleteJob` (idempotent), `ResolveActions` (where to download the `uses:` actions), `UploadSummary` (job summary of a step); for CI runners |
26+| `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `ListAnnotations`, `GetStepSummaries`, `CancelRun`, `RerunRun`, `ListChecks`, `ListRunners`, `RemoveRunner` |
2727 | `ServerService` | `GetVersion` (server version and feature list), `GetSigningKey` (commit signing key) |
2828
2929 Tokens carry scopes only; presets such as `cli` or `agent` are a client concern.
@@ -22,8 +22,8 @@ Handlers are mounted under `/-/api/` by the server. Errors are Connect codes.
22 | `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |22 | `MergeRequestService` | `CreateMergeRequest`, `ListMergeRequests`, `GetMergeRequest` (commits, diff, comments), `AddComment`, `ResolveComment`, `CloseMergeRequest`, `MergeMergeRequest`, `MarkRead` |
23 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |23 | `SessionService` | `CreateLoginLink`, `SignOutEverywhere` (owner only) |
24 | `EventService` | `Watch` (streamed, resumable) |24 | `EventService` | `Watch` (streamed, resumable) |
25-| `RunnerService` | `RegisterRunner`, `FetchJob` (long poll), `UpdateJob`, `AppendLog` (offset-idempotent), `Heartbeat`, `WatchJob` (cancel requests, streamed), `CompleteJob` (idempotent); for CI runners |25+| `RunnerService` | `RegisterRunner`, `FetchJob` (long poll), `UpdateJob` (steps, annotations), `AppendLog` (offset-idempotent), `Heartbeat`, `WatchJob` (cancel requests, streamed), `CompleteJob` (idempotent), `ResolveActions` (where to download the `uses:` actions), `UploadSummary` (job summary of a step); for CI runners |
26-| `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `CancelRun`, `RerunRun`, `ListChecks`, `ListRunners`, `RemoveRunner` |26+| `RunService` | `ListRuns`, `GetRun`, `GetJob`, `GetJobLog` (streamed, follow), `ListAnnotations`, `GetStepSummaries`, `CancelRun`, `RerunRun`, `ListChecks`, `ListRunners`, `RemoveRunner` |
27 | `ServerService` | `GetVersion` (server version and feature list), `GetSigningKey` (commit signing key) |27 | `ServerService` | `GetVersion` (server version and feature list), `GetSigningKey` (commit signing key) |
28 28
29 Tokens carry scopes only; presets such as `cli` or `agent` are a client concern.29 Tokens carry scopes only; presets such as `cli` or `agent` are a client concern.
M gen/ermite/ermiteconnect/run.connect.go +101 -9
@@ -41,6 +41,12 @@ const (
4141 RunServiceGetRunProcedure = "/ermite.RunService/GetRun"
4242 // RunServiceGetJobProcedure is the fully-qualified name of the RunService's GetJob RPC.
4343 RunServiceGetJobProcedure = "/ermite.RunService/GetJob"
44+ // RunServiceListAnnotationsProcedure is the fully-qualified name of the RunService's
45+ // ListAnnotations RPC.
46+ RunServiceListAnnotationsProcedure = "/ermite.RunService/ListAnnotations"
47+ // RunServiceGetStepSummariesProcedure is the fully-qualified name of the RunService's
48+ // GetStepSummaries RPC.
49+ RunServiceGetStepSummariesProcedure = "/ermite.RunService/GetStepSummaries"
4450 // RunServiceGetJobLogProcedure is the fully-qualified name of the RunService's GetJobLog RPC.
4551 RunServiceGetJobLogProcedure = "/ermite.RunService/GetJobLog"
4652 // RunServiceCancelRunProcedure is the fully-qualified name of the RunService's CancelRun RPC.
@@ -70,6 +76,25 @@ type RunServiceClient interface {
7076 // GetJob returns one job with its steps. Fails with not_found if the job
7177 // or the attempt does not exist.
7278 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)
79+ // ListAnnotations lists the annotations of a run attempt, optionally of one
80+ // job, ordered by job (as in GetRun), step number, then the order in which
81+ // the step produced them. For each job it gives the annotations of the
82+ // attempt in which that job executed (RunJob.attempt), which is lower than
83+ // 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
84+ // 1,000 annotations (truncated tells). A run without annotations gives an
85+ // empty list. Only servers with the feature "ci.annotations" implement it
86+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
87+ // the job does not exist, or if the job is not a job of the run.
88+ ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error)
89+ // GetStepSummaries returns the job summaries (the Markdown written to
90+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
91+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
92+ // steps that have one, in step order; truncated says there are more. Needs
93+ // the same access as GetJob. Only servers with the feature
94+ // "ci.summaries" implement it (unimplemented otherwise). A job without
95+ // summaries gives an empty list. Fails with not_found if the job or the
96+ // attempt does not exist.
97+ GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error)
7398 // GetJobLog streams the lines of the log of a job, from a line number. The
7499 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
75100 // text each.
@@ -148,6 +173,18 @@ func NewRunServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...
148173 connect.WithSchema(runServiceMethods.ByName("GetJob")),
149174 connect.WithClientOptions(opts...),
150175 ),
176+ listAnnotations: connect.NewClient[ermite.ListAnnotationsRequest, ermite.ListAnnotationsResponse](
177+ httpClient,
178+ baseURL+RunServiceListAnnotationsProcedure,
179+ connect.WithSchema(runServiceMethods.ByName("ListAnnotations")),
180+ connect.WithClientOptions(opts...),
181+ ),
182+ getStepSummaries: connect.NewClient[ermite.GetStepSummariesRequest, ermite.GetStepSummariesResponse](
183+ httpClient,
184+ baseURL+RunServiceGetStepSummariesProcedure,
185+ connect.WithSchema(runServiceMethods.ByName("GetStepSummaries")),
186+ connect.WithClientOptions(opts...),
187+ ),
151188 getJobLog: connect.NewClient[ermite.GetJobLogRequest, ermite.GetJobLogResponse](
152189 httpClient,
153190 baseURL+RunServiceGetJobLogProcedure,
@@ -189,15 +226,17 @@ func NewRunServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...
189226
190227 // runServiceClient implements RunServiceClient.
191228 type runServiceClient struct {
192- listRuns *connect.Client[ermite.ListRunsRequest, ermite.ListRunsResponse]
193- getRun *connect.Client[ermite.GetRunRequest, ermite.GetRunResponse]
194- getJob *connect.Client[ermite.GetJobRequest, ermite.GetJobResponse]
195- getJobLog *connect.Client[ermite.GetJobLogRequest, ermite.GetJobLogResponse]
196- cancelRun *connect.Client[ermite.CancelRunRequest, ermite.CancelRunResponse]
197- rerunRun *connect.Client[ermite.RerunRunRequest, ermite.RerunRunResponse]
198- listChecks *connect.Client[ermite.ListChecksRequest, ermite.ListChecksResponse]
199- listRunners *connect.Client[ermite.ListRunnersRequest, ermite.ListRunnersResponse]
200- removeRunner *connect.Client[ermite.RemoveRunnerRequest, ermite.RemoveRunnerResponse]
229+ listRuns *connect.Client[ermite.ListRunsRequest, ermite.ListRunsResponse]
230+ getRun *connect.Client[ermite.GetRunRequest, ermite.GetRunResponse]
231+ getJob *connect.Client[ermite.GetJobRequest, ermite.GetJobResponse]
232+ listAnnotations *connect.Client[ermite.ListAnnotationsRequest, ermite.ListAnnotationsResponse]
233+ getStepSummaries *connect.Client[ermite.GetStepSummariesRequest, ermite.GetStepSummariesResponse]
234+ getJobLog *connect.Client[ermite.GetJobLogRequest, ermite.GetJobLogResponse]
235+ cancelRun *connect.Client[ermite.CancelRunRequest, ermite.CancelRunResponse]
236+ rerunRun *connect.Client[ermite.RerunRunRequest, ermite.RerunRunResponse]
237+ listChecks *connect.Client[ermite.ListChecksRequest, ermite.ListChecksResponse]
238+ listRunners *connect.Client[ermite.ListRunnersRequest, ermite.ListRunnersResponse]
239+ removeRunner *connect.Client[ermite.RemoveRunnerRequest, ermite.RemoveRunnerResponse]
201240 }
202241
203242 // ListRuns calls ermite.RunService.ListRuns.
@@ -215,6 +254,16 @@ func (c *runServiceClient) GetJob(ctx context.Context, req *connect.Request[ermi
215254 return c.getJob.CallUnary(ctx, req)
216255 }
217256
257+// ListAnnotations calls ermite.RunService.ListAnnotations.
258+func (c *runServiceClient) ListAnnotations(ctx context.Context, req *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) {
259+ return c.listAnnotations.CallUnary(ctx, req)
260+}
261+
262+// GetStepSummaries calls ermite.RunService.GetStepSummaries.
263+func (c *runServiceClient) GetStepSummaries(ctx context.Context, req *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error) {
264+ return c.getStepSummaries.CallUnary(ctx, req)
265+}
266+
218267 // GetJobLog calls ermite.RunService.GetJobLog.
219268 func (c *runServiceClient) GetJobLog(ctx context.Context, req *connect.Request[ermite.GetJobLogRequest]) (*connect.ServerStreamForClient[ermite.GetJobLogResponse], error) {
220269 return c.getJobLog.CallServerStream(ctx, req)
@@ -260,6 +309,25 @@ type RunServiceHandler interface {
260309 // GetJob returns one job with its steps. Fails with not_found if the job
261310 // or the attempt does not exist.
262311 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)
312+ // ListAnnotations lists the annotations of a run attempt, optionally of one
313+ // job, ordered by job (as in GetRun), step number, then the order in which
314+ // the step produced them. For each job it gives the annotations of the
315+ // attempt in which that job executed (RunJob.attempt), which is lower than
316+ // 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
317+ // 1,000 annotations (truncated tells). A run without annotations gives an
318+ // empty list. Only servers with the feature "ci.annotations" implement it
319+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
320+ // the job does not exist, or if the job is not a job of the run.
321+ ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error)
322+ // GetStepSummaries returns the job summaries (the Markdown written to
323+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
324+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
325+ // steps that have one, in step order; truncated says there are more. Needs
326+ // the same access as GetJob. Only servers with the feature
327+ // "ci.summaries" implement it (unimplemented otherwise). A job without
328+ // summaries gives an empty list. Fails with not_found if the job or the
329+ // attempt does not exist.
330+ GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error)
263331 // GetJobLog streams the lines of the log of a job, from a line number. The
264332 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
265333 // text each.
@@ -334,6 +402,18 @@ func NewRunServiceHandler(svc RunServiceHandler, opts ...connect.HandlerOption)
334402 connect.WithSchema(runServiceMethods.ByName("GetJob")),
335403 connect.WithHandlerOptions(opts...),
336404 )
405+ runServiceListAnnotationsHandler := connect.NewUnaryHandler(
406+ RunServiceListAnnotationsProcedure,
407+ svc.ListAnnotations,
408+ connect.WithSchema(runServiceMethods.ByName("ListAnnotations")),
409+ connect.WithHandlerOptions(opts...),
410+ )
411+ runServiceGetStepSummariesHandler := connect.NewUnaryHandler(
412+ RunServiceGetStepSummariesProcedure,
413+ svc.GetStepSummaries,
414+ connect.WithSchema(runServiceMethods.ByName("GetStepSummaries")),
415+ connect.WithHandlerOptions(opts...),
416+ )
337417 runServiceGetJobLogHandler := connect.NewServerStreamHandler(
338418 RunServiceGetJobLogProcedure,
339419 svc.GetJobLog,
@@ -378,6 +458,10 @@ func NewRunServiceHandler(svc RunServiceHandler, opts ...connect.HandlerOption)
378458 runServiceGetRunHandler.ServeHTTP(w, r)
379459 case RunServiceGetJobProcedure:
380460 runServiceGetJobHandler.ServeHTTP(w, r)
461+ case RunServiceListAnnotationsProcedure:
462+ runServiceListAnnotationsHandler.ServeHTTP(w, r)
463+ case RunServiceGetStepSummariesProcedure:
464+ runServiceGetStepSummariesHandler.ServeHTTP(w, r)
381465 case RunServiceGetJobLogProcedure:
382466 runServiceGetJobLogHandler.ServeHTTP(w, r)
383467 case RunServiceCancelRunProcedure:
@@ -411,6 +495,14 @@ func (UnimplementedRunServiceHandler) GetJob(context.Context, *connect.Request[e
411495 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJob is not implemented"))
412496 }
413497
498+func (UnimplementedRunServiceHandler) ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) {
499+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.ListAnnotations is not implemented"))
500+}
501+
502+func (UnimplementedRunServiceHandler) GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error) {
503+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetStepSummaries is not implemented"))
504+}
505+
414506 func (UnimplementedRunServiceHandler) GetJobLog(context.Context, *connect.Request[ermite.GetJobLogRequest], *connect.ServerStream[ermite.GetJobLogResponse]) error {
415507 return connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJobLog is not implemented"))
416508 }
@@ -41,6 +41,12 @@ const (
41 RunServiceGetRunProcedure = "/ermite.RunService/GetRun"41 RunServiceGetRunProcedure = "/ermite.RunService/GetRun"
42 // RunServiceGetJobProcedure is the fully-qualified name of the RunService's GetJob RPC.42 // RunServiceGetJobProcedure is the fully-qualified name of the RunService's GetJob RPC.
43 RunServiceGetJobProcedure = "/ermite.RunService/GetJob"43 RunServiceGetJobProcedure = "/ermite.RunService/GetJob"
44+ // RunServiceListAnnotationsProcedure is the fully-qualified name of the RunService's
45+ // ListAnnotations RPC.
46+ RunServiceListAnnotationsProcedure = "/ermite.RunService/ListAnnotations"
47+ // RunServiceGetStepSummariesProcedure is the fully-qualified name of the RunService's
48+ // GetStepSummaries RPC.
49+ RunServiceGetStepSummariesProcedure = "/ermite.RunService/GetStepSummaries"
44 // RunServiceGetJobLogProcedure is the fully-qualified name of the RunService's GetJobLog RPC.50 // RunServiceGetJobLogProcedure is the fully-qualified name of the RunService's GetJobLog RPC.
45 RunServiceGetJobLogProcedure = "/ermite.RunService/GetJobLog"51 RunServiceGetJobLogProcedure = "/ermite.RunService/GetJobLog"
46 // RunServiceCancelRunProcedure is the fully-qualified name of the RunService's CancelRun RPC.52 // RunServiceCancelRunProcedure is the fully-qualified name of the RunService's CancelRun RPC.
@@ -70,6 +76,25 @@ type RunServiceClient interface {
70 // GetJob returns one job with its steps. Fails with not_found if the job76 // GetJob returns one job with its steps. Fails with not_found if the job
71 // or the attempt does not exist.77 // or the attempt does not exist.
72 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)78 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)
79+ // ListAnnotations lists the annotations of a run attempt, optionally of one
80+ // job, ordered by job (as in GetRun), step number, then the order in which
81+ // the step produced them. For each job it gives the annotations of the
82+ // attempt in which that job executed (RunJob.attempt), which is lower than
83+ // 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
84+ // 1,000 annotations (truncated tells). A run without annotations gives an
85+ // empty list. Only servers with the feature "ci.annotations" implement it
86+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
87+ // the job does not exist, or if the job is not a job of the run.
88+ ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error)
89+ // GetStepSummaries returns the job summaries (the Markdown written to
90+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
91+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
92+ // steps that have one, in step order; truncated says there are more. Needs
93+ // the same access as GetJob. Only servers with the feature
94+ // "ci.summaries" implement it (unimplemented otherwise). A job without
95+ // summaries gives an empty list. Fails with not_found if the job or the
96+ // attempt does not exist.
97+ GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error)
73 // GetJobLog streams the lines of the log of a job, from a line number. The98 // GetJobLog streams the lines of the log of a job, from a line number. The
74 // server sends them in order in messages of at most 1,000 lines and 64 KiB of99 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
75 // text each.100 // text each.
@@ -148,6 +173,18 @@ func NewRunServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...
148 connect.WithSchema(runServiceMethods.ByName("GetJob")),173 connect.WithSchema(runServiceMethods.ByName("GetJob")),
149 connect.WithClientOptions(opts...),174 connect.WithClientOptions(opts...),
150 ),175 ),
176+ listAnnotations: connect.NewClient[ermite.ListAnnotationsRequest, ermite.ListAnnotationsResponse](
177+ httpClient,
178+ baseURL+RunServiceListAnnotationsProcedure,
179+ connect.WithSchema(runServiceMethods.ByName("ListAnnotations")),
180+ connect.WithClientOptions(opts...),
181+ ),
182+ getStepSummaries: connect.NewClient[ermite.GetStepSummariesRequest, ermite.GetStepSummariesResponse](
183+ httpClient,
184+ baseURL+RunServiceGetStepSummariesProcedure,
185+ connect.WithSchema(runServiceMethods.ByName("GetStepSummaries")),
186+ connect.WithClientOptions(opts...),
187+ ),
151 getJobLog: connect.NewClient[ermite.GetJobLogRequest, ermite.GetJobLogResponse](188 getJobLog: connect.NewClient[ermite.GetJobLogRequest, ermite.GetJobLogResponse](
152 httpClient,189 httpClient,
153 baseURL+RunServiceGetJobLogProcedure,190 baseURL+RunServiceGetJobLogProcedure,
@@ -189,15 +226,17 @@ func NewRunServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...
189 226
190 // runServiceClient implements RunServiceClient.227 // runServiceClient implements RunServiceClient.
191 type runServiceClient struct {228 type runServiceClient struct {
192- listRuns *connect.Client[ermite.ListRunsRequest, ermite.ListRunsResponse]229+ listRuns *connect.Client[ermite.ListRunsRequest, ermite.ListRunsResponse]
193- getRun *connect.Client[ermite.GetRunRequest, ermite.GetRunResponse]230+ getRun *connect.Client[ermite.GetRunRequest, ermite.GetRunResponse]
194- getJob *connect.Client[ermite.GetJobRequest, ermite.GetJobResponse]231+ getJob *connect.Client[ermite.GetJobRequest, ermite.GetJobResponse]
195- getJobLog *connect.Client[ermite.GetJobLogRequest, ermite.GetJobLogResponse]232+ listAnnotations *connect.Client[ermite.ListAnnotationsRequest, ermite.ListAnnotationsResponse]
196- cancelRun *connect.Client[ermite.CancelRunRequest, ermite.CancelRunResponse]233+ getStepSummaries *connect.Client[ermite.GetStepSummariesRequest, ermite.GetStepSummariesResponse]
197- rerunRun *connect.Client[ermite.RerunRunRequest, ermite.RerunRunResponse]234+ getJobLog *connect.Client[ermite.GetJobLogRequest, ermite.GetJobLogResponse]
198- listChecks *connect.Client[ermite.ListChecksRequest, ermite.ListChecksResponse]235+ cancelRun *connect.Client[ermite.CancelRunRequest, ermite.CancelRunResponse]
199- listRunners *connect.Client[ermite.ListRunnersRequest, ermite.ListRunnersResponse]236+ rerunRun *connect.Client[ermite.RerunRunRequest, ermite.RerunRunResponse]
200- removeRunner *connect.Client[ermite.RemoveRunnerRequest, ermite.RemoveRunnerResponse]237+ listChecks *connect.Client[ermite.ListChecksRequest, ermite.ListChecksResponse]
238+ listRunners *connect.Client[ermite.ListRunnersRequest, ermite.ListRunnersResponse]
239+ removeRunner *connect.Client[ermite.RemoveRunnerRequest, ermite.RemoveRunnerResponse]
201 }240 }
202 241
203 // ListRuns calls ermite.RunService.ListRuns.242 // ListRuns calls ermite.RunService.ListRuns.
@@ -215,6 +254,16 @@ func (c *runServiceClient) GetJob(ctx context.Context, req *connect.Request[ermi
215 return c.getJob.CallUnary(ctx, req)254 return c.getJob.CallUnary(ctx, req)
216 }255 }
217 256
257+// ListAnnotations calls ermite.RunService.ListAnnotations.
258+func (c *runServiceClient) ListAnnotations(ctx context.Context, req *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) {
259+ return c.listAnnotations.CallUnary(ctx, req)
260+}
261+
262+// GetStepSummaries calls ermite.RunService.GetStepSummaries.
263+func (c *runServiceClient) GetStepSummaries(ctx context.Context, req *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error) {
264+ return c.getStepSummaries.CallUnary(ctx, req)
265+}
266+
218 // GetJobLog calls ermite.RunService.GetJobLog.267 // GetJobLog calls ermite.RunService.GetJobLog.
219 func (c *runServiceClient) GetJobLog(ctx context.Context, req *connect.Request[ermite.GetJobLogRequest]) (*connect.ServerStreamForClient[ermite.GetJobLogResponse], error) {268 func (c *runServiceClient) GetJobLog(ctx context.Context, req *connect.Request[ermite.GetJobLogRequest]) (*connect.ServerStreamForClient[ermite.GetJobLogResponse], error) {
220 return c.getJobLog.CallServerStream(ctx, req)269 return c.getJobLog.CallServerStream(ctx, req)
@@ -260,6 +309,25 @@ type RunServiceHandler interface {
260 // GetJob returns one job with its steps. Fails with not_found if the job309 // GetJob returns one job with its steps. Fails with not_found if the job
261 // or the attempt does not exist.310 // or the attempt does not exist.
262 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)311 GetJob(context.Context, *connect.Request[ermite.GetJobRequest]) (*connect.Response[ermite.GetJobResponse], error)
312+ // ListAnnotations lists the annotations of a run attempt, optionally of one
313+ // job, ordered by job (as in GetRun), step number, then the order in which
314+ // the step produced them. For each job it gives the annotations of the
315+ // attempt in which that job executed (RunJob.attempt), which is lower than
316+ // 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
317+ // 1,000 annotations (truncated tells). A run without annotations gives an
318+ // empty list. Only servers with the feature "ci.annotations" implement it
319+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
320+ // the job does not exist, or if the job is not a job of the run.
321+ ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error)
322+ // GetStepSummaries returns the job summaries (the Markdown written to
323+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
324+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
325+ // steps that have one, in step order; truncated says there are more. Needs
326+ // the same access as GetJob. Only servers with the feature
327+ // "ci.summaries" implement it (unimplemented otherwise). A job without
328+ // summaries gives an empty list. Fails with not_found if the job or the
329+ // attempt does not exist.
330+ GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error)
263 // GetJobLog streams the lines of the log of a job, from a line number. The331 // GetJobLog streams the lines of the log of a job, from a line number. The
264 // server sends them in order in messages of at most 1,000 lines and 64 KiB of332 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
265 // text each.333 // text each.
@@ -334,6 +402,18 @@ func NewRunServiceHandler(svc RunServiceHandler, opts ...connect.HandlerOption)
334 connect.WithSchema(runServiceMethods.ByName("GetJob")),402 connect.WithSchema(runServiceMethods.ByName("GetJob")),
335 connect.WithHandlerOptions(opts...),403 connect.WithHandlerOptions(opts...),
336 )404 )
405+ runServiceListAnnotationsHandler := connect.NewUnaryHandler(
406+ RunServiceListAnnotationsProcedure,
407+ svc.ListAnnotations,
408+ connect.WithSchema(runServiceMethods.ByName("ListAnnotations")),
409+ connect.WithHandlerOptions(opts...),
410+ )
411+ runServiceGetStepSummariesHandler := connect.NewUnaryHandler(
412+ RunServiceGetStepSummariesProcedure,
413+ svc.GetStepSummaries,
414+ connect.WithSchema(runServiceMethods.ByName("GetStepSummaries")),
415+ connect.WithHandlerOptions(opts...),
416+ )
337 runServiceGetJobLogHandler := connect.NewServerStreamHandler(417 runServiceGetJobLogHandler := connect.NewServerStreamHandler(
338 RunServiceGetJobLogProcedure,418 RunServiceGetJobLogProcedure,
339 svc.GetJobLog,419 svc.GetJobLog,
@@ -378,6 +458,10 @@ func NewRunServiceHandler(svc RunServiceHandler, opts ...connect.HandlerOption)
378 runServiceGetRunHandler.ServeHTTP(w, r)458 runServiceGetRunHandler.ServeHTTP(w, r)
379 case RunServiceGetJobProcedure:459 case RunServiceGetJobProcedure:
380 runServiceGetJobHandler.ServeHTTP(w, r)460 runServiceGetJobHandler.ServeHTTP(w, r)
461+ case RunServiceListAnnotationsProcedure:
462+ runServiceListAnnotationsHandler.ServeHTTP(w, r)
463+ case RunServiceGetStepSummariesProcedure:
464+ runServiceGetStepSummariesHandler.ServeHTTP(w, r)
381 case RunServiceGetJobLogProcedure:465 case RunServiceGetJobLogProcedure:
382 runServiceGetJobLogHandler.ServeHTTP(w, r)466 runServiceGetJobLogHandler.ServeHTTP(w, r)
383 case RunServiceCancelRunProcedure:467 case RunServiceCancelRunProcedure:
@@ -411,6 +495,14 @@ func (UnimplementedRunServiceHandler) GetJob(context.Context, *connect.Request[e
411 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJob is not implemented"))495 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJob is not implemented"))
412 }496 }
413 497
498+func (UnimplementedRunServiceHandler) ListAnnotations(context.Context, *connect.Request[ermite.ListAnnotationsRequest]) (*connect.Response[ermite.ListAnnotationsResponse], error) {
499+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.ListAnnotations is not implemented"))
500+}
501+
502+func (UnimplementedRunServiceHandler) GetStepSummaries(context.Context, *connect.Request[ermite.GetStepSummariesRequest]) (*connect.Response[ermite.GetStepSummariesResponse], error) {
503+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetStepSummaries is not implemented"))
504+}
505+
414 func (UnimplementedRunServiceHandler) GetJobLog(context.Context, *connect.Request[ermite.GetJobLogRequest], *connect.ServerStream[ermite.GetJobLogResponse]) error {506 func (UnimplementedRunServiceHandler) GetJobLog(context.Context, *connect.Request[ermite.GetJobLogRequest], *connect.ServerStream[ermite.GetJobLogResponse]) error {
415 return connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJobLog is not implemented"))507 return connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunService.GetJobLog is not implemented"))
416 }508 }
M gen/ermite/ermiteconnect/runner.connect.go +184 -12
@@ -51,6 +51,12 @@ const (
5151 // RunnerServiceCompleteJobProcedure is the fully-qualified name of the RunnerService's CompleteJob
5252 // RPC.
5353 RunnerServiceCompleteJobProcedure = "/ermite.RunnerService/CompleteJob"
54+ // RunnerServiceResolveActionsProcedure is the fully-qualified name of the RunnerService's
55+ // ResolveActions RPC.
56+ RunnerServiceResolveActionsProcedure = "/ermite.RunnerService/ResolveActions"
57+ // RunnerServiceUploadSummaryProcedure is the fully-qualified name of the RunnerService's
58+ // UploadSummary RPC.
59+ RunnerServiceUploadSummaryProcedure = "/ermite.RunnerService/UploadSummary"
5460 )
5561
5662 // RunnerServiceClient is a client for the ermite.RunnerService service.
@@ -105,10 +111,21 @@ type RunnerServiceClient interface {
105111 // identical call changes nothing, so a runner may retry after a network
106112 // error. To end the job use CompleteJob.
107113 //
108- // Fails with invalid_argument if a rule is broken, with failed_precondition
109- // if a step goes back (a COMPLETED step cannot change, a step cannot go from
110- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail
111- // if the job has ended.
114+ // Annotations are applied with the steps, in the same atomic step: for each
115+ // step_number present in annotations, the annotations of that step stored
116+ // so far are replaced by the ones of the request, so a retry never
117+ // duplicates them. A step number absent from the request keeps its
118+ // annotations. The step of an annotation need not be in the steps of the
119+ // same call, and may already be COMPLETED: its annotations can still be
120+ // replaced (the rule that a COMPLETED step cannot change applies to
121+ // StepUpdate, not to annotations), until the job ends. A runner sends one
122+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
123+ // so replacements apply in the order of the calls.
124+ //
125+ // Fails with invalid_argument if a rule is broken (including the annotation
126+ // limits), with failed_precondition if a step goes back (a COMPLETED step
127+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
128+ // failed_precondition and a JobEnded detail if the job has ended.
112129 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)
113130 // AppendLog appends lines to the log of a job. Needs the job token.
114131 //
@@ -213,9 +230,57 @@ type RunnerServiceClient interface {
213230 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
214231 // they never started and the job did not end by cancellation).
215232 //
216- // Fails with invalid_argument if a rule is broken (including the output
217- // limits) and failed_precondition if a step goes back, as in UpdateJob.
233+ // Annotations are applied as in UpdateJob (replacement per step number, also
234+ // for COMPLETED steps and steps not in steps), together with the conclusion.
235+ // Summaries are not part of this call: a runner sends them with
236+ // UploadSummary before it.
237+ //
238+ // Fails with invalid_argument if a rule is broken (including the output and
239+ // annotation limits) and failed_precondition if a step goes back, as in
240+ // UpdateJob.
218241 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)
242+ // ResolveActions turns the "uses" of workflow and action steps into what the
243+ // runner needs to download the actions, as GitHub's action download info
244+ // does. Needs the job token; the job_id must be the one of the token. It
245+ // may be called as often as needed while the job runs (the runner calls it
246+ // once per level of composite actions, see the runner's depth limit of 9).
247+ // The runner then downloads each archive itself, from the sandbox, with the
248+ // token of the ResolvedAction when there is one.
249+ //
250+ // The response has one ResolvedAction per ActionRef, in the same order. A
251+ // reference that cannot be resolved (unknown repository, tag or branch, a
252+ // repository without access, a "uses" that GitHub itself would reject) does
253+ // not fail the call: its ResolvedAction has only ref and error, where error
254+ // is the message GitHub gives for the same failure, which the runner prints
255+ // as is. Only a failure of the call itself (credential, ended job, bad
256+ // request, server error) is an RPC error; the runner then fails the job.
257+ //
258+ // Resolution is stable for a run attempt: the same ref resolves to the same
259+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
260+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
261+ // job gets its own (ResolvedAction.token).
262+ //
263+ // Fails with unauthenticated or permission_denied as the other job RPCs,
264+ // with failed_precondition and a JobEnded detail if the job has ended, and
265+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
266+ // local action ("./path") or a Docker image ("docker://"), which the runner
267+ // handles without the server.
268+ ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error)
269+ // UploadSummary stores the job summary of one step: the Markdown that the
270+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
271+ // The runner masks it before sending it, and sends it after the step ended
272+ // and before CompleteJob.
273+ //
274+ // It is idempotent: the summary of a step is replaced by each call, so a
275+ // retry changes nothing, and an empty markdown removes the summary of the
276+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
277+ // server reads requests of up to 1 MiB plus the envelope (job id, step
278+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
279+ // their own message size limit above that.
280+ //
281+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
282+ // and with failed_precondition and a JobEnded detail if the job has ended.
283+ UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error)
219284 }
220285
221286 // NewRunnerServiceClient constructs a client for the ermite.RunnerService service. By default, it
@@ -271,6 +336,18 @@ func NewRunnerServiceClient(httpClient connect.HTTPClient, baseURL string, opts
271336 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),
272337 connect.WithClientOptions(opts...),
273338 ),
339+ resolveActions: connect.NewClient[ermite.ResolveActionsRequest, ermite.ResolveActionsResponse](
340+ httpClient,
341+ baseURL+RunnerServiceResolveActionsProcedure,
342+ connect.WithSchema(runnerServiceMethods.ByName("ResolveActions")),
343+ connect.WithClientOptions(opts...),
344+ ),
345+ uploadSummary: connect.NewClient[ermite.UploadSummaryRequest, ermite.UploadSummaryResponse](
346+ httpClient,
347+ baseURL+RunnerServiceUploadSummaryProcedure,
348+ connect.WithSchema(runnerServiceMethods.ByName("UploadSummary")),
349+ connect.WithClientOptions(opts...),
350+ ),
274351 }
275352 }
276353
@@ -283,6 +360,8 @@ type runnerServiceClient struct {
283360 heartbeat *connect.Client[ermite.HeartbeatRequest, ermite.HeartbeatResponse]
284361 watchJob *connect.Client[ermite.WatchJobRequest, ermite.WatchJobResponse]
285362 completeJob *connect.Client[ermite.CompleteJobRequest, ermite.CompleteJobResponse]
363+ resolveActions *connect.Client[ermite.ResolveActionsRequest, ermite.ResolveActionsResponse]
364+ uploadSummary *connect.Client[ermite.UploadSummaryRequest, ermite.UploadSummaryResponse]
286365 }
287366
288367 // RegisterRunner calls ermite.RunnerService.RegisterRunner.
@@ -320,6 +399,16 @@ func (c *runnerServiceClient) CompleteJob(ctx context.Context, req *connect.Requ
320399 return c.completeJob.CallUnary(ctx, req)
321400 }
322401
402+// ResolveActions calls ermite.RunnerService.ResolveActions.
403+func (c *runnerServiceClient) ResolveActions(ctx context.Context, req *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error) {
404+ return c.resolveActions.CallUnary(ctx, req)
405+}
406+
407+// UploadSummary calls ermite.RunnerService.UploadSummary.
408+func (c *runnerServiceClient) UploadSummary(ctx context.Context, req *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error) {
409+ return c.uploadSummary.CallUnary(ctx, req)
410+}
411+
323412 // RunnerServiceHandler is an implementation of the ermite.RunnerService service.
324413 type RunnerServiceHandler interface {
325414 // RegisterRunner registers a runner and returns its runner token, which is
@@ -372,10 +461,21 @@ type RunnerServiceHandler interface {
372461 // identical call changes nothing, so a runner may retry after a network
373462 // error. To end the job use CompleteJob.
374463 //
375- // Fails with invalid_argument if a rule is broken, with failed_precondition
376- // if a step goes back (a COMPLETED step cannot change, a step cannot go from
377- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail
378- // if the job has ended.
464+ // Annotations are applied with the steps, in the same atomic step: for each
465+ // step_number present in annotations, the annotations of that step stored
466+ // so far are replaced by the ones of the request, so a retry never
467+ // duplicates them. A step number absent from the request keeps its
468+ // annotations. The step of an annotation need not be in the steps of the
469+ // same call, and may already be COMPLETED: its annotations can still be
470+ // replaced (the rule that a COMPLETED step cannot change applies to
471+ // StepUpdate, not to annotations), until the job ends. A runner sends one
472+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
473+ // so replacements apply in the order of the calls.
474+ //
475+ // Fails with invalid_argument if a rule is broken (including the annotation
476+ // limits), with failed_precondition if a step goes back (a COMPLETED step
477+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
478+ // failed_precondition and a JobEnded detail if the job has ended.
379479 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)
380480 // AppendLog appends lines to the log of a job. Needs the job token.
381481 //
@@ -480,9 +580,57 @@ type RunnerServiceHandler interface {
480580 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
481581 // they never started and the job did not end by cancellation).
482582 //
483- // Fails with invalid_argument if a rule is broken (including the output
484- // limits) and failed_precondition if a step goes back, as in UpdateJob.
583+ // Annotations are applied as in UpdateJob (replacement per step number, also
584+ // for COMPLETED steps and steps not in steps), together with the conclusion.
585+ // Summaries are not part of this call: a runner sends them with
586+ // UploadSummary before it.
587+ //
588+ // Fails with invalid_argument if a rule is broken (including the output and
589+ // annotation limits) and failed_precondition if a step goes back, as in
590+ // UpdateJob.
485591 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)
592+ // ResolveActions turns the "uses" of workflow and action steps into what the
593+ // runner needs to download the actions, as GitHub's action download info
594+ // does. Needs the job token; the job_id must be the one of the token. It
595+ // may be called as often as needed while the job runs (the runner calls it
596+ // once per level of composite actions, see the runner's depth limit of 9).
597+ // The runner then downloads each archive itself, from the sandbox, with the
598+ // token of the ResolvedAction when there is one.
599+ //
600+ // The response has one ResolvedAction per ActionRef, in the same order. A
601+ // reference that cannot be resolved (unknown repository, tag or branch, a
602+ // repository without access, a "uses" that GitHub itself would reject) does
603+ // not fail the call: its ResolvedAction has only ref and error, where error
604+ // is the message GitHub gives for the same failure, which the runner prints
605+ // as is. Only a failure of the call itself (credential, ended job, bad
606+ // request, server error) is an RPC error; the runner then fails the job.
607+ //
608+ // Resolution is stable for a run attempt: the same ref resolves to the same
609+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
610+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
611+ // job gets its own (ResolvedAction.token).
612+ //
613+ // Fails with unauthenticated or permission_denied as the other job RPCs,
614+ // with failed_precondition and a JobEnded detail if the job has ended, and
615+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
616+ // local action ("./path") or a Docker image ("docker://"), which the runner
617+ // handles without the server.
618+ ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error)
619+ // UploadSummary stores the job summary of one step: the Markdown that the
620+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
621+ // The runner masks it before sending it, and sends it after the step ended
622+ // and before CompleteJob.
623+ //
624+ // It is idempotent: the summary of a step is replaced by each call, so a
625+ // retry changes nothing, and an empty markdown removes the summary of the
626+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
627+ // server reads requests of up to 1 MiB plus the envelope (job id, step
628+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
629+ // their own message size limit above that.
630+ //
631+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
632+ // and with failed_precondition and a JobEnded detail if the job has ended.
633+ UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error)
486634 }
487635
488636 // NewRunnerServiceHandler builds an HTTP handler from the service implementation. It returns the
@@ -534,6 +682,18 @@ func NewRunnerServiceHandler(svc RunnerServiceHandler, opts ...connect.HandlerOp
534682 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),
535683 connect.WithHandlerOptions(opts...),
536684 )
685+ runnerServiceResolveActionsHandler := connect.NewUnaryHandler(
686+ RunnerServiceResolveActionsProcedure,
687+ svc.ResolveActions,
688+ connect.WithSchema(runnerServiceMethods.ByName("ResolveActions")),
689+ connect.WithHandlerOptions(opts...),
690+ )
691+ runnerServiceUploadSummaryHandler := connect.NewUnaryHandler(
692+ RunnerServiceUploadSummaryProcedure,
693+ svc.UploadSummary,
694+ connect.WithSchema(runnerServiceMethods.ByName("UploadSummary")),
695+ connect.WithHandlerOptions(opts...),
696+ )
537697 return "/ermite.RunnerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
538698 switch r.URL.Path {
539699 case RunnerServiceRegisterRunnerProcedure:
@@ -550,6 +710,10 @@ func NewRunnerServiceHandler(svc RunnerServiceHandler, opts ...connect.HandlerOp
550710 runnerServiceWatchJobHandler.ServeHTTP(w, r)
551711 case RunnerServiceCompleteJobProcedure:
552712 runnerServiceCompleteJobHandler.ServeHTTP(w, r)
713+ case RunnerServiceResolveActionsProcedure:
714+ runnerServiceResolveActionsHandler.ServeHTTP(w, r)
715+ case RunnerServiceUploadSummaryProcedure:
716+ runnerServiceUploadSummaryHandler.ServeHTTP(w, r)
553717 default:
554718 http.NotFound(w, r)
555719 }
@@ -586,3 +750,11 @@ func (UnimplementedRunnerServiceHandler) WatchJob(context.Context, *connect.Requ
586750 func (UnimplementedRunnerServiceHandler) CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error) {
587751 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.CompleteJob is not implemented"))
588752 }
753+
754+func (UnimplementedRunnerServiceHandler) ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error) {
755+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.ResolveActions is not implemented"))
756+}
757+
758+func (UnimplementedRunnerServiceHandler) UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error) {
759+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.UploadSummary is not implemented"))
760+}
@@ -51,6 +51,12 @@ const (
51 // RunnerServiceCompleteJobProcedure is the fully-qualified name of the RunnerService's CompleteJob51 // RunnerServiceCompleteJobProcedure is the fully-qualified name of the RunnerService's CompleteJob
52 // RPC.52 // RPC.
53 RunnerServiceCompleteJobProcedure = "/ermite.RunnerService/CompleteJob"53 RunnerServiceCompleteJobProcedure = "/ermite.RunnerService/CompleteJob"
54+ // RunnerServiceResolveActionsProcedure is the fully-qualified name of the RunnerService's
55+ // ResolveActions RPC.
56+ RunnerServiceResolveActionsProcedure = "/ermite.RunnerService/ResolveActions"
57+ // RunnerServiceUploadSummaryProcedure is the fully-qualified name of the RunnerService's
58+ // UploadSummary RPC.
59+ RunnerServiceUploadSummaryProcedure = "/ermite.RunnerService/UploadSummary"
54 )60 )
55 61
56 // RunnerServiceClient is a client for the ermite.RunnerService service.62 // RunnerServiceClient is a client for the ermite.RunnerService service.
@@ -105,10 +111,21 @@ type RunnerServiceClient interface {
105 // identical call changes nothing, so a runner may retry after a network111 // identical call changes nothing, so a runner may retry after a network
106 // error. To end the job use CompleteJob.112 // error. To end the job use CompleteJob.
107 //113 //
108- // Fails with invalid_argument if a rule is broken, with failed_precondition114+ // Annotations are applied with the steps, in the same atomic step: for each
109- // if a step goes back (a COMPLETED step cannot change, a step cannot go from115+ // step_number present in annotations, the annotations of that step stored
110- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail116+ // so far are replaced by the ones of the request, so a retry never
111- // if the job has ended.117+ // duplicates them. A step number absent from the request keeps its
118+ // annotations. The step of an annotation need not be in the steps of the
119+ // same call, and may already be COMPLETED: its annotations can still be
120+ // replaced (the rule that a COMPLETED step cannot change applies to
121+ // StepUpdate, not to annotations), until the job ends. A runner sends one
122+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
123+ // so replacements apply in the order of the calls.
124+ //
125+ // Fails with invalid_argument if a rule is broken (including the annotation
126+ // limits), with failed_precondition if a step goes back (a COMPLETED step
127+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
128+ // failed_precondition and a JobEnded detail if the job has ended.
112 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)129 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)
113 // AppendLog appends lines to the log of a job. Needs the job token.130 // AppendLog appends lines to the log of a job. Needs the job token.
114 //131 //
@@ -213,9 +230,57 @@ type RunnerServiceClient interface {
213 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when230 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
214 // they never started and the job did not end by cancellation).231 // they never started and the job did not end by cancellation).
215 //232 //
216- // Fails with invalid_argument if a rule is broken (including the output233+ // Annotations are applied as in UpdateJob (replacement per step number, also
217- // limits) and failed_precondition if a step goes back, as in UpdateJob.234+ // for COMPLETED steps and steps not in steps), together with the conclusion.
235+ // Summaries are not part of this call: a runner sends them with
236+ // UploadSummary before it.
237+ //
238+ // Fails with invalid_argument if a rule is broken (including the output and
239+ // annotation limits) and failed_precondition if a step goes back, as in
240+ // UpdateJob.
218 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)241 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)
242+ // ResolveActions turns the "uses" of workflow and action steps into what the
243+ // runner needs to download the actions, as GitHub's action download info
244+ // does. Needs the job token; the job_id must be the one of the token. It
245+ // may be called as often as needed while the job runs (the runner calls it
246+ // once per level of composite actions, see the runner's depth limit of 9).
247+ // The runner then downloads each archive itself, from the sandbox, with the
248+ // token of the ResolvedAction when there is one.
249+ //
250+ // The response has one ResolvedAction per ActionRef, in the same order. A
251+ // reference that cannot be resolved (unknown repository, tag or branch, a
252+ // repository without access, a "uses" that GitHub itself would reject) does
253+ // not fail the call: its ResolvedAction has only ref and error, where error
254+ // is the message GitHub gives for the same failure, which the runner prints
255+ // as is. Only a failure of the call itself (credential, ended job, bad
256+ // request, server error) is an RPC error; the runner then fails the job.
257+ //
258+ // Resolution is stable for a run attempt: the same ref resolves to the same
259+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
260+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
261+ // job gets its own (ResolvedAction.token).
262+ //
263+ // Fails with unauthenticated or permission_denied as the other job RPCs,
264+ // with failed_precondition and a JobEnded detail if the job has ended, and
265+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
266+ // local action ("./path") or a Docker image ("docker://"), which the runner
267+ // handles without the server.
268+ ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error)
269+ // UploadSummary stores the job summary of one step: the Markdown that the
270+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
271+ // The runner masks it before sending it, and sends it after the step ended
272+ // and before CompleteJob.
273+ //
274+ // It is idempotent: the summary of a step is replaced by each call, so a
275+ // retry changes nothing, and an empty markdown removes the summary of the
276+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
277+ // server reads requests of up to 1 MiB plus the envelope (job id, step
278+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
279+ // their own message size limit above that.
280+ //
281+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
282+ // and with failed_precondition and a JobEnded detail if the job has ended.
283+ UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error)
219 }284 }
220 285
221 // NewRunnerServiceClient constructs a client for the ermite.RunnerService service. By default, it286 // NewRunnerServiceClient constructs a client for the ermite.RunnerService service. By default, it
@@ -271,6 +336,18 @@ func NewRunnerServiceClient(httpClient connect.HTTPClient, baseURL string, opts
271 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),336 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),
272 connect.WithClientOptions(opts...),337 connect.WithClientOptions(opts...),
273 ),338 ),
339+ resolveActions: connect.NewClient[ermite.ResolveActionsRequest, ermite.ResolveActionsResponse](
340+ httpClient,
341+ baseURL+RunnerServiceResolveActionsProcedure,
342+ connect.WithSchema(runnerServiceMethods.ByName("ResolveActions")),
343+ connect.WithClientOptions(opts...),
344+ ),
345+ uploadSummary: connect.NewClient[ermite.UploadSummaryRequest, ermite.UploadSummaryResponse](
346+ httpClient,
347+ baseURL+RunnerServiceUploadSummaryProcedure,
348+ connect.WithSchema(runnerServiceMethods.ByName("UploadSummary")),
349+ connect.WithClientOptions(opts...),
350+ ),
274 }351 }
275 }352 }
276 353
@@ -283,6 +360,8 @@ type runnerServiceClient struct {
283 heartbeat *connect.Client[ermite.HeartbeatRequest, ermite.HeartbeatResponse]360 heartbeat *connect.Client[ermite.HeartbeatRequest, ermite.HeartbeatResponse]
284 watchJob *connect.Client[ermite.WatchJobRequest, ermite.WatchJobResponse]361 watchJob *connect.Client[ermite.WatchJobRequest, ermite.WatchJobResponse]
285 completeJob *connect.Client[ermite.CompleteJobRequest, ermite.CompleteJobResponse]362 completeJob *connect.Client[ermite.CompleteJobRequest, ermite.CompleteJobResponse]
363+ resolveActions *connect.Client[ermite.ResolveActionsRequest, ermite.ResolveActionsResponse]
364+ uploadSummary *connect.Client[ermite.UploadSummaryRequest, ermite.UploadSummaryResponse]
286 }365 }
287 366
288 // RegisterRunner calls ermite.RunnerService.RegisterRunner.367 // RegisterRunner calls ermite.RunnerService.RegisterRunner.
@@ -320,6 +399,16 @@ func (c *runnerServiceClient) CompleteJob(ctx context.Context, req *connect.Requ
320 return c.completeJob.CallUnary(ctx, req)399 return c.completeJob.CallUnary(ctx, req)
321 }400 }
322 401
402+// ResolveActions calls ermite.RunnerService.ResolveActions.
403+func (c *runnerServiceClient) ResolveActions(ctx context.Context, req *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error) {
404+ return c.resolveActions.CallUnary(ctx, req)
405+}
406+
407+// UploadSummary calls ermite.RunnerService.UploadSummary.
408+func (c *runnerServiceClient) UploadSummary(ctx context.Context, req *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error) {
409+ return c.uploadSummary.CallUnary(ctx, req)
410+}
411+
323 // RunnerServiceHandler is an implementation of the ermite.RunnerService service.412 // RunnerServiceHandler is an implementation of the ermite.RunnerService service.
324 type RunnerServiceHandler interface {413 type RunnerServiceHandler interface {
325 // RegisterRunner registers a runner and returns its runner token, which is414 // RegisterRunner registers a runner and returns its runner token, which is
@@ -372,10 +461,21 @@ type RunnerServiceHandler interface {
372 // identical call changes nothing, so a runner may retry after a network461 // identical call changes nothing, so a runner may retry after a network
373 // error. To end the job use CompleteJob.462 // error. To end the job use CompleteJob.
374 //463 //
375- // Fails with invalid_argument if a rule is broken, with failed_precondition464+ // Annotations are applied with the steps, in the same atomic step: for each
376- // if a step goes back (a COMPLETED step cannot change, a step cannot go from465+ // step_number present in annotations, the annotations of that step stored
377- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail466+ // so far are replaced by the ones of the request, so a retry never
378- // if the job has ended.467+ // duplicates them. A step number absent from the request keeps its
468+ // annotations. The step of an annotation need not be in the steps of the
469+ // same call, and may already be COMPLETED: its annotations can still be
470+ // replaced (the rule that a COMPLETED step cannot change applies to
471+ // StepUpdate, not to annotations), until the job ends. A runner sends one
472+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
473+ // so replacements apply in the order of the calls.
474+ //
475+ // Fails with invalid_argument if a rule is broken (including the annotation
476+ // limits), with failed_precondition if a step goes back (a COMPLETED step
477+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
478+ // failed_precondition and a JobEnded detail if the job has ended.
379 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)479 UpdateJob(context.Context, *connect.Request[ermite.UpdateJobRequest]) (*connect.Response[ermite.UpdateJobResponse], error)
380 // AppendLog appends lines to the log of a job. Needs the job token.480 // AppendLog appends lines to the log of a job. Needs the job token.
381 //481 //
@@ -480,9 +580,57 @@ type RunnerServiceHandler interface {
480 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when580 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
481 // they never started and the job did not end by cancellation).581 // they never started and the job did not end by cancellation).
482 //582 //
483- // Fails with invalid_argument if a rule is broken (including the output583+ // Annotations are applied as in UpdateJob (replacement per step number, also
484- // limits) and failed_precondition if a step goes back, as in UpdateJob.584+ // for COMPLETED steps and steps not in steps), together with the conclusion.
585+ // Summaries are not part of this call: a runner sends them with
586+ // UploadSummary before it.
587+ //
588+ // Fails with invalid_argument if a rule is broken (including the output and
589+ // annotation limits) and failed_precondition if a step goes back, as in
590+ // UpdateJob.
485 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)591 CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error)
592+ // ResolveActions turns the "uses" of workflow and action steps into what the
593+ // runner needs to download the actions, as GitHub's action download info
594+ // does. Needs the job token; the job_id must be the one of the token. It
595+ // may be called as often as needed while the job runs (the runner calls it
596+ // once per level of composite actions, see the runner's depth limit of 9).
597+ // The runner then downloads each archive itself, from the sandbox, with the
598+ // token of the ResolvedAction when there is one.
599+ //
600+ // The response has one ResolvedAction per ActionRef, in the same order. A
601+ // reference that cannot be resolved (unknown repository, tag or branch, a
602+ // repository without access, a "uses" that GitHub itself would reject) does
603+ // not fail the call: its ResolvedAction has only ref and error, where error
604+ // is the message GitHub gives for the same failure, which the runner prints
605+ // as is. Only a failure of the call itself (credential, ended job, bad
606+ // request, server error) is an RPC error; the runner then fails the job.
607+ //
608+ // Resolution is stable for a run attempt: the same ref resolves to the same
609+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
610+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
611+ // job gets its own (ResolvedAction.token).
612+ //
613+ // Fails with unauthenticated or permission_denied as the other job RPCs,
614+ // with failed_precondition and a JobEnded detail if the job has ended, and
615+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
616+ // local action ("./path") or a Docker image ("docker://"), which the runner
617+ // handles without the server.
618+ ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error)
619+ // UploadSummary stores the job summary of one step: the Markdown that the
620+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
621+ // The runner masks it before sending it, and sends it after the step ended
622+ // and before CompleteJob.
623+ //
624+ // It is idempotent: the summary of a step is replaced by each call, so a
625+ // retry changes nothing, and an empty markdown removes the summary of the
626+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
627+ // server reads requests of up to 1 MiB plus the envelope (job id, step
628+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
629+ // their own message size limit above that.
630+ //
631+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
632+ // and with failed_precondition and a JobEnded detail if the job has ended.
633+ UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error)
486 }634 }
487 635
488 // NewRunnerServiceHandler builds an HTTP handler from the service implementation. It returns the636 // NewRunnerServiceHandler builds an HTTP handler from the service implementation. It returns the
@@ -534,6 +682,18 @@ func NewRunnerServiceHandler(svc RunnerServiceHandler, opts ...connect.HandlerOp
534 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),682 connect.WithSchema(runnerServiceMethods.ByName("CompleteJob")),
535 connect.WithHandlerOptions(opts...),683 connect.WithHandlerOptions(opts...),
536 )684 )
685+ runnerServiceResolveActionsHandler := connect.NewUnaryHandler(
686+ RunnerServiceResolveActionsProcedure,
687+ svc.ResolveActions,
688+ connect.WithSchema(runnerServiceMethods.ByName("ResolveActions")),
689+ connect.WithHandlerOptions(opts...),
690+ )
691+ runnerServiceUploadSummaryHandler := connect.NewUnaryHandler(
692+ RunnerServiceUploadSummaryProcedure,
693+ svc.UploadSummary,
694+ connect.WithSchema(runnerServiceMethods.ByName("UploadSummary")),
695+ connect.WithHandlerOptions(opts...),
696+ )
537 return "/ermite.RunnerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {697 return "/ermite.RunnerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
538 switch r.URL.Path {698 switch r.URL.Path {
539 case RunnerServiceRegisterRunnerProcedure:699 case RunnerServiceRegisterRunnerProcedure:
@@ -550,6 +710,10 @@ func NewRunnerServiceHandler(svc RunnerServiceHandler, opts ...connect.HandlerOp
550 runnerServiceWatchJobHandler.ServeHTTP(w, r)710 runnerServiceWatchJobHandler.ServeHTTP(w, r)
551 case RunnerServiceCompleteJobProcedure:711 case RunnerServiceCompleteJobProcedure:
552 runnerServiceCompleteJobHandler.ServeHTTP(w, r)712 runnerServiceCompleteJobHandler.ServeHTTP(w, r)
713+ case RunnerServiceResolveActionsProcedure:
714+ runnerServiceResolveActionsHandler.ServeHTTP(w, r)
715+ case RunnerServiceUploadSummaryProcedure:
716+ runnerServiceUploadSummaryHandler.ServeHTTP(w, r)
553 default:717 default:
554 http.NotFound(w, r)718 http.NotFound(w, r)
555 }719 }
@@ -586,3 +750,11 @@ func (UnimplementedRunnerServiceHandler) WatchJob(context.Context, *connect.Requ
586 func (UnimplementedRunnerServiceHandler) CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error) {750 func (UnimplementedRunnerServiceHandler) CompleteJob(context.Context, *connect.Request[ermite.CompleteJobRequest]) (*connect.Response[ermite.CompleteJobResponse], error) {
587 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.CompleteJob is not implemented"))751 return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.CompleteJob is not implemented"))
588 }752 }
753+
754+func (UnimplementedRunnerServiceHandler) ResolveActions(context.Context, *connect.Request[ermite.ResolveActionsRequest]) (*connect.Response[ermite.ResolveActionsResponse], error) {
755+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.ResolveActions is not implemented"))
756+}
757+
758+func (UnimplementedRunnerServiceHandler) UploadSummary(context.Context, *connect.Request[ermite.UploadSummaryRequest]) (*connect.Response[ermite.UploadSummaryResponse], error) {
759+ return nil, connect.NewError(connect.CodeUnimplemented, errors.New("ermite.RunnerService.UploadSummary is not implemented"))
760+}
M gen/ermite/run.pb.go +550 -132
@@ -521,7 +521,12 @@ type Step struct {
521521 // LogEnd is the number of the line after the last one of the step. For an
522522 // IN_PROGRESS step it is the number of lines held at the time of the
523523 // call and grows; for a step without a line it equals log_start.
524- LogEnd int64 `protobuf:"varint,8,opt,name=log_end,json=logEnd,proto3" json:"log_end,omitempty"`
524+ LogEnd int64 `protobuf:"varint,8,opt,name=log_end,json=logEnd,proto3" json:"log_end,omitempty"`
525+ // Outcome is how the step ended before continue-on-error was applied, as
526+ // StepUpdate.outcome: it differs from conclusion only for a failed step with
527+ // continue-on-error. Unset until state is COMPLETED, and for a step stored
528+ // by a server or runner before this field existed (read it as conclusion).
529+ Outcome CiConclusion `protobuf:"varint,9,opt,name=outcome,proto3,enum=ermite.CiConclusion" json:"outcome,omitempty"`
525530 unknownFields protoimpl.UnknownFields
526531 sizeCache protoimpl.SizeCache
527532 }
@@ -612,6 +617,13 @@ func (x *Step) GetLogEnd() int64 {
612617 return 0
613618 }
614619
620+func (x *Step) GetOutcome() CiConclusion {
621+ if x != nil {
622+ return x.Outcome
623+ }
624+ return CiConclusion_CI_CONCLUSION_UNSPECIFIED
625+}
626+
615627 // Check is the result of one job on one commit, the unit shown next to a
616628 // commit or a merge request and counted by the merge rules. There is one per
617629 // job instance, named like GitHub's checks.
@@ -1288,6 +1300,370 @@ func (x *GetJobResponse) GetJob() *RunJob {
12881300 return nil
12891301 }
12901302
1303+// ListAnnotationsRequest selects the annotations of a run.
1304+type ListAnnotationsRequest struct {
1305+ state protoimpl.MessageState `protogen:"open.v1"`
1306+ // Repo is the repository name.
1307+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1308+ // RunId is the Run.id.
1309+ RunId int64 `protobuf:"varint,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"`
1310+ // Attempt is the attempt to read. 0 means the latest, and then each job
1311+ // contributes the annotations of its own RunJob.attempt (not necessarily the
1312+ // latest attempt of the run, see ListAnnotations).
1313+ Attempt int32 `protobuf:"varint,3,opt,name=attempt,proto3" json:"attempt,omitempty"`
1314+ // JobId restricts the result to one job (RunJob.id). Empty means every job
1315+ // of the run.
1316+ JobId string `protobuf:"bytes,4,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1317+ unknownFields protoimpl.UnknownFields
1318+ sizeCache protoimpl.SizeCache
1319+}
1320+
1321+func (x *ListAnnotationsRequest) Reset() {
1322+ *x = ListAnnotationsRequest{}
1323+ mi := &file_ermite_run_proto_msgTypes[11]
1324+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1325+ ms.StoreMessageInfo(mi)
1326+}
1327+
1328+func (x *ListAnnotationsRequest) String() string {
1329+ return protoimpl.X.MessageStringOf(x)
1330+}
1331+
1332+func (*ListAnnotationsRequest) ProtoMessage() {}
1333+
1334+func (x *ListAnnotationsRequest) ProtoReflect() protoreflect.Message {
1335+ mi := &file_ermite_run_proto_msgTypes[11]
1336+ if x != nil {
1337+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1338+ if ms.LoadMessageInfo() == nil {
1339+ ms.StoreMessageInfo(mi)
1340+ }
1341+ return ms
1342+ }
1343+ return mi.MessageOf(x)
1344+}
1345+
1346+// Deprecated: Use ListAnnotationsRequest.ProtoReflect.Descriptor instead.
1347+func (*ListAnnotationsRequest) Descriptor() ([]byte, []int) {
1348+ return file_ermite_run_proto_rawDescGZIP(), []int{11}
1349+}
1350+
1351+func (x *ListAnnotationsRequest) GetRepo() string {
1352+ if x != nil {
1353+ return x.Repo
1354+ }
1355+ return ""
1356+}
1357+
1358+func (x *ListAnnotationsRequest) GetRunId() int64 {
1359+ if x != nil {
1360+ return x.RunId
1361+ }
1362+ return 0
1363+}
1364+
1365+func (x *ListAnnotationsRequest) GetAttempt() int32 {
1366+ if x != nil {
1367+ return x.Attempt
1368+ }
1369+ return 0
1370+}
1371+
1372+func (x *ListAnnotationsRequest) GetJobId() string {
1373+ if x != nil {
1374+ return x.JobId
1375+ }
1376+ return ""
1377+}
1378+
1379+// ListAnnotationsResponse holds the annotations of a run.
1380+type ListAnnotationsResponse struct {
1381+ state protoimpl.MessageState `protogen:"open.v1"`
1382+ // Annotations are the annotations, at most 1,000.
1383+ Annotations []*JobAnnotation `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"`
1384+ // Truncated is true when there are more annotations than annotations holds.
1385+ Truncated bool `protobuf:"varint,2,opt,name=truncated,proto3" json:"truncated,omitempty"`
1386+ unknownFields protoimpl.UnknownFields
1387+ sizeCache protoimpl.SizeCache
1388+}
1389+
1390+func (x *ListAnnotationsResponse) Reset() {
1391+ *x = ListAnnotationsResponse{}
1392+ mi := &file_ermite_run_proto_msgTypes[12]
1393+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1394+ ms.StoreMessageInfo(mi)
1395+}
1396+
1397+func (x *ListAnnotationsResponse) String() string {
1398+ return protoimpl.X.MessageStringOf(x)
1399+}
1400+
1401+func (*ListAnnotationsResponse) ProtoMessage() {}
1402+
1403+func (x *ListAnnotationsResponse) ProtoReflect() protoreflect.Message {
1404+ mi := &file_ermite_run_proto_msgTypes[12]
1405+ if x != nil {
1406+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1407+ if ms.LoadMessageInfo() == nil {
1408+ ms.StoreMessageInfo(mi)
1409+ }
1410+ return ms
1411+ }
1412+ return mi.MessageOf(x)
1413+}
1414+
1415+// Deprecated: Use ListAnnotationsResponse.ProtoReflect.Descriptor instead.
1416+func (*ListAnnotationsResponse) Descriptor() ([]byte, []int) {
1417+ return file_ermite_run_proto_rawDescGZIP(), []int{12}
1418+}
1419+
1420+func (x *ListAnnotationsResponse) GetAnnotations() []*JobAnnotation {
1421+ if x != nil {
1422+ return x.Annotations
1423+ }
1424+ return nil
1425+}
1426+
1427+func (x *ListAnnotationsResponse) GetTruncated() bool {
1428+ if x != nil {
1429+ return x.Truncated
1430+ }
1431+ return false
1432+}
1433+
1434+// JobAnnotation is an annotation with the job it belongs to.
1435+type JobAnnotation struct {
1436+ state protoimpl.MessageState `protogen:"open.v1"`
1437+ // JobId is the RunJob.id of the job.
1438+ JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1439+ // Annotation is the annotation as the runner sent it, after the server
1440+ // checked it. Its step_number is the step of the job.
1441+ Annotation *Annotation `protobuf:"bytes,2,opt,name=annotation,proto3" json:"annotation,omitempty"`
1442+ unknownFields protoimpl.UnknownFields
1443+ sizeCache protoimpl.SizeCache
1444+}
1445+
1446+func (x *JobAnnotation) Reset() {
1447+ *x = JobAnnotation{}
1448+ mi := &file_ermite_run_proto_msgTypes[13]
1449+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1450+ ms.StoreMessageInfo(mi)
1451+}
1452+
1453+func (x *JobAnnotation) String() string {
1454+ return protoimpl.X.MessageStringOf(x)
1455+}
1456+
1457+func (*JobAnnotation) ProtoMessage() {}
1458+
1459+func (x *JobAnnotation) ProtoReflect() protoreflect.Message {
1460+ mi := &file_ermite_run_proto_msgTypes[13]
1461+ if x != nil {
1462+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1463+ if ms.LoadMessageInfo() == nil {
1464+ ms.StoreMessageInfo(mi)
1465+ }
1466+ return ms
1467+ }
1468+ return mi.MessageOf(x)
1469+}
1470+
1471+// Deprecated: Use JobAnnotation.ProtoReflect.Descriptor instead.
1472+func (*JobAnnotation) Descriptor() ([]byte, []int) {
1473+ return file_ermite_run_proto_rawDescGZIP(), []int{13}
1474+}
1475+
1476+func (x *JobAnnotation) GetJobId() string {
1477+ if x != nil {
1478+ return x.JobId
1479+ }
1480+ return ""
1481+}
1482+
1483+func (x *JobAnnotation) GetAnnotation() *Annotation {
1484+ if x != nil {
1485+ return x.Annotation
1486+ }
1487+ return nil
1488+}
1489+
1490+// GetStepSummariesRequest selects a job.
1491+type GetStepSummariesRequest struct {
1492+ state protoimpl.MessageState `protogen:"open.v1"`
1493+ // Repo is the repository name.
1494+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1495+ // JobId is the RunJob.id.
1496+ JobId string `protobuf:"bytes,2,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1497+ // Attempt is the RunJob.attempt to read. 0 means the latest.
1498+ Attempt int32 `protobuf:"varint,3,opt,name=attempt,proto3" json:"attempt,omitempty"`
1499+ unknownFields protoimpl.UnknownFields
1500+ sizeCache protoimpl.SizeCache
1501+}
1502+
1503+func (x *GetStepSummariesRequest) Reset() {
1504+ *x = GetStepSummariesRequest{}
1505+ mi := &file_ermite_run_proto_msgTypes[14]
1506+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1507+ ms.StoreMessageInfo(mi)
1508+}
1509+
1510+func (x *GetStepSummariesRequest) String() string {
1511+ return protoimpl.X.MessageStringOf(x)
1512+}
1513+
1514+func (*GetStepSummariesRequest) ProtoMessage() {}
1515+
1516+func (x *GetStepSummariesRequest) ProtoReflect() protoreflect.Message {
1517+ mi := &file_ermite_run_proto_msgTypes[14]
1518+ if x != nil {
1519+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1520+ if ms.LoadMessageInfo() == nil {
1521+ ms.StoreMessageInfo(mi)
1522+ }
1523+ return ms
1524+ }
1525+ return mi.MessageOf(x)
1526+}
1527+
1528+// Deprecated: Use GetStepSummariesRequest.ProtoReflect.Descriptor instead.
1529+func (*GetStepSummariesRequest) Descriptor() ([]byte, []int) {
1530+ return file_ermite_run_proto_rawDescGZIP(), []int{14}
1531+}
1532+
1533+func (x *GetStepSummariesRequest) GetRepo() string {
1534+ if x != nil {
1535+ return x.Repo
1536+ }
1537+ return ""
1538+}
1539+
1540+func (x *GetStepSummariesRequest) GetJobId() string {
1541+ if x != nil {
1542+ return x.JobId
1543+ }
1544+ return ""
1545+}
1546+
1547+func (x *GetStepSummariesRequest) GetAttempt() int32 {
1548+ if x != nil {
1549+ return x.Attempt
1550+ }
1551+ return 0
1552+}
1553+
1554+// GetStepSummariesResponse holds the summaries of a job.
1555+type GetStepSummariesResponse struct {
1556+ state protoimpl.MessageState `protogen:"open.v1"`
1557+ // Summaries are the summaries of the steps that have one, ordered by step
1558+ // number: at most 20, the first 20 steps having one.
1559+ Summaries []*StepSummary `protobuf:"bytes,1,rep,name=summaries,proto3" json:"summaries,omitempty"`
1560+ // Truncated is true when the job has more than 20 steps with a summary and
1561+ // summaries holds only the first 20.
1562+ Truncated bool `protobuf:"varint,2,opt,name=truncated,proto3" json:"truncated,omitempty"`
1563+ unknownFields protoimpl.UnknownFields
1564+ sizeCache protoimpl.SizeCache
1565+}
1566+
1567+func (x *GetStepSummariesResponse) Reset() {
1568+ *x = GetStepSummariesResponse{}
1569+ mi := &file_ermite_run_proto_msgTypes[15]
1570+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1571+ ms.StoreMessageInfo(mi)
1572+}
1573+
1574+func (x *GetStepSummariesResponse) String() string {
1575+ return protoimpl.X.MessageStringOf(x)
1576+}
1577+
1578+func (*GetStepSummariesResponse) ProtoMessage() {}
1579+
1580+func (x *GetStepSummariesResponse) ProtoReflect() protoreflect.Message {
1581+ mi := &file_ermite_run_proto_msgTypes[15]
1582+ if x != nil {
1583+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1584+ if ms.LoadMessageInfo() == nil {
1585+ ms.StoreMessageInfo(mi)
1586+ }
1587+ return ms
1588+ }
1589+ return mi.MessageOf(x)
1590+}
1591+
1592+// Deprecated: Use GetStepSummariesResponse.ProtoReflect.Descriptor instead.
1593+func (*GetStepSummariesResponse) Descriptor() ([]byte, []int) {
1594+ return file_ermite_run_proto_rawDescGZIP(), []int{15}
1595+}
1596+
1597+func (x *GetStepSummariesResponse) GetSummaries() []*StepSummary {
1598+ if x != nil {
1599+ return x.Summaries
1600+ }
1601+ return nil
1602+}
1603+
1604+func (x *GetStepSummariesResponse) GetTruncated() bool {
1605+ if x != nil {
1606+ return x.Truncated
1607+ }
1608+ return false
1609+}
1610+
1611+// StepSummary is the job summary of one step.
1612+type StepSummary struct {
1613+ state protoimpl.MessageState `protogen:"open.v1"`
1614+ // StepNumber is the number of the step (see Step.number).
1615+ StepNumber int32 `protobuf:"varint,1,opt,name=step_number,json=stepNumber,proto3" json:"step_number,omitempty"`
1616+ // Markdown is the summary as uploaded, at most 1 MiB. Clients render it
1617+ // safely: it is untrusted content (raw HTML and script URLs must not run).
1618+ Markdown string `protobuf:"bytes,2,opt,name=markdown,proto3" json:"markdown,omitempty"`
1619+ unknownFields protoimpl.UnknownFields
1620+ sizeCache protoimpl.SizeCache
1621+}
1622+
1623+func (x *StepSummary) Reset() {
1624+ *x = StepSummary{}
1625+ mi := &file_ermite_run_proto_msgTypes[16]
1626+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1627+ ms.StoreMessageInfo(mi)
1628+}
1629+
1630+func (x *StepSummary) String() string {
1631+ return protoimpl.X.MessageStringOf(x)
1632+}
1633+
1634+func (*StepSummary) ProtoMessage() {}
1635+
1636+func (x *StepSummary) ProtoReflect() protoreflect.Message {
1637+ mi := &file_ermite_run_proto_msgTypes[16]
1638+ if x != nil {
1639+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1640+ if ms.LoadMessageInfo() == nil {
1641+ ms.StoreMessageInfo(mi)
1642+ }
1643+ return ms
1644+ }
1645+ return mi.MessageOf(x)
1646+}
1647+
1648+// Deprecated: Use StepSummary.ProtoReflect.Descriptor instead.
1649+func (*StepSummary) Descriptor() ([]byte, []int) {
1650+ return file_ermite_run_proto_rawDescGZIP(), []int{16}
1651+}
1652+
1653+func (x *StepSummary) GetStepNumber() int32 {
1654+ if x != nil {
1655+ return x.StepNumber
1656+ }
1657+ return 0
1658+}
1659+
1660+func (x *StepSummary) GetMarkdown() string {
1661+ if x != nil {
1662+ return x.Markdown
1663+ }
1664+ return ""
1665+}
1666+
12911667 // GetJobLogRequest selects the lines to stream.
12921668 type GetJobLogRequest struct {
12931669 state protoimpl.MessageState `protogen:"open.v1"`
@@ -1308,7 +1684,7 @@ type GetJobLogRequest struct {
13081684
13091685 func (x *GetJobLogRequest) Reset() {
13101686 *x = GetJobLogRequest{}
1311- mi := &file_ermite_run_proto_msgTypes[11]
1687+ mi := &file_ermite_run_proto_msgTypes[17]
13121688 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
13131689 ms.StoreMessageInfo(mi)
13141690 }
@@ -1320,7 +1696,7 @@ func (x *GetJobLogRequest) String() string {
13201696 func (*GetJobLogRequest) ProtoMessage() {}
13211697
13221698 func (x *GetJobLogRequest) ProtoReflect() protoreflect.Message {
1323- mi := &file_ermite_run_proto_msgTypes[11]
1699+ mi := &file_ermite_run_proto_msgTypes[17]
13241700 if x != nil {
13251701 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
13261702 if ms.LoadMessageInfo() == nil {
@@ -1333,7 +1709,7 @@ func (x *GetJobLogRequest) ProtoReflect() protoreflect.Message {
13331709
13341710 // Deprecated: Use GetJobLogRequest.ProtoReflect.Descriptor instead.
13351711 func (*GetJobLogRequest) Descriptor() ([]byte, []int) {
1336- return file_ermite_run_proto_rawDescGZIP(), []int{11}
1712+ return file_ermite_run_proto_rawDescGZIP(), []int{17}
13371713 }
13381714
13391715 func (x *GetJobLogRequest) GetRepo() string {
@@ -1385,7 +1761,7 @@ type GetJobLogResponse struct {
13851761
13861762 func (x *GetJobLogResponse) Reset() {
13871763 *x = GetJobLogResponse{}
1388- mi := &file_ermite_run_proto_msgTypes[12]
1764+ mi := &file_ermite_run_proto_msgTypes[18]
13891765 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
13901766 ms.StoreMessageInfo(mi)
13911767 }
@@ -1397,7 +1773,7 @@ func (x *GetJobLogResponse) String() string {
13971773 func (*GetJobLogResponse) ProtoMessage() {}
13981774
13991775 func (x *GetJobLogResponse) ProtoReflect() protoreflect.Message {
1400- mi := &file_ermite_run_proto_msgTypes[12]
1776+ mi := &file_ermite_run_proto_msgTypes[18]
14011777 if x != nil {
14021778 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
14031779 if ms.LoadMessageInfo() == nil {
@@ -1410,7 +1786,7 @@ func (x *GetJobLogResponse) ProtoReflect() protoreflect.Message {
14101786
14111787 // Deprecated: Use GetJobLogResponse.ProtoReflect.Descriptor instead.
14121788 func (*GetJobLogResponse) Descriptor() ([]byte, []int) {
1413- return file_ermite_run_proto_rawDescGZIP(), []int{12}
1789+ return file_ermite_run_proto_rawDescGZIP(), []int{18}
14141790 }
14151791
14161792 func (x *GetJobLogResponse) GetOffset() int64 {
@@ -1449,7 +1825,7 @@ type JobLogLine struct {
14491825
14501826 func (x *JobLogLine) Reset() {
14511827 *x = JobLogLine{}
1452- mi := &file_ermite_run_proto_msgTypes[13]
1828+ mi := &file_ermite_run_proto_msgTypes[19]
14531829 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
14541830 ms.StoreMessageInfo(mi)
14551831 }
@@ -1461,7 +1837,7 @@ func (x *JobLogLine) String() string {
14611837 func (*JobLogLine) ProtoMessage() {}
14621838
14631839 func (x *JobLogLine) ProtoReflect() protoreflect.Message {
1464- mi := &file_ermite_run_proto_msgTypes[13]
1840+ mi := &file_ermite_run_proto_msgTypes[19]
14651841 if x != nil {
14661842 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
14671843 if ms.LoadMessageInfo() == nil {
@@ -1474,7 +1850,7 @@ func (x *JobLogLine) ProtoReflect() protoreflect.Message {
14741850
14751851 // Deprecated: Use JobLogLine.ProtoReflect.Descriptor instead.
14761852 func (*JobLogLine) Descriptor() ([]byte, []int) {
1477- return file_ermite_run_proto_rawDescGZIP(), []int{13}
1853+ return file_ermite_run_proto_rawDescGZIP(), []int{19}
14781854 }
14791855
14801856 func (x *JobLogLine) GetStep() int32 {
@@ -1518,7 +1894,7 @@ type CancelRunRequest struct {
15181894
15191895 func (x *CancelRunRequest) Reset() {
15201896 *x = CancelRunRequest{}
1521- mi := &file_ermite_run_proto_msgTypes[14]
1897+ mi := &file_ermite_run_proto_msgTypes[20]
15221898 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
15231899 ms.StoreMessageInfo(mi)
15241900 }
@@ -1530,7 +1906,7 @@ func (x *CancelRunRequest) String() string {
15301906 func (*CancelRunRequest) ProtoMessage() {}
15311907
15321908 func (x *CancelRunRequest) ProtoReflect() protoreflect.Message {
1533- mi := &file_ermite_run_proto_msgTypes[14]
1909+ mi := &file_ermite_run_proto_msgTypes[20]
15341910 if x != nil {
15351911 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
15361912 if ms.LoadMessageInfo() == nil {
@@ -1543,7 +1919,7 @@ func (x *CancelRunRequest) ProtoReflect() protoreflect.Message {
15431919
15441920 // Deprecated: Use CancelRunRequest.ProtoReflect.Descriptor instead.
15451921 func (*CancelRunRequest) Descriptor() ([]byte, []int) {
1546- return file_ermite_run_proto_rawDescGZIP(), []int{14}
1922+ return file_ermite_run_proto_rawDescGZIP(), []int{20}
15471923 }
15481924
15491925 func (x *CancelRunRequest) GetRepo() string {
@@ -1571,7 +1947,7 @@ type CancelRunResponse struct {
15711947
15721948 func (x *CancelRunResponse) Reset() {
15731949 *x = CancelRunResponse{}
1574- mi := &file_ermite_run_proto_msgTypes[15]
1950+ mi := &file_ermite_run_proto_msgTypes[21]
15751951 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
15761952 ms.StoreMessageInfo(mi)
15771953 }
@@ -1583,7 +1959,7 @@ func (x *CancelRunResponse) String() string {
15831959 func (*CancelRunResponse) ProtoMessage() {}
15841960
15851961 func (x *CancelRunResponse) ProtoReflect() protoreflect.Message {
1586- mi := &file_ermite_run_proto_msgTypes[15]
1962+ mi := &file_ermite_run_proto_msgTypes[21]
15871963 if x != nil {
15881964 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
15891965 if ms.LoadMessageInfo() == nil {
@@ -1596,7 +1972,7 @@ func (x *CancelRunResponse) ProtoReflect() protoreflect.Message {
15961972
15971973 // Deprecated: Use CancelRunResponse.ProtoReflect.Descriptor instead.
15981974 func (*CancelRunResponse) Descriptor() ([]byte, []int) {
1599- return file_ermite_run_proto_rawDescGZIP(), []int{15}
1975+ return file_ermite_run_proto_rawDescGZIP(), []int{21}
16001976 }
16011977
16021978 func (x *CancelRunResponse) GetRun() *Run {
@@ -1625,7 +2001,7 @@ type RerunRunRequest struct {
16252001
16262002 func (x *RerunRunRequest) Reset() {
16272003 *x = RerunRunRequest{}
1628- mi := &file_ermite_run_proto_msgTypes[16]
2004+ mi := &file_ermite_run_proto_msgTypes[22]
16292005 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
16302006 ms.StoreMessageInfo(mi)
16312007 }
@@ -1637,7 +2013,7 @@ func (x *RerunRunRequest) String() string {
16372013 func (*RerunRunRequest) ProtoMessage() {}
16382014
16392015 func (x *RerunRunRequest) ProtoReflect() protoreflect.Message {
1640- mi := &file_ermite_run_proto_msgTypes[16]
2016+ mi := &file_ermite_run_proto_msgTypes[22]
16412017 if x != nil {
16422018 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
16432019 if ms.LoadMessageInfo() == nil {
@@ -1650,7 +2026,7 @@ func (x *RerunRunRequest) ProtoReflect() protoreflect.Message {
16502026
16512027 // Deprecated: Use RerunRunRequest.ProtoReflect.Descriptor instead.
16522028 func (*RerunRunRequest) Descriptor() ([]byte, []int) {
1653- return file_ermite_run_proto_rawDescGZIP(), []int{16}
2029+ return file_ermite_run_proto_rawDescGZIP(), []int{22}
16542030 }
16552031
16562032 func (x *RerunRunRequest) GetRepo() string {
@@ -1685,7 +2061,7 @@ type RerunRunResponse struct {
16852061
16862062 func (x *RerunRunResponse) Reset() {
16872063 *x = RerunRunResponse{}
1688- mi := &file_ermite_run_proto_msgTypes[17]
2064+ mi := &file_ermite_run_proto_msgTypes[23]
16892065 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
16902066 ms.StoreMessageInfo(mi)
16912067 }
@@ -1697,7 +2073,7 @@ func (x *RerunRunResponse) String() string {
16972073 func (*RerunRunResponse) ProtoMessage() {}
16982074
16992075 func (x *RerunRunResponse) ProtoReflect() protoreflect.Message {
1700- mi := &file_ermite_run_proto_msgTypes[17]
2076+ mi := &file_ermite_run_proto_msgTypes[23]
17012077 if x != nil {
17022078 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
17032079 if ms.LoadMessageInfo() == nil {
@@ -1710,7 +2086,7 @@ func (x *RerunRunResponse) ProtoReflect() protoreflect.Message {
17102086
17112087 // Deprecated: Use RerunRunResponse.ProtoReflect.Descriptor instead.
17122088 func (*RerunRunResponse) Descriptor() ([]byte, []int) {
1713- return file_ermite_run_proto_rawDescGZIP(), []int{17}
2089+ return file_ermite_run_proto_rawDescGZIP(), []int{23}
17142090 }
17152091
17162092 func (x *RerunRunResponse) GetRun() *Run {
@@ -1734,7 +2110,7 @@ type ListChecksRequest struct {
17342110
17352111 func (x *ListChecksRequest) Reset() {
17362112 *x = ListChecksRequest{}
1737- mi := &file_ermite_run_proto_msgTypes[18]
2113+ mi := &file_ermite_run_proto_msgTypes[24]
17382114 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
17392115 ms.StoreMessageInfo(mi)
17402116 }
@@ -1746,7 +2122,7 @@ func (x *ListChecksRequest) String() string {
17462122 func (*ListChecksRequest) ProtoMessage() {}
17472123
17482124 func (x *ListChecksRequest) ProtoReflect() protoreflect.Message {
1749- mi := &file_ermite_run_proto_msgTypes[18]
2125+ mi := &file_ermite_run_proto_msgTypes[24]
17502126 if x != nil {
17512127 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
17522128 if ms.LoadMessageInfo() == nil {
@@ -1759,7 +2135,7 @@ func (x *ListChecksRequest) ProtoReflect() protoreflect.Message {
17592135
17602136 // Deprecated: Use ListChecksRequest.ProtoReflect.Descriptor instead.
17612137 func (*ListChecksRequest) Descriptor() ([]byte, []int) {
1762- return file_ermite_run_proto_rawDescGZIP(), []int{18}
2138+ return file_ermite_run_proto_rawDescGZIP(), []int{24}
17632139 }
17642140
17652141 func (x *ListChecksRequest) GetRepo() string {
@@ -1790,7 +2166,7 @@ type ListChecksResponse struct {
17902166
17912167 func (x *ListChecksResponse) Reset() {
17922168 *x = ListChecksResponse{}
1793- mi := &file_ermite_run_proto_msgTypes[19]
2169+ mi := &file_ermite_run_proto_msgTypes[25]
17942170 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
17952171 ms.StoreMessageInfo(mi)
17962172 }
@@ -1802,7 +2178,7 @@ func (x *ListChecksResponse) String() string {
18022178 func (*ListChecksResponse) ProtoMessage() {}
18032179
18042180 func (x *ListChecksResponse) ProtoReflect() protoreflect.Message {
1805- mi := &file_ermite_run_proto_msgTypes[19]
2181+ mi := &file_ermite_run_proto_msgTypes[25]
18062182 if x != nil {
18072183 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
18082184 if ms.LoadMessageInfo() == nil {
@@ -1815,7 +2191,7 @@ func (x *ListChecksResponse) ProtoReflect() protoreflect.Message {
18152191
18162192 // Deprecated: Use ListChecksResponse.ProtoReflect.Descriptor instead.
18172193 func (*ListChecksResponse) Descriptor() ([]byte, []int) {
1818- return file_ermite_run_proto_rawDescGZIP(), []int{19}
2194+ return file_ermite_run_proto_rawDescGZIP(), []int{25}
18192195 }
18202196
18212197 func (x *ListChecksResponse) GetChecks() []*Check {
@@ -1846,7 +2222,7 @@ type ListRunnersRequest struct {
18462222
18472223 func (x *ListRunnersRequest) Reset() {
18482224 *x = ListRunnersRequest{}
1849- mi := &file_ermite_run_proto_msgTypes[20]
2225+ mi := &file_ermite_run_proto_msgTypes[26]
18502226 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
18512227 ms.StoreMessageInfo(mi)
18522228 }
@@ -1858,7 +2234,7 @@ func (x *ListRunnersRequest) String() string {
18582234 func (*ListRunnersRequest) ProtoMessage() {}
18592235
18602236 func (x *ListRunnersRequest) ProtoReflect() protoreflect.Message {
1861- mi := &file_ermite_run_proto_msgTypes[20]
2237+ mi := &file_ermite_run_proto_msgTypes[26]
18622238 if x != nil {
18632239 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
18642240 if ms.LoadMessageInfo() == nil {
@@ -1871,7 +2247,7 @@ func (x *ListRunnersRequest) ProtoReflect() protoreflect.Message {
18712247
18722248 // Deprecated: Use ListRunnersRequest.ProtoReflect.Descriptor instead.
18732249 func (*ListRunnersRequest) Descriptor() ([]byte, []int) {
1874- return file_ermite_run_proto_rawDescGZIP(), []int{20}
2250+ return file_ermite_run_proto_rawDescGZIP(), []int{26}
18752251 }
18762252
18772253 func (x *ListRunnersRequest) GetPageSize() int32 {
@@ -1902,7 +2278,7 @@ type ListRunnersResponse struct {
19022278
19032279 func (x *ListRunnersResponse) Reset() {
19042280 *x = ListRunnersResponse{}
1905- mi := &file_ermite_run_proto_msgTypes[21]
2281+ mi := &file_ermite_run_proto_msgTypes[27]
19062282 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
19072283 ms.StoreMessageInfo(mi)
19082284 }
@@ -1914,7 +2290,7 @@ func (x *ListRunnersResponse) String() string {
19142290 func (*ListRunnersResponse) ProtoMessage() {}
19152291
19162292 func (x *ListRunnersResponse) ProtoReflect() protoreflect.Message {
1917- mi := &file_ermite_run_proto_msgTypes[21]
2293+ mi := &file_ermite_run_proto_msgTypes[27]
19182294 if x != nil {
19192295 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
19202296 if ms.LoadMessageInfo() == nil {
@@ -1927,7 +2303,7 @@ func (x *ListRunnersResponse) ProtoReflect() protoreflect.Message {
19272303
19282304 // Deprecated: Use ListRunnersResponse.ProtoReflect.Descriptor instead.
19292305 func (*ListRunnersResponse) Descriptor() ([]byte, []int) {
1930- return file_ermite_run_proto_rawDescGZIP(), []int{21}
2306+ return file_ermite_run_proto_rawDescGZIP(), []int{27}
19312307 }
19322308
19332309 func (x *ListRunnersResponse) GetRunners() []*Runner {
@@ -1955,7 +2331,7 @@ type RemoveRunnerRequest struct {
19552331
19562332 func (x *RemoveRunnerRequest) Reset() {
19572333 *x = RemoveRunnerRequest{}
1958- mi := &file_ermite_run_proto_msgTypes[22]
2334+ mi := &file_ermite_run_proto_msgTypes[28]
19592335 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
19602336 ms.StoreMessageInfo(mi)
19612337 }
@@ -1967,7 +2343,7 @@ func (x *RemoveRunnerRequest) String() string {
19672343 func (*RemoveRunnerRequest) ProtoMessage() {}
19682344
19692345 func (x *RemoveRunnerRequest) ProtoReflect() protoreflect.Message {
1970- mi := &file_ermite_run_proto_msgTypes[22]
2346+ mi := &file_ermite_run_proto_msgTypes[28]
19712347 if x != nil {
19722348 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
19732349 if ms.LoadMessageInfo() == nil {
@@ -1980,7 +2356,7 @@ func (x *RemoveRunnerRequest) ProtoReflect() protoreflect.Message {
19802356
19812357 // Deprecated: Use RemoveRunnerRequest.ProtoReflect.Descriptor instead.
19822358 func (*RemoveRunnerRequest) Descriptor() ([]byte, []int) {
1983- return file_ermite_run_proto_rawDescGZIP(), []int{22}
2359+ return file_ermite_run_proto_rawDescGZIP(), []int{28}
19842360 }
19852361
19862362 func (x *RemoveRunnerRequest) GetRunnerId() string {
@@ -1999,7 +2375,7 @@ type RemoveRunnerResponse struct {
19992375
20002376 func (x *RemoveRunnerResponse) Reset() {
20012377 *x = RemoveRunnerResponse{}
2002- mi := &file_ermite_run_proto_msgTypes[23]
2378+ mi := &file_ermite_run_proto_msgTypes[29]
20032379 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
20042380 ms.StoreMessageInfo(mi)
20052381 }
@@ -2011,7 +2387,7 @@ func (x *RemoveRunnerResponse) String() string {
20112387 func (*RemoveRunnerResponse) ProtoMessage() {}
20122388
20132389 func (x *RemoveRunnerResponse) ProtoReflect() protoreflect.Message {
2014- mi := &file_ermite_run_proto_msgTypes[23]
2390+ mi := &file_ermite_run_proto_msgTypes[29]
20152391 if x != nil {
20162392 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
20172393 if ms.LoadMessageInfo() == nil {
@@ -2024,7 +2400,7 @@ func (x *RemoveRunnerResponse) ProtoReflect() protoreflect.Message {
20242400
20252401 // Deprecated: Use RemoveRunnerResponse.ProtoReflect.Descriptor instead.
20262402 func (*RemoveRunnerResponse) Descriptor() ([]byte, []int) {
2027- return file_ermite_run_proto_rawDescGZIP(), []int{23}
2403+ return file_ermite_run_proto_rawDescGZIP(), []int{29}
20282404 }
20292405
20302406 var File_ermite_run_proto protoreflect.FileDescriptor
@@ -2082,7 +2458,7 @@ const file_ermite_run_proto_rawDesc = "" +
20822458 "\n" +
20832459 "started_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
20842460 "\fcompleted_at\x18\x12 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x18\n" +
2085- "\aversion\x18\x13 \x01(\x03R\aversion\"\xc1\x02\n" +
2461+ "\aversion\x18\x13 \x01(\x03R\aversion\"\xf1\x02\n" +
20862462 "\x04Step\x12\x16\n" +
20872463 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
20882464 "\x04name\x18\x02 \x01(\tR\x04name\x12'\n" +
@@ -2094,7 +2470,8 @@ const file_ermite_run_proto_rawDesc = "" +
20942470 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
20952471 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +
20962472 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x17\n" +
2097- "\alog_end\x18\b \x01(\x03R\x06logEnd\"\x98\x03\n" +
2473+ "\alog_end\x18\b \x01(\x03R\x06logEnd\x12.\n" +
2474+ "\aoutcome\x18\t \x01(\x0e2\x14.ermite.CiConclusionR\aoutcome\"\x98\x03\n" +
20982475 "\x05Check\x12\x0e\n" +
20992476 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
21002477 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +
@@ -2148,7 +2525,31 @@ const file_ermite_run_proto_rawDesc = "" +
21482525 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
21492526 "\aattempt\x18\x03 \x01(\x05R\aattempt\"2\n" +
21502527 "\x0eGetJobResponse\x12 \n" +
2151- "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"\x87\x01\n" +
2528+ "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"t\n" +
2529+ "\x16ListAnnotationsRequest\x12\x12\n" +
2530+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
2531+ "\x06run_id\x18\x02 \x01(\x03R\x05runId\x12\x18\n" +
2532+ "\aattempt\x18\x03 \x01(\x05R\aattempt\x12\x15\n" +
2533+ "\x06job_id\x18\x04 \x01(\tR\x05jobId\"p\n" +
2534+ "\x17ListAnnotationsResponse\x127\n" +
2535+ "\vannotations\x18\x01 \x03(\v2\x15.ermite.JobAnnotationR\vannotations\x12\x1c\n" +
2536+ "\ttruncated\x18\x02 \x01(\bR\ttruncated\"Z\n" +
2537+ "\rJobAnnotation\x12\x15\n" +
2538+ "\x06job_id\x18\x01 \x01(\tR\x05jobId\x122\n" +
2539+ "\n" +
2540+ "annotation\x18\x02 \x01(\v2\x12.ermite.AnnotationR\n" +
2541+ "annotation\"^\n" +
2542+ "\x17GetStepSummariesRequest\x12\x12\n" +
2543+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
2544+ "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
2545+ "\aattempt\x18\x03 \x01(\x05R\aattempt\"k\n" +
2546+ "\x18GetStepSummariesResponse\x121\n" +
2547+ "\tsummaries\x18\x01 \x03(\v2\x13.ermite.StepSummaryR\tsummaries\x12\x1c\n" +
2548+ "\ttruncated\x18\x02 \x01(\bR\ttruncated\"J\n" +
2549+ "\vStepSummary\x12\x1f\n" +
2550+ "\vstep_number\x18\x01 \x01(\x05R\n" +
2551+ "stepNumber\x12\x1a\n" +
2552+ "\bmarkdown\x18\x02 \x01(\tR\bmarkdown\"\x87\x01\n" +
21522553 "\x10GetJobLogRequest\x12\x12\n" +
21532554 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
21542555 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
@@ -2191,12 +2592,14 @@ const file_ermite_run_proto_rawDesc = "" +
21912592 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"2\n" +
21922593 "\x13RemoveRunnerRequest\x12\x1b\n" +
21932594 "\trunner_id\x18\x01 \x01(\tR\brunnerId\"\x16\n" +
2194- "\x14RemoveRunnerResponse2\xda\x04\n" +
2595+ "\x14RemoveRunnerResponse2\x85\x06\n" +
21952596 "\n" +
21962597 "RunService\x12=\n" +
21972598 "\bListRuns\x12\x17.ermite.ListRunsRequest\x1a\x18.ermite.ListRunsResponse\x127\n" +
21982599 "\x06GetRun\x12\x15.ermite.GetRunRequest\x1a\x16.ermite.GetRunResponse\x127\n" +
2199- "\x06GetJob\x12\x15.ermite.GetJobRequest\x1a\x16.ermite.GetJobResponse\x12B\n" +
2600+ "\x06GetJob\x12\x15.ermite.GetJobRequest\x1a\x16.ermite.GetJobResponse\x12R\n" +
2601+ "\x0fListAnnotations\x12\x1e.ermite.ListAnnotationsRequest\x1a\x1f.ermite.ListAnnotationsResponse\x12U\n" +
2602+ "\x10GetStepSummaries\x12\x1f.ermite.GetStepSummariesRequest\x1a .ermite.GetStepSummariesResponse\x12B\n" +
22002603 "\tGetJobLog\x12\x18.ermite.GetJobLogRequest\x1a\x19.ermite.GetJobLogResponse0\x01\x12@\n" +
22012604 "\tCancelRun\x12\x18.ermite.CancelRunRequest\x1a\x19.ermite.CancelRunResponse\x12=\n" +
22022605 "\bRerunRun\x12\x17.ermite.RerunRunRequest\x1a\x18.ermite.RerunRunResponse\x12C\n" +
@@ -2219,96 +2622,111 @@ func file_ermite_run_proto_rawDescGZIP() []byte {
22192622 return file_ermite_run_proto_rawDescData
22202623 }
22212624
2222-var file_ermite_run_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
2625+var file_ermite_run_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
22232626 var file_ermite_run_proto_goTypes = []any{
2224- (*Run)(nil), // 0: ermite.Run
2225- (*RunJob)(nil), // 1: ermite.RunJob
2226- (*Step)(nil), // 2: ermite.Step
2227- (*Check)(nil), // 3: ermite.Check
2228- (*Runner)(nil), // 4: ermite.Runner
2229- (*ListRunsRequest)(nil), // 5: ermite.ListRunsRequest
2230- (*ListRunsResponse)(nil), // 6: ermite.ListRunsResponse
2231- (*GetRunRequest)(nil), // 7: ermite.GetRunRequest
2232- (*GetRunResponse)(nil), // 8: ermite.GetRunResponse
2233- (*GetJobRequest)(nil), // 9: ermite.GetJobRequest
2234- (*GetJobResponse)(nil), // 10: ermite.GetJobResponse
2235- (*GetJobLogRequest)(nil), // 11: ermite.GetJobLogRequest
2236- (*GetJobLogResponse)(nil), // 12: ermite.GetJobLogResponse
2237- (*JobLogLine)(nil), // 13: ermite.JobLogLine
2238- (*CancelRunRequest)(nil), // 14: ermite.CancelRunRequest
2239- (*CancelRunResponse)(nil), // 15: ermite.CancelRunResponse
2240- (*RerunRunRequest)(nil), // 16: ermite.RerunRunRequest
2241- (*RerunRunResponse)(nil), // 17: ermite.RerunRunResponse
2242- (*ListChecksRequest)(nil), // 18: ermite.ListChecksRequest
2243- (*ListChecksResponse)(nil), // 19: ermite.ListChecksResponse
2244- (*ListRunnersRequest)(nil), // 20: ermite.ListRunnersRequest
2245- (*ListRunnersResponse)(nil), // 21: ermite.ListRunnersResponse
2246- (*RemoveRunnerRequest)(nil), // 22: ermite.RemoveRunnerRequest
2247- (*RemoveRunnerResponse)(nil), // 23: ermite.RemoveRunnerResponse
2248- (CiStatus)(0), // 24: ermite.CiStatus
2249- (CiConclusion)(0), // 25: ermite.CiConclusion
2250- (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp
2251- (RunnerIsolation)(0), // 27: ermite.RunnerIsolation
2252- (StepState)(0), // 28: ermite.StepState
2627+ (*Run)(nil), // 0: ermite.Run
2628+ (*RunJob)(nil), // 1: ermite.RunJob
2629+ (*Step)(nil), // 2: ermite.Step
2630+ (*Check)(nil), // 3: ermite.Check
2631+ (*Runner)(nil), // 4: ermite.Runner
2632+ (*ListRunsRequest)(nil), // 5: ermite.ListRunsRequest
2633+ (*ListRunsResponse)(nil), // 6: ermite.ListRunsResponse
2634+ (*GetRunRequest)(nil), // 7: ermite.GetRunRequest
2635+ (*GetRunResponse)(nil), // 8: ermite.GetRunResponse
2636+ (*GetJobRequest)(nil), // 9: ermite.GetJobRequest
2637+ (*GetJobResponse)(nil), // 10: ermite.GetJobResponse
2638+ (*ListAnnotationsRequest)(nil), // 11: ermite.ListAnnotationsRequest
2639+ (*ListAnnotationsResponse)(nil), // 12: ermite.ListAnnotationsResponse
2640+ (*JobAnnotation)(nil), // 13: ermite.JobAnnotation
2641+ (*GetStepSummariesRequest)(nil), // 14: ermite.GetStepSummariesRequest
2642+ (*GetStepSummariesResponse)(nil), // 15: ermite.GetStepSummariesResponse
2643+ (*StepSummary)(nil), // 16: ermite.StepSummary
2644+ (*GetJobLogRequest)(nil), // 17: ermite.GetJobLogRequest
2645+ (*GetJobLogResponse)(nil), // 18: ermite.GetJobLogResponse
2646+ (*JobLogLine)(nil), // 19: ermite.JobLogLine
2647+ (*CancelRunRequest)(nil), // 20: ermite.CancelRunRequest
2648+ (*CancelRunResponse)(nil), // 21: ermite.CancelRunResponse
2649+ (*RerunRunRequest)(nil), // 22: ermite.RerunRunRequest
2650+ (*RerunRunResponse)(nil), // 23: ermite.RerunRunResponse
2651+ (*ListChecksRequest)(nil), // 24: ermite.ListChecksRequest
2652+ (*ListChecksResponse)(nil), // 25: ermite.ListChecksResponse
2653+ (*ListRunnersRequest)(nil), // 26: ermite.ListRunnersRequest
2654+ (*ListRunnersResponse)(nil), // 27: ermite.ListRunnersResponse
2655+ (*RemoveRunnerRequest)(nil), // 28: ermite.RemoveRunnerRequest
2656+ (*RemoveRunnerResponse)(nil), // 29: ermite.RemoveRunnerResponse
2657+ (CiStatus)(0), // 30: ermite.CiStatus
2658+ (CiConclusion)(0), // 31: ermite.CiConclusion
2659+ (*timestamppb.Timestamp)(nil), // 32: google.protobuf.Timestamp
2660+ (RunnerIsolation)(0), // 33: ermite.RunnerIsolation
2661+ (StepState)(0), // 34: ermite.StepState
2662+ (*Annotation)(nil), // 35: ermite.Annotation
22532663 }
22542664 var file_ermite_run_proto_depIdxs = []int32{
2255- 24, // 0: ermite.Run.status:type_name -> ermite.CiStatus
2256- 25, // 1: ermite.Run.conclusion:type_name -> ermite.CiConclusion
2257- 26, // 2: ermite.Run.created_at:type_name -> google.protobuf.Timestamp
2258- 26, // 3: ermite.Run.started_at:type_name -> google.protobuf.Timestamp
2259- 26, // 4: ermite.Run.completed_at:type_name -> google.protobuf.Timestamp
2260- 24, // 5: ermite.RunJob.status:type_name -> ermite.CiStatus
2261- 25, // 6: ermite.RunJob.conclusion:type_name -> ermite.CiConclusion
2262- 27, // 7: ermite.RunJob.isolation:type_name -> ermite.RunnerIsolation
2665+ 30, // 0: ermite.Run.status:type_name -> ermite.CiStatus
2666+ 31, // 1: ermite.Run.conclusion:type_name -> ermite.CiConclusion
2667+ 32, // 2: ermite.Run.created_at:type_name -> google.protobuf.Timestamp
2668+ 32, // 3: ermite.Run.started_at:type_name -> google.protobuf.Timestamp
2669+ 32, // 4: ermite.Run.completed_at:type_name -> google.protobuf.Timestamp
2670+ 30, // 5: ermite.RunJob.status:type_name -> ermite.CiStatus
2671+ 31, // 6: ermite.RunJob.conclusion:type_name -> ermite.CiConclusion
2672+ 33, // 7: ermite.RunJob.isolation:type_name -> ermite.RunnerIsolation
22632673 2, // 8: ermite.RunJob.steps:type_name -> ermite.Step
2264- 26, // 9: ermite.RunJob.created_at:type_name -> google.protobuf.Timestamp
2265- 26, // 10: ermite.RunJob.started_at:type_name -> google.protobuf.Timestamp
2266- 26, // 11: ermite.RunJob.completed_at:type_name -> google.protobuf.Timestamp
2267- 28, // 12: ermite.Step.state:type_name -> ermite.StepState
2268- 25, // 13: ermite.Step.conclusion:type_name -> ermite.CiConclusion
2269- 26, // 14: ermite.Step.started_at:type_name -> google.protobuf.Timestamp
2270- 26, // 15: ermite.Step.completed_at:type_name -> google.protobuf.Timestamp
2271- 24, // 16: ermite.Check.status:type_name -> ermite.CiStatus
2272- 25, // 17: ermite.Check.conclusion:type_name -> ermite.CiConclusion
2273- 26, // 18: ermite.Check.started_at:type_name -> google.protobuf.Timestamp
2274- 26, // 19: ermite.Check.completed_at:type_name -> google.protobuf.Timestamp
2275- 27, // 20: ermite.Runner.isolation:type_name -> ermite.RunnerIsolation
2276- 26, // 21: ermite.Runner.registered_at:type_name -> google.protobuf.Timestamp
2277- 26, // 22: ermite.Runner.last_seen:type_name -> google.protobuf.Timestamp
2278- 24, // 23: ermite.ListRunsRequest.status:type_name -> ermite.CiStatus
2279- 0, // 24: ermite.ListRunsResponse.runs:type_name -> ermite.Run
2280- 0, // 25: ermite.GetRunResponse.run:type_name -> ermite.Run
2281- 1, // 26: ermite.GetRunResponse.jobs:type_name -> ermite.RunJob
2282- 1, // 27: ermite.GetJobResponse.job:type_name -> ermite.RunJob
2283- 13, // 28: ermite.GetJobLogResponse.lines:type_name -> ermite.JobLogLine
2284- 26, // 29: ermite.JobLogLine.time:type_name -> google.protobuf.Timestamp
2285- 0, // 30: ermite.CancelRunResponse.run:type_name -> ermite.Run
2286- 0, // 31: ermite.RerunRunResponse.run:type_name -> ermite.Run
2287- 3, // 32: ermite.ListChecksResponse.checks:type_name -> ermite.Check
2288- 4, // 33: ermite.ListRunnersResponse.runners:type_name -> ermite.Runner
2289- 5, // 34: ermite.RunService.ListRuns:input_type -> ermite.ListRunsRequest
2290- 7, // 35: ermite.RunService.GetRun:input_type -> ermite.GetRunRequest
2291- 9, // 36: ermite.RunService.GetJob:input_type -> ermite.GetJobRequest
2292- 11, // 37: ermite.RunService.GetJobLog:input_type -> ermite.GetJobLogRequest
2293- 14, // 38: ermite.RunService.CancelRun:input_type -> ermite.CancelRunRequest
2294- 16, // 39: ermite.RunService.RerunRun:input_type -> ermite.RerunRunRequest
2295- 18, // 40: ermite.RunService.ListChecks:input_type -> ermite.ListChecksRequest
2296- 20, // 41: ermite.RunService.ListRunners:input_type -> ermite.ListRunnersRequest
2297- 22, // 42: ermite.RunService.RemoveRunner:input_type -> ermite.RemoveRunnerRequest
2298- 6, // 43: ermite.RunService.ListRuns:output_type -> ermite.ListRunsResponse
2299- 8, // 44: ermite.RunService.GetRun:output_type -> ermite.GetRunResponse
2300- 10, // 45: ermite.RunService.GetJob:output_type -> ermite.GetJobResponse
2301- 12, // 46: ermite.RunService.GetJobLog:output_type -> ermite.GetJobLogResponse
2302- 15, // 47: ermite.RunService.CancelRun:output_type -> ermite.CancelRunResponse
2303- 17, // 48: ermite.RunService.RerunRun:output_type -> ermite.RerunRunResponse
2304- 19, // 49: ermite.RunService.ListChecks:output_type -> ermite.ListChecksResponse
2305- 21, // 50: ermite.RunService.ListRunners:output_type -> ermite.ListRunnersResponse
2306- 23, // 51: ermite.RunService.RemoveRunner:output_type -> ermite.RemoveRunnerResponse
2307- 43, // [43:52] is the sub-list for method output_type
2308- 34, // [34:43] is the sub-list for method input_type
2309- 34, // [34:34] is the sub-list for extension type_name
2310- 34, // [34:34] is the sub-list for extension extendee
2311- 0, // [0:34] is the sub-list for field type_name
2674+ 32, // 9: ermite.RunJob.created_at:type_name -> google.protobuf.Timestamp
2675+ 32, // 10: ermite.RunJob.started_at:type_name -> google.protobuf.Timestamp
2676+ 32, // 11: ermite.RunJob.completed_at:type_name -> google.protobuf.Timestamp
2677+ 34, // 12: ermite.Step.state:type_name -> ermite.StepState
2678+ 31, // 13: ermite.Step.conclusion:type_name -> ermite.CiConclusion
2679+ 32, // 14: ermite.Step.started_at:type_name -> google.protobuf.Timestamp
2680+ 32, // 15: ermite.Step.completed_at:type_name -> google.protobuf.Timestamp
2681+ 31, // 16: ermite.Step.outcome:type_name -> ermite.CiConclusion
2682+ 30, // 17: ermite.Check.status:type_name -> ermite.CiStatus
2683+ 31, // 18: ermite.Check.conclusion:type_name -> ermite.CiConclusion
2684+ 32, // 19: ermite.Check.started_at:type_name -> google.protobuf.Timestamp
2685+ 32, // 20: ermite.Check.completed_at:type_name -> google.protobuf.Timestamp
2686+ 33, // 21: ermite.Runner.isolation:type_name -> ermite.RunnerIsolation
2687+ 32, // 22: ermite.Runner.registered_at:type_name -> google.protobuf.Timestamp
2688+ 32, // 23: ermite.Runner.last_seen:type_name -> google.protobuf.Timestamp
2689+ 30, // 24: ermite.ListRunsRequest.status:type_name -> ermite.CiStatus
2690+ 0, // 25: ermite.ListRunsResponse.runs:type_name -> ermite.Run
2691+ 0, // 26: ermite.GetRunResponse.run:type_name -> ermite.Run
2692+ 1, // 27: ermite.GetRunResponse.jobs:type_name -> ermite.RunJob
2693+ 1, // 28: ermite.GetJobResponse.job:type_name -> ermite.RunJob
2694+ 13, // 29: ermite.ListAnnotationsResponse.annotations:type_name -> ermite.JobAnnotation
2695+ 35, // 30: ermite.JobAnnotation.annotation:type_name -> ermite.Annotation
2696+ 16, // 31: ermite.GetStepSummariesResponse.summaries:type_name -> ermite.StepSummary
2697+ 19, // 32: ermite.GetJobLogResponse.lines:type_name -> ermite.JobLogLine
2698+ 32, // 33: ermite.JobLogLine.time:type_name -> google.protobuf.Timestamp
2699+ 0, // 34: ermite.CancelRunResponse.run:type_name -> ermite.Run
2700+ 0, // 35: ermite.RerunRunResponse.run:type_name -> ermite.Run
2701+ 3, // 36: ermite.ListChecksResponse.checks:type_name -> ermite.Check
2702+ 4, // 37: ermite.ListRunnersResponse.runners:type_name -> ermite.Runner
2703+ 5, // 38: ermite.RunService.ListRuns:input_type -> ermite.ListRunsRequest
2704+ 7, // 39: ermite.RunService.GetRun:input_type -> ermite.GetRunRequest
2705+ 9, // 40: ermite.RunService.GetJob:input_type -> ermite.GetJobRequest
2706+ 11, // 41: ermite.RunService.ListAnnotations:input_type -> ermite.ListAnnotationsRequest
2707+ 14, // 42: ermite.RunService.GetStepSummaries:input_type -> ermite.GetStepSummariesRequest
2708+ 17, // 43: ermite.RunService.GetJobLog:input_type -> ermite.GetJobLogRequest
2709+ 20, // 44: ermite.RunService.CancelRun:input_type -> ermite.CancelRunRequest
2710+ 22, // 45: ermite.RunService.RerunRun:input_type -> ermite.RerunRunRequest
2711+ 24, // 46: ermite.RunService.ListChecks:input_type -> ermite.ListChecksRequest
2712+ 26, // 47: ermite.RunService.ListRunners:input_type -> ermite.ListRunnersRequest
2713+ 28, // 48: ermite.RunService.RemoveRunner:input_type -> ermite.RemoveRunnerRequest
2714+ 6, // 49: ermite.RunService.ListRuns:output_type -> ermite.ListRunsResponse
2715+ 8, // 50: ermite.RunService.GetRun:output_type -> ermite.GetRunResponse
2716+ 10, // 51: ermite.RunService.GetJob:output_type -> ermite.GetJobResponse
2717+ 12, // 52: ermite.RunService.ListAnnotations:output_type -> ermite.ListAnnotationsResponse
2718+ 15, // 53: ermite.RunService.GetStepSummaries:output_type -> ermite.GetStepSummariesResponse
2719+ 18, // 54: ermite.RunService.GetJobLog:output_type -> ermite.GetJobLogResponse
2720+ 21, // 55: ermite.RunService.CancelRun:output_type -> ermite.CancelRunResponse
2721+ 23, // 56: ermite.RunService.RerunRun:output_type -> ermite.RerunRunResponse
2722+ 25, // 57: ermite.RunService.ListChecks:output_type -> ermite.ListChecksResponse
2723+ 27, // 58: ermite.RunService.ListRunners:output_type -> ermite.ListRunnersResponse
2724+ 29, // 59: ermite.RunService.RemoveRunner:output_type -> ermite.RemoveRunnerResponse
2725+ 49, // [49:60] is the sub-list for method output_type
2726+ 38, // [38:49] is the sub-list for method input_type
2727+ 38, // [38:38] is the sub-list for extension type_name
2728+ 38, // [38:38] is the sub-list for extension extendee
2729+ 0, // [0:38] is the sub-list for field type_name
23122730 }
23132731
23142732 func init() { file_ermite_run_proto_init() }
@@ -2323,7 +2741,7 @@ func file_ermite_run_proto_init() {
23232741 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
23242742 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_run_proto_rawDesc), len(file_ermite_run_proto_rawDesc)),
23252743 NumEnums: 0,
2326- NumMessages: 24,
2744+ NumMessages: 30,
23272745 NumExtensions: 0,
23282746 NumServices: 1,
23292747 },
@@ -521,7 +521,12 @@ type Step struct {
521 // LogEnd is the number of the line after the last one of the step. For an521 // LogEnd is the number of the line after the last one of the step. For an
522 // IN_PROGRESS step it is the number of lines held at the time of the522 // IN_PROGRESS step it is the number of lines held at the time of the
523 // call and grows; for a step without a line it equals log_start.523 // call and grows; for a step without a line it equals log_start.
524- LogEnd int64 `protobuf:"varint,8,opt,name=log_end,json=logEnd,proto3" json:"log_end,omitempty"`524+ LogEnd int64 `protobuf:"varint,8,opt,name=log_end,json=logEnd,proto3" json:"log_end,omitempty"`
525+ // Outcome is how the step ended before continue-on-error was applied, as
526+ // StepUpdate.outcome: it differs from conclusion only for a failed step with
527+ // continue-on-error. Unset until state is COMPLETED, and for a step stored
528+ // by a server or runner before this field existed (read it as conclusion).
529+ Outcome CiConclusion `protobuf:"varint,9,opt,name=outcome,proto3,enum=ermite.CiConclusion" json:"outcome,omitempty"`
525 unknownFields protoimpl.UnknownFields530 unknownFields protoimpl.UnknownFields
526 sizeCache protoimpl.SizeCache531 sizeCache protoimpl.SizeCache
527 }532 }
@@ -612,6 +617,13 @@ func (x *Step) GetLogEnd() int64 {
612 return 0617 return 0
613 }618 }
614 619
620+func (x *Step) GetOutcome() CiConclusion {
621+ if x != nil {
622+ return x.Outcome
623+ }
624+ return CiConclusion_CI_CONCLUSION_UNSPECIFIED
625+}
626+
615 // Check is the result of one job on one commit, the unit shown next to a627 // Check is the result of one job on one commit, the unit shown next to a
616 // commit or a merge request and counted by the merge rules. There is one per628 // commit or a merge request and counted by the merge rules. There is one per
617 // job instance, named like GitHub's checks.629 // job instance, named like GitHub's checks.
@@ -1288,6 +1300,370 @@ func (x *GetJobResponse) GetJob() *RunJob {
1288 return nil1300 return nil
1289 }1301 }
1290 1302
1303+// ListAnnotationsRequest selects the annotations of a run.
1304+type ListAnnotationsRequest struct {
1305+ state protoimpl.MessageState `protogen:"open.v1"`
1306+ // Repo is the repository name.
1307+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1308+ // RunId is the Run.id.
1309+ RunId int64 `protobuf:"varint,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"`
1310+ // Attempt is the attempt to read. 0 means the latest, and then each job
1311+ // contributes the annotations of its own RunJob.attempt (not necessarily the
1312+ // latest attempt of the run, see ListAnnotations).
1313+ Attempt int32 `protobuf:"varint,3,opt,name=attempt,proto3" json:"attempt,omitempty"`
1314+ // JobId restricts the result to one job (RunJob.id). Empty means every job
1315+ // of the run.
1316+ JobId string `protobuf:"bytes,4,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1317+ unknownFields protoimpl.UnknownFields
1318+ sizeCache protoimpl.SizeCache
1319+}
1320+
1321+func (x *ListAnnotationsRequest) Reset() {
1322+ *x = ListAnnotationsRequest{}
1323+ mi := &file_ermite_run_proto_msgTypes[11]
1324+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1325+ ms.StoreMessageInfo(mi)
1326+}
1327+
1328+func (x *ListAnnotationsRequest) String() string {
1329+ return protoimpl.X.MessageStringOf(x)
1330+}
1331+
1332+func (*ListAnnotationsRequest) ProtoMessage() {}
1333+
1334+func (x *ListAnnotationsRequest) ProtoReflect() protoreflect.Message {
1335+ mi := &file_ermite_run_proto_msgTypes[11]
1336+ if x != nil {
1337+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1338+ if ms.LoadMessageInfo() == nil {
1339+ ms.StoreMessageInfo(mi)
1340+ }
1341+ return ms
1342+ }
1343+ return mi.MessageOf(x)
1344+}
1345+
1346+// Deprecated: Use ListAnnotationsRequest.ProtoReflect.Descriptor instead.
1347+func (*ListAnnotationsRequest) Descriptor() ([]byte, []int) {
1348+ return file_ermite_run_proto_rawDescGZIP(), []int{11}
1349+}
1350+
1351+func (x *ListAnnotationsRequest) GetRepo() string {
1352+ if x != nil {
1353+ return x.Repo
1354+ }
1355+ return ""
1356+}
1357+
1358+func (x *ListAnnotationsRequest) GetRunId() int64 {
1359+ if x != nil {
1360+ return x.RunId
1361+ }
1362+ return 0
1363+}
1364+
1365+func (x *ListAnnotationsRequest) GetAttempt() int32 {
1366+ if x != nil {
1367+ return x.Attempt
1368+ }
1369+ return 0
1370+}
1371+
1372+func (x *ListAnnotationsRequest) GetJobId() string {
1373+ if x != nil {
1374+ return x.JobId
1375+ }
1376+ return ""
1377+}
1378+
1379+// ListAnnotationsResponse holds the annotations of a run.
1380+type ListAnnotationsResponse struct {
1381+ state protoimpl.MessageState `protogen:"open.v1"`
1382+ // Annotations are the annotations, at most 1,000.
1383+ Annotations []*JobAnnotation `protobuf:"bytes,1,rep,name=annotations,proto3" json:"annotations,omitempty"`
1384+ // Truncated is true when there are more annotations than annotations holds.
1385+ Truncated bool `protobuf:"varint,2,opt,name=truncated,proto3" json:"truncated,omitempty"`
1386+ unknownFields protoimpl.UnknownFields
1387+ sizeCache protoimpl.SizeCache
1388+}
1389+
1390+func (x *ListAnnotationsResponse) Reset() {
1391+ *x = ListAnnotationsResponse{}
1392+ mi := &file_ermite_run_proto_msgTypes[12]
1393+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1394+ ms.StoreMessageInfo(mi)
1395+}
1396+
1397+func (x *ListAnnotationsResponse) String() string {
1398+ return protoimpl.X.MessageStringOf(x)
1399+}
1400+
1401+func (*ListAnnotationsResponse) ProtoMessage() {}
1402+
1403+func (x *ListAnnotationsResponse) ProtoReflect() protoreflect.Message {
1404+ mi := &file_ermite_run_proto_msgTypes[12]
1405+ if x != nil {
1406+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1407+ if ms.LoadMessageInfo() == nil {
1408+ ms.StoreMessageInfo(mi)
1409+ }
1410+ return ms
1411+ }
1412+ return mi.MessageOf(x)
1413+}
1414+
1415+// Deprecated: Use ListAnnotationsResponse.ProtoReflect.Descriptor instead.
1416+func (*ListAnnotationsResponse) Descriptor() ([]byte, []int) {
1417+ return file_ermite_run_proto_rawDescGZIP(), []int{12}
1418+}
1419+
1420+func (x *ListAnnotationsResponse) GetAnnotations() []*JobAnnotation {
1421+ if x != nil {
1422+ return x.Annotations
1423+ }
1424+ return nil
1425+}
1426+
1427+func (x *ListAnnotationsResponse) GetTruncated() bool {
1428+ if x != nil {
1429+ return x.Truncated
1430+ }
1431+ return false
1432+}
1433+
1434+// JobAnnotation is an annotation with the job it belongs to.
1435+type JobAnnotation struct {
1436+ state protoimpl.MessageState `protogen:"open.v1"`
1437+ // JobId is the RunJob.id of the job.
1438+ JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1439+ // Annotation is the annotation as the runner sent it, after the server
1440+ // checked it. Its step_number is the step of the job.
1441+ Annotation *Annotation `protobuf:"bytes,2,opt,name=annotation,proto3" json:"annotation,omitempty"`
1442+ unknownFields protoimpl.UnknownFields
1443+ sizeCache protoimpl.SizeCache
1444+}
1445+
1446+func (x *JobAnnotation) Reset() {
1447+ *x = JobAnnotation{}
1448+ mi := &file_ermite_run_proto_msgTypes[13]
1449+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1450+ ms.StoreMessageInfo(mi)
1451+}
1452+
1453+func (x *JobAnnotation) String() string {
1454+ return protoimpl.X.MessageStringOf(x)
1455+}
1456+
1457+func (*JobAnnotation) ProtoMessage() {}
1458+
1459+func (x *JobAnnotation) ProtoReflect() protoreflect.Message {
1460+ mi := &file_ermite_run_proto_msgTypes[13]
1461+ if x != nil {
1462+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1463+ if ms.LoadMessageInfo() == nil {
1464+ ms.StoreMessageInfo(mi)
1465+ }
1466+ return ms
1467+ }
1468+ return mi.MessageOf(x)
1469+}
1470+
1471+// Deprecated: Use JobAnnotation.ProtoReflect.Descriptor instead.
1472+func (*JobAnnotation) Descriptor() ([]byte, []int) {
1473+ return file_ermite_run_proto_rawDescGZIP(), []int{13}
1474+}
1475+
1476+func (x *JobAnnotation) GetJobId() string {
1477+ if x != nil {
1478+ return x.JobId
1479+ }
1480+ return ""
1481+}
1482+
1483+func (x *JobAnnotation) GetAnnotation() *Annotation {
1484+ if x != nil {
1485+ return x.Annotation
1486+ }
1487+ return nil
1488+}
1489+
1490+// GetStepSummariesRequest selects a job.
1491+type GetStepSummariesRequest struct {
1492+ state protoimpl.MessageState `protogen:"open.v1"`
1493+ // Repo is the repository name.
1494+ Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
1495+ // JobId is the RunJob.id.
1496+ JobId string `protobuf:"bytes,2,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"`
1497+ // Attempt is the RunJob.attempt to read. 0 means the latest.
1498+ Attempt int32 `protobuf:"varint,3,opt,name=attempt,proto3" json:"attempt,omitempty"`
1499+ unknownFields protoimpl.UnknownFields
1500+ sizeCache protoimpl.SizeCache
1501+}
1502+
1503+func (x *GetStepSummariesRequest) Reset() {
1504+ *x = GetStepSummariesRequest{}
1505+ mi := &file_ermite_run_proto_msgTypes[14]
1506+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1507+ ms.StoreMessageInfo(mi)
1508+}
1509+
1510+func (x *GetStepSummariesRequest) String() string {
1511+ return protoimpl.X.MessageStringOf(x)
1512+}
1513+
1514+func (*GetStepSummariesRequest) ProtoMessage() {}
1515+
1516+func (x *GetStepSummariesRequest) ProtoReflect() protoreflect.Message {
1517+ mi := &file_ermite_run_proto_msgTypes[14]
1518+ if x != nil {
1519+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1520+ if ms.LoadMessageInfo() == nil {
1521+ ms.StoreMessageInfo(mi)
1522+ }
1523+ return ms
1524+ }
1525+ return mi.MessageOf(x)
1526+}
1527+
1528+// Deprecated: Use GetStepSummariesRequest.ProtoReflect.Descriptor instead.
1529+func (*GetStepSummariesRequest) Descriptor() ([]byte, []int) {
1530+ return file_ermite_run_proto_rawDescGZIP(), []int{14}
1531+}
1532+
1533+func (x *GetStepSummariesRequest) GetRepo() string {
1534+ if x != nil {
1535+ return x.Repo
1536+ }
1537+ return ""
1538+}
1539+
1540+func (x *GetStepSummariesRequest) GetJobId() string {
1541+ if x != nil {
1542+ return x.JobId
1543+ }
1544+ return ""
1545+}
1546+
1547+func (x *GetStepSummariesRequest) GetAttempt() int32 {
1548+ if x != nil {
1549+ return x.Attempt
1550+ }
1551+ return 0
1552+}
1553+
1554+// GetStepSummariesResponse holds the summaries of a job.
1555+type GetStepSummariesResponse struct {
1556+ state protoimpl.MessageState `protogen:"open.v1"`
1557+ // Summaries are the summaries of the steps that have one, ordered by step
1558+ // number: at most 20, the first 20 steps having one.
1559+ Summaries []*StepSummary `protobuf:"bytes,1,rep,name=summaries,proto3" json:"summaries,omitempty"`
1560+ // Truncated is true when the job has more than 20 steps with a summary and
1561+ // summaries holds only the first 20.
1562+ Truncated bool `protobuf:"varint,2,opt,name=truncated,proto3" json:"truncated,omitempty"`
1563+ unknownFields protoimpl.UnknownFields
1564+ sizeCache protoimpl.SizeCache
1565+}
1566+
1567+func (x *GetStepSummariesResponse) Reset() {
1568+ *x = GetStepSummariesResponse{}
1569+ mi := &file_ermite_run_proto_msgTypes[15]
1570+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1571+ ms.StoreMessageInfo(mi)
1572+}
1573+
1574+func (x *GetStepSummariesResponse) String() string {
1575+ return protoimpl.X.MessageStringOf(x)
1576+}
1577+
1578+func (*GetStepSummariesResponse) ProtoMessage() {}
1579+
1580+func (x *GetStepSummariesResponse) ProtoReflect() protoreflect.Message {
1581+ mi := &file_ermite_run_proto_msgTypes[15]
1582+ if x != nil {
1583+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1584+ if ms.LoadMessageInfo() == nil {
1585+ ms.StoreMessageInfo(mi)
1586+ }
1587+ return ms
1588+ }
1589+ return mi.MessageOf(x)
1590+}
1591+
1592+// Deprecated: Use GetStepSummariesResponse.ProtoReflect.Descriptor instead.
1593+func (*GetStepSummariesResponse) Descriptor() ([]byte, []int) {
1594+ return file_ermite_run_proto_rawDescGZIP(), []int{15}
1595+}
1596+
1597+func (x *GetStepSummariesResponse) GetSummaries() []*StepSummary {
1598+ if x != nil {
1599+ return x.Summaries
1600+ }
1601+ return nil
1602+}
1603+
1604+func (x *GetStepSummariesResponse) GetTruncated() bool {
1605+ if x != nil {
1606+ return x.Truncated
1607+ }
1608+ return false
1609+}
1610+
1611+// StepSummary is the job summary of one step.
1612+type StepSummary struct {
1613+ state protoimpl.MessageState `protogen:"open.v1"`
1614+ // StepNumber is the number of the step (see Step.number).
1615+ StepNumber int32 `protobuf:"varint,1,opt,name=step_number,json=stepNumber,proto3" json:"step_number,omitempty"`
1616+ // Markdown is the summary as uploaded, at most 1 MiB. Clients render it
1617+ // safely: it is untrusted content (raw HTML and script URLs must not run).
1618+ Markdown string `protobuf:"bytes,2,opt,name=markdown,proto3" json:"markdown,omitempty"`
1619+ unknownFields protoimpl.UnknownFields
1620+ sizeCache protoimpl.SizeCache
1621+}
1622+
1623+func (x *StepSummary) Reset() {
1624+ *x = StepSummary{}
1625+ mi := &file_ermite_run_proto_msgTypes[16]
1626+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1627+ ms.StoreMessageInfo(mi)
1628+}
1629+
1630+func (x *StepSummary) String() string {
1631+ return protoimpl.X.MessageStringOf(x)
1632+}
1633+
1634+func (*StepSummary) ProtoMessage() {}
1635+
1636+func (x *StepSummary) ProtoReflect() protoreflect.Message {
1637+ mi := &file_ermite_run_proto_msgTypes[16]
1638+ if x != nil {
1639+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1640+ if ms.LoadMessageInfo() == nil {
1641+ ms.StoreMessageInfo(mi)
1642+ }
1643+ return ms
1644+ }
1645+ return mi.MessageOf(x)
1646+}
1647+
1648+// Deprecated: Use StepSummary.ProtoReflect.Descriptor instead.
1649+func (*StepSummary) Descriptor() ([]byte, []int) {
1650+ return file_ermite_run_proto_rawDescGZIP(), []int{16}
1651+}
1652+
1653+func (x *StepSummary) GetStepNumber() int32 {
1654+ if x != nil {
1655+ return x.StepNumber
1656+ }
1657+ return 0
1658+}
1659+
1660+func (x *StepSummary) GetMarkdown() string {
1661+ if x != nil {
1662+ return x.Markdown
1663+ }
1664+ return ""
1665+}
1666+
1291 // GetJobLogRequest selects the lines to stream.1667 // GetJobLogRequest selects the lines to stream.
1292 type GetJobLogRequest struct {1668 type GetJobLogRequest struct {
1293 state protoimpl.MessageState `protogen:"open.v1"`1669 state protoimpl.MessageState `protogen:"open.v1"`
@@ -1308,7 +1684,7 @@ type GetJobLogRequest struct {
1308 1684
1309 func (x *GetJobLogRequest) Reset() {1685 func (x *GetJobLogRequest) Reset() {
1310 *x = GetJobLogRequest{}1686 *x = GetJobLogRequest{}
1311- mi := &file_ermite_run_proto_msgTypes[11]1687+ mi := &file_ermite_run_proto_msgTypes[17]
1312 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1688 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1313 ms.StoreMessageInfo(mi)1689 ms.StoreMessageInfo(mi)
1314 }1690 }
@@ -1320,7 +1696,7 @@ func (x *GetJobLogRequest) String() string {
1320 func (*GetJobLogRequest) ProtoMessage() {}1696 func (*GetJobLogRequest) ProtoMessage() {}
1321 1697
1322 func (x *GetJobLogRequest) ProtoReflect() protoreflect.Message {1698 func (x *GetJobLogRequest) ProtoReflect() protoreflect.Message {
1323- mi := &file_ermite_run_proto_msgTypes[11]1699+ mi := &file_ermite_run_proto_msgTypes[17]
1324 if x != nil {1700 if x != nil {
1325 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1701 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1326 if ms.LoadMessageInfo() == nil {1702 if ms.LoadMessageInfo() == nil {
@@ -1333,7 +1709,7 @@ func (x *GetJobLogRequest) ProtoReflect() protoreflect.Message {
1333 1709
1334 // Deprecated: Use GetJobLogRequest.ProtoReflect.Descriptor instead.1710 // Deprecated: Use GetJobLogRequest.ProtoReflect.Descriptor instead.
1335 func (*GetJobLogRequest) Descriptor() ([]byte, []int) {1711 func (*GetJobLogRequest) Descriptor() ([]byte, []int) {
1336- return file_ermite_run_proto_rawDescGZIP(), []int{11}1712+ return file_ermite_run_proto_rawDescGZIP(), []int{17}
1337 }1713 }
1338 1714
1339 func (x *GetJobLogRequest) GetRepo() string {1715 func (x *GetJobLogRequest) GetRepo() string {
@@ -1385,7 +1761,7 @@ type GetJobLogResponse struct {
1385 1761
1386 func (x *GetJobLogResponse) Reset() {1762 func (x *GetJobLogResponse) Reset() {
1387 *x = GetJobLogResponse{}1763 *x = GetJobLogResponse{}
1388- mi := &file_ermite_run_proto_msgTypes[12]1764+ mi := &file_ermite_run_proto_msgTypes[18]
1389 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1765 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1390 ms.StoreMessageInfo(mi)1766 ms.StoreMessageInfo(mi)
1391 }1767 }
@@ -1397,7 +1773,7 @@ func (x *GetJobLogResponse) String() string {
1397 func (*GetJobLogResponse) ProtoMessage() {}1773 func (*GetJobLogResponse) ProtoMessage() {}
1398 1774
1399 func (x *GetJobLogResponse) ProtoReflect() protoreflect.Message {1775 func (x *GetJobLogResponse) ProtoReflect() protoreflect.Message {
1400- mi := &file_ermite_run_proto_msgTypes[12]1776+ mi := &file_ermite_run_proto_msgTypes[18]
1401 if x != nil {1777 if x != nil {
1402 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1778 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1403 if ms.LoadMessageInfo() == nil {1779 if ms.LoadMessageInfo() == nil {
@@ -1410,7 +1786,7 @@ func (x *GetJobLogResponse) ProtoReflect() protoreflect.Message {
1410 1786
1411 // Deprecated: Use GetJobLogResponse.ProtoReflect.Descriptor instead.1787 // Deprecated: Use GetJobLogResponse.ProtoReflect.Descriptor instead.
1412 func (*GetJobLogResponse) Descriptor() ([]byte, []int) {1788 func (*GetJobLogResponse) Descriptor() ([]byte, []int) {
1413- return file_ermite_run_proto_rawDescGZIP(), []int{12}1789+ return file_ermite_run_proto_rawDescGZIP(), []int{18}
1414 }1790 }
1415 1791
1416 func (x *GetJobLogResponse) GetOffset() int64 {1792 func (x *GetJobLogResponse) GetOffset() int64 {
@@ -1449,7 +1825,7 @@ type JobLogLine struct {
1449 1825
1450 func (x *JobLogLine) Reset() {1826 func (x *JobLogLine) Reset() {
1451 *x = JobLogLine{}1827 *x = JobLogLine{}
1452- mi := &file_ermite_run_proto_msgTypes[13]1828+ mi := &file_ermite_run_proto_msgTypes[19]
1453 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1829 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1454 ms.StoreMessageInfo(mi)1830 ms.StoreMessageInfo(mi)
1455 }1831 }
@@ -1461,7 +1837,7 @@ func (x *JobLogLine) String() string {
1461 func (*JobLogLine) ProtoMessage() {}1837 func (*JobLogLine) ProtoMessage() {}
1462 1838
1463 func (x *JobLogLine) ProtoReflect() protoreflect.Message {1839 func (x *JobLogLine) ProtoReflect() protoreflect.Message {
1464- mi := &file_ermite_run_proto_msgTypes[13]1840+ mi := &file_ermite_run_proto_msgTypes[19]
1465 if x != nil {1841 if x != nil {
1466 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1842 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1467 if ms.LoadMessageInfo() == nil {1843 if ms.LoadMessageInfo() == nil {
@@ -1474,7 +1850,7 @@ func (x *JobLogLine) ProtoReflect() protoreflect.Message {
1474 1850
1475 // Deprecated: Use JobLogLine.ProtoReflect.Descriptor instead.1851 // Deprecated: Use JobLogLine.ProtoReflect.Descriptor instead.
1476 func (*JobLogLine) Descriptor() ([]byte, []int) {1852 func (*JobLogLine) Descriptor() ([]byte, []int) {
1477- return file_ermite_run_proto_rawDescGZIP(), []int{13}1853+ return file_ermite_run_proto_rawDescGZIP(), []int{19}
1478 }1854 }
1479 1855
1480 func (x *JobLogLine) GetStep() int32 {1856 func (x *JobLogLine) GetStep() int32 {
@@ -1518,7 +1894,7 @@ type CancelRunRequest struct {
1518 1894
1519 func (x *CancelRunRequest) Reset() {1895 func (x *CancelRunRequest) Reset() {
1520 *x = CancelRunRequest{}1896 *x = CancelRunRequest{}
1521- mi := &file_ermite_run_proto_msgTypes[14]1897+ mi := &file_ermite_run_proto_msgTypes[20]
1522 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1898 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1523 ms.StoreMessageInfo(mi)1899 ms.StoreMessageInfo(mi)
1524 }1900 }
@@ -1530,7 +1906,7 @@ func (x *CancelRunRequest) String() string {
1530 func (*CancelRunRequest) ProtoMessage() {}1906 func (*CancelRunRequest) ProtoMessage() {}
1531 1907
1532 func (x *CancelRunRequest) ProtoReflect() protoreflect.Message {1908 func (x *CancelRunRequest) ProtoReflect() protoreflect.Message {
1533- mi := &file_ermite_run_proto_msgTypes[14]1909+ mi := &file_ermite_run_proto_msgTypes[20]
1534 if x != nil {1910 if x != nil {
1535 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1911 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1536 if ms.LoadMessageInfo() == nil {1912 if ms.LoadMessageInfo() == nil {
@@ -1543,7 +1919,7 @@ func (x *CancelRunRequest) ProtoReflect() protoreflect.Message {
1543 1919
1544 // Deprecated: Use CancelRunRequest.ProtoReflect.Descriptor instead.1920 // Deprecated: Use CancelRunRequest.ProtoReflect.Descriptor instead.
1545 func (*CancelRunRequest) Descriptor() ([]byte, []int) {1921 func (*CancelRunRequest) Descriptor() ([]byte, []int) {
1546- return file_ermite_run_proto_rawDescGZIP(), []int{14}1922+ return file_ermite_run_proto_rawDescGZIP(), []int{20}
1547 }1923 }
1548 1924
1549 func (x *CancelRunRequest) GetRepo() string {1925 func (x *CancelRunRequest) GetRepo() string {
@@ -1571,7 +1947,7 @@ type CancelRunResponse struct {
1571 1947
1572 func (x *CancelRunResponse) Reset() {1948 func (x *CancelRunResponse) Reset() {
1573 *x = CancelRunResponse{}1949 *x = CancelRunResponse{}
1574- mi := &file_ermite_run_proto_msgTypes[15]1950+ mi := &file_ermite_run_proto_msgTypes[21]
1575 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1951 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1576 ms.StoreMessageInfo(mi)1952 ms.StoreMessageInfo(mi)
1577 }1953 }
@@ -1583,7 +1959,7 @@ func (x *CancelRunResponse) String() string {
1583 func (*CancelRunResponse) ProtoMessage() {}1959 func (*CancelRunResponse) ProtoMessage() {}
1584 1960
1585 func (x *CancelRunResponse) ProtoReflect() protoreflect.Message {1961 func (x *CancelRunResponse) ProtoReflect() protoreflect.Message {
1586- mi := &file_ermite_run_proto_msgTypes[15]1962+ mi := &file_ermite_run_proto_msgTypes[21]
1587 if x != nil {1963 if x != nil {
1588 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1964 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1589 if ms.LoadMessageInfo() == nil {1965 if ms.LoadMessageInfo() == nil {
@@ -1596,7 +1972,7 @@ func (x *CancelRunResponse) ProtoReflect() protoreflect.Message {
1596 1972
1597 // Deprecated: Use CancelRunResponse.ProtoReflect.Descriptor instead.1973 // Deprecated: Use CancelRunResponse.ProtoReflect.Descriptor instead.
1598 func (*CancelRunResponse) Descriptor() ([]byte, []int) {1974 func (*CancelRunResponse) Descriptor() ([]byte, []int) {
1599- return file_ermite_run_proto_rawDescGZIP(), []int{15}1975+ return file_ermite_run_proto_rawDescGZIP(), []int{21}
1600 }1976 }
1601 1977
1602 func (x *CancelRunResponse) GetRun() *Run {1978 func (x *CancelRunResponse) GetRun() *Run {
@@ -1625,7 +2001,7 @@ type RerunRunRequest struct {
1625 2001
1626 func (x *RerunRunRequest) Reset() {2002 func (x *RerunRunRequest) Reset() {
1627 *x = RerunRunRequest{}2003 *x = RerunRunRequest{}
1628- mi := &file_ermite_run_proto_msgTypes[16]2004+ mi := &file_ermite_run_proto_msgTypes[22]
1629 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2005 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1630 ms.StoreMessageInfo(mi)2006 ms.StoreMessageInfo(mi)
1631 }2007 }
@@ -1637,7 +2013,7 @@ func (x *RerunRunRequest) String() string {
1637 func (*RerunRunRequest) ProtoMessage() {}2013 func (*RerunRunRequest) ProtoMessage() {}
1638 2014
1639 func (x *RerunRunRequest) ProtoReflect() protoreflect.Message {2015 func (x *RerunRunRequest) ProtoReflect() protoreflect.Message {
1640- mi := &file_ermite_run_proto_msgTypes[16]2016+ mi := &file_ermite_run_proto_msgTypes[22]
1641 if x != nil {2017 if x != nil {
1642 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2018 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1643 if ms.LoadMessageInfo() == nil {2019 if ms.LoadMessageInfo() == nil {
@@ -1650,7 +2026,7 @@ func (x *RerunRunRequest) ProtoReflect() protoreflect.Message {
1650 2026
1651 // Deprecated: Use RerunRunRequest.ProtoReflect.Descriptor instead.2027 // Deprecated: Use RerunRunRequest.ProtoReflect.Descriptor instead.
1652 func (*RerunRunRequest) Descriptor() ([]byte, []int) {2028 func (*RerunRunRequest) Descriptor() ([]byte, []int) {
1653- return file_ermite_run_proto_rawDescGZIP(), []int{16}2029+ return file_ermite_run_proto_rawDescGZIP(), []int{22}
1654 }2030 }
1655 2031
1656 func (x *RerunRunRequest) GetRepo() string {2032 func (x *RerunRunRequest) GetRepo() string {
@@ -1685,7 +2061,7 @@ type RerunRunResponse struct {
1685 2061
1686 func (x *RerunRunResponse) Reset() {2062 func (x *RerunRunResponse) Reset() {
1687 *x = RerunRunResponse{}2063 *x = RerunRunResponse{}
1688- mi := &file_ermite_run_proto_msgTypes[17]2064+ mi := &file_ermite_run_proto_msgTypes[23]
1689 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2065 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1690 ms.StoreMessageInfo(mi)2066 ms.StoreMessageInfo(mi)
1691 }2067 }
@@ -1697,7 +2073,7 @@ func (x *RerunRunResponse) String() string {
1697 func (*RerunRunResponse) ProtoMessage() {}2073 func (*RerunRunResponse) ProtoMessage() {}
1698 2074
1699 func (x *RerunRunResponse) ProtoReflect() protoreflect.Message {2075 func (x *RerunRunResponse) ProtoReflect() protoreflect.Message {
1700- mi := &file_ermite_run_proto_msgTypes[17]2076+ mi := &file_ermite_run_proto_msgTypes[23]
1701 if x != nil {2077 if x != nil {
1702 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2078 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1703 if ms.LoadMessageInfo() == nil {2079 if ms.LoadMessageInfo() == nil {
@@ -1710,7 +2086,7 @@ func (x *RerunRunResponse) ProtoReflect() protoreflect.Message {
1710 2086
1711 // Deprecated: Use RerunRunResponse.ProtoReflect.Descriptor instead.2087 // Deprecated: Use RerunRunResponse.ProtoReflect.Descriptor instead.
1712 func (*RerunRunResponse) Descriptor() ([]byte, []int) {2088 func (*RerunRunResponse) Descriptor() ([]byte, []int) {
1713- return file_ermite_run_proto_rawDescGZIP(), []int{17}2089+ return file_ermite_run_proto_rawDescGZIP(), []int{23}
1714 }2090 }
1715 2091
1716 func (x *RerunRunResponse) GetRun() *Run {2092 func (x *RerunRunResponse) GetRun() *Run {
@@ -1734,7 +2110,7 @@ type ListChecksRequest struct {
1734 2110
1735 func (x *ListChecksRequest) Reset() {2111 func (x *ListChecksRequest) Reset() {
1736 *x = ListChecksRequest{}2112 *x = ListChecksRequest{}
1737- mi := &file_ermite_run_proto_msgTypes[18]2113+ mi := &file_ermite_run_proto_msgTypes[24]
1738 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2114 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1739 ms.StoreMessageInfo(mi)2115 ms.StoreMessageInfo(mi)
1740 }2116 }
@@ -1746,7 +2122,7 @@ func (x *ListChecksRequest) String() string {
1746 func (*ListChecksRequest) ProtoMessage() {}2122 func (*ListChecksRequest) ProtoMessage() {}
1747 2123
1748 func (x *ListChecksRequest) ProtoReflect() protoreflect.Message {2124 func (x *ListChecksRequest) ProtoReflect() protoreflect.Message {
1749- mi := &file_ermite_run_proto_msgTypes[18]2125+ mi := &file_ermite_run_proto_msgTypes[24]
1750 if x != nil {2126 if x != nil {
1751 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2127 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1752 if ms.LoadMessageInfo() == nil {2128 if ms.LoadMessageInfo() == nil {
@@ -1759,7 +2135,7 @@ func (x *ListChecksRequest) ProtoReflect() protoreflect.Message {
1759 2135
1760 // Deprecated: Use ListChecksRequest.ProtoReflect.Descriptor instead.2136 // Deprecated: Use ListChecksRequest.ProtoReflect.Descriptor instead.
1761 func (*ListChecksRequest) Descriptor() ([]byte, []int) {2137 func (*ListChecksRequest) Descriptor() ([]byte, []int) {
1762- return file_ermite_run_proto_rawDescGZIP(), []int{18}2138+ return file_ermite_run_proto_rawDescGZIP(), []int{24}
1763 }2139 }
1764 2140
1765 func (x *ListChecksRequest) GetRepo() string {2141 func (x *ListChecksRequest) GetRepo() string {
@@ -1790,7 +2166,7 @@ type ListChecksResponse struct {
1790 2166
1791 func (x *ListChecksResponse) Reset() {2167 func (x *ListChecksResponse) Reset() {
1792 *x = ListChecksResponse{}2168 *x = ListChecksResponse{}
1793- mi := &file_ermite_run_proto_msgTypes[19]2169+ mi := &file_ermite_run_proto_msgTypes[25]
1794 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2170 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1795 ms.StoreMessageInfo(mi)2171 ms.StoreMessageInfo(mi)
1796 }2172 }
@@ -1802,7 +2178,7 @@ func (x *ListChecksResponse) String() string {
1802 func (*ListChecksResponse) ProtoMessage() {}2178 func (*ListChecksResponse) ProtoMessage() {}
1803 2179
1804 func (x *ListChecksResponse) ProtoReflect() protoreflect.Message {2180 func (x *ListChecksResponse) ProtoReflect() protoreflect.Message {
1805- mi := &file_ermite_run_proto_msgTypes[19]2181+ mi := &file_ermite_run_proto_msgTypes[25]
1806 if x != nil {2182 if x != nil {
1807 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2183 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1808 if ms.LoadMessageInfo() == nil {2184 if ms.LoadMessageInfo() == nil {
@@ -1815,7 +2191,7 @@ func (x *ListChecksResponse) ProtoReflect() protoreflect.Message {
1815 2191
1816 // Deprecated: Use ListChecksResponse.ProtoReflect.Descriptor instead.2192 // Deprecated: Use ListChecksResponse.ProtoReflect.Descriptor instead.
1817 func (*ListChecksResponse) Descriptor() ([]byte, []int) {2193 func (*ListChecksResponse) Descriptor() ([]byte, []int) {
1818- return file_ermite_run_proto_rawDescGZIP(), []int{19}2194+ return file_ermite_run_proto_rawDescGZIP(), []int{25}
1819 }2195 }
1820 2196
1821 func (x *ListChecksResponse) GetChecks() []*Check {2197 func (x *ListChecksResponse) GetChecks() []*Check {
@@ -1846,7 +2222,7 @@ type ListRunnersRequest struct {
1846 2222
1847 func (x *ListRunnersRequest) Reset() {2223 func (x *ListRunnersRequest) Reset() {
1848 *x = ListRunnersRequest{}2224 *x = ListRunnersRequest{}
1849- mi := &file_ermite_run_proto_msgTypes[20]2225+ mi := &file_ermite_run_proto_msgTypes[26]
1850 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2226 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1851 ms.StoreMessageInfo(mi)2227 ms.StoreMessageInfo(mi)
1852 }2228 }
@@ -1858,7 +2234,7 @@ func (x *ListRunnersRequest) String() string {
1858 func (*ListRunnersRequest) ProtoMessage() {}2234 func (*ListRunnersRequest) ProtoMessage() {}
1859 2235
1860 func (x *ListRunnersRequest) ProtoReflect() protoreflect.Message {2236 func (x *ListRunnersRequest) ProtoReflect() protoreflect.Message {
1861- mi := &file_ermite_run_proto_msgTypes[20]2237+ mi := &file_ermite_run_proto_msgTypes[26]
1862 if x != nil {2238 if x != nil {
1863 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2239 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1864 if ms.LoadMessageInfo() == nil {2240 if ms.LoadMessageInfo() == nil {
@@ -1871,7 +2247,7 @@ func (x *ListRunnersRequest) ProtoReflect() protoreflect.Message {
1871 2247
1872 // Deprecated: Use ListRunnersRequest.ProtoReflect.Descriptor instead.2248 // Deprecated: Use ListRunnersRequest.ProtoReflect.Descriptor instead.
1873 func (*ListRunnersRequest) Descriptor() ([]byte, []int) {2249 func (*ListRunnersRequest) Descriptor() ([]byte, []int) {
1874- return file_ermite_run_proto_rawDescGZIP(), []int{20}2250+ return file_ermite_run_proto_rawDescGZIP(), []int{26}
1875 }2251 }
1876 2252
1877 func (x *ListRunnersRequest) GetPageSize() int32 {2253 func (x *ListRunnersRequest) GetPageSize() int32 {
@@ -1902,7 +2278,7 @@ type ListRunnersResponse struct {
1902 2278
1903 func (x *ListRunnersResponse) Reset() {2279 func (x *ListRunnersResponse) Reset() {
1904 *x = ListRunnersResponse{}2280 *x = ListRunnersResponse{}
1905- mi := &file_ermite_run_proto_msgTypes[21]2281+ mi := &file_ermite_run_proto_msgTypes[27]
1906 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2282 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1907 ms.StoreMessageInfo(mi)2283 ms.StoreMessageInfo(mi)
1908 }2284 }
@@ -1914,7 +2290,7 @@ func (x *ListRunnersResponse) String() string {
1914 func (*ListRunnersResponse) ProtoMessage() {}2290 func (*ListRunnersResponse) ProtoMessage() {}
1915 2291
1916 func (x *ListRunnersResponse) ProtoReflect() protoreflect.Message {2292 func (x *ListRunnersResponse) ProtoReflect() protoreflect.Message {
1917- mi := &file_ermite_run_proto_msgTypes[21]2293+ mi := &file_ermite_run_proto_msgTypes[27]
1918 if x != nil {2294 if x != nil {
1919 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2295 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1920 if ms.LoadMessageInfo() == nil {2296 if ms.LoadMessageInfo() == nil {
@@ -1927,7 +2303,7 @@ func (x *ListRunnersResponse) ProtoReflect() protoreflect.Message {
1927 2303
1928 // Deprecated: Use ListRunnersResponse.ProtoReflect.Descriptor instead.2304 // Deprecated: Use ListRunnersResponse.ProtoReflect.Descriptor instead.
1929 func (*ListRunnersResponse) Descriptor() ([]byte, []int) {2305 func (*ListRunnersResponse) Descriptor() ([]byte, []int) {
1930- return file_ermite_run_proto_rawDescGZIP(), []int{21}2306+ return file_ermite_run_proto_rawDescGZIP(), []int{27}
1931 }2307 }
1932 2308
1933 func (x *ListRunnersResponse) GetRunners() []*Runner {2309 func (x *ListRunnersResponse) GetRunners() []*Runner {
@@ -1955,7 +2331,7 @@ type RemoveRunnerRequest struct {
1955 2331
1956 func (x *RemoveRunnerRequest) Reset() {2332 func (x *RemoveRunnerRequest) Reset() {
1957 *x = RemoveRunnerRequest{}2333 *x = RemoveRunnerRequest{}
1958- mi := &file_ermite_run_proto_msgTypes[22]2334+ mi := &file_ermite_run_proto_msgTypes[28]
1959 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2335 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1960 ms.StoreMessageInfo(mi)2336 ms.StoreMessageInfo(mi)
1961 }2337 }
@@ -1967,7 +2343,7 @@ func (x *RemoveRunnerRequest) String() string {
1967 func (*RemoveRunnerRequest) ProtoMessage() {}2343 func (*RemoveRunnerRequest) ProtoMessage() {}
1968 2344
1969 func (x *RemoveRunnerRequest) ProtoReflect() protoreflect.Message {2345 func (x *RemoveRunnerRequest) ProtoReflect() protoreflect.Message {
1970- mi := &file_ermite_run_proto_msgTypes[22]2346+ mi := &file_ermite_run_proto_msgTypes[28]
1971 if x != nil {2347 if x != nil {
1972 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2348 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1973 if ms.LoadMessageInfo() == nil {2349 if ms.LoadMessageInfo() == nil {
@@ -1980,7 +2356,7 @@ func (x *RemoveRunnerRequest) ProtoReflect() protoreflect.Message {
1980 2356
1981 // Deprecated: Use RemoveRunnerRequest.ProtoReflect.Descriptor instead.2357 // Deprecated: Use RemoveRunnerRequest.ProtoReflect.Descriptor instead.
1982 func (*RemoveRunnerRequest) Descriptor() ([]byte, []int) {2358 func (*RemoveRunnerRequest) Descriptor() ([]byte, []int) {
1983- return file_ermite_run_proto_rawDescGZIP(), []int{22}2359+ return file_ermite_run_proto_rawDescGZIP(), []int{28}
1984 }2360 }
1985 2361
1986 func (x *RemoveRunnerRequest) GetRunnerId() string {2362 func (x *RemoveRunnerRequest) GetRunnerId() string {
@@ -1999,7 +2375,7 @@ type RemoveRunnerResponse struct {
1999 2375
2000 func (x *RemoveRunnerResponse) Reset() {2376 func (x *RemoveRunnerResponse) Reset() {
2001 *x = RemoveRunnerResponse{}2377 *x = RemoveRunnerResponse{}
2002- mi := &file_ermite_run_proto_msgTypes[23]2378+ mi := &file_ermite_run_proto_msgTypes[29]
2003 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2379 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2004 ms.StoreMessageInfo(mi)2380 ms.StoreMessageInfo(mi)
2005 }2381 }
@@ -2011,7 +2387,7 @@ func (x *RemoveRunnerResponse) String() string {
2011 func (*RemoveRunnerResponse) ProtoMessage() {}2387 func (*RemoveRunnerResponse) ProtoMessage() {}
2012 2388
2013 func (x *RemoveRunnerResponse) ProtoReflect() protoreflect.Message {2389 func (x *RemoveRunnerResponse) ProtoReflect() protoreflect.Message {
2014- mi := &file_ermite_run_proto_msgTypes[23]2390+ mi := &file_ermite_run_proto_msgTypes[29]
2015 if x != nil {2391 if x != nil {
2016 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))2392 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2017 if ms.LoadMessageInfo() == nil {2393 if ms.LoadMessageInfo() == nil {
@@ -2024,7 +2400,7 @@ func (x *RemoveRunnerResponse) ProtoReflect() protoreflect.Message {
2024 2400
2025 // Deprecated: Use RemoveRunnerResponse.ProtoReflect.Descriptor instead.2401 // Deprecated: Use RemoveRunnerResponse.ProtoReflect.Descriptor instead.
2026 func (*RemoveRunnerResponse) Descriptor() ([]byte, []int) {2402 func (*RemoveRunnerResponse) Descriptor() ([]byte, []int) {
2027- return file_ermite_run_proto_rawDescGZIP(), []int{23}2403+ return file_ermite_run_proto_rawDescGZIP(), []int{29}
2028 }2404 }
2029 2405
2030 var File_ermite_run_proto protoreflect.FileDescriptor2406 var File_ermite_run_proto protoreflect.FileDescriptor
@@ -2082,7 +2458,7 @@ const file_ermite_run_proto_rawDesc = "" +
2082 "\n" +2458 "\n" +
2083 "started_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +2459 "started_at\x18\x11 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
2084 "\fcompleted_at\x18\x12 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x18\n" +2460 "\fcompleted_at\x18\x12 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x18\n" +
2085- "\aversion\x18\x13 \x01(\x03R\aversion\"\xc1\x02\n" +2461+ "\aversion\x18\x13 \x01(\x03R\aversion\"\xf1\x02\n" +
2086 "\x04Step\x12\x16\n" +2462 "\x04Step\x12\x16\n" +
2087 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +2463 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
2088 "\x04name\x18\x02 \x01(\tR\x04name\x12'\n" +2464 "\x04name\x18\x02 \x01(\tR\x04name\x12'\n" +
@@ -2094,7 +2470,8 @@ const file_ermite_run_proto_rawDesc = "" +
2094 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +2470 "started_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x12=\n" +
2095 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +2471 "\fcompleted_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\vcompletedAt\x12\x1b\n" +
2096 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x17\n" +2472 "\tlog_start\x18\a \x01(\x03R\blogStart\x12\x17\n" +
2097- "\alog_end\x18\b \x01(\x03R\x06logEnd\"\x98\x03\n" +2473+ "\alog_end\x18\b \x01(\x03R\x06logEnd\x12.\n" +
2474+ "\aoutcome\x18\t \x01(\x0e2\x14.ermite.CiConclusionR\aoutcome\"\x98\x03\n" +
2098 "\x05Check\x12\x0e\n" +2475 "\x05Check\x12\x0e\n" +
2099 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +2476 "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
2100 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +2477 "\x04repo\x18\x02 \x01(\tR\x04repo\x12\x10\n" +
@@ -2148,7 +2525,31 @@ const file_ermite_run_proto_rawDesc = "" +
2148 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +2525 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
2149 "\aattempt\x18\x03 \x01(\x05R\aattempt\"2\n" +2526 "\aattempt\x18\x03 \x01(\x05R\aattempt\"2\n" +
2150 "\x0eGetJobResponse\x12 \n" +2527 "\x0eGetJobResponse\x12 \n" +
2151- "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"\x87\x01\n" +2528+ "\x03job\x18\x01 \x01(\v2\x0e.ermite.RunJobR\x03job\"t\n" +
2529+ "\x16ListAnnotationsRequest\x12\x12\n" +
2530+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
2531+ "\x06run_id\x18\x02 \x01(\x03R\x05runId\x12\x18\n" +
2532+ "\aattempt\x18\x03 \x01(\x05R\aattempt\x12\x15\n" +
2533+ "\x06job_id\x18\x04 \x01(\tR\x05jobId\"p\n" +
2534+ "\x17ListAnnotationsResponse\x127\n" +
2535+ "\vannotations\x18\x01 \x03(\v2\x15.ermite.JobAnnotationR\vannotations\x12\x1c\n" +
2536+ "\ttruncated\x18\x02 \x01(\bR\ttruncated\"Z\n" +
2537+ "\rJobAnnotation\x12\x15\n" +
2538+ "\x06job_id\x18\x01 \x01(\tR\x05jobId\x122\n" +
2539+ "\n" +
2540+ "annotation\x18\x02 \x01(\v2\x12.ermite.AnnotationR\n" +
2541+ "annotation\"^\n" +
2542+ "\x17GetStepSummariesRequest\x12\x12\n" +
2543+ "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
2544+ "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
2545+ "\aattempt\x18\x03 \x01(\x05R\aattempt\"k\n" +
2546+ "\x18GetStepSummariesResponse\x121\n" +
2547+ "\tsummaries\x18\x01 \x03(\v2\x13.ermite.StepSummaryR\tsummaries\x12\x1c\n" +
2548+ "\ttruncated\x18\x02 \x01(\bR\ttruncated\"J\n" +
2549+ "\vStepSummary\x12\x1f\n" +
2550+ "\vstep_number\x18\x01 \x01(\x05R\n" +
2551+ "stepNumber\x12\x1a\n" +
2552+ "\bmarkdown\x18\x02 \x01(\tR\bmarkdown\"\x87\x01\n" +
2152 "\x10GetJobLogRequest\x12\x12\n" +2553 "\x10GetJobLogRequest\x12\x12\n" +
2153 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +2554 "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x15\n" +
2154 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +2555 "\x06job_id\x18\x02 \x01(\tR\x05jobId\x12\x18\n" +
@@ -2191,12 +2592,14 @@ const file_ermite_run_proto_rawDesc = "" +
2191 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"2\n" +2592 "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"2\n" +
2192 "\x13RemoveRunnerRequest\x12\x1b\n" +2593 "\x13RemoveRunnerRequest\x12\x1b\n" +
2193 "\trunner_id\x18\x01 \x01(\tR\brunnerId\"\x16\n" +2594 "\trunner_id\x18\x01 \x01(\tR\brunnerId\"\x16\n" +
2194- "\x14RemoveRunnerResponse2\xda\x04\n" +2595+ "\x14RemoveRunnerResponse2\x85\x06\n" +
2195 "\n" +2596 "\n" +
2196 "RunService\x12=\n" +2597 "RunService\x12=\n" +
2197 "\bListRuns\x12\x17.ermite.ListRunsRequest\x1a\x18.ermite.ListRunsResponse\x127\n" +2598 "\bListRuns\x12\x17.ermite.ListRunsRequest\x1a\x18.ermite.ListRunsResponse\x127\n" +
2198 "\x06GetRun\x12\x15.ermite.GetRunRequest\x1a\x16.ermite.GetRunResponse\x127\n" +2599 "\x06GetRun\x12\x15.ermite.GetRunRequest\x1a\x16.ermite.GetRunResponse\x127\n" +
2199- "\x06GetJob\x12\x15.ermite.GetJobRequest\x1a\x16.ermite.GetJobResponse\x12B\n" +2600+ "\x06GetJob\x12\x15.ermite.GetJobRequest\x1a\x16.ermite.GetJobResponse\x12R\n" +
2601+ "\x0fListAnnotations\x12\x1e.ermite.ListAnnotationsRequest\x1a\x1f.ermite.ListAnnotationsResponse\x12U\n" +
2602+ "\x10GetStepSummaries\x12\x1f.ermite.GetStepSummariesRequest\x1a .ermite.GetStepSummariesResponse\x12B\n" +
2200 "\tGetJobLog\x12\x18.ermite.GetJobLogRequest\x1a\x19.ermite.GetJobLogResponse0\x01\x12@\n" +2603 "\tGetJobLog\x12\x18.ermite.GetJobLogRequest\x1a\x19.ermite.GetJobLogResponse0\x01\x12@\n" +
2201 "\tCancelRun\x12\x18.ermite.CancelRunRequest\x1a\x19.ermite.CancelRunResponse\x12=\n" +2604 "\tCancelRun\x12\x18.ermite.CancelRunRequest\x1a\x19.ermite.CancelRunResponse\x12=\n" +
2202 "\bRerunRun\x12\x17.ermite.RerunRunRequest\x1a\x18.ermite.RerunRunResponse\x12C\n" +2605 "\bRerunRun\x12\x17.ermite.RerunRunRequest\x1a\x18.ermite.RerunRunResponse\x12C\n" +
@@ -2219,96 +2622,111 @@ func file_ermite_run_proto_rawDescGZIP() []byte {
2219 return file_ermite_run_proto_rawDescData2622 return file_ermite_run_proto_rawDescData
2220 }2623 }
2221 2624
2222-var file_ermite_run_proto_msgTypes = make([]protoimpl.MessageInfo, 24)2625+var file_ermite_run_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
2223 var file_ermite_run_proto_goTypes = []any{2626 var file_ermite_run_proto_goTypes = []any{
2224- (*Run)(nil), // 0: ermite.Run2627+ (*Run)(nil), // 0: ermite.Run
2225- (*RunJob)(nil), // 1: ermite.RunJob2628+ (*RunJob)(nil), // 1: ermite.RunJob
2226- (*Step)(nil), // 2: ermite.Step2629+ (*Step)(nil), // 2: ermite.Step
2227- (*Check)(nil), // 3: ermite.Check2630+ (*Check)(nil), // 3: ermite.Check
2228- (*Runner)(nil), // 4: ermite.Runner2631+ (*Runner)(nil), // 4: ermite.Runner
2229- (*ListRunsRequest)(nil), // 5: ermite.ListRunsRequest2632+ (*ListRunsRequest)(nil), // 5: ermite.ListRunsRequest
2230- (*ListRunsResponse)(nil), // 6: ermite.ListRunsResponse2633+ (*ListRunsResponse)(nil), // 6: ermite.ListRunsResponse
2231- (*GetRunRequest)(nil), // 7: ermite.GetRunRequest2634+ (*GetRunRequest)(nil), // 7: ermite.GetRunRequest
2232- (*GetRunResponse)(nil), // 8: ermite.GetRunResponse2635+ (*GetRunResponse)(nil), // 8: ermite.GetRunResponse
2233- (*GetJobRequest)(nil), // 9: ermite.GetJobRequest2636+ (*GetJobRequest)(nil), // 9: ermite.GetJobRequest
2234- (*GetJobResponse)(nil), // 10: ermite.GetJobResponse2637+ (*GetJobResponse)(nil), // 10: ermite.GetJobResponse
2235- (*GetJobLogRequest)(nil), // 11: ermite.GetJobLogRequest2638+ (*ListAnnotationsRequest)(nil), // 11: ermite.ListAnnotationsRequest
2236- (*GetJobLogResponse)(nil), // 12: ermite.GetJobLogResponse2639+ (*ListAnnotationsResponse)(nil), // 12: ermite.ListAnnotationsResponse
2237- (*JobLogLine)(nil), // 13: ermite.JobLogLine2640+ (*JobAnnotation)(nil), // 13: ermite.JobAnnotation
2238- (*CancelRunRequest)(nil), // 14: ermite.CancelRunRequest2641+ (*GetStepSummariesRequest)(nil), // 14: ermite.GetStepSummariesRequest
2239- (*CancelRunResponse)(nil), // 15: ermite.CancelRunResponse2642+ (*GetStepSummariesResponse)(nil), // 15: ermite.GetStepSummariesResponse
2240- (*RerunRunRequest)(nil), // 16: ermite.RerunRunRequest2643+ (*StepSummary)(nil), // 16: ermite.StepSummary
2241- (*RerunRunResponse)(nil), // 17: ermite.RerunRunResponse2644+ (*GetJobLogRequest)(nil), // 17: ermite.GetJobLogRequest
2242- (*ListChecksRequest)(nil), // 18: ermite.ListChecksRequest2645+ (*GetJobLogResponse)(nil), // 18: ermite.GetJobLogResponse
2243- (*ListChecksResponse)(nil), // 19: ermite.ListChecksResponse2646+ (*JobLogLine)(nil), // 19: ermite.JobLogLine
2244- (*ListRunnersRequest)(nil), // 20: ermite.ListRunnersRequest2647+ (*CancelRunRequest)(nil), // 20: ermite.CancelRunRequest
2245- (*ListRunnersResponse)(nil), // 21: ermite.ListRunnersResponse2648+ (*CancelRunResponse)(nil), // 21: ermite.CancelRunResponse
2246- (*RemoveRunnerRequest)(nil), // 22: ermite.RemoveRunnerRequest2649+ (*RerunRunRequest)(nil), // 22: ermite.RerunRunRequest
2247- (*RemoveRunnerResponse)(nil), // 23: ermite.RemoveRunnerResponse2650+ (*RerunRunResponse)(nil), // 23: ermite.RerunRunResponse
2248- (CiStatus)(0), // 24: ermite.CiStatus2651+ (*ListChecksRequest)(nil), // 24: ermite.ListChecksRequest
2249- (CiConclusion)(0), // 25: ermite.CiConclusion2652+ (*ListChecksResponse)(nil), // 25: ermite.ListChecksResponse
2250- (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp2653+ (*ListRunnersRequest)(nil), // 26: ermite.ListRunnersRequest
2251- (RunnerIsolation)(0), // 27: ermite.RunnerIsolation2654+ (*ListRunnersResponse)(nil), // 27: ermite.ListRunnersResponse
2252- (StepState)(0), // 28: ermite.StepState2655+ (*RemoveRunnerRequest)(nil), // 28: ermite.RemoveRunnerRequest
2656+ (*RemoveRunnerResponse)(nil), // 29: ermite.RemoveRunnerResponse
2657+ (CiStatus)(0), // 30: ermite.CiStatus
2658+ (CiConclusion)(0), // 31: ermite.CiConclusion
2659+ (*timestamppb.Timestamp)(nil), // 32: google.protobuf.Timestamp
2660+ (RunnerIsolation)(0), // 33: ermite.RunnerIsolation
2661+ (StepState)(0), // 34: ermite.StepState
2662+ (*Annotation)(nil), // 35: ermite.Annotation
2253 }2663 }
2254 var file_ermite_run_proto_depIdxs = []int32{2664 var file_ermite_run_proto_depIdxs = []int32{
2255- 24, // 0: ermite.Run.status:type_name -> ermite.CiStatus2665+ 30, // 0: ermite.Run.status:type_name -> ermite.CiStatus
2256- 25, // 1: ermite.Run.conclusion:type_name -> ermite.CiConclusion2666+ 31, // 1: ermite.Run.conclusion:type_name -> ermite.CiConclusion
2257- 26, // 2: ermite.Run.created_at:type_name -> google.protobuf.Timestamp2667+ 32, // 2: ermite.Run.created_at:type_name -> google.protobuf.Timestamp
2258- 26, // 3: ermite.Run.started_at:type_name -> google.protobuf.Timestamp2668+ 32, // 3: ermite.Run.started_at:type_name -> google.protobuf.Timestamp
2259- 26, // 4: ermite.Run.completed_at:type_name -> google.protobuf.Timestamp2669+ 32, // 4: ermite.Run.completed_at:type_name -> google.protobuf.Timestamp
2260- 24, // 5: ermite.RunJob.status:type_name -> ermite.CiStatus2670+ 30, // 5: ermite.RunJob.status:type_name -> ermite.CiStatus
2261- 25, // 6: ermite.RunJob.conclusion:type_name -> ermite.CiConclusion2671+ 31, // 6: ermite.RunJob.conclusion:type_name -> ermite.CiConclusion
2262- 27, // 7: ermite.RunJob.isolation:type_name -> ermite.RunnerIsolation2672+ 33, // 7: ermite.RunJob.isolation:type_name -> ermite.RunnerIsolation
2263 2, // 8: ermite.RunJob.steps:type_name -> ermite.Step2673 2, // 8: ermite.RunJob.steps:type_name -> ermite.Step
2264- 26, // 9: ermite.RunJob.created_at:type_name -> google.protobuf.Timestamp2674+ 32, // 9: ermite.RunJob.created_at:type_name -> google.protobuf.Timestamp
2265- 26, // 10: ermite.RunJob.started_at:type_name -> google.protobuf.Timestamp2675+ 32, // 10: ermite.RunJob.started_at:type_name -> google.protobuf.Timestamp
2266- 26, // 11: ermite.RunJob.completed_at:type_name -> google.protobuf.Timestamp2676+ 32, // 11: ermite.RunJob.completed_at:type_name -> google.protobuf.Timestamp
2267- 28, // 12: ermite.Step.state:type_name -> ermite.StepState2677+ 34, // 12: ermite.Step.state:type_name -> ermite.StepState
2268- 25, // 13: ermite.Step.conclusion:type_name -> ermite.CiConclusion2678+ 31, // 13: ermite.Step.conclusion:type_name -> ermite.CiConclusion
2269- 26, // 14: ermite.Step.started_at:type_name -> google.protobuf.Timestamp2679+ 32, // 14: ermite.Step.started_at:type_name -> google.protobuf.Timestamp
2270- 26, // 15: ermite.Step.completed_at:type_name -> google.protobuf.Timestamp2680+ 32, // 15: ermite.Step.completed_at:type_name -> google.protobuf.Timestamp
2271- 24, // 16: ermite.Check.status:type_name -> ermite.CiStatus2681+ 31, // 16: ermite.Step.outcome:type_name -> ermite.CiConclusion
2272- 25, // 17: ermite.Check.conclusion:type_name -> ermite.CiConclusion2682+ 30, // 17: ermite.Check.status:type_name -> ermite.CiStatus
2273- 26, // 18: ermite.Check.started_at:type_name -> google.protobuf.Timestamp2683+ 31, // 18: ermite.Check.conclusion:type_name -> ermite.CiConclusion
2274- 26, // 19: ermite.Check.completed_at:type_name -> google.protobuf.Timestamp2684+ 32, // 19: ermite.Check.started_at:type_name -> google.protobuf.Timestamp
2275- 27, // 20: ermite.Runner.isolation:type_name -> ermite.RunnerIsolation2685+ 32, // 20: ermite.Check.completed_at:type_name -> google.protobuf.Timestamp
2276- 26, // 21: ermite.Runner.registered_at:type_name -> google.protobuf.Timestamp2686+ 33, // 21: ermite.Runner.isolation:type_name -> ermite.RunnerIsolation
2277- 26, // 22: ermite.Runner.last_seen:type_name -> google.protobuf.Timestamp2687+ 32, // 22: ermite.Runner.registered_at:type_name -> google.protobuf.Timestamp
2278- 24, // 23: ermite.ListRunsRequest.status:type_name -> ermite.CiStatus2688+ 32, // 23: ermite.Runner.last_seen:type_name -> google.protobuf.Timestamp
2279- 0, // 24: ermite.ListRunsResponse.runs:type_name -> ermite.Run2689+ 30, // 24: ermite.ListRunsRequest.status:type_name -> ermite.CiStatus
2280- 0, // 25: ermite.GetRunResponse.run:type_name -> ermite.Run2690+ 0, // 25: ermite.ListRunsResponse.runs:type_name -> ermite.Run
2281- 1, // 26: ermite.GetRunResponse.jobs:type_name -> ermite.RunJob2691+ 0, // 26: ermite.GetRunResponse.run:type_name -> ermite.Run
2282- 1, // 27: ermite.GetJobResponse.job:type_name -> ermite.RunJob2692+ 1, // 27: ermite.GetRunResponse.jobs:type_name -> ermite.RunJob
2283- 13, // 28: ermite.GetJobLogResponse.lines:type_name -> ermite.JobLogLine2693+ 1, // 28: ermite.GetJobResponse.job:type_name -> ermite.RunJob
2284- 26, // 29: ermite.JobLogLine.time:type_name -> google.protobuf.Timestamp2694+ 13, // 29: ermite.ListAnnotationsResponse.annotations:type_name -> ermite.JobAnnotation
2285- 0, // 30: ermite.CancelRunResponse.run:type_name -> ermite.Run2695+ 35, // 30: ermite.JobAnnotation.annotation:type_name -> ermite.Annotation
2286- 0, // 31: ermite.RerunRunResponse.run:type_name -> ermite.Run2696+ 16, // 31: ermite.GetStepSummariesResponse.summaries:type_name -> ermite.StepSummary
2287- 3, // 32: ermite.ListChecksResponse.checks:type_name -> ermite.Check2697+ 19, // 32: ermite.GetJobLogResponse.lines:type_name -> ermite.JobLogLine
2288- 4, // 33: ermite.ListRunnersResponse.runners:type_name -> ermite.Runner2698+ 32, // 33: ermite.JobLogLine.time:type_name -> google.protobuf.Timestamp
2289- 5, // 34: ermite.RunService.ListRuns:input_type -> ermite.ListRunsRequest2699+ 0, // 34: ermite.CancelRunResponse.run:type_name -> ermite.Run
2290- 7, // 35: ermite.RunService.GetRun:input_type -> ermite.GetRunRequest2700+ 0, // 35: ermite.RerunRunResponse.run:type_name -> ermite.Run
2291- 9, // 36: ermite.RunService.GetJob:input_type -> ermite.GetJobRequest2701+ 3, // 36: ermite.ListChecksResponse.checks:type_name -> ermite.Check
2292- 11, // 37: ermite.RunService.GetJobLog:input_type -> ermite.GetJobLogRequest2702+ 4, // 37: ermite.ListRunnersResponse.runners:type_name -> ermite.Runner
2293- 14, // 38: ermite.RunService.CancelRun:input_type -> ermite.CancelRunRequest2703+ 5, // 38: ermite.RunService.ListRuns:input_type -> ermite.ListRunsRequest
2294- 16, // 39: ermite.RunService.RerunRun:input_type -> ermite.RerunRunRequest2704+ 7, // 39: ermite.RunService.GetRun:input_type -> ermite.GetRunRequest
2295- 18, // 40: ermite.RunService.ListChecks:input_type -> ermite.ListChecksRequest2705+ 9, // 40: ermite.RunService.GetJob:input_type -> ermite.GetJobRequest
2296- 20, // 41: ermite.RunService.ListRunners:input_type -> ermite.ListRunnersRequest2706+ 11, // 41: ermite.RunService.ListAnnotations:input_type -> ermite.ListAnnotationsRequest
2297- 22, // 42: ermite.RunService.RemoveRunner:input_type -> ermite.RemoveRunnerRequest2707+ 14, // 42: ermite.RunService.GetStepSummaries:input_type -> ermite.GetStepSummariesRequest
2298- 6, // 43: ermite.RunService.ListRuns:output_type -> ermite.ListRunsResponse2708+ 17, // 43: ermite.RunService.GetJobLog:input_type -> ermite.GetJobLogRequest
2299- 8, // 44: ermite.RunService.GetRun:output_type -> ermite.GetRunResponse2709+ 20, // 44: ermite.RunService.CancelRun:input_type -> ermite.CancelRunRequest
2300- 10, // 45: ermite.RunService.GetJob:output_type -> ermite.GetJobResponse2710+ 22, // 45: ermite.RunService.RerunRun:input_type -> ermite.RerunRunRequest
2301- 12, // 46: ermite.RunService.GetJobLog:output_type -> ermite.GetJobLogResponse2711+ 24, // 46: ermite.RunService.ListChecks:input_type -> ermite.ListChecksRequest
2302- 15, // 47: ermite.RunService.CancelRun:output_type -> ermite.CancelRunResponse2712+ 26, // 47: ermite.RunService.ListRunners:input_type -> ermite.ListRunnersRequest
2303- 17, // 48: ermite.RunService.RerunRun:output_type -> ermite.RerunRunResponse2713+ 28, // 48: ermite.RunService.RemoveRunner:input_type -> ermite.RemoveRunnerRequest
2304- 19, // 49: ermite.RunService.ListChecks:output_type -> ermite.ListChecksResponse2714+ 6, // 49: ermite.RunService.ListRuns:output_type -> ermite.ListRunsResponse
2305- 21, // 50: ermite.RunService.ListRunners:output_type -> ermite.ListRunnersResponse2715+ 8, // 50: ermite.RunService.GetRun:output_type -> ermite.GetRunResponse
2306- 23, // 51: ermite.RunService.RemoveRunner:output_type -> ermite.RemoveRunnerResponse2716+ 10, // 51: ermite.RunService.GetJob:output_type -> ermite.GetJobResponse
2307- 43, // [43:52] is the sub-list for method output_type2717+ 12, // 52: ermite.RunService.ListAnnotations:output_type -> ermite.ListAnnotationsResponse
2308- 34, // [34:43] is the sub-list for method input_type2718+ 15, // 53: ermite.RunService.GetStepSummaries:output_type -> ermite.GetStepSummariesResponse
2309- 34, // [34:34] is the sub-list for extension type_name2719+ 18, // 54: ermite.RunService.GetJobLog:output_type -> ermite.GetJobLogResponse
2310- 34, // [34:34] is the sub-list for extension extendee2720+ 21, // 55: ermite.RunService.CancelRun:output_type -> ermite.CancelRunResponse
2311- 0, // [0:34] is the sub-list for field type_name2721+ 23, // 56: ermite.RunService.RerunRun:output_type -> ermite.RerunRunResponse
2722+ 25, // 57: ermite.RunService.ListChecks:output_type -> ermite.ListChecksResponse
2723+ 27, // 58: ermite.RunService.ListRunners:output_type -> ermite.ListRunnersResponse
2724+ 29, // 59: ermite.RunService.RemoveRunner:output_type -> ermite.RemoveRunnerResponse
2725+ 49, // [49:60] is the sub-list for method output_type
2726+ 38, // [38:49] is the sub-list for method input_type
2727+ 38, // [38:38] is the sub-list for extension type_name
2728+ 38, // [38:38] is the sub-list for extension extendee
2729+ 0, // [0:38] is the sub-list for field type_name
2312 }2730 }
2313 2731
2314 func init() { file_ermite_run_proto_init() }2732 func init() { file_ermite_run_proto_init() }
@@ -2323,7 +2741,7 @@ func file_ermite_run_proto_init() {
2323 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),2741 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
2324 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_run_proto_rawDesc), len(file_ermite_run_proto_rawDesc)),2742 RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_run_proto_rawDesc), len(file_ermite_run_proto_rawDesc)),
2325 NumEnums: 0,2743 NumEnums: 0,
2326- NumMessages: 24,2744+ NumMessages: 30,
2327 NumExtensions: 0,2745 NumExtensions: 0,
2328 NumServices: 1,2746 NumServices: 1,
2329 },2747 },
M gen/ermite/runner.pb.go +838 -78 generated file: collapsed
M gen/ermite/server.pb.go +5 -1 generated file: collapsed
M gen_test.go +100 -0
@@ -54,10 +54,14 @@ func TestProcedures(t *testing.T) {
5454 {ermiteconnect.RunnerServiceHeartbeatProcedure, "/ermite.RunnerService/Heartbeat"},
5555 {ermiteconnect.RunnerServiceWatchJobProcedure, "/ermite.RunnerService/WatchJob"},
5656 {ermiteconnect.RunnerServiceCompleteJobProcedure, "/ermite.RunnerService/CompleteJob"},
57+ {ermiteconnect.RunnerServiceResolveActionsProcedure, "/ermite.RunnerService/ResolveActions"},
58+ {ermiteconnect.RunnerServiceUploadSummaryProcedure, "/ermite.RunnerService/UploadSummary"},
5759 {ermiteconnect.RunServiceListRunsProcedure, "/ermite.RunService/ListRuns"},
5860 {ermiteconnect.RunServiceGetRunProcedure, "/ermite.RunService/GetRun"},
5961 {ermiteconnect.RunServiceGetJobProcedure, "/ermite.RunService/GetJob"},
6062 {ermiteconnect.RunServiceGetJobLogProcedure, "/ermite.RunService/GetJobLog"},
63+ {ermiteconnect.RunServiceListAnnotationsProcedure, "/ermite.RunService/ListAnnotations"},
64+ {ermiteconnect.RunServiceGetStepSummariesProcedure, "/ermite.RunService/GetStepSummaries"},
6165 {ermiteconnect.RunServiceCancelRunProcedure, "/ermite.RunService/CancelRun"},
6266 {ermiteconnect.RunServiceRerunRunProcedure, "/ermite.RunService/RerunRun"},
6367 {ermiteconnect.RunServiceListChecksProcedure, "/ermite.RunService/ListChecks"},
@@ -120,6 +124,13 @@ func TestEnumNumbers(t *testing.T) {
120124 {"CANCEL_REASON_USER", int32(ermite.CancelReason_CANCEL_REASON_USER), 1},
121125 {"CANCEL_REASON_FAIL_FAST", int32(ermite.CancelReason_CANCEL_REASON_FAIL_FAST), 2},
122126 {"CANCEL_REASON_TIMEOUT", int32(ermite.CancelReason_CANCEL_REASON_TIMEOUT), 3},
127+ {"ANNOTATION_LEVEL_UNSPECIFIED", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED), 0},
128+ {"ANNOTATION_LEVEL_NOTICE", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_NOTICE), 1},
129+ {"ANNOTATION_LEVEL_WARNING", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_WARNING), 2},
130+ {"ANNOTATION_LEVEL_FAILURE", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_FAILURE), 3},
131+ {"ACTION_SOURCE_UNSPECIFIED", int32(ermite.ActionSource_ACTION_SOURCE_UNSPECIFIED), 0},
132+ {"ACTION_SOURCE_GITHUB", int32(ermite.ActionSource_ACTION_SOURCE_GITHUB), 1},
133+ {"ACTION_SOURCE_ERMITE", int32(ermite.ActionSource_ACTION_SOURCE_ERMITE), 2},
123134 }
124135 for _, e := range enums {
125136 if e.got != e.want {
@@ -350,3 +361,92 @@ func TestRunNameField(t *testing.T) {
350361 t.Errorf("round trip: name %q, workflow_name %q", out.GetName(), out.GetWorkflowName())
351362 }
352363 }
364+
365+// TestCI2FieldNumbers pins the numbers of the fields added for CI-2.
366+func TestCI2FieldNumbers(t *testing.T) {
367+ tests := []struct {
368+ msg proto.Message
369+ fields map[string]int
370+ }{
371+ {&ermite.Job{}, map[string]int{"github_token": 15}},
372+ {&ermite.UpdateJobRequest{}, map[string]int{"annotations": 3}},
373+ {&ermite.CompleteJobRequest{}, map[string]int{"annotations": 6}},
374+ {&ermite.StepUpdate{}, map[string]int{"outcome": 7}},
375+ {&ermite.Step{}, map[string]int{"outcome": 9}},
376+ {&ermite.Annotation{}, map[string]int{
377+ "level": 1, "title": 2, "message": 3, "file": 4, "start_line": 5,
378+ "end_line": 6, "start_column": 7, "end_column": 8, "step_number": 9,
379+ }},
380+ {&ermite.ActionRef{}, map[string]int{"uses": 1}},
381+ {&ermite.ResolveActionsRequest{}, map[string]int{"job_id": 1, "refs": 2}},
382+ {&ermite.ResolveActionsResponse{}, map[string]int{"actions": 1}},
383+ {&ermite.ResolvedAction{}, map[string]int{
384+ "ref": 1, "name_with_owner": 2, "path": 3, "resolved_sha": 4,
385+ "tarball_url": 5, "token": 6, "source": 7, "error": 8,
386+ }},
387+ {&ermite.UploadSummaryRequest{}, map[string]int{"job_id": 1, "step_number": 2, "markdown": 3}},
388+ {&ermite.ListAnnotationsRequest{}, map[string]int{"repo": 1, "run_id": 2, "attempt": 3, "job_id": 4}},
389+ {&ermite.ListAnnotationsResponse{}, map[string]int{"annotations": 1, "truncated": 2}},
390+ {&ermite.JobAnnotation{}, map[string]int{"job_id": 1, "annotation": 2}},
391+ {&ermite.GetStepSummariesRequest{}, map[string]int{"repo": 1, "job_id": 2, "attempt": 3}},
392+ {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1, "truncated": 2}},
393+ {&ermite.StepSummary{}, map[string]int{"step_number": 1, "markdown": 2}},
394+ }
395+ for _, tt := range tests {
396+ md := tt.msg.ProtoReflect().Descriptor()
397+ for name, num := range tt.fields {
398+ if fd := md.Fields().ByName(protoreflect.Name(name)); fd == nil || int(fd.Number()) != num {
399+ t.Errorf("%s.%s: %v, want number %d", md.Name(), name, fd, num)
400+ }
401+ }
402+ }
403+}
404+
405+// TestCI2RoundTrip checks that the CI-2 messages survive the wire.
406+func TestCI2RoundTrip(t *testing.T) {
407+ msgs := []proto.Message{
408+ &ermite.Job{JobId: "j1", GithubToken: "ermitegh_x"},
409+ &ermite.UpdateJobRequest{
410+ JobId: "j1",
411+ Steps: []*ermite.StepUpdate{{
412+ Number: 2, State: ermite.StepState_STEP_STATE_COMPLETED,
413+ Conclusion: ermite.CiConclusion_CI_CONCLUSION_SUCCESS,
414+ Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE,
415+ }},
416+ Annotations: []*ermite.Annotation{{
417+ Level: ermite.AnnotationLevel_ANNOTATION_LEVEL_WARNING, Title: "t", Message: "m",
418+ File: "a.go", StartLine: 1, EndLine: 2, StartColumn: 3, EndColumn: 4, StepNumber: 2,
419+ }},
420+ },
421+ &ermite.CompleteJobRequest{
422+ JobId: "j1",
423+ Conclusion: ermite.CiConclusion_CI_CONCLUSION_SUCCESS,
424+ Annotations: []*ermite.Annotation{{Level: ermite.AnnotationLevel_ANNOTATION_LEVEL_FAILURE, Message: "m", StepNumber: 3}},
425+ },
426+ &ermite.ResolveActionsRequest{JobId: "j1", Refs: []*ermite.ActionRef{{Uses: "actions/checkout@v4"}, {Uses: "o/r/p@main"}}},
427+ &ermite.ResolveActionsResponse{Actions: []*ermite.ResolvedAction{
428+ {
429+ Ref: "o/r/p@main", NameWithOwner: "o/r", Path: "p", ResolvedSha: "0123456789012345678901234567890123456789",
430+ TarballUrl: "https://example.test/o/r.tar.gz", Token: "t", Source: ermite.ActionSource_ACTION_SOURCE_ERMITE,
431+ },
432+ {Ref: "x/y@z", Error: "Unable to resolve action `x/y@z`, unable to find version `z`"},
433+ }},
434+ &ermite.UploadSummaryRequest{JobId: "j1", StepNumber: 2, Markdown: "# hi"},
435+ &ermite.ListAnnotationsResponse{Annotations: []*ermite.JobAnnotation{{JobId: "j1", Annotation: &ermite.Annotation{Message: "m"}}}, Truncated: true},
436+ &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}, Truncated: true},
437+ &ermite.RunJob{Id: "j1", Steps: []*ermite.Step{{Number: 2, Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE}}},
438+ }
439+ for _, in := range msgs {
440+ b, err := proto.Marshal(in)
441+ if err != nil {
442+ t.Fatal(err)
443+ }
444+ out := in.ProtoReflect().New().Interface()
445+ if err := proto.Unmarshal(b, out); err != nil {
446+ t.Fatal(err)
447+ }
448+ if !proto.Equal(in, out) {
449+ t.Errorf("%T: round trip mismatch: %v != %v", in, out, in)
450+ }
451+ }
452+}
@@ -54,10 +54,14 @@ func TestProcedures(t *testing.T) {
54 {ermiteconnect.RunnerServiceHeartbeatProcedure, "/ermite.RunnerService/Heartbeat"},54 {ermiteconnect.RunnerServiceHeartbeatProcedure, "/ermite.RunnerService/Heartbeat"},
55 {ermiteconnect.RunnerServiceWatchJobProcedure, "/ermite.RunnerService/WatchJob"},55 {ermiteconnect.RunnerServiceWatchJobProcedure, "/ermite.RunnerService/WatchJob"},
56 {ermiteconnect.RunnerServiceCompleteJobProcedure, "/ermite.RunnerService/CompleteJob"},56 {ermiteconnect.RunnerServiceCompleteJobProcedure, "/ermite.RunnerService/CompleteJob"},
57+ {ermiteconnect.RunnerServiceResolveActionsProcedure, "/ermite.RunnerService/ResolveActions"},
58+ {ermiteconnect.RunnerServiceUploadSummaryProcedure, "/ermite.RunnerService/UploadSummary"},
57 {ermiteconnect.RunServiceListRunsProcedure, "/ermite.RunService/ListRuns"},59 {ermiteconnect.RunServiceListRunsProcedure, "/ermite.RunService/ListRuns"},
58 {ermiteconnect.RunServiceGetRunProcedure, "/ermite.RunService/GetRun"},60 {ermiteconnect.RunServiceGetRunProcedure, "/ermite.RunService/GetRun"},
59 {ermiteconnect.RunServiceGetJobProcedure, "/ermite.RunService/GetJob"},61 {ermiteconnect.RunServiceGetJobProcedure, "/ermite.RunService/GetJob"},
60 {ermiteconnect.RunServiceGetJobLogProcedure, "/ermite.RunService/GetJobLog"},62 {ermiteconnect.RunServiceGetJobLogProcedure, "/ermite.RunService/GetJobLog"},
63+ {ermiteconnect.RunServiceListAnnotationsProcedure, "/ermite.RunService/ListAnnotations"},
64+ {ermiteconnect.RunServiceGetStepSummariesProcedure, "/ermite.RunService/GetStepSummaries"},
61 {ermiteconnect.RunServiceCancelRunProcedure, "/ermite.RunService/CancelRun"},65 {ermiteconnect.RunServiceCancelRunProcedure, "/ermite.RunService/CancelRun"},
62 {ermiteconnect.RunServiceRerunRunProcedure, "/ermite.RunService/RerunRun"},66 {ermiteconnect.RunServiceRerunRunProcedure, "/ermite.RunService/RerunRun"},
63 {ermiteconnect.RunServiceListChecksProcedure, "/ermite.RunService/ListChecks"},67 {ermiteconnect.RunServiceListChecksProcedure, "/ermite.RunService/ListChecks"},
@@ -120,6 +124,13 @@ func TestEnumNumbers(t *testing.T) {
120 {"CANCEL_REASON_USER", int32(ermite.CancelReason_CANCEL_REASON_USER), 1},124 {"CANCEL_REASON_USER", int32(ermite.CancelReason_CANCEL_REASON_USER), 1},
121 {"CANCEL_REASON_FAIL_FAST", int32(ermite.CancelReason_CANCEL_REASON_FAIL_FAST), 2},125 {"CANCEL_REASON_FAIL_FAST", int32(ermite.CancelReason_CANCEL_REASON_FAIL_FAST), 2},
122 {"CANCEL_REASON_TIMEOUT", int32(ermite.CancelReason_CANCEL_REASON_TIMEOUT), 3},126 {"CANCEL_REASON_TIMEOUT", int32(ermite.CancelReason_CANCEL_REASON_TIMEOUT), 3},
127+ {"ANNOTATION_LEVEL_UNSPECIFIED", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED), 0},
128+ {"ANNOTATION_LEVEL_NOTICE", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_NOTICE), 1},
129+ {"ANNOTATION_LEVEL_WARNING", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_WARNING), 2},
130+ {"ANNOTATION_LEVEL_FAILURE", int32(ermite.AnnotationLevel_ANNOTATION_LEVEL_FAILURE), 3},
131+ {"ACTION_SOURCE_UNSPECIFIED", int32(ermite.ActionSource_ACTION_SOURCE_UNSPECIFIED), 0},
132+ {"ACTION_SOURCE_GITHUB", int32(ermite.ActionSource_ACTION_SOURCE_GITHUB), 1},
133+ {"ACTION_SOURCE_ERMITE", int32(ermite.ActionSource_ACTION_SOURCE_ERMITE), 2},
123 }134 }
124 for _, e := range enums {135 for _, e := range enums {
125 if e.got != e.want {136 if e.got != e.want {
@@ -350,3 +361,92 @@ func TestRunNameField(t *testing.T) {
350 t.Errorf("round trip: name %q, workflow_name %q", out.GetName(), out.GetWorkflowName())361 t.Errorf("round trip: name %q, workflow_name %q", out.GetName(), out.GetWorkflowName())
351 }362 }
352 }363 }
364+
365+// TestCI2FieldNumbers pins the numbers of the fields added for CI-2.
366+func TestCI2FieldNumbers(t *testing.T) {
367+ tests := []struct {
368+ msg proto.Message
369+ fields map[string]int
370+ }{
371+ {&ermite.Job{}, map[string]int{"github_token": 15}},
372+ {&ermite.UpdateJobRequest{}, map[string]int{"annotations": 3}},
373+ {&ermite.CompleteJobRequest{}, map[string]int{"annotations": 6}},
374+ {&ermite.StepUpdate{}, map[string]int{"outcome": 7}},
375+ {&ermite.Step{}, map[string]int{"outcome": 9}},
376+ {&ermite.Annotation{}, map[string]int{
377+ "level": 1, "title": 2, "message": 3, "file": 4, "start_line": 5,
378+ "end_line": 6, "start_column": 7, "end_column": 8, "step_number": 9,
379+ }},
380+ {&ermite.ActionRef{}, map[string]int{"uses": 1}},
381+ {&ermite.ResolveActionsRequest{}, map[string]int{"job_id": 1, "refs": 2}},
382+ {&ermite.ResolveActionsResponse{}, map[string]int{"actions": 1}},
383+ {&ermite.ResolvedAction{}, map[string]int{
384+ "ref": 1, "name_with_owner": 2, "path": 3, "resolved_sha": 4,
385+ "tarball_url": 5, "token": 6, "source": 7, "error": 8,
386+ }},
387+ {&ermite.UploadSummaryRequest{}, map[string]int{"job_id": 1, "step_number": 2, "markdown": 3}},
388+ {&ermite.ListAnnotationsRequest{}, map[string]int{"repo": 1, "run_id": 2, "attempt": 3, "job_id": 4}},
389+ {&ermite.ListAnnotationsResponse{}, map[string]int{"annotations": 1, "truncated": 2}},
390+ {&ermite.JobAnnotation{}, map[string]int{"job_id": 1, "annotation": 2}},
391+ {&ermite.GetStepSummariesRequest{}, map[string]int{"repo": 1, "job_id": 2, "attempt": 3}},
392+ {&ermite.GetStepSummariesResponse{}, map[string]int{"summaries": 1, "truncated": 2}},
393+ {&ermite.StepSummary{}, map[string]int{"step_number": 1, "markdown": 2}},
394+ }
395+ for _, tt := range tests {
396+ md := tt.msg.ProtoReflect().Descriptor()
397+ for name, num := range tt.fields {
398+ if fd := md.Fields().ByName(protoreflect.Name(name)); fd == nil || int(fd.Number()) != num {
399+ t.Errorf("%s.%s: %v, want number %d", md.Name(), name, fd, num)
400+ }
401+ }
402+ }
403+}
404+
405+// TestCI2RoundTrip checks that the CI-2 messages survive the wire.
406+func TestCI2RoundTrip(t *testing.T) {
407+ msgs := []proto.Message{
408+ &ermite.Job{JobId: "j1", GithubToken: "ermitegh_x"},
409+ &ermite.UpdateJobRequest{
410+ JobId: "j1",
411+ Steps: []*ermite.StepUpdate{{
412+ Number: 2, State: ermite.StepState_STEP_STATE_COMPLETED,
413+ Conclusion: ermite.CiConclusion_CI_CONCLUSION_SUCCESS,
414+ Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE,
415+ }},
416+ Annotations: []*ermite.Annotation{{
417+ Level: ermite.AnnotationLevel_ANNOTATION_LEVEL_WARNING, Title: "t", Message: "m",
418+ File: "a.go", StartLine: 1, EndLine: 2, StartColumn: 3, EndColumn: 4, StepNumber: 2,
419+ }},
420+ },
421+ &ermite.CompleteJobRequest{
422+ JobId: "j1",
423+ Conclusion: ermite.CiConclusion_CI_CONCLUSION_SUCCESS,
424+ Annotations: []*ermite.Annotation{{Level: ermite.AnnotationLevel_ANNOTATION_LEVEL_FAILURE, Message: "m", StepNumber: 3}},
425+ },
426+ &ermite.ResolveActionsRequest{JobId: "j1", Refs: []*ermite.ActionRef{{Uses: "actions/checkout@v4"}, {Uses: "o/r/p@main"}}},
427+ &ermite.ResolveActionsResponse{Actions: []*ermite.ResolvedAction{
428+ {
429+ Ref: "o/r/p@main", NameWithOwner: "o/r", Path: "p", ResolvedSha: "0123456789012345678901234567890123456789",
430+ TarballUrl: "https://example.test/o/r.tar.gz", Token: "t", Source: ermite.ActionSource_ACTION_SOURCE_ERMITE,
431+ },
432+ {Ref: "x/y@z", Error: "Unable to resolve action `x/y@z`, unable to find version `z`"},
433+ }},
434+ &ermite.UploadSummaryRequest{JobId: "j1", StepNumber: 2, Markdown: "# hi"},
435+ &ermite.ListAnnotationsResponse{Annotations: []*ermite.JobAnnotation{{JobId: "j1", Annotation: &ermite.Annotation{Message: "m"}}}, Truncated: true},
436+ &ermite.GetStepSummariesResponse{Summaries: []*ermite.StepSummary{{StepNumber: 2, Markdown: "# hi"}}, Truncated: true},
437+ &ermite.RunJob{Id: "j1", Steps: []*ermite.Step{{Number: 2, Outcome: ermite.CiConclusion_CI_CONCLUSION_FAILURE}}},
438+ }
439+ for _, in := range msgs {
440+ b, err := proto.Marshal(in)
441+ if err != nil {
442+ t.Fatal(err)
443+ }
444+ out := in.ProtoReflect().New().Interface()
445+ if err := proto.Unmarshal(b, out); err != nil {
446+ t.Fatal(err)
447+ }
448+ if !proto.Equal(in, out) {
449+ t.Errorf("%T: round trip mismatch: %v != %v", in, out, in)
450+ }
451+ }
452+}
M proto/ermite/run.proto +93 -5
@@ -172,6 +172,11 @@ message Step {
172172 // IN_PROGRESS step it is the number of lines held at the time of the
173173 // call and grows; for a step without a line it equals log_start.
174174 int64 log_end = 8;
175+ // Outcome is how the step ended before continue-on-error was applied, as
176+ // StepUpdate.outcome: it differs from conclusion only for a failed step with
177+ // continue-on-error. Unset until state is COMPLETED, and for a step stored
178+ // by a server or runner before this field existed (read it as conclusion).
179+ CiConclusion outcome = 9;
175180 }
176181
177182 // Check is the result of one job on one commit, the unit shown next to a
@@ -238,9 +243,9 @@ message Runner {
238243 // RunService reads and controls CI runs, like `gh run` does on GitHub. It is for
239244 // owners and their tools; runners use RunnerService.
240245 //
241-// Runs, jobs, checks and logs belong to a repository, and reading them needs
242-// the same access as reading it: nothing for a public repository, the
243-// repo:read scope for a private one. A repository that does not exist or that
246+// Runs, jobs, checks, logs, annotations and summaries belong to a repository,
247+// and reading them needs the same access as reading it: nothing for a public
248+// repository, the repo:read scope for a private one. A repository that does not exist or that
244249 // the caller cannot read gives not_found; so does a run or a job that belongs
245250 // to another repository than the one named (ids are global but are always
246251 // checked against the repository). Cancelling and re-running need the ci:write
@@ -255,10 +260,13 @@ message Runner {
255260 // page_token is the next_page_token of a previous response for the same
256261 // request (other fields must be unchanged).
257262 //
258-// Servers that implement the runs side (every RPC but ListRunners and
259-// RemoveRunner) list "ci.runs" in GetVersionResponse.features; those that
263+// Servers that implement the runs side (every RPC but ListRunners,
264+// RemoveRunner, ListAnnotations and GetStepSummaries) list "ci.runs" in
265+// GetVersionResponse.features; those that
260266 // implement the runners side list "ci.runners", as RunnerService does. A server
261267 // that honours the filters of ListRunsRequest also lists "ci.runs.filters".
268+// ListAnnotations needs "ci.annotations" and GetStepSummaries "ci.summaries",
269+// which are also the features of the runner side of each.
262270 service RunService {
263271 // ListRuns lists the runs of a repository, highest id (newest) first. Each
264272 // run is described by its latest attempt. The filters narrow the result; a
@@ -273,6 +281,25 @@ service RunService {
273281 // GetJob returns one job with its steps. Fails with not_found if the job
274282 // or the attempt does not exist.
275283 rpc GetJob(GetJobRequest) returns (GetJobResponse);
284+ // ListAnnotations lists the annotations of a run attempt, optionally of one
285+ // job, ordered by job (as in GetRun), step number, then the order in which
286+ // the step produced them. For each job it gives the annotations of the
287+ // attempt in which that job executed (RunJob.attempt), which is lower than
288+ // 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
289+ // 1,000 annotations (truncated tells). A run without annotations gives an
290+ // empty list. Only servers with the feature "ci.annotations" implement it
291+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
292+ // the job does not exist, or if the job is not a job of the run.
293+ rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse);
294+ // GetStepSummaries returns the job summaries (the Markdown written to
295+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
296+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
297+ // steps that have one, in step order; truncated says there are more. Needs
298+ // the same access as GetJob. Only servers with the feature
299+ // "ci.summaries" implement it (unimplemented otherwise). A job without
300+ // summaries gives an empty list. Fails with not_found if the job or the
301+ // attempt does not exist.
302+ rpc GetStepSummaries(GetStepSummariesRequest) returns (GetStepSummariesResponse);
276303 // GetJobLog streams the lines of the log of a job, from a line number. The
277304 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
278305 // text each.
@@ -393,6 +420,67 @@ message GetJobResponse {
393420 RunJob job = 1;
394421 }
395422
423+// ListAnnotationsRequest selects the annotations of a run.
424+message ListAnnotationsRequest {
425+ // Repo is the repository name.
426+ string repo = 1;
427+ // RunId is the Run.id.
428+ int64 run_id = 2;
429+ // Attempt is the attempt to read. 0 means the latest, and then each job
430+ // contributes the annotations of its own RunJob.attempt (not necessarily the
431+ // latest attempt of the run, see ListAnnotations).
432+ int32 attempt = 3;
433+ // JobId restricts the result to one job (RunJob.id). Empty means every job
434+ // of the run.
435+ string job_id = 4;
436+}
437+
438+// ListAnnotationsResponse holds the annotations of a run.
439+message ListAnnotationsResponse {
440+ // Annotations are the annotations, at most 1,000.
441+ repeated JobAnnotation annotations = 1;
442+ // Truncated is true when there are more annotations than annotations holds.
443+ bool truncated = 2;
444+}
445+
446+// JobAnnotation is an annotation with the job it belongs to.
447+message JobAnnotation {
448+ // JobId is the RunJob.id of the job.
449+ string job_id = 1;
450+ // Annotation is the annotation as the runner sent it, after the server
451+ // checked it. Its step_number is the step of the job.
452+ Annotation annotation = 2;
453+}
454+
455+// GetStepSummariesRequest selects a job.
456+message GetStepSummariesRequest {
457+ // Repo is the repository name.
458+ string repo = 1;
459+ // JobId is the RunJob.id.
460+ string job_id = 2;
461+ // Attempt is the RunJob.attempt to read. 0 means the latest.
462+ int32 attempt = 3;
463+}
464+
465+// GetStepSummariesResponse holds the summaries of a job.
466+message GetStepSummariesResponse {
467+ // Summaries are the summaries of the steps that have one, ordered by step
468+ // number: at most 20, the first 20 steps having one.
469+ repeated StepSummary summaries = 1;
470+ // Truncated is true when the job has more than 20 steps with a summary and
471+ // summaries holds only the first 20.
472+ bool truncated = 2;
473+}
474+
475+// StepSummary is the job summary of one step.
476+message StepSummary {
477+ // StepNumber is the number of the step (see Step.number).
478+ int32 step_number = 1;
479+ // Markdown is the summary as uploaded, at most 1 MiB. Clients render it
480+ // safely: it is untrusted content (raw HTML and script URLs must not run).
481+ string markdown = 2;
482+}
483+
396484 // GetJobLogRequest selects the lines to stream.
397485 message GetJobLogRequest {
398486 // Repo is the repository name.
@@ -172,6 +172,11 @@ message Step {
172 // IN_PROGRESS step it is the number of lines held at the time of the172 // IN_PROGRESS step it is the number of lines held at the time of the
173 // call and grows; for a step without a line it equals log_start.173 // call and grows; for a step without a line it equals log_start.
174 int64 log_end = 8;174 int64 log_end = 8;
175+ // Outcome is how the step ended before continue-on-error was applied, as
176+ // StepUpdate.outcome: it differs from conclusion only for a failed step with
177+ // continue-on-error. Unset until state is COMPLETED, and for a step stored
178+ // by a server or runner before this field existed (read it as conclusion).
179+ CiConclusion outcome = 9;
175 }180 }
176 181
177 // Check is the result of one job on one commit, the unit shown next to a182 // Check is the result of one job on one commit, the unit shown next to a
@@ -238,9 +243,9 @@ message Runner {
238 // RunService reads and controls CI runs, like `gh run` does on GitHub. It is for243 // RunService reads and controls CI runs, like `gh run` does on GitHub. It is for
239 // owners and their tools; runners use RunnerService.244 // owners and their tools; runners use RunnerService.
240 //245 //
241-// Runs, jobs, checks and logs belong to a repository, and reading them needs246+// Runs, jobs, checks, logs, annotations and summaries belong to a repository,
242-// the same access as reading it: nothing for a public repository, the247+// and reading them needs the same access as reading it: nothing for a public
243-// repo:read scope for a private one. A repository that does not exist or that248+// repository, the repo:read scope for a private one. A repository that does not exist or that
244 // the caller cannot read gives not_found; so does a run or a job that belongs249 // the caller cannot read gives not_found; so does a run or a job that belongs
245 // to another repository than the one named (ids are global but are always250 // to another repository than the one named (ids are global but are always
246 // checked against the repository). Cancelling and re-running need the ci:write251 // checked against the repository). Cancelling and re-running need the ci:write
@@ -255,10 +260,13 @@ message Runner {
255 // page_token is the next_page_token of a previous response for the same260 // page_token is the next_page_token of a previous response for the same
256 // request (other fields must be unchanged).261 // request (other fields must be unchanged).
257 //262 //
258-// Servers that implement the runs side (every RPC but ListRunners and263+// Servers that implement the runs side (every RPC but ListRunners,
259-// RemoveRunner) list "ci.runs" in GetVersionResponse.features; those that264+// RemoveRunner, ListAnnotations and GetStepSummaries) list "ci.runs" in
265+// GetVersionResponse.features; those that
260 // implement the runners side list "ci.runners", as RunnerService does. A server266 // implement the runners side list "ci.runners", as RunnerService does. A server
261 // that honours the filters of ListRunsRequest also lists "ci.runs.filters".267 // that honours the filters of ListRunsRequest also lists "ci.runs.filters".
268+// ListAnnotations needs "ci.annotations" and GetStepSummaries "ci.summaries",
269+// which are also the features of the runner side of each.
262 service RunService {270 service RunService {
263 // ListRuns lists the runs of a repository, highest id (newest) first. Each271 // ListRuns lists the runs of a repository, highest id (newest) first. Each
264 // run is described by its latest attempt. The filters narrow the result; a272 // run is described by its latest attempt. The filters narrow the result; a
@@ -273,6 +281,25 @@ service RunService {
273 // GetJob returns one job with its steps. Fails with not_found if the job281 // GetJob returns one job with its steps. Fails with not_found if the job
274 // or the attempt does not exist.282 // or the attempt does not exist.
275 rpc GetJob(GetJobRequest) returns (GetJobResponse);283 rpc GetJob(GetJobRequest) returns (GetJobResponse);
284+ // ListAnnotations lists the annotations of a run attempt, optionally of one
285+ // job, ordered by job (as in GetRun), step number, then the order in which
286+ // the step produced them. For each job it gives the annotations of the
287+ // attempt in which that job executed (RunJob.attempt), which is lower than
288+ // 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
289+ // 1,000 annotations (truncated tells). A run without annotations gives an
290+ // empty list. Only servers with the feature "ci.annotations" implement it
291+ // (unimplemented otherwise). Fails with not_found if the run, the attempt or
292+ // the job does not exist, or if the job is not a job of the run.
293+ rpc ListAnnotations(ListAnnotationsRequest) returns (ListAnnotationsResponse);
294+ // GetStepSummaries returns the job summaries (the Markdown written to
295+ // GITHUB_STEP_SUMMARY) of the steps of a job that have one, ordered by step
296+ // number. Like GitHub, it returns at most 20 summaries per job: the first 20
297+ // steps that have one, in step order; truncated says there are more. Needs
298+ // the same access as GetJob. Only servers with the feature
299+ // "ci.summaries" implement it (unimplemented otherwise). A job without
300+ // summaries gives an empty list. Fails with not_found if the job or the
301+ // attempt does not exist.
302+ rpc GetStepSummaries(GetStepSummariesRequest) returns (GetStepSummariesResponse);
276 // GetJobLog streams the lines of the log of a job, from a line number. The303 // GetJobLog streams the lines of the log of a job, from a line number. The
277 // server sends them in order in messages of at most 1,000 lines and 64 KiB of304 // server sends them in order in messages of at most 1,000 lines and 64 KiB of
278 // text each.305 // text each.
@@ -393,6 +420,67 @@ message GetJobResponse {
393 RunJob job = 1;420 RunJob job = 1;
394 }421 }
395 422
423+// ListAnnotationsRequest selects the annotations of a run.
424+message ListAnnotationsRequest {
425+ // Repo is the repository name.
426+ string repo = 1;
427+ // RunId is the Run.id.
428+ int64 run_id = 2;
429+ // Attempt is the attempt to read. 0 means the latest, and then each job
430+ // contributes the annotations of its own RunJob.attempt (not necessarily the
431+ // latest attempt of the run, see ListAnnotations).
432+ int32 attempt = 3;
433+ // JobId restricts the result to one job (RunJob.id). Empty means every job
434+ // of the run.
435+ string job_id = 4;
436+}
437+
438+// ListAnnotationsResponse holds the annotations of a run.
439+message ListAnnotationsResponse {
440+ // Annotations are the annotations, at most 1,000.
441+ repeated JobAnnotation annotations = 1;
442+ // Truncated is true when there are more annotations than annotations holds.
443+ bool truncated = 2;
444+}
445+
446+// JobAnnotation is an annotation with the job it belongs to.
447+message JobAnnotation {
448+ // JobId is the RunJob.id of the job.
449+ string job_id = 1;
450+ // Annotation is the annotation as the runner sent it, after the server
451+ // checked it. Its step_number is the step of the job.
452+ Annotation annotation = 2;
453+}
454+
455+// GetStepSummariesRequest selects a job.
456+message GetStepSummariesRequest {
457+ // Repo is the repository name.
458+ string repo = 1;
459+ // JobId is the RunJob.id.
460+ string job_id = 2;
461+ // Attempt is the RunJob.attempt to read. 0 means the latest.
462+ int32 attempt = 3;
463+}
464+
465+// GetStepSummariesResponse holds the summaries of a job.
466+message GetStepSummariesResponse {
467+ // Summaries are the summaries of the steps that have one, ordered by step
468+ // number: at most 20, the first 20 steps having one.
469+ repeated StepSummary summaries = 1;
470+ // Truncated is true when the job has more than 20 steps with a summary and
471+ // summaries holds only the first 20.
472+ bool truncated = 2;
473+}
474+
475+// StepSummary is the job summary of one step.
476+message StepSummary {
477+ // StepNumber is the number of the step (see Step.number).
478+ int32 step_number = 1;
479+ // Markdown is the summary as uploaded, at most 1 MiB. Clients render it
480+ // safely: it is untrusted content (raw HTML and script URLs must not run).
481+ string markdown = 2;
482+}
483+
396 // GetJobLogRequest selects the lines to stream.484 // GetJobLogRequest selects the lines to stream.
397 message GetJobLogRequest {485 message GetJobLogRequest {
398 // Repo is the repository name.486 // Repo is the repository name.
M proto/ermite/runner.proto +251 -12
@@ -93,6 +93,32 @@ enum CancelReason {
9393 CANCEL_REASON_TIMEOUT = 3;
9494 }
9595
96+// AnnotationLevel is the severity of an annotation, with the values of
97+// GitHub's check run annotation levels ("notice", "warning", "failure"). The
98+// workflow commands ::notice, ::warning and ::error produce NOTICE, WARNING and
99+// FAILURE.
100+enum AnnotationLevel {
101+ // Not set. Rejected in requests, never returned by the server.
102+ ANNOTATION_LEVEL_UNSPECIFIED = 0;
103+ // Information: ::notice.
104+ ANNOTATION_LEVEL_NOTICE = 1;
105+ // A problem that does not fail the job by itself: ::warning.
106+ ANNOTATION_LEVEL_WARNING = 2;
107+ // An error: ::error.
108+ ANNOTATION_LEVEL_FAILURE = 3;
109+}
110+
111+// ActionSource says where the server found an action.
112+enum ActionSource {
113+ // Not set. Only in a ResolvedAction that carries an error.
114+ ACTION_SOURCE_UNSPECIFIED = 0;
115+ // github.com: the archive is downloaded from GitHub, without a token.
116+ ACTION_SOURCE_GITHUB = 1;
117+ // A repository of this server, which wins over a github.com repository of
118+ // the same name (as GitHub Enterprise Server's own actions do).
119+ ACTION_SOURCE_ERMITE = 2;
120+}
121+
96122 // RunnerService is what a CI runner (ermite-runner) calls to get jobs and
97123 // report on them. It is not for people: owners use RunService.
98124 //
@@ -104,8 +130,8 @@ enum CancelReason {
104130 // - FetchJob: the runner token returned by RegisterRunner. It identifies the
105131 // runner and only works for FetchJob. It is "ermiterun_" followed by 43
106132 // base64url characters (32 random bytes, no padding).
107-// - UpdateJob, AppendLog, Heartbeat, WatchJob, CompleteJob: the job token of
108-// the Job that FetchJob returned. It is valid for that one job and that
133+// - UpdateJob, AppendLog, Heartbeat, WatchJob, CompleteJob, ResolveActions,
134+// UploadSummary: the job token of the Job that FetchJob returned. It is valid for that one job and that
109135 // one assignment. It is "ermitejob_" followed by 43 base64url characters
110136 // (32 random bytes, no padding). The job_id of the request must be the
111137 // one of the token.
@@ -120,8 +146,8 @@ enum CancelReason {
120146 //
121147 // The end of a job. A job ends when its conclusion is set, by CompleteJob or
122148 // by the server (cancellation not honoured, lost runner, log limit, queue
123-// timeout). From then on UpdateJob, AppendLog, Heartbeat and WatchJob answer
124-// failed_precondition with a JobEnded error detail (a JobEnded message in the
149+// timeout). From then on UpdateJob, AppendLog, Heartbeat, WatchJob,
150+// ResolveActions and UploadSummary answer failed_precondition with a JobEnded error detail (a JobEnded message in the
125151 // Connect error details) that gives the conclusion; the runner stops the job
126152 // and sends nothing more. The job token is still recognised for 24 hours after
127153 // the end, so that these calls can say so and so that CompleteJob, the only
@@ -132,14 +158,22 @@ enum CancelReason {
132158 // Secrets and trust. Runner tokens and job tokens are secrets: the server
133159 // never logs them and clients must not log them. The job token stays in the
134160 // runner host process; it is never given to the sandbox that runs the job's
135-// code. A runner receives the jobs of every repository, with their workflow
161+// code. The job's repository token (Job.github_token) is another secret: it is
162+// the one the sandbox does get, and it only reads the repository of the run.
163+// A runner receives the jobs of every repository, with their workflow
136164 // files, contexts and (from CI-2) their code, and from CI-3 their secrets: the
137165 // runner:register scope therefore effectively gives read access to the code
138166 // and the secrets of every repository, private ones included. Give it only to
139167 // runners you operate.
140168 //
141169 // Servers that implement this service list "ci.runners" in
142-// GetVersionResponse.features.
170+// GetVersionResponse.features. Those that implement ResolveActions and
171+// Job.github_token also list "ci.actions", those that accept annotations
172+// (UpdateJobRequest.annotations, CompleteJobRequest.annotations) list
173+// "ci.annotations", and those that implement UploadSummary list
174+// "ci.summaries". A server without a feature ignores the fields of that
175+// feature (protobuf drops unknown fields) and answers unimplemented to its
176+// RPCs; a runner that needs one checks GetVersion first.
143177 service RunnerService {
144178 // RegisterRunner registers a runner and returns its runner token, which is
145179 // shown only in this response; the runner keeps it. The caller needs the
@@ -191,10 +225,21 @@ service RunnerService {
191225 // identical call changes nothing, so a runner may retry after a network
192226 // error. To end the job use CompleteJob.
193227 //
194- // Fails with invalid_argument if a rule is broken, with failed_precondition
195- // if a step goes back (a COMPLETED step cannot change, a step cannot go from
196- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail
197- // if the job has ended.
228+ // Annotations are applied with the steps, in the same atomic step: for each
229+ // step_number present in annotations, the annotations of that step stored
230+ // so far are replaced by the ones of the request, so a retry never
231+ // duplicates them. A step number absent from the request keeps its
232+ // annotations. The step of an annotation need not be in the steps of the
233+ // same call, and may already be COMPLETED: its annotations can still be
234+ // replaced (the rule that a COMPLETED step cannot change applies to
235+ // StepUpdate, not to annotations), until the job ends. A runner sends one
236+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
237+ // so replacements apply in the order of the calls.
238+ //
239+ // Fails with invalid_argument if a rule is broken (including the annotation
240+ // limits), with failed_precondition if a step goes back (a COMPLETED step
241+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
242+ // failed_precondition and a JobEnded detail if the job has ended.
198243 rpc UpdateJob(UpdateJobRequest) returns (UpdateJobResponse);
199244 // AppendLog appends lines to the log of a job. Needs the job token.
200245 //
@@ -299,9 +344,57 @@ service RunnerService {
299344 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
300345 // they never started and the job did not end by cancellation).
301346 //
302- // Fails with invalid_argument if a rule is broken (including the output
303- // limits) and failed_precondition if a step goes back, as in UpdateJob.
347+ // Annotations are applied as in UpdateJob (replacement per step number, also
348+ // for COMPLETED steps and steps not in steps), together with the conclusion.
349+ // Summaries are not part of this call: a runner sends them with
350+ // UploadSummary before it.
351+ //
352+ // Fails with invalid_argument if a rule is broken (including the output and
353+ // annotation limits) and failed_precondition if a step goes back, as in
354+ // UpdateJob.
304355 rpc CompleteJob(CompleteJobRequest) returns (CompleteJobResponse);
356+ // ResolveActions turns the "uses" of workflow and action steps into what the
357+ // runner needs to download the actions, as GitHub's action download info
358+ // does. Needs the job token; the job_id must be the one of the token. It
359+ // may be called as often as needed while the job runs (the runner calls it
360+ // once per level of composite actions, see the runner's depth limit of 9).
361+ // The runner then downloads each archive itself, from the sandbox, with the
362+ // token of the ResolvedAction when there is one.
363+ //
364+ // The response has one ResolvedAction per ActionRef, in the same order. A
365+ // reference that cannot be resolved (unknown repository, tag or branch, a
366+ // repository without access, a "uses" that GitHub itself would reject) does
367+ // not fail the call: its ResolvedAction has only ref and error, where error
368+ // is the message GitHub gives for the same failure, which the runner prints
369+ // as is. Only a failure of the call itself (credential, ended job, bad
370+ // request, server error) is an RPC error; the runner then fails the job.
371+ //
372+ // Resolution is stable for a run attempt: the same ref resolves to the same
373+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
374+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
375+ // job gets its own (ResolvedAction.token).
376+ //
377+ // Fails with unauthenticated or permission_denied as the other job RPCs,
378+ // with failed_precondition and a JobEnded detail if the job has ended, and
379+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
380+ // local action ("./path") or a Docker image ("docker://"), which the runner
381+ // handles without the server.
382+ rpc ResolveActions(ResolveActionsRequest) returns (ResolveActionsResponse);
383+ // UploadSummary stores the job summary of one step: the Markdown that the
384+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
385+ // The runner masks it before sending it, and sends it after the step ended
386+ // and before CompleteJob.
387+ //
388+ // It is idempotent: the summary of a step is replaced by each call, so a
389+ // retry changes nothing, and an empty markdown removes the summary of the
390+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
391+ // server reads requests of up to 1 MiB plus the envelope (job id, step
392+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
393+ // their own message size limit above that.
394+ //
395+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
396+ // and with failed_precondition and a JobEnded detail if the job has ended.
397+ rpc UploadSummary(UploadSummaryRequest) returns (UploadSummaryResponse);
305398 }
306399
307400 // RegisterRunnerRequest describes the runner to register.
@@ -437,6 +530,18 @@ message Job {
437530 // Ref is the full ref name that triggered the run, for example
438531 // "refs/heads/main" or "refs/tags/v1.0.0".
439532 string ref = 14;
533+ // GithubToken is the job repository token, the "github.token" and
534+ // "secrets.GITHUB_TOKEN" of the job: "ermitegh_" and 43 base64url characters
535+ // (32 random bytes, no padding). Unlike job_token it is meant for the code of
536+ // the job: the runner gives it to the sandbox (actions/checkout clones with
537+ // it). It can only read the repository of the run (read-only, whatever
538+ // "permissions:" says), and is valid from the assignment until the job ends
539+ // (it is revoked then, on cancellation and when the job is lost). It is a
540+ // secret: the runner registers it in its masker before anything runs, and
541+ // neither the runner nor the server logs it. It is shown only in this
542+ // response, or in a repeat of the same poll_id; a new assignment of the same
543+ // job has a new one. Empty from servers without the feature "ci.actions".
544+ string github_token = 15;
440545 }
441546
442547 // UpdateJobRequest reports the steps of a running job.
@@ -449,6 +554,13 @@ message UpdateJobRequest {
449554 // implicit "Set up job" is 1, the steps of the workflow follow in order, and
450555 // the implicit "Complete job" is last.
451556 repeated StepUpdate steps = 2;
557+ // Annotations are the annotations of the steps that the call names: for
558+ // each step_number present, all the annotations of that step known so far,
559+ // not only the new ones (see the rules on UpdateJob). At most 10 per level
560+ // and per step, and each one within the limits of Annotation; otherwise the
561+ // whole call is invalid_argument. The server ignores them without the
562+ // feature "ci.annotations".
563+ repeated Annotation annotations = 3;
452564 }
453565
454566 // StepUpdate is the state of one step as the runner knows it.
@@ -472,6 +584,14 @@ message StepUpdate {
472584 // CompletedAt is when the step ended, by the clock of the runner. Required
473585 // when state is COMPLETED.
474586 google.protobuf.Timestamp completed_at = 6;
587+ // Outcome is how the step ended before continue-on-error was applied, GitHub's
588+ // "steps.<id>.outcome", whereas conclusion is the result after it
589+ // ("steps.<id>.conclusion"). Same values as conclusion. They differ only for
590+ // a step with continue-on-error that failed: outcome FAILURE, conclusion
591+ // SUCCESS. Set by the runner when state is COMPLETED and UNSPECIFIED
592+ // otherwise; UNSPECIFIED in a COMPLETED step means the same as conclusion
593+ // (a runner that does not know the field).
594+ CiConclusion outcome = 7;
475595 }
476596
477597 // UpdateJobResponse is empty.
@@ -504,6 +624,11 @@ message CompleteJobRequest {
504624 // Steps are the final steps, with the same meaning as UpdateJobRequest.steps,
505625 // applied in the same atomic step as the conclusion.
506626 repeated StepUpdate steps = 5;
627+ // Annotations are those of the steps that changed since the last call, with
628+ // the rules of UpdateJobRequest.annotations (all the annotations of each
629+ // step named). The server ignores them without the feature
630+ // "ci.annotations".
631+ repeated Annotation annotations = 6;
507632 }
508633
509634 // CompleteJobResponse is the stored result of a job.
@@ -620,3 +745,117 @@ message CancelRequest {
620745 // server.
621746 google.protobuf.Timestamp requested_at = 3;
622747 }
748+
749+// Annotation is a message attached to a step, and optionally to a place in a
750+// file of the repository, like an annotation of a GitHub check run. The runner
751+// produces them from the workflow commands ::notice, ::warning and ::error and
752+// from problem matchers, after masking.
753+//
754+// Limits, checked by the server: at most 10 annotations of each level per step
755+// (the runner sends no more: the ones beyond only reach the log, as with
756+// GitHub). A call that breaks a limit below is rejected whole with
757+// invalid_argument. Lengths count characters (Unicode code points), not bytes.
758+message Annotation {
759+ // Level is the severity. Required.
760+ AnnotationLevel level = 1;
761+ // Title is the optional title, at most 255 characters. Empty when not given.
762+ string title = 2;
763+ // Message is the text. Required, not empty, at most 4,096 characters; a
764+ // longer one is invalid_argument. The runner never sends a longer one: like
765+ // GitHub, it only logs such an annotation.
766+ string message = 3;
767+ // File is the path the annotation is about, relative to the repository when
768+ // the runner can tell, else as given. At most 1,024 characters. Empty when
769+ // the annotation is not about a file.
770+ string file = 4;
771+ // StartLine is the first line, counted from 1. 0 when not given.
772+ int32 start_line = 5;
773+ // EndLine is the last line, counted from 1, not before start_line. 0 when
774+ // not given.
775+ int32 end_line = 6;
776+ // StartColumn is the first column, counted from 1. 0 when not given.
777+ int32 start_column = 7;
778+ // EndColumn is the last column, counted from 1. 0 when not given.
779+ int32 end_column = 8;
780+ // StepNumber is the number of the step that produced it (see
781+ // StepUpdate.number), from 1 to 1,000. An annotation of a step inside a
782+ // composite action belongs to the step of the workflow that uses the action.
783+ int32 step_number = 9;
784+}
785+
786+// ActionRef is an action to resolve.
787+message ActionRef {
788+ // Uses is the value of "uses" as written, after expression evaluation, for
789+ // example "actions/checkout@v4" or "owner/repo/path/to/action@ref". Required.
790+ string uses = 1;
791+}
792+
793+// ResolveActionsRequest lists the actions to resolve.
794+message ResolveActionsRequest {
795+ // JobId is the Job.job_id. It must be the job of the token.
796+ string job_id = 1;
797+ // Refs are the actions to resolve, at most 100. Duplicates are allowed and
798+ // answered one by one.
799+ repeated ActionRef refs = 2;
800+}
801+
802+// ResolveActionsResponse holds the resolution of each action.
803+message ResolveActionsResponse {
804+ // Actions has one entry per ActionRef of the request, in the same order.
805+ repeated ResolvedAction actions = 1;
806+}
807+
808+// ResolvedAction is where to download one action, or why it cannot be.
809+message ResolvedAction {
810+ // Ref is the ActionRef.uses of the request, unchanged.
811+ string ref = 1;
812+ // NameWithOwner is the repository of the action, "owner/repo", with the
813+ // case of the repository as the source gives it. Empty when error is set.
814+ string name_with_owner = 2;
815+ // Path is the sub-path of the action inside the repository, a clean
816+ // relative path: "path/to/action" for "owner/repo/path/to/action@ref", with
817+ // "/" separators, no leading or trailing slash, no empty, "." or ".."
818+ // element, never absolute. Empty for an action at the root of the
819+ // repository.
820+ string path = 3;
821+ // ResolvedSha is the full id of the commit the ref points to, 40 lowercase
822+ // hexadecimal characters for SHA-1 (the commit that an annotated tag points
823+ // to, not the tag object). Stable for a run attempt: every job and every
824+ // call of the attempt gets the same value for the same ref. Empty when error
825+ // is set.
826+ string resolved_sha = 4;
827+ // TarballUrl is where to download the archive of the repository at
828+ // resolved_sha, a gzip-compressed tar with one top-level directory. The
829+ // runner downloads it from the sandbox. Empty when error is set.
830+ string tarball_url = 5;
831+ // Token authenticates the download: the runner sends it as "Authorization:
832+ // Basic" with the user "x-access-token". Empty for ACTION_SOURCE_GITHUB.
833+ // For ACTION_SOURCE_ERMITE it is a read token for that one repository,
834+ // valid until the job ends, so a job can use an action of another private
835+ // repository of the server that its own repository token cannot read. It is
836+ // issued per job and never shared across jobs (two jobs resolving the same
837+ // action get different tokens). It is a secret: the runner masks it, and neither the runner nor the server logs
838+ // it.
839+ string token = 6;
840+ // Source is where the action was found. UNSPECIFIED when error is set.
841+ ActionSource source = 7;
842+ // Error is why the reference could not be resolved, in the words of GitHub
843+ // for the same failure. Empty when the action was resolved, in which case
844+ // the other fields describe it.
845+ string error = 8;
846+}
847+
848+// UploadSummaryRequest carries the job summary of one step.
849+message UploadSummaryRequest {
850+ // JobId is the Job.job_id. It must be the job of the token.
851+ string job_id = 1;
852+ // StepNumber is the number of the step that wrote the summary (see
853+ // StepUpdate.number), from 1 to 1,000.
854+ int32 step_number = 2;
855+ // Markdown is the summary, masked, valid UTF-8, at most 1 MiB (1,048,576
856+ // bytes). Empty removes the summary of the step.
857+ string markdown = 3;
858+}
859+
860+// UploadSummaryResponse is empty.
861+message UploadSummaryResponse {}
@@ -93,6 +93,32 @@ enum CancelReason {
93 CANCEL_REASON_TIMEOUT = 3;93 CANCEL_REASON_TIMEOUT = 3;
94 }94 }
95 95
96+// AnnotationLevel is the severity of an annotation, with the values of
97+// GitHub's check run annotation levels ("notice", "warning", "failure"). The
98+// workflow commands ::notice, ::warning and ::error produce NOTICE, WARNING and
99+// FAILURE.
100+enum AnnotationLevel {
101+ // Not set. Rejected in requests, never returned by the server.
102+ ANNOTATION_LEVEL_UNSPECIFIED = 0;
103+ // Information: ::notice.
104+ ANNOTATION_LEVEL_NOTICE = 1;
105+ // A problem that does not fail the job by itself: ::warning.
106+ ANNOTATION_LEVEL_WARNING = 2;
107+ // An error: ::error.
108+ ANNOTATION_LEVEL_FAILURE = 3;
109+}
110+
111+// ActionSource says where the server found an action.
112+enum ActionSource {
113+ // Not set. Only in a ResolvedAction that carries an error.
114+ ACTION_SOURCE_UNSPECIFIED = 0;
115+ // github.com: the archive is downloaded from GitHub, without a token.
116+ ACTION_SOURCE_GITHUB = 1;
117+ // A repository of this server, which wins over a github.com repository of
118+ // the same name (as GitHub Enterprise Server's own actions do).
119+ ACTION_SOURCE_ERMITE = 2;
120+}
121+
96 // RunnerService is what a CI runner (ermite-runner) calls to get jobs and122 // RunnerService is what a CI runner (ermite-runner) calls to get jobs and
97 // report on them. It is not for people: owners use RunService.123 // report on them. It is not for people: owners use RunService.
98 //124 //
@@ -104,8 +130,8 @@ enum CancelReason {
104 // - FetchJob: the runner token returned by RegisterRunner. It identifies the130 // - FetchJob: the runner token returned by RegisterRunner. It identifies the
105 // runner and only works for FetchJob. It is "ermiterun_" followed by 43131 // runner and only works for FetchJob. It is "ermiterun_" followed by 43
106 // base64url characters (32 random bytes, no padding).132 // base64url characters (32 random bytes, no padding).
107-// - UpdateJob, AppendLog, Heartbeat, WatchJob, CompleteJob: the job token of133+// - UpdateJob, AppendLog, Heartbeat, WatchJob, CompleteJob, ResolveActions,
108-// the Job that FetchJob returned. It is valid for that one job and that134+// UploadSummary: the job token of the Job that FetchJob returned. It is valid for that one job and that
109 // one assignment. It is "ermitejob_" followed by 43 base64url characters135 // one assignment. It is "ermitejob_" followed by 43 base64url characters
110 // (32 random bytes, no padding). The job_id of the request must be the136 // (32 random bytes, no padding). The job_id of the request must be the
111 // one of the token.137 // one of the token.
@@ -120,8 +146,8 @@ enum CancelReason {
120 //146 //
121 // The end of a job. A job ends when its conclusion is set, by CompleteJob or147 // The end of a job. A job ends when its conclusion is set, by CompleteJob or
122 // by the server (cancellation not honoured, lost runner, log limit, queue148 // by the server (cancellation not honoured, lost runner, log limit, queue
123-// timeout). From then on UpdateJob, AppendLog, Heartbeat and WatchJob answer149+// timeout). From then on UpdateJob, AppendLog, Heartbeat, WatchJob,
124-// failed_precondition with a JobEnded error detail (a JobEnded message in the150+// ResolveActions and UploadSummary answer failed_precondition with a JobEnded error detail (a JobEnded message in the
125 // Connect error details) that gives the conclusion; the runner stops the job151 // Connect error details) that gives the conclusion; the runner stops the job
126 // and sends nothing more. The job token is still recognised for 24 hours after152 // and sends nothing more. The job token is still recognised for 24 hours after
127 // the end, so that these calls can say so and so that CompleteJob, the only153 // the end, so that these calls can say so and so that CompleteJob, the only
@@ -132,14 +158,22 @@ enum CancelReason {
132 // Secrets and trust. Runner tokens and job tokens are secrets: the server158 // Secrets and trust. Runner tokens and job tokens are secrets: the server
133 // never logs them and clients must not log them. The job token stays in the159 // never logs them and clients must not log them. The job token stays in the
134 // runner host process; it is never given to the sandbox that runs the job's160 // runner host process; it is never given to the sandbox that runs the job's
135-// code. A runner receives the jobs of every repository, with their workflow161+// code. The job's repository token (Job.github_token) is another secret: it is
162+// the one the sandbox does get, and it only reads the repository of the run.
163+// A runner receives the jobs of every repository, with their workflow
136 // files, contexts and (from CI-2) their code, and from CI-3 their secrets: the164 // files, contexts and (from CI-2) their code, and from CI-3 their secrets: the
137 // runner:register scope therefore effectively gives read access to the code165 // runner:register scope therefore effectively gives read access to the code
138 // and the secrets of every repository, private ones included. Give it only to166 // and the secrets of every repository, private ones included. Give it only to
139 // runners you operate.167 // runners you operate.
140 //168 //
141 // Servers that implement this service list "ci.runners" in169 // Servers that implement this service list "ci.runners" in
142-// GetVersionResponse.features.170+// GetVersionResponse.features. Those that implement ResolveActions and
171+// Job.github_token also list "ci.actions", those that accept annotations
172+// (UpdateJobRequest.annotations, CompleteJobRequest.annotations) list
173+// "ci.annotations", and those that implement UploadSummary list
174+// "ci.summaries". A server without a feature ignores the fields of that
175+// feature (protobuf drops unknown fields) and answers unimplemented to its
176+// RPCs; a runner that needs one checks GetVersion first.
143 service RunnerService {177 service RunnerService {
144 // RegisterRunner registers a runner and returns its runner token, which is178 // RegisterRunner registers a runner and returns its runner token, which is
145 // shown only in this response; the runner keeps it. The caller needs the179 // shown only in this response; the runner keeps it. The caller needs the
@@ -191,10 +225,21 @@ service RunnerService {
191 // identical call changes nothing, so a runner may retry after a network225 // identical call changes nothing, so a runner may retry after a network
192 // error. To end the job use CompleteJob.226 // error. To end the job use CompleteJob.
193 //227 //
194- // Fails with invalid_argument if a rule is broken, with failed_precondition228+ // Annotations are applied with the steps, in the same atomic step: for each
195- // if a step goes back (a COMPLETED step cannot change, a step cannot go from229+ // step_number present in annotations, the annotations of that step stored
196- // IN_PROGRESS to PENDING) and with failed_precondition and a JobEnded detail230+ // so far are replaced by the ones of the request, so a retry never
197- // if the job has ended.231+ // duplicates them. A step number absent from the request keeps its
232+ // annotations. The step of an annotation need not be in the steps of the
233+ // same call, and may already be COMPLETED: its annotations can still be
234+ // replaced (the rule that a COMPLETED step cannot change applies to
235+ // StepUpdate, not to annotations), until the job ends. A runner sends one
236+ // UpdateJob (or CompleteJob) at a time for a job, never concurrent calls,
237+ // so replacements apply in the order of the calls.
238+ //
239+ // Fails with invalid_argument if a rule is broken (including the annotation
240+ // limits), with failed_precondition if a step goes back (a COMPLETED step
241+ // cannot change, a step cannot go from IN_PROGRESS to PENDING) and with
242+ // failed_precondition and a JobEnded detail if the job has ended.
198 rpc UpdateJob(UpdateJobRequest) returns (UpdateJobResponse);243 rpc UpdateJob(UpdateJobRequest) returns (UpdateJobResponse);
199 // AppendLog appends lines to the log of a job. Needs the job token.244 // AppendLog appends lines to the log of a job. Needs the job token.
200 //245 //
@@ -299,9 +344,57 @@ service RunnerService {
299 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when344 // ends are completed by the server as CI_CONCLUSION_CANCELLED (or SKIPPED when
300 // they never started and the job did not end by cancellation).345 // they never started and the job did not end by cancellation).
301 //346 //
302- // Fails with invalid_argument if a rule is broken (including the output347+ // Annotations are applied as in UpdateJob (replacement per step number, also
303- // limits) and failed_precondition if a step goes back, as in UpdateJob.348+ // for COMPLETED steps and steps not in steps), together with the conclusion.
349+ // Summaries are not part of this call: a runner sends them with
350+ // UploadSummary before it.
351+ //
352+ // Fails with invalid_argument if a rule is broken (including the output and
353+ // annotation limits) and failed_precondition if a step goes back, as in
354+ // UpdateJob.
304 rpc CompleteJob(CompleteJobRequest) returns (CompleteJobResponse);355 rpc CompleteJob(CompleteJobRequest) returns (CompleteJobResponse);
356+ // ResolveActions turns the "uses" of workflow and action steps into what the
357+ // runner needs to download the actions, as GitHub's action download info
358+ // does. Needs the job token; the job_id must be the one of the token. It
359+ // may be called as often as needed while the job runs (the runner calls it
360+ // once per level of composite actions, see the runner's depth limit of 9).
361+ // The runner then downloads each archive itself, from the sandbox, with the
362+ // token of the ResolvedAction when there is one.
363+ //
364+ // The response has one ResolvedAction per ActionRef, in the same order. A
365+ // reference that cannot be resolved (unknown repository, tag or branch, a
366+ // repository without access, a "uses" that GitHub itself would reject) does
367+ // not fail the call: its ResolvedAction has only ref and error, where error
368+ // is the message GitHub gives for the same failure, which the runner prints
369+ // as is. Only a failure of the call itself (credential, ended job, bad
370+ // request, server error) is an RPC error; the runner then fails the job.
371+ //
372+ // Resolution is stable for a run attempt: the same ref resolves to the same
373+ // sha (ResolvedAction.resolved_sha) for every job and every call of that
374+ // attempt. A re-run attempt resolves again. Tokens are not shared: each
375+ // job gets its own (ResolvedAction.token).
376+ //
377+ // Fails with unauthenticated or permission_denied as the other job RPCs,
378+ // with failed_precondition and a JobEnded detail if the job has ended, and
379+ // with invalid_argument if there are more than 100 refs or if a "uses" is a
380+ // local action ("./path") or a Docker image ("docker://"), which the runner
381+ // handles without the server.
382+ rpc ResolveActions(ResolveActionsRequest) returns (ResolveActionsResponse);
383+ // UploadSummary stores the job summary of one step: the Markdown that the
384+ // step wrote to the file named by GITHUB_STEP_SUMMARY. Needs the job token.
385+ // The runner masks it before sending it, and sends it after the step ended
386+ // and before CompleteJob.
387+ //
388+ // It is idempotent: the summary of a step is replaced by each call, so a
389+ // retry changes nothing, and an empty markdown removes the summary of the
390+ // step. The Markdown is at most 1 MiB (1,048,576 bytes) and valid UTF-8. The
391+ // server reads requests of up to 1 MiB plus the envelope (job id, step
392+ // number, framing), so a summary of exactly 1 MiB is accepted; clients set
393+ // their own message size limit above that.
394+ //
395+ // Fails with invalid_argument if a rule is broken (size, UTF-8, step number)
396+ // and with failed_precondition and a JobEnded detail if the job has ended.
397+ rpc UploadSummary(UploadSummaryRequest) returns (UploadSummaryResponse);
305 }398 }
306 399
307 // RegisterRunnerRequest describes the runner to register.400 // RegisterRunnerRequest describes the runner to register.
@@ -437,6 +530,18 @@ message Job {
437 // Ref is the full ref name that triggered the run, for example530 // Ref is the full ref name that triggered the run, for example
438 // "refs/heads/main" or "refs/tags/v1.0.0".531 // "refs/heads/main" or "refs/tags/v1.0.0".
439 string ref = 14;532 string ref = 14;
533+ // GithubToken is the job repository token, the "github.token" and
534+ // "secrets.GITHUB_TOKEN" of the job: "ermitegh_" and 43 base64url characters
535+ // (32 random bytes, no padding). Unlike job_token it is meant for the code of
536+ // the job: the runner gives it to the sandbox (actions/checkout clones with
537+ // it). It can only read the repository of the run (read-only, whatever
538+ // "permissions:" says), and is valid from the assignment until the job ends
539+ // (it is revoked then, on cancellation and when the job is lost). It is a
540+ // secret: the runner registers it in its masker before anything runs, and
541+ // neither the runner nor the server logs it. It is shown only in this
542+ // response, or in a repeat of the same poll_id; a new assignment of the same
543+ // job has a new one. Empty from servers without the feature "ci.actions".
544+ string github_token = 15;
440 }545 }
441 546
442 // UpdateJobRequest reports the steps of a running job.547 // UpdateJobRequest reports the steps of a running job.
@@ -449,6 +554,13 @@ message UpdateJobRequest {
449 // implicit "Set up job" is 1, the steps of the workflow follow in order, and554 // implicit "Set up job" is 1, the steps of the workflow follow in order, and
450 // the implicit "Complete job" is last.555 // the implicit "Complete job" is last.
451 repeated StepUpdate steps = 2;556 repeated StepUpdate steps = 2;
557+ // Annotations are the annotations of the steps that the call names: for
558+ // each step_number present, all the annotations of that step known so far,
559+ // not only the new ones (see the rules on UpdateJob). At most 10 per level
560+ // and per step, and each one within the limits of Annotation; otherwise the
561+ // whole call is invalid_argument. The server ignores them without the
562+ // feature "ci.annotations".
563+ repeated Annotation annotations = 3;
452 }564 }
453 565
454 // StepUpdate is the state of one step as the runner knows it.566 // StepUpdate is the state of one step as the runner knows it.
@@ -472,6 +584,14 @@ message StepUpdate {
472 // CompletedAt is when the step ended, by the clock of the runner. Required584 // CompletedAt is when the step ended, by the clock of the runner. Required
473 // when state is COMPLETED.585 // when state is COMPLETED.
474 google.protobuf.Timestamp completed_at = 6;586 google.protobuf.Timestamp completed_at = 6;
587+ // Outcome is how the step ended before continue-on-error was applied, GitHub's
588+ // "steps.<id>.outcome", whereas conclusion is the result after it
589+ // ("steps.<id>.conclusion"). Same values as conclusion. They differ only for
590+ // a step with continue-on-error that failed: outcome FAILURE, conclusion
591+ // SUCCESS. Set by the runner when state is COMPLETED and UNSPECIFIED
592+ // otherwise; UNSPECIFIED in a COMPLETED step means the same as conclusion
593+ // (a runner that does not know the field).
594+ CiConclusion outcome = 7;
475 }595 }
476 596
477 // UpdateJobResponse is empty.597 // UpdateJobResponse is empty.
@@ -504,6 +624,11 @@ message CompleteJobRequest {
504 // Steps are the final steps, with the same meaning as UpdateJobRequest.steps,624 // Steps are the final steps, with the same meaning as UpdateJobRequest.steps,
505 // applied in the same atomic step as the conclusion.625 // applied in the same atomic step as the conclusion.
506 repeated StepUpdate steps = 5;626 repeated StepUpdate steps = 5;
627+ // Annotations are those of the steps that changed since the last call, with
628+ // the rules of UpdateJobRequest.annotations (all the annotations of each
629+ // step named). The server ignores them without the feature
630+ // "ci.annotations".
631+ repeated Annotation annotations = 6;
507 }632 }
508 633
509 // CompleteJobResponse is the stored result of a job.634 // CompleteJobResponse is the stored result of a job.
@@ -620,3 +745,117 @@ message CancelRequest {
620 // server.745 // server.
621 google.protobuf.Timestamp requested_at = 3;746 google.protobuf.Timestamp requested_at = 3;
622 }747 }
748+
749+// Annotation is a message attached to a step, and optionally to a place in a
750+// file of the repository, like an annotation of a GitHub check run. The runner
751+// produces them from the workflow commands ::notice, ::warning and ::error and
752+// from problem matchers, after masking.
753+//
754+// Limits, checked by the server: at most 10 annotations of each level per step
755+// (the runner sends no more: the ones beyond only reach the log, as with
756+// GitHub). A call that breaks a limit below is rejected whole with
757+// invalid_argument. Lengths count characters (Unicode code points), not bytes.
758+message Annotation {
759+ // Level is the severity. Required.
760+ AnnotationLevel level = 1;
761+ // Title is the optional title, at most 255 characters. Empty when not given.
762+ string title = 2;
763+ // Message is the text. Required, not empty, at most 4,096 characters; a
764+ // longer one is invalid_argument. The runner never sends a longer one: like
765+ // GitHub, it only logs such an annotation.
766+ string message = 3;
767+ // File is the path the annotation is about, relative to the repository when
768+ // the runner can tell, else as given. At most 1,024 characters. Empty when
769+ // the annotation is not about a file.
770+ string file = 4;
771+ // StartLine is the first line, counted from 1. 0 when not given.
772+ int32 start_line = 5;
773+ // EndLine is the last line, counted from 1, not before start_line. 0 when
774+ // not given.
775+ int32 end_line = 6;
776+ // StartColumn is the first column, counted from 1. 0 when not given.
777+ int32 start_column = 7;
778+ // EndColumn is the last column, counted from 1. 0 when not given.
779+ int32 end_column = 8;
780+ // StepNumber is the number of the step that produced it (see
781+ // StepUpdate.number), from 1 to 1,000. An annotation of a step inside a
782+ // composite action belongs to the step of the workflow that uses the action.
783+ int32 step_number = 9;
784+}
785+
786+// ActionRef is an action to resolve.
787+message ActionRef {
788+ // Uses is the value of "uses" as written, after expression evaluation, for
789+ // example "actions/checkout@v4" or "owner/repo/path/to/action@ref". Required.
790+ string uses = 1;
791+}
792+
793+// ResolveActionsRequest lists the actions to resolve.
794+message ResolveActionsRequest {
795+ // JobId is the Job.job_id. It must be the job of the token.
796+ string job_id = 1;
797+ // Refs are the actions to resolve, at most 100. Duplicates are allowed and
798+ // answered one by one.
799+ repeated ActionRef refs = 2;
800+}
801+
802+// ResolveActionsResponse holds the resolution of each action.
803+message ResolveActionsResponse {
804+ // Actions has one entry per ActionRef of the request, in the same order.
805+ repeated ResolvedAction actions = 1;
806+}
807+
808+// ResolvedAction is where to download one action, or why it cannot be.
809+message ResolvedAction {
810+ // Ref is the ActionRef.uses of the request, unchanged.
811+ string ref = 1;
812+ // NameWithOwner is the repository of the action, "owner/repo", with the
813+ // case of the repository as the source gives it. Empty when error is set.
814+ string name_with_owner = 2;
815+ // Path is the sub-path of the action inside the repository, a clean
816+ // relative path: "path/to/action" for "owner/repo/path/to/action@ref", with
817+ // "/" separators, no leading or trailing slash, no empty, "." or ".."
818+ // element, never absolute. Empty for an action at the root of the
819+ // repository.
820+ string path = 3;
821+ // ResolvedSha is the full id of the commit the ref points to, 40 lowercase
822+ // hexadecimal characters for SHA-1 (the commit that an annotated tag points
823+ // to, not the tag object). Stable for a run attempt: every job and every
824+ // call of the attempt gets the same value for the same ref. Empty when error
825+ // is set.
826+ string resolved_sha = 4;
827+ // TarballUrl is where to download the archive of the repository at
828+ // resolved_sha, a gzip-compressed tar with one top-level directory. The
829+ // runner downloads it from the sandbox. Empty when error is set.
830+ string tarball_url = 5;
831+ // Token authenticates the download: the runner sends it as "Authorization:
832+ // Basic" with the user "x-access-token". Empty for ACTION_SOURCE_GITHUB.
833+ // For ACTION_SOURCE_ERMITE it is a read token for that one repository,
834+ // valid until the job ends, so a job can use an action of another private
835+ // repository of the server that its own repository token cannot read. It is
836+ // issued per job and never shared across jobs (two jobs resolving the same
837+ // action get different tokens). It is a secret: the runner masks it, and neither the runner nor the server logs
838+ // it.
839+ string token = 6;
840+ // Source is where the action was found. UNSPECIFIED when error is set.
841+ ActionSource source = 7;
842+ // Error is why the reference could not be resolved, in the words of GitHub
843+ // for the same failure. Empty when the action was resolved, in which case
844+ // the other fields describe it.
845+ string error = 8;
846+}
847+
848+// UploadSummaryRequest carries the job summary of one step.
849+message UploadSummaryRequest {
850+ // JobId is the Job.job_id. It must be the job of the token.
851+ string job_id = 1;
852+ // StepNumber is the number of the step that wrote the summary (see
853+ // StepUpdate.number), from 1 to 1,000.
854+ int32 step_number = 2;
855+ // Markdown is the summary, masked, valid UTF-8, at most 1 MiB (1,048,576
856+ // bytes). Empty removes the summary of the step.
857+ string markdown = 3;
858+}
859+
860+// UploadSummaryResponse is empty.
861+message UploadSummaryResponse {}
M proto/ermite/server.proto +5 -1
@@ -35,7 +35,11 @@ message GetVersionResponse {
3535 // identifiers are "ci.runs" (RunService runs, jobs, logs, checks, and the
3636 // run_updated and job_updated events), "ci.runs.filters" (ListRuns honours
3737 // its filters) and "ci.runners" (RunnerService, and RunService.ListRunners
38- // and RemoveRunner).
38+ // and RemoveRunner). The CI execution identifiers are "ci.actions"
39+ // (RunnerService.ResolveActions and Job.github_token), "ci.annotations"
40+ // (annotations in UpdateJob and CompleteJob, and RunService.ListAnnotations)
41+ // and "ci.summaries" (RunnerService.UploadSummary and
42+ // RunService.GetStepSummaries).
3943 repeated string features = 2;
4044 }
4145
@@ -35,7 +35,11 @@ message GetVersionResponse {
35 // identifiers are "ci.runs" (RunService runs, jobs, logs, checks, and the35 // identifiers are "ci.runs" (RunService runs, jobs, logs, checks, and the
36 // run_updated and job_updated events), "ci.runs.filters" (ListRuns honours36 // run_updated and job_updated events), "ci.runs.filters" (ListRuns honours
37 // its filters) and "ci.runners" (RunnerService, and RunService.ListRunners37 // its filters) and "ci.runners" (RunnerService, and RunService.ListRunners
38- // and RemoveRunner).38+ // and RemoveRunner). The CI execution identifiers are "ci.actions"
39+ // (RunnerService.ResolveActions and Job.github_token), "ci.annotations"
40+ // (annotations in UpdateJob and CompleteJob, and RunService.ListAnnotations)
41+ // and "ci.summaries" (RunnerService.UploadSummary and
42+ // RunService.GetStepSummaries).
39 repeated string features = 2;43 repeated string features = 2;
40 }44 }
41 45

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 18

↑↓ moveenter openesc close