detached d727ef4

feat(execstream): carry annotations, summaries and step outcomes

commit
d727ef4bcd2380fd52da59468e7ab1700869da13
author
brice · · 2026-10-13 14:41 UTC
parent
de0182d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +478 -65
M internal/execstream/exec.proto +47 -0
@@ -25,6 +25,8 @@ message Frame {
2525 StepCompleted step_completed = 7; // executor -> host
2626 Log log = 8; // executor -> host
2727 JobResult job_result = 9; // executor -> host, before Exit
28+ StepAnnotations step_annotations = 10; // executor -> host, before the StepCompleted of the step
29+ StepSummary step_summary = 11; // executor -> host, before the StepCompleted of the step
2830 }
2931 }
3032
@@ -66,6 +68,11 @@ message JobSpec {
6668 // executor, and booting the sandbox takes time. 0 means "use
6769 // timeout_minutes from now".
6870 int64 deadline_ms = 12;
71+ // send_annotations and send_summaries say that the server keeps annotations
72+ // (feature ci.annotations) and step summaries (ci.summaries). The executor
73+ // sends StepAnnotations and StepSummary frames only when they are set.
74+ bool send_annotations = 13;
75+ bool send_summaries = 14;
6976 }
7077
7178 enum StreamKind {
@@ -117,6 +124,46 @@ message StepCompleted {
117124 string name = 2;
118125 StepConclusion conclusion = 3;
119126 int64 unix_nano = 4;
127+ // outcome is steps.<id>.outcome: the result before continue-on-error. It
128+ // differs from conclusion only for a failed step with continue-on-error.
129+ // UNSPECIFIED means the same as conclusion.
130+ StepConclusion outcome = 5;
131+}
132+
133+enum AnnotationLevel {
134+ ANNOTATION_LEVEL_UNSPECIFIED = 0;
135+ ANNOTATION_LEVEL_NOTICE = 1;
136+ ANNOTATION_LEVEL_WARNING = 2;
137+ ANNOTATION_LEVEL_FAILURE = 3;
138+}
139+
140+// Annotation is one ::notice, ::warning or ::error (or a problem matcher
141+// match), masked. The host validates every field again before it sends them.
142+message Annotation {
143+ AnnotationLevel level = 1;
144+ string title = 2;
145+ string message = 3;
146+ string file = 4; // relative to the repository when the file is in it
147+ int32 start_line = 5;
148+ int32 end_line = 6;
149+ int32 start_column = 7;
150+ int32 end_column = 8;
151+}
152+
153+// StepAnnotations is the complete list of the annotations of a step (the ones
154+// the runner keeps: at most 10 per level), replacing any earlier list of that
155+// step. Annotations of the steps inside a composite action are those of the
156+// step of the workflow that uses it.
157+message StepAnnotations {
158+ int32 step = 1;
159+ repeated Annotation annotations = 2;
160+}
161+
162+// StepSummary is the masked content of GITHUB_STEP_SUMMARY after a step, at
163+// most 1 MiB.
164+message StepSummary {
165+ int32 step = 1;
166+ string markdown = 2;
120167 }
121168
122169 enum StepConclusion {
@@ -25,6 +25,8 @@ message Frame {
25 StepCompleted step_completed = 7; // executor -> host25 StepCompleted step_completed = 7; // executor -> host
26 Log log = 8; // executor -> host26 Log log = 8; // executor -> host
27 JobResult job_result = 9; // executor -> host, before Exit27 JobResult job_result = 9; // executor -> host, before Exit
28+ StepAnnotations step_annotations = 10; // executor -> host, before the StepCompleted of the step
29+ StepSummary step_summary = 11; // executor -> host, before the StepCompleted of the step
28 }30 }
29 }31 }
30 32
@@ -66,6 +68,11 @@ message JobSpec {
66 // executor, and booting the sandbox takes time. 0 means "use68 // executor, and booting the sandbox takes time. 0 means "use
67 // timeout_minutes from now".69 // timeout_minutes from now".
68 int64 deadline_ms = 12;70 int64 deadline_ms = 12;
71+ // send_annotations and send_summaries say that the server keeps annotations
72+ // (feature ci.annotations) and step summaries (ci.summaries). The executor
73+ // sends StepAnnotations and StepSummary frames only when they are set.
74+ bool send_annotations = 13;
75+ bool send_summaries = 14;
69 }76 }
70 77
71 enum StreamKind {78 enum StreamKind {
@@ -117,6 +124,46 @@ message StepCompleted {
117 string name = 2;124 string name = 2;
118 StepConclusion conclusion = 3;125 StepConclusion conclusion = 3;
119 int64 unix_nano = 4;126 int64 unix_nano = 4;
127+ // outcome is steps.<id>.outcome: the result before continue-on-error. It
128+ // differs from conclusion only for a failed step with continue-on-error.
129+ // UNSPECIFIED means the same as conclusion.
130+ StepConclusion outcome = 5;
131+}
132+
133+enum AnnotationLevel {
134+ ANNOTATION_LEVEL_UNSPECIFIED = 0;
135+ ANNOTATION_LEVEL_NOTICE = 1;
136+ ANNOTATION_LEVEL_WARNING = 2;
137+ ANNOTATION_LEVEL_FAILURE = 3;
138+}
139+
140+// Annotation is one ::notice, ::warning or ::error (or a problem matcher
141+// match), masked. The host validates every field again before it sends them.
142+message Annotation {
143+ AnnotationLevel level = 1;
144+ string title = 2;
145+ string message = 3;
146+ string file = 4; // relative to the repository when the file is in it
147+ int32 start_line = 5;
148+ int32 end_line = 6;
149+ int32 start_column = 7;
150+ int32 end_column = 8;
151+}
152+
153+// StepAnnotations is the complete list of the annotations of a step (the ones
154+// the runner keeps: at most 10 per level), replacing any earlier list of that
155+// step. Annotations of the steps inside a composite action are those of the
156+// step of the workflow that uses it.
157+message StepAnnotations {
158+ int32 step = 1;
159+ repeated Annotation annotations = 2;
160+}
161+
162+// StepSummary is the masked content of GITHUB_STEP_SUMMARY after a step, at
163+// most 1 MiB.
164+message StepSummary {
165+ int32 step = 1;
166+ string markdown = 2;
120 }167 }
121 168
122 enum StepConclusion {169 enum StepConclusion {
M internal/execstream/execpb/exec.pb.go +431 -65
@@ -131,6 +131,58 @@ func (CancelKind) EnumDescriptor() ([]byte, []int) {
131131 return file_exec_proto_rawDescGZIP(), []int{1}
132132 }
133133
134+type AnnotationLevel int32
135+
136+const (
137+ AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED AnnotationLevel = 0
138+ AnnotationLevel_ANNOTATION_LEVEL_NOTICE AnnotationLevel = 1
139+ AnnotationLevel_ANNOTATION_LEVEL_WARNING AnnotationLevel = 2
140+ AnnotationLevel_ANNOTATION_LEVEL_FAILURE AnnotationLevel = 3
141+)
142+
143+// Enum value maps for AnnotationLevel.
144+var (
145+ AnnotationLevel_name = map[int32]string{
146+ 0: "ANNOTATION_LEVEL_UNSPECIFIED",
147+ 1: "ANNOTATION_LEVEL_NOTICE",
148+ 2: "ANNOTATION_LEVEL_WARNING",
149+ 3: "ANNOTATION_LEVEL_FAILURE",
150+ }
151+ AnnotationLevel_value = map[string]int32{
152+ "ANNOTATION_LEVEL_UNSPECIFIED": 0,
153+ "ANNOTATION_LEVEL_NOTICE": 1,
154+ "ANNOTATION_LEVEL_WARNING": 2,
155+ "ANNOTATION_LEVEL_FAILURE": 3,
156+ }
157+)
158+
159+func (x AnnotationLevel) Enum() *AnnotationLevel {
160+ p := new(AnnotationLevel)
161+ *p = x
162+ return p
163+}
164+
165+func (x AnnotationLevel) String() string {
166+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
167+}
168+
169+func (AnnotationLevel) Descriptor() protoreflect.EnumDescriptor {
170+ return file_exec_proto_enumTypes[2].Descriptor()
171+}
172+
173+func (AnnotationLevel) Type() protoreflect.EnumType {
174+ return &file_exec_proto_enumTypes[2]
175+}
176+
177+func (x AnnotationLevel) Number() protoreflect.EnumNumber {
178+ return protoreflect.EnumNumber(x)
179+}
180+
181+// Deprecated: Use AnnotationLevel.Descriptor instead.
182+func (AnnotationLevel) EnumDescriptor() ([]byte, []int) {
183+ return file_exec_proto_rawDescGZIP(), []int{2}
184+}
185+
134186 type StepConclusion int32
135187
136188 const (
@@ -173,11 +225,11 @@ func (x StepConclusion) String() string {
173225 }
174226
175227 func (StepConclusion) Descriptor() protoreflect.EnumDescriptor {
176- return file_exec_proto_enumTypes[2].Descriptor()
228+ return file_exec_proto_enumTypes[3].Descriptor()
177229 }
178230
179231 func (StepConclusion) Type() protoreflect.EnumType {
180- return &file_exec_proto_enumTypes[2]
232+ return &file_exec_proto_enumTypes[3]
181233 }
182234
183235 func (x StepConclusion) Number() protoreflect.EnumNumber {
@@ -186,7 +238,7 @@ func (x StepConclusion) Number() protoreflect.EnumNumber {
186238
187239 // Deprecated: Use StepConclusion.Descriptor instead.
188240 func (StepConclusion) EnumDescriptor() ([]byte, []int) {
189- return file_exec_proto_rawDescGZIP(), []int{2}
241+ return file_exec_proto_rawDescGZIP(), []int{3}
190242 }
191243
192244 // Frame is the only message on the stream.
@@ -203,6 +255,8 @@ type Frame struct {
203255 // *Frame_StepCompleted
204256 // *Frame_Log
205257 // *Frame_JobResult
258+ // *Frame_StepAnnotations
259+ // *Frame_StepSummary
206260 Body isFrame_Body `protobuf_oneof:"body"`
207261 unknownFields protoimpl.UnknownFields
208262 sizeCache protoimpl.SizeCache
@@ -326,6 +380,24 @@ func (x *Frame) GetJobResult() *JobResult {
326380 return nil
327381 }
328382
383+func (x *Frame) GetStepAnnotations() *StepAnnotations {
384+ if x != nil {
385+ if x, ok := x.Body.(*Frame_StepAnnotations); ok {
386+ return x.StepAnnotations
387+ }
388+ }
389+ return nil
390+}
391+
392+func (x *Frame) GetStepSummary() *StepSummary {
393+ if x != nil {
394+ if x, ok := x.Body.(*Frame_StepSummary); ok {
395+ return x.StepSummary
396+ }
397+ }
398+ return nil
399+}
400+
329401 type isFrame_Body interface {
330402 isFrame_Body()
331403 }
@@ -366,6 +438,14 @@ type Frame_JobResult struct {
366438 JobResult *JobResult `protobuf:"bytes,9,opt,name=job_result,json=jobResult,proto3,oneof"` // executor -> host, before Exit
367439 }
368440
441+type Frame_StepAnnotations struct {
442+ StepAnnotations *StepAnnotations `protobuf:"bytes,10,opt,name=step_annotations,json=stepAnnotations,proto3,oneof"` // executor -> host, before the StepCompleted of the step
443+}
444+
445+type Frame_StepSummary struct {
446+ StepSummary *StepSummary `protobuf:"bytes,11,opt,name=step_summary,json=stepSummary,proto3,oneof"` // executor -> host, before the StepCompleted of the step
447+}
448+
369449 func (*Frame_Hello) isFrame_Body() {}
370450
371451 func (*Frame_Run) isFrame_Body() {}
@@ -384,6 +464,10 @@ func (*Frame_Log) isFrame_Body() {}
384464
385465 func (*Frame_JobResult) isFrame_Body() {}
386466
467+func (*Frame_StepAnnotations) isFrame_Body() {}
468+
469+func (*Frame_StepSummary) isFrame_Body() {}
470+
387471 type Hello struct {
388472 state protoimpl.MessageState `protogen:"open.v1"`
389473 Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` // runner version of the executor
@@ -530,9 +614,14 @@ type JobSpec struct {
530614 // the job (runner.proto: Job.timeout_minutes), not from the start of the
531615 // executor, and booting the sandbox takes time. 0 means "use
532616 // timeout_minutes from now".
533- DeadlineMs int64 `protobuf:"varint,12,opt,name=deadline_ms,json=deadlineMs,proto3" json:"deadline_ms,omitempty"`
534- unknownFields protoimpl.UnknownFields
535- sizeCache protoimpl.SizeCache
617+ DeadlineMs int64 `protobuf:"varint,12,opt,name=deadline_ms,json=deadlineMs,proto3" json:"deadline_ms,omitempty"`
618+ // send_annotations and send_summaries say that the server keeps annotations
619+ // (feature ci.annotations) and step summaries (ci.summaries). The executor
620+ // sends StepAnnotations and StepSummary frames only when they are set.
621+ SendAnnotations bool `protobuf:"varint,13,opt,name=send_annotations,json=sendAnnotations,proto3" json:"send_annotations,omitempty"`
622+ SendSummaries bool `protobuf:"varint,14,opt,name=send_summaries,json=sendSummaries,proto3" json:"send_summaries,omitempty"`
623+ unknownFields protoimpl.UnknownFields
624+ sizeCache protoimpl.SizeCache
536625 }
537626
538627 func (x *JobSpec) Reset() {
@@ -649,6 +738,20 @@ func (x *JobSpec) GetDeadlineMs() int64 {
649738 return 0
650739 }
651740
741+func (x *JobSpec) GetSendAnnotations() bool {
742+ if x != nil {
743+ return x.SendAnnotations
744+ }
745+ return false
746+}
747+
748+func (x *JobSpec) GetSendSummaries() bool {
749+ if x != nil {
750+ return x.SendSummaries
751+ }
752+ return false
753+}
754+
652755 type Output struct {
653756 state protoimpl.MessageState `protogen:"open.v1"`
654757 Stream StreamKind `protobuf:"varint,1,opt,name=stream,proto3,enum=ermite.runner.exec.v1.StreamKind" json:"stream,omitempty"`
@@ -883,11 +986,15 @@ func (x *StepStarted) GetUnixNano() int64 {
883986 }
884987
885988 type StepCompleted struct {
886- state protoimpl.MessageState `protogen:"open.v1"`
887- Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
888- Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
889- Conclusion StepConclusion `protobuf:"varint,3,opt,name=conclusion,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"conclusion,omitempty"`
890- UnixNano int64 `protobuf:"varint,4,opt,name=unix_nano,json=unixNano,proto3" json:"unix_nano,omitempty"`
989+ state protoimpl.MessageState `protogen:"open.v1"`
990+ Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
991+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
992+ Conclusion StepConclusion `protobuf:"varint,3,opt,name=conclusion,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"conclusion,omitempty"`
993+ UnixNano int64 `protobuf:"varint,4,opt,name=unix_nano,json=unixNano,proto3" json:"unix_nano,omitempty"`
994+ // outcome is steps.<id>.outcome: the result before continue-on-error. It
995+ // differs from conclusion only for a failed step with continue-on-error.
996+ // UNSPECIFIED means the same as conclusion.
997+ Outcome StepConclusion `protobuf:"varint,5,opt,name=outcome,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"outcome,omitempty"`
891998 unknownFields protoimpl.UnknownFields
892999 sizeCache protoimpl.SizeCache
8931000 }
@@ -950,6 +1057,225 @@ func (x *StepCompleted) GetUnixNano() int64 {
9501057 return 0
9511058 }
9521059
1060+func (x *StepCompleted) GetOutcome() StepConclusion {
1061+ if x != nil {
1062+ return x.Outcome
1063+ }
1064+ return StepConclusion_STEP_CONCLUSION_UNSPECIFIED
1065+}
1066+
1067+// Annotation is one ::notice, ::warning or ::error (or a problem matcher
1068+// match), masked. The host validates every field again before it sends them.
1069+type Annotation struct {
1070+ state protoimpl.MessageState `protogen:"open.v1"`
1071+ Level AnnotationLevel `protobuf:"varint,1,opt,name=level,proto3,enum=ermite.runner.exec.v1.AnnotationLevel" json:"level,omitempty"`
1072+ Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
1073+ Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
1074+ File string `protobuf:"bytes,4,opt,name=file,proto3" json:"file,omitempty"` // relative to the repository when the file is in it
1075+ StartLine int32 `protobuf:"varint,5,opt,name=start_line,json=startLine,proto3" json:"start_line,omitempty"`
1076+ EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"`
1077+ StartColumn int32 `protobuf:"varint,7,opt,name=start_column,json=startColumn,proto3" json:"start_column,omitempty"`
1078+ EndColumn int32 `protobuf:"varint,8,opt,name=end_column,json=endColumn,proto3" json:"end_column,omitempty"`
1079+ unknownFields protoimpl.UnknownFields
1080+ sizeCache protoimpl.SizeCache
1081+}
1082+
1083+func (x *Annotation) Reset() {
1084+ *x = Annotation{}
1085+ mi := &file_exec_proto_msgTypes[9]
1086+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1087+ ms.StoreMessageInfo(mi)
1088+}
1089+
1090+func (x *Annotation) String() string {
1091+ return protoimpl.X.MessageStringOf(x)
1092+}
1093+
1094+func (*Annotation) ProtoMessage() {}
1095+
1096+func (x *Annotation) ProtoReflect() protoreflect.Message {
1097+ mi := &file_exec_proto_msgTypes[9]
1098+ if x != nil {
1099+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1100+ if ms.LoadMessageInfo() == nil {
1101+ ms.StoreMessageInfo(mi)
1102+ }
1103+ return ms
1104+ }
1105+ return mi.MessageOf(x)
1106+}
1107+
1108+// Deprecated: Use Annotation.ProtoReflect.Descriptor instead.
1109+func (*Annotation) Descriptor() ([]byte, []int) {
1110+ return file_exec_proto_rawDescGZIP(), []int{9}
1111+}
1112+
1113+func (x *Annotation) GetLevel() AnnotationLevel {
1114+ if x != nil {
1115+ return x.Level
1116+ }
1117+ return AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED
1118+}
1119+
1120+func (x *Annotation) GetTitle() string {
1121+ if x != nil {
1122+ return x.Title
1123+ }
1124+ return ""
1125+}
1126+
1127+func (x *Annotation) GetMessage() string {
1128+ if x != nil {
1129+ return x.Message
1130+ }
1131+ return ""
1132+}
1133+
1134+func (x *Annotation) GetFile() string {
1135+ if x != nil {
1136+ return x.File
1137+ }
1138+ return ""
1139+}
1140+
1141+func (x *Annotation) GetStartLine() int32 {
1142+ if x != nil {
1143+ return x.StartLine
1144+ }
1145+ return 0
1146+}
1147+
1148+func (x *Annotation) GetEndLine() int32 {
1149+ if x != nil {
1150+ return x.EndLine
1151+ }
1152+ return 0
1153+}
1154+
1155+func (x *Annotation) GetStartColumn() int32 {
1156+ if x != nil {
1157+ return x.StartColumn
1158+ }
1159+ return 0
1160+}
1161+
1162+func (x *Annotation) GetEndColumn() int32 {
1163+ if x != nil {
1164+ return x.EndColumn
1165+ }
1166+ return 0
1167+}
1168+
1169+// StepAnnotations is the complete list of the annotations of a step (the ones
1170+// the runner keeps: at most 10 per level), replacing any earlier list of that
1171+// step. Annotations of the steps inside a composite action are those of the
1172+// step of the workflow that uses it.
1173+type StepAnnotations struct {
1174+ state protoimpl.MessageState `protogen:"open.v1"`
1175+ Step int32 `protobuf:"varint,1,opt,name=step,proto3" json:"step,omitempty"`
1176+ Annotations []*Annotation `protobuf:"bytes,2,rep,name=annotations,proto3" json:"annotations,omitempty"`
1177+ unknownFields protoimpl.UnknownFields
1178+ sizeCache protoimpl.SizeCache
1179+}
1180+
1181+func (x *StepAnnotations) Reset() {
1182+ *x = StepAnnotations{}
1183+ mi := &file_exec_proto_msgTypes[10]
1184+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1185+ ms.StoreMessageInfo(mi)
1186+}
1187+
1188+func (x *StepAnnotations) String() string {
1189+ return protoimpl.X.MessageStringOf(x)
1190+}
1191+
1192+func (*StepAnnotations) ProtoMessage() {}
1193+
1194+func (x *StepAnnotations) ProtoReflect() protoreflect.Message {
1195+ mi := &file_exec_proto_msgTypes[10]
1196+ if x != nil {
1197+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1198+ if ms.LoadMessageInfo() == nil {
1199+ ms.StoreMessageInfo(mi)
1200+ }
1201+ return ms
1202+ }
1203+ return mi.MessageOf(x)
1204+}
1205+
1206+// Deprecated: Use StepAnnotations.ProtoReflect.Descriptor instead.
1207+func (*StepAnnotations) Descriptor() ([]byte, []int) {
1208+ return file_exec_proto_rawDescGZIP(), []int{10}
1209+}
1210+
1211+func (x *StepAnnotations) GetStep() int32 {
1212+ if x != nil {
1213+ return x.Step
1214+ }
1215+ return 0
1216+}
1217+
1218+func (x *StepAnnotations) GetAnnotations() []*Annotation {
1219+ if x != nil {
1220+ return x.Annotations
1221+ }
1222+ return nil
1223+}
1224+
1225+// StepSummary is the masked content of GITHUB_STEP_SUMMARY after a step, at
1226+// most 1 MiB.
1227+type StepSummary struct {
1228+ state protoimpl.MessageState `protogen:"open.v1"`
1229+ Step int32 `protobuf:"varint,1,opt,name=step,proto3" json:"step,omitempty"`
1230+ Markdown string `protobuf:"bytes,2,opt,name=markdown,proto3" json:"markdown,omitempty"`
1231+ unknownFields protoimpl.UnknownFields
1232+ sizeCache protoimpl.SizeCache
1233+}
1234+
1235+func (x *StepSummary) Reset() {
1236+ *x = StepSummary{}
1237+ mi := &file_exec_proto_msgTypes[11]
1238+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1239+ ms.StoreMessageInfo(mi)
1240+}
1241+
1242+func (x *StepSummary) String() string {
1243+ return protoimpl.X.MessageStringOf(x)
1244+}
1245+
1246+func (*StepSummary) ProtoMessage() {}
1247+
1248+func (x *StepSummary) ProtoReflect() protoreflect.Message {
1249+ mi := &file_exec_proto_msgTypes[11]
1250+ if x != nil {
1251+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1252+ if ms.LoadMessageInfo() == nil {
1253+ ms.StoreMessageInfo(mi)
1254+ }
1255+ return ms
1256+ }
1257+ return mi.MessageOf(x)
1258+}
1259+
1260+// Deprecated: Use StepSummary.ProtoReflect.Descriptor instead.
1261+func (*StepSummary) Descriptor() ([]byte, []int) {
1262+ return file_exec_proto_rawDescGZIP(), []int{11}
1263+}
1264+
1265+func (x *StepSummary) GetStep() int32 {
1266+ if x != nil {
1267+ return x.Step
1268+ }
1269+ return 0
1270+}
1271+
1272+func (x *StepSummary) GetMarkdown() string {
1273+ if x != nil {
1274+ return x.Markdown
1275+ }
1276+ return ""
1277+}
1278+
9531279 // Log is one line of the job log, without terminator, valid UTF-8. A line of
9541280 // more than 64 KiB is cut by the executor into pieces at character boundaries;
9551281 // every piece but the first has continued set (the AppendLog rule).
@@ -965,7 +1291,7 @@ type Log struct {
9651291
9661292 func (x *Log) Reset() {
9671293 *x = Log{}
968- mi := &file_exec_proto_msgTypes[9]
1294+ mi := &file_exec_proto_msgTypes[12]
9691295 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9701296 ms.StoreMessageInfo(mi)
9711297 }
@@ -977,7 +1303,7 @@ func (x *Log) String() string {
9771303 func (*Log) ProtoMessage() {}
9781304
9791305 func (x *Log) ProtoReflect() protoreflect.Message {
980- mi := &file_exec_proto_msgTypes[9]
1306+ mi := &file_exec_proto_msgTypes[12]
9811307 if x != nil {
9821308 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9831309 if ms.LoadMessageInfo() == nil {
@@ -990,7 +1316,7 @@ func (x *Log) ProtoReflect() protoreflect.Message {
9901316
9911317 // Deprecated: Use Log.ProtoReflect.Descriptor instead.
9921318 func (*Log) Descriptor() ([]byte, []int) {
993- return file_exec_proto_rawDescGZIP(), []int{9}
1319+ return file_exec_proto_rawDescGZIP(), []int{12}
9941320 }
9951321
9961322 func (x *Log) GetStep() int32 {
@@ -1034,7 +1360,7 @@ type JobResult struct {
10341360
10351361 func (x *JobResult) Reset() {
10361362 *x = JobResult{}
1037- mi := &file_exec_proto_msgTypes[10]
1363+ mi := &file_exec_proto_msgTypes[13]
10381364 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10391365 ms.StoreMessageInfo(mi)
10401366 }
@@ -1046,7 +1372,7 @@ func (x *JobResult) String() string {
10461372 func (*JobResult) ProtoMessage() {}
10471373
10481374 func (x *JobResult) ProtoReflect() protoreflect.Message {
1049- mi := &file_exec_proto_msgTypes[10]
1375+ mi := &file_exec_proto_msgTypes[13]
10501376 if x != nil {
10511377 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10521378 if ms.LoadMessageInfo() == nil {
@@ -1059,7 +1385,7 @@ func (x *JobResult) ProtoReflect() protoreflect.Message {
10591385
10601386 // Deprecated: Use JobResult.ProtoReflect.Descriptor instead.
10611387 func (*JobResult) Descriptor() ([]byte, []int) {
1062- return file_exec_proto_rawDescGZIP(), []int{10}
1388+ return file_exec_proto_rawDescGZIP(), []int{13}
10631389 }
10641390
10651391 func (x *JobResult) GetConclusion() StepConclusion {
@@ -1095,7 +1421,7 @@ var File_exec_proto protoreflect.FileDescriptor
10951421 const file_exec_proto_rawDesc = "" +
10961422 "\n" +
10971423 "\n" +
1098- "exec.proto\x12\x15ermite.runner.exec.v1\"\xa5\x04\n" +
1424+ "exec.proto\x12\x15ermite.runner.exec.v1\"\xc3\x05\n" +
10991425 "\x05Frame\x124\n" +
11001426 "\x05hello\x18\x01 \x01(\v2\x1c.ermite.runner.exec.v1.HelloH\x00R\x05hello\x12.\n" +
11011427 "\x03run\x18\x02 \x01(\v2\x1a.ermite.runner.exec.v1.RunH\x00R\x03run\x127\n" +
@@ -1106,7 +1432,10 @@ const file_exec_proto_rawDesc = "" +
11061432 "\x0estep_completed\x18\a \x01(\v2$.ermite.runner.exec.v1.StepCompletedH\x00R\rstepCompleted\x12.\n" +
11071433 "\x03log\x18\b \x01(\v2\x1a.ermite.runner.exec.v1.LogH\x00R\x03log\x12A\n" +
11081434 "\n" +
1109- "job_result\x18\t \x01(\v2 .ermite.runner.exec.v1.JobResultH\x00R\tjobResultB\x06\n" +
1435+ "job_result\x18\t \x01(\v2 .ermite.runner.exec.v1.JobResultH\x00R\tjobResult\x12S\n" +
1436+ "\x10step_annotations\x18\n" +
1437+ " \x01(\v2&.ermite.runner.exec.v1.StepAnnotationsH\x00R\x0fstepAnnotations\x12G\n" +
1438+ "\fstep_summary\x18\v \x01(\v2\".ermite.runner.exec.v1.StepSummaryH\x00R\vstepSummaryB\x06\n" +
11101439 "\x04body\"W\n" +
11111440 "\x05Hello\x12\x18\n" +
11121441 "\aversion\x18\x01 \x01(\tR\aversion\x12\x18\n" +
@@ -1118,7 +1447,7 @@ const file_exec_proto_rawDesc = "" +
11181447 "\x03job\x18\x03 \x01(\v2\x1e.ermite.runner.exec.v1.JobSpecR\x03job\x1a6\n" +
11191448 "\bEnvEntry\x12\x10\n" +
11201449 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
1121- "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x8b\x03\n" +
1450+ "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xdd\x03\n" +
11221451 "\aJobSpec\x12#\n" +
11231452 "\rworkflow_path\x18\x01 \x01(\tR\fworkflowPath\x12#\n" +
11241453 "\rworkflow_yaml\x18\x02 \x01(\tR\fworkflowYaml\x12\x17\n" +
@@ -1134,7 +1463,9 @@ const file_exec_proto_rawDesc = "" +
11341463 " \x01(\tR\x11runnerEnvironment\x12\x14\n" +
11351464 "\x05debug\x18\v \x01(\bR\x05debug\x12\x1f\n" +
11361465 "\vdeadline_ms\x18\f \x01(\x03R\n" +
1137- "deadlineMs\"t\n" +
1466+ "deadlineMs\x12)\n" +
1467+ "\x10send_annotations\x18\r \x01(\bR\x0fsendAnnotations\x12%\n" +
1468+ "\x0esend_summaries\x18\x0e \x01(\bR\rsendSummaries\"t\n" +
11381469 "\x06Output\x129\n" +
11391470 "\x06stream\x18\x01 \x01(\x0e2!.ermite.runner.exec.v1.StreamKindR\x06stream\x12\x12\n" +
11401471 "\x04data\x18\x02 \x01(\fR\x04data\x12\x1b\n" +
@@ -1148,14 +1479,33 @@ const file_exec_proto_rawDesc = "" +
11481479 "\vStepStarted\x12\x16\n" +
11491480 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
11501481 "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" +
1151- "\tunix_nano\x18\x03 \x01(\x03R\bunixNano\"\x9f\x01\n" +
1482+ "\tunix_nano\x18\x03 \x01(\x03R\bunixNano\"\xe0\x01\n" +
11521483 "\rStepCompleted\x12\x16\n" +
11531484 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
11541485 "\x04name\x18\x02 \x01(\tR\x04name\x12E\n" +
11551486 "\n" +
11561487 "conclusion\x18\x03 \x01(\x0e2%.ermite.runner.exec.v1.StepConclusionR\n" +
11571488 "conclusion\x12\x1b\n" +
1158- "\tunix_nano\x18\x04 \x01(\x03R\bunixNano\"h\n" +
1489+ "\tunix_nano\x18\x04 \x01(\x03R\bunixNano\x12?\n" +
1490+ "\aoutcome\x18\x05 \x01(\x0e2%.ermite.runner.exec.v1.StepConclusionR\aoutcome\"\x8a\x02\n" +
1491+ "\n" +
1492+ "Annotation\x12<\n" +
1493+ "\x05level\x18\x01 \x01(\x0e2&.ermite.runner.exec.v1.AnnotationLevelR\x05level\x12\x14\n" +
1494+ "\x05title\x18\x02 \x01(\tR\x05title\x12\x18\n" +
1495+ "\amessage\x18\x03 \x01(\tR\amessage\x12\x12\n" +
1496+ "\x04file\x18\x04 \x01(\tR\x04file\x12\x1d\n" +
1497+ "\n" +
1498+ "start_line\x18\x05 \x01(\x05R\tstartLine\x12\x19\n" +
1499+ "\bend_line\x18\x06 \x01(\x05R\aendLine\x12!\n" +
1500+ "\fstart_column\x18\a \x01(\x05R\vstartColumn\x12\x1d\n" +
1501+ "\n" +
1502+ "end_column\x18\b \x01(\x05R\tendColumn\"j\n" +
1503+ "\x0fStepAnnotations\x12\x12\n" +
1504+ "\x04step\x18\x01 \x01(\x05R\x04step\x12C\n" +
1505+ "\vannotations\x18\x02 \x03(\v2!.ermite.runner.exec.v1.AnnotationR\vannotations\"=\n" +
1506+ "\vStepSummary\x12\x12\n" +
1507+ "\x04step\x18\x01 \x01(\x05R\x04step\x12\x1a\n" +
1508+ "\bmarkdown\x18\x02 \x01(\tR\bmarkdown\"h\n" +
11591509 "\x03Log\x12\x12\n" +
11601510 "\x04step\x18\x01 \x01(\x05R\x04step\x12\x1b\n" +
11611511 "\tunix_nano\x18\x02 \x01(\x03R\bunixNano\x12\x12\n" +
@@ -1181,7 +1531,12 @@ const file_exec_proto_rawDesc = "" +
11811531 "\x17CANCEL_KIND_UNSPECIFIED\x10\x00\x12\x14\n" +
11821532 "\x10CANCEL_KIND_USER\x10\x01\x12\x17\n" +
11831533 "\x13CANCEL_KIND_TIMEOUT\x10\x02\x12\x18\n" +
1184- "\x14CANCEL_KIND_SHUTDOWN\x10\x03*\xc6\x01\n" +
1534+ "\x14CANCEL_KIND_SHUTDOWN\x10\x03*\x8c\x01\n" +
1535+ "\x0fAnnotationLevel\x12 \n" +
1536+ "\x1cANNOTATION_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n" +
1537+ "\x17ANNOTATION_LEVEL_NOTICE\x10\x01\x12\x1c\n" +
1538+ "\x18ANNOTATION_LEVEL_WARNING\x10\x02\x12\x1c\n" +
1539+ "\x18ANNOTATION_LEVEL_FAILURE\x10\x03*\xc6\x01\n" +
11851540 "\x0eStepConclusion\x12\x1f\n" +
11861541 "\x1bSTEP_CONCLUSION_UNSPECIFIED\x10\x00\x12\x1b\n" +
11871542 "\x17STEP_CONCLUSION_SUCCESS\x10\x01\x12\x1b\n" +
@@ -1202,48 +1557,57 @@ func file_exec_proto_rawDescGZIP() []byte {
12021557 return file_exec_proto_rawDescData
12031558 }
12041559
1205-var file_exec_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
1206-var file_exec_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
1560+var file_exec_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
1561+var file_exec_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
12071562 var file_exec_proto_goTypes = []any{
1208- (StreamKind)(0), // 0: ermite.runner.exec.v1.StreamKind
1209- (CancelKind)(0), // 1: ermite.runner.exec.v1.CancelKind
1210- (StepConclusion)(0), // 2: ermite.runner.exec.v1.StepConclusion
1211- (*Frame)(nil), // 3: ermite.runner.exec.v1.Frame
1212- (*Hello)(nil), // 4: ermite.runner.exec.v1.Hello
1213- (*Run)(nil), // 5: ermite.runner.exec.v1.Run
1214- (*JobSpec)(nil), // 6: ermite.runner.exec.v1.JobSpec
1215- (*Output)(nil), // 7: ermite.runner.exec.v1.Output
1216- (*Exit)(nil), // 8: ermite.runner.exec.v1.Exit
1217- (*Cancel)(nil), // 9: ermite.runner.exec.v1.Cancel
1218- (*StepStarted)(nil), // 10: ermite.runner.exec.v1.StepStarted
1219- (*StepCompleted)(nil), // 11: ermite.runner.exec.v1.StepCompleted
1220- (*Log)(nil), // 12: ermite.runner.exec.v1.Log
1221- (*JobResult)(nil), // 13: ermite.runner.exec.v1.JobResult
1222- nil, // 14: ermite.runner.exec.v1.Run.EnvEntry
1223- nil, // 15: ermite.runner.exec.v1.JobResult.OutputsEntry
1563+ (StreamKind)(0), // 0: ermite.runner.exec.v1.StreamKind
1564+ (CancelKind)(0), // 1: ermite.runner.exec.v1.CancelKind
1565+ (AnnotationLevel)(0), // 2: ermite.runner.exec.v1.AnnotationLevel
1566+ (StepConclusion)(0), // 3: ermite.runner.exec.v1.StepConclusion
1567+ (*Frame)(nil), // 4: ermite.runner.exec.v1.Frame
1568+ (*Hello)(nil), // 5: ermite.runner.exec.v1.Hello
1569+ (*Run)(nil), // 6: ermite.runner.exec.v1.Run
1570+ (*JobSpec)(nil), // 7: ermite.runner.exec.v1.JobSpec
1571+ (*Output)(nil), // 8: ermite.runner.exec.v1.Output
1572+ (*Exit)(nil), // 9: ermite.runner.exec.v1.Exit
1573+ (*Cancel)(nil), // 10: ermite.runner.exec.v1.Cancel
1574+ (*StepStarted)(nil), // 11: ermite.runner.exec.v1.StepStarted
1575+ (*StepCompleted)(nil), // 12: ermite.runner.exec.v1.StepCompleted
1576+ (*Annotation)(nil), // 13: ermite.runner.exec.v1.Annotation
1577+ (*StepAnnotations)(nil), // 14: ermite.runner.exec.v1.StepAnnotations
1578+ (*StepSummary)(nil), // 15: ermite.runner.exec.v1.StepSummary
1579+ (*Log)(nil), // 16: ermite.runner.exec.v1.Log
1580+ (*JobResult)(nil), // 17: ermite.runner.exec.v1.JobResult
1581+ nil, // 18: ermite.runner.exec.v1.Run.EnvEntry
1582+ nil, // 19: ermite.runner.exec.v1.JobResult.OutputsEntry
12241583 }
12251584 var file_exec_proto_depIdxs = []int32{
1226- 4, // 0: ermite.runner.exec.v1.Frame.hello:type_name -> ermite.runner.exec.v1.Hello
1227- 5, // 1: ermite.runner.exec.v1.Frame.run:type_name -> ermite.runner.exec.v1.Run
1228- 7, // 2: ermite.runner.exec.v1.Frame.output:type_name -> ermite.runner.exec.v1.Output
1229- 8, // 3: ermite.runner.exec.v1.Frame.exit:type_name -> ermite.runner.exec.v1.Exit
1230- 9, // 4: ermite.runner.exec.v1.Frame.cancel:type_name -> ermite.runner.exec.v1.Cancel
1231- 10, // 5: ermite.runner.exec.v1.Frame.step_started:type_name -> ermite.runner.exec.v1.StepStarted
1232- 11, // 6: ermite.runner.exec.v1.Frame.step_completed:type_name -> ermite.runner.exec.v1.StepCompleted
1233- 12, // 7: ermite.runner.exec.v1.Frame.log:type_name -> ermite.runner.exec.v1.Log
1234- 13, // 8: ermite.runner.exec.v1.Frame.job_result:type_name -> ermite.runner.exec.v1.JobResult
1235- 14, // 9: ermite.runner.exec.v1.Run.env:type_name -> ermite.runner.exec.v1.Run.EnvEntry
1236- 6, // 10: ermite.runner.exec.v1.Run.job:type_name -> ermite.runner.exec.v1.JobSpec
1237- 0, // 11: ermite.runner.exec.v1.Output.stream:type_name -> ermite.runner.exec.v1.StreamKind
1238- 1, // 12: ermite.runner.exec.v1.Cancel.kind:type_name -> ermite.runner.exec.v1.CancelKind
1239- 2, // 13: ermite.runner.exec.v1.StepCompleted.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1240- 2, // 14: ermite.runner.exec.v1.JobResult.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1241- 15, // 15: ermite.runner.exec.v1.JobResult.outputs:type_name -> ermite.runner.exec.v1.JobResult.OutputsEntry
1242- 16, // [16:16] is the sub-list for method output_type
1243- 16, // [16:16] is the sub-list for method input_type
1244- 16, // [16:16] is the sub-list for extension type_name
1245- 16, // [16:16] is the sub-list for extension extendee
1246- 0, // [0:16] is the sub-list for field type_name
1585+ 5, // 0: ermite.runner.exec.v1.Frame.hello:type_name -> ermite.runner.exec.v1.Hello
1586+ 6, // 1: ermite.runner.exec.v1.Frame.run:type_name -> ermite.runner.exec.v1.Run
1587+ 8, // 2: ermite.runner.exec.v1.Frame.output:type_name -> ermite.runner.exec.v1.Output
1588+ 9, // 3: ermite.runner.exec.v1.Frame.exit:type_name -> ermite.runner.exec.v1.Exit
1589+ 10, // 4: ermite.runner.exec.v1.Frame.cancel:type_name -> ermite.runner.exec.v1.Cancel
1590+ 11, // 5: ermite.runner.exec.v1.Frame.step_started:type_name -> ermite.runner.exec.v1.StepStarted
1591+ 12, // 6: ermite.runner.exec.v1.Frame.step_completed:type_name -> ermite.runner.exec.v1.StepCompleted
1592+ 16, // 7: ermite.runner.exec.v1.Frame.log:type_name -> ermite.runner.exec.v1.Log
1593+ 17, // 8: ermite.runner.exec.v1.Frame.job_result:type_name -> ermite.runner.exec.v1.JobResult
1594+ 14, // 9: ermite.runner.exec.v1.Frame.step_annotations:type_name -> ermite.runner.exec.v1.StepAnnotations
1595+ 15, // 10: ermite.runner.exec.v1.Frame.step_summary:type_name -> ermite.runner.exec.v1.StepSummary
1596+ 18, // 11: ermite.runner.exec.v1.Run.env:type_name -> ermite.runner.exec.v1.Run.EnvEntry
1597+ 7, // 12: ermite.runner.exec.v1.Run.job:type_name -> ermite.runner.exec.v1.JobSpec
1598+ 0, // 13: ermite.runner.exec.v1.Output.stream:type_name -> ermite.runner.exec.v1.StreamKind
1599+ 1, // 14: ermite.runner.exec.v1.Cancel.kind:type_name -> ermite.runner.exec.v1.CancelKind
1600+ 3, // 15: ermite.runner.exec.v1.StepCompleted.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1601+ 3, // 16: ermite.runner.exec.v1.StepCompleted.outcome:type_name -> ermite.runner.exec.v1.StepConclusion
1602+ 2, // 17: ermite.runner.exec.v1.Annotation.level:type_name -> ermite.runner.exec.v1.AnnotationLevel
1603+ 13, // 18: ermite.runner.exec.v1.StepAnnotations.annotations:type_name -> ermite.runner.exec.v1.Annotation
1604+ 3, // 19: ermite.runner.exec.v1.JobResult.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1605+ 19, // 20: ermite.runner.exec.v1.JobResult.outputs:type_name -> ermite.runner.exec.v1.JobResult.OutputsEntry
1606+ 21, // [21:21] is the sub-list for method output_type
1607+ 21, // [21:21] is the sub-list for method input_type
1608+ 21, // [21:21] is the sub-list for extension type_name
1609+ 21, // [21:21] is the sub-list for extension extendee
1610+ 0, // [0:21] is the sub-list for field type_name
12471611 }
12481612
12491613 func init() { file_exec_proto_init() }
@@ -1261,14 +1625,16 @@ func file_exec_proto_init() {
12611625 (*Frame_StepCompleted)(nil),
12621626 (*Frame_Log)(nil),
12631627 (*Frame_JobResult)(nil),
1628+ (*Frame_StepAnnotations)(nil),
1629+ (*Frame_StepSummary)(nil),
12641630 }
12651631 type x struct{}
12661632 out := protoimpl.TypeBuilder{
12671633 File: protoimpl.DescBuilder{
12681634 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
12691635 RawDescriptor: unsafe.Slice(unsafe.StringData(file_exec_proto_rawDesc), len(file_exec_proto_rawDesc)),
1270- NumEnums: 3,
1271- NumMessages: 13,
1636+ NumEnums: 4,
1637+ NumMessages: 16,
12721638 NumExtensions: 0,
12731639 NumServices: 0,
12741640 },
@@ -131,6 +131,58 @@ func (CancelKind) EnumDescriptor() ([]byte, []int) {
131 return file_exec_proto_rawDescGZIP(), []int{1}131 return file_exec_proto_rawDescGZIP(), []int{1}
132 }132 }
133 133
134+type AnnotationLevel int32
135+
136+const (
137+ AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED AnnotationLevel = 0
138+ AnnotationLevel_ANNOTATION_LEVEL_NOTICE AnnotationLevel = 1
139+ AnnotationLevel_ANNOTATION_LEVEL_WARNING AnnotationLevel = 2
140+ AnnotationLevel_ANNOTATION_LEVEL_FAILURE AnnotationLevel = 3
141+)
142+
143+// Enum value maps for AnnotationLevel.
144+var (
145+ AnnotationLevel_name = map[int32]string{
146+ 0: "ANNOTATION_LEVEL_UNSPECIFIED",
147+ 1: "ANNOTATION_LEVEL_NOTICE",
148+ 2: "ANNOTATION_LEVEL_WARNING",
149+ 3: "ANNOTATION_LEVEL_FAILURE",
150+ }
151+ AnnotationLevel_value = map[string]int32{
152+ "ANNOTATION_LEVEL_UNSPECIFIED": 0,
153+ "ANNOTATION_LEVEL_NOTICE": 1,
154+ "ANNOTATION_LEVEL_WARNING": 2,
155+ "ANNOTATION_LEVEL_FAILURE": 3,
156+ }
157+)
158+
159+func (x AnnotationLevel) Enum() *AnnotationLevel {
160+ p := new(AnnotationLevel)
161+ *p = x
162+ return p
163+}
164+
165+func (x AnnotationLevel) String() string {
166+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
167+}
168+
169+func (AnnotationLevel) Descriptor() protoreflect.EnumDescriptor {
170+ return file_exec_proto_enumTypes[2].Descriptor()
171+}
172+
173+func (AnnotationLevel) Type() protoreflect.EnumType {
174+ return &file_exec_proto_enumTypes[2]
175+}
176+
177+func (x AnnotationLevel) Number() protoreflect.EnumNumber {
178+ return protoreflect.EnumNumber(x)
179+}
180+
181+// Deprecated: Use AnnotationLevel.Descriptor instead.
182+func (AnnotationLevel) EnumDescriptor() ([]byte, []int) {
183+ return file_exec_proto_rawDescGZIP(), []int{2}
184+}
185+
134 type StepConclusion int32186 type StepConclusion int32
135 187
136 const (188 const (
@@ -173,11 +225,11 @@ func (x StepConclusion) String() string {
173 }225 }
174 226
175 func (StepConclusion) Descriptor() protoreflect.EnumDescriptor {227 func (StepConclusion) Descriptor() protoreflect.EnumDescriptor {
176- return file_exec_proto_enumTypes[2].Descriptor()228+ return file_exec_proto_enumTypes[3].Descriptor()
177 }229 }
178 230
179 func (StepConclusion) Type() protoreflect.EnumType {231 func (StepConclusion) Type() protoreflect.EnumType {
180- return &file_exec_proto_enumTypes[2]232+ return &file_exec_proto_enumTypes[3]
181 }233 }
182 234
183 func (x StepConclusion) Number() protoreflect.EnumNumber {235 func (x StepConclusion) Number() protoreflect.EnumNumber {
@@ -186,7 +238,7 @@ func (x StepConclusion) Number() protoreflect.EnumNumber {
186 238
187 // Deprecated: Use StepConclusion.Descriptor instead.239 // Deprecated: Use StepConclusion.Descriptor instead.
188 func (StepConclusion) EnumDescriptor() ([]byte, []int) {240 func (StepConclusion) EnumDescriptor() ([]byte, []int) {
189- return file_exec_proto_rawDescGZIP(), []int{2}241+ return file_exec_proto_rawDescGZIP(), []int{3}
190 }242 }
191 243
192 // Frame is the only message on the stream.244 // Frame is the only message on the stream.
@@ -203,6 +255,8 @@ type Frame struct {
203 // *Frame_StepCompleted255 // *Frame_StepCompleted
204 // *Frame_Log256 // *Frame_Log
205 // *Frame_JobResult257 // *Frame_JobResult
258+ // *Frame_StepAnnotations
259+ // *Frame_StepSummary
206 Body isFrame_Body `protobuf_oneof:"body"`260 Body isFrame_Body `protobuf_oneof:"body"`
207 unknownFields protoimpl.UnknownFields261 unknownFields protoimpl.UnknownFields
208 sizeCache protoimpl.SizeCache262 sizeCache protoimpl.SizeCache
@@ -326,6 +380,24 @@ func (x *Frame) GetJobResult() *JobResult {
326 return nil380 return nil
327 }381 }
328 382
383+func (x *Frame) GetStepAnnotations() *StepAnnotations {
384+ if x != nil {
385+ if x, ok := x.Body.(*Frame_StepAnnotations); ok {
386+ return x.StepAnnotations
387+ }
388+ }
389+ return nil
390+}
391+
392+func (x *Frame) GetStepSummary() *StepSummary {
393+ if x != nil {
394+ if x, ok := x.Body.(*Frame_StepSummary); ok {
395+ return x.StepSummary
396+ }
397+ }
398+ return nil
399+}
400+
329 type isFrame_Body interface {401 type isFrame_Body interface {
330 isFrame_Body()402 isFrame_Body()
331 }403 }
@@ -366,6 +438,14 @@ type Frame_JobResult struct {
366 JobResult *JobResult `protobuf:"bytes,9,opt,name=job_result,json=jobResult,proto3,oneof"` // executor -> host, before Exit438 JobResult *JobResult `protobuf:"bytes,9,opt,name=job_result,json=jobResult,proto3,oneof"` // executor -> host, before Exit
367 }439 }
368 440
441+type Frame_StepAnnotations struct {
442+ StepAnnotations *StepAnnotations `protobuf:"bytes,10,opt,name=step_annotations,json=stepAnnotations,proto3,oneof"` // executor -> host, before the StepCompleted of the step
443+}
444+
445+type Frame_StepSummary struct {
446+ StepSummary *StepSummary `protobuf:"bytes,11,opt,name=step_summary,json=stepSummary,proto3,oneof"` // executor -> host, before the StepCompleted of the step
447+}
448+
369 func (*Frame_Hello) isFrame_Body() {}449 func (*Frame_Hello) isFrame_Body() {}
370 450
371 func (*Frame_Run) isFrame_Body() {}451 func (*Frame_Run) isFrame_Body() {}
@@ -384,6 +464,10 @@ func (*Frame_Log) isFrame_Body() {}
384 464
385 func (*Frame_JobResult) isFrame_Body() {}465 func (*Frame_JobResult) isFrame_Body() {}
386 466
467+func (*Frame_StepAnnotations) isFrame_Body() {}
468+
469+func (*Frame_StepSummary) isFrame_Body() {}
470+
387 type Hello struct {471 type Hello struct {
388 state protoimpl.MessageState `protogen:"open.v1"`472 state protoimpl.MessageState `protogen:"open.v1"`
389 Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` // runner version of the executor473 Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` // runner version of the executor
@@ -530,9 +614,14 @@ type JobSpec struct {
530 // the job (runner.proto: Job.timeout_minutes), not from the start of the614 // the job (runner.proto: Job.timeout_minutes), not from the start of the
531 // executor, and booting the sandbox takes time. 0 means "use615 // executor, and booting the sandbox takes time. 0 means "use
532 // timeout_minutes from now".616 // timeout_minutes from now".
533- DeadlineMs int64 `protobuf:"varint,12,opt,name=deadline_ms,json=deadlineMs,proto3" json:"deadline_ms,omitempty"`617+ DeadlineMs int64 `protobuf:"varint,12,opt,name=deadline_ms,json=deadlineMs,proto3" json:"deadline_ms,omitempty"`
534- unknownFields protoimpl.UnknownFields618+ // send_annotations and send_summaries say that the server keeps annotations
535- sizeCache protoimpl.SizeCache619+ // (feature ci.annotations) and step summaries (ci.summaries). The executor
620+ // sends StepAnnotations and StepSummary frames only when they are set.
621+ SendAnnotations bool `protobuf:"varint,13,opt,name=send_annotations,json=sendAnnotations,proto3" json:"send_annotations,omitempty"`
622+ SendSummaries bool `protobuf:"varint,14,opt,name=send_summaries,json=sendSummaries,proto3" json:"send_summaries,omitempty"`
623+ unknownFields protoimpl.UnknownFields
624+ sizeCache protoimpl.SizeCache
536 }625 }
537 626
538 func (x *JobSpec) Reset() {627 func (x *JobSpec) Reset() {
@@ -649,6 +738,20 @@ func (x *JobSpec) GetDeadlineMs() int64 {
649 return 0738 return 0
650 }739 }
651 740
741+func (x *JobSpec) GetSendAnnotations() bool {
742+ if x != nil {
743+ return x.SendAnnotations
744+ }
745+ return false
746+}
747+
748+func (x *JobSpec) GetSendSummaries() bool {
749+ if x != nil {
750+ return x.SendSummaries
751+ }
752+ return false
753+}
754+
652 type Output struct {755 type Output struct {
653 state protoimpl.MessageState `protogen:"open.v1"`756 state protoimpl.MessageState `protogen:"open.v1"`
654 Stream StreamKind `protobuf:"varint,1,opt,name=stream,proto3,enum=ermite.runner.exec.v1.StreamKind" json:"stream,omitempty"`757 Stream StreamKind `protobuf:"varint,1,opt,name=stream,proto3,enum=ermite.runner.exec.v1.StreamKind" json:"stream,omitempty"`
@@ -883,11 +986,15 @@ func (x *StepStarted) GetUnixNano() int64 {
883 }986 }
884 987
885 type StepCompleted struct {988 type StepCompleted struct {
886- state protoimpl.MessageState `protogen:"open.v1"`989+ state protoimpl.MessageState `protogen:"open.v1"`
887- Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`990+ Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
888- Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`991+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
889- Conclusion StepConclusion `protobuf:"varint,3,opt,name=conclusion,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"conclusion,omitempty"`992+ Conclusion StepConclusion `protobuf:"varint,3,opt,name=conclusion,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"conclusion,omitempty"`
890- UnixNano int64 `protobuf:"varint,4,opt,name=unix_nano,json=unixNano,proto3" json:"unix_nano,omitempty"`993+ UnixNano int64 `protobuf:"varint,4,opt,name=unix_nano,json=unixNano,proto3" json:"unix_nano,omitempty"`
994+ // outcome is steps.<id>.outcome: the result before continue-on-error. It
995+ // differs from conclusion only for a failed step with continue-on-error.
996+ // UNSPECIFIED means the same as conclusion.
997+ Outcome StepConclusion `protobuf:"varint,5,opt,name=outcome,proto3,enum=ermite.runner.exec.v1.StepConclusion" json:"outcome,omitempty"`
891 unknownFields protoimpl.UnknownFields998 unknownFields protoimpl.UnknownFields
892 sizeCache protoimpl.SizeCache999 sizeCache protoimpl.SizeCache
893 }1000 }
@@ -950,6 +1057,225 @@ func (x *StepCompleted) GetUnixNano() int64 {
950 return 01057 return 0
951 }1058 }
952 1059
1060+func (x *StepCompleted) GetOutcome() StepConclusion {
1061+ if x != nil {
1062+ return x.Outcome
1063+ }
1064+ return StepConclusion_STEP_CONCLUSION_UNSPECIFIED
1065+}
1066+
1067+// Annotation is one ::notice, ::warning or ::error (or a problem matcher
1068+// match), masked. The host validates every field again before it sends them.
1069+type Annotation struct {
1070+ state protoimpl.MessageState `protogen:"open.v1"`
1071+ Level AnnotationLevel `protobuf:"varint,1,opt,name=level,proto3,enum=ermite.runner.exec.v1.AnnotationLevel" json:"level,omitempty"`
1072+ Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
1073+ Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
1074+ File string `protobuf:"bytes,4,opt,name=file,proto3" json:"file,omitempty"` // relative to the repository when the file is in it
1075+ StartLine int32 `protobuf:"varint,5,opt,name=start_line,json=startLine,proto3" json:"start_line,omitempty"`
1076+ EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"`
1077+ StartColumn int32 `protobuf:"varint,7,opt,name=start_column,json=startColumn,proto3" json:"start_column,omitempty"`
1078+ EndColumn int32 `protobuf:"varint,8,opt,name=end_column,json=endColumn,proto3" json:"end_column,omitempty"`
1079+ unknownFields protoimpl.UnknownFields
1080+ sizeCache protoimpl.SizeCache
1081+}
1082+
1083+func (x *Annotation) Reset() {
1084+ *x = Annotation{}
1085+ mi := &file_exec_proto_msgTypes[9]
1086+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1087+ ms.StoreMessageInfo(mi)
1088+}
1089+
1090+func (x *Annotation) String() string {
1091+ return protoimpl.X.MessageStringOf(x)
1092+}
1093+
1094+func (*Annotation) ProtoMessage() {}
1095+
1096+func (x *Annotation) ProtoReflect() protoreflect.Message {
1097+ mi := &file_exec_proto_msgTypes[9]
1098+ if x != nil {
1099+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1100+ if ms.LoadMessageInfo() == nil {
1101+ ms.StoreMessageInfo(mi)
1102+ }
1103+ return ms
1104+ }
1105+ return mi.MessageOf(x)
1106+}
1107+
1108+// Deprecated: Use Annotation.ProtoReflect.Descriptor instead.
1109+func (*Annotation) Descriptor() ([]byte, []int) {
1110+ return file_exec_proto_rawDescGZIP(), []int{9}
1111+}
1112+
1113+func (x *Annotation) GetLevel() AnnotationLevel {
1114+ if x != nil {
1115+ return x.Level
1116+ }
1117+ return AnnotationLevel_ANNOTATION_LEVEL_UNSPECIFIED
1118+}
1119+
1120+func (x *Annotation) GetTitle() string {
1121+ if x != nil {
1122+ return x.Title
1123+ }
1124+ return ""
1125+}
1126+
1127+func (x *Annotation) GetMessage() string {
1128+ if x != nil {
1129+ return x.Message
1130+ }
1131+ return ""
1132+}
1133+
1134+func (x *Annotation) GetFile() string {
1135+ if x != nil {
1136+ return x.File
1137+ }
1138+ return ""
1139+}
1140+
1141+func (x *Annotation) GetStartLine() int32 {
1142+ if x != nil {
1143+ return x.StartLine
1144+ }
1145+ return 0
1146+}
1147+
1148+func (x *Annotation) GetEndLine() int32 {
1149+ if x != nil {
1150+ return x.EndLine
1151+ }
1152+ return 0
1153+}
1154+
1155+func (x *Annotation) GetStartColumn() int32 {
1156+ if x != nil {
1157+ return x.StartColumn
1158+ }
1159+ return 0
1160+}
1161+
1162+func (x *Annotation) GetEndColumn() int32 {
1163+ if x != nil {
1164+ return x.EndColumn
1165+ }
1166+ return 0
1167+}
1168+
1169+// StepAnnotations is the complete list of the annotations of a step (the ones
1170+// the runner keeps: at most 10 per level), replacing any earlier list of that
1171+// step. Annotations of the steps inside a composite action are those of the
1172+// step of the workflow that uses it.
1173+type StepAnnotations struct {
1174+ state protoimpl.MessageState `protogen:"open.v1"`
1175+ Step int32 `protobuf:"varint,1,opt,name=step,proto3" json:"step,omitempty"`
1176+ Annotations []*Annotation `protobuf:"bytes,2,rep,name=annotations,proto3" json:"annotations,omitempty"`
1177+ unknownFields protoimpl.UnknownFields
1178+ sizeCache protoimpl.SizeCache
1179+}
1180+
1181+func (x *StepAnnotations) Reset() {
1182+ *x = StepAnnotations{}
1183+ mi := &file_exec_proto_msgTypes[10]
1184+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1185+ ms.StoreMessageInfo(mi)
1186+}
1187+
1188+func (x *StepAnnotations) String() string {
1189+ return protoimpl.X.MessageStringOf(x)
1190+}
1191+
1192+func (*StepAnnotations) ProtoMessage() {}
1193+
1194+func (x *StepAnnotations) ProtoReflect() protoreflect.Message {
1195+ mi := &file_exec_proto_msgTypes[10]
1196+ if x != nil {
1197+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1198+ if ms.LoadMessageInfo() == nil {
1199+ ms.StoreMessageInfo(mi)
1200+ }
1201+ return ms
1202+ }
1203+ return mi.MessageOf(x)
1204+}
1205+
1206+// Deprecated: Use StepAnnotations.ProtoReflect.Descriptor instead.
1207+func (*StepAnnotations) Descriptor() ([]byte, []int) {
1208+ return file_exec_proto_rawDescGZIP(), []int{10}
1209+}
1210+
1211+func (x *StepAnnotations) GetStep() int32 {
1212+ if x != nil {
1213+ return x.Step
1214+ }
1215+ return 0
1216+}
1217+
1218+func (x *StepAnnotations) GetAnnotations() []*Annotation {
1219+ if x != nil {
1220+ return x.Annotations
1221+ }
1222+ return nil
1223+}
1224+
1225+// StepSummary is the masked content of GITHUB_STEP_SUMMARY after a step, at
1226+// most 1 MiB.
1227+type StepSummary struct {
1228+ state protoimpl.MessageState `protogen:"open.v1"`
1229+ Step int32 `protobuf:"varint,1,opt,name=step,proto3" json:"step,omitempty"`
1230+ Markdown string `protobuf:"bytes,2,opt,name=markdown,proto3" json:"markdown,omitempty"`
1231+ unknownFields protoimpl.UnknownFields
1232+ sizeCache protoimpl.SizeCache
1233+}
1234+
1235+func (x *StepSummary) Reset() {
1236+ *x = StepSummary{}
1237+ mi := &file_exec_proto_msgTypes[11]
1238+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1239+ ms.StoreMessageInfo(mi)
1240+}
1241+
1242+func (x *StepSummary) String() string {
1243+ return protoimpl.X.MessageStringOf(x)
1244+}
1245+
1246+func (*StepSummary) ProtoMessage() {}
1247+
1248+func (x *StepSummary) ProtoReflect() protoreflect.Message {
1249+ mi := &file_exec_proto_msgTypes[11]
1250+ if x != nil {
1251+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1252+ if ms.LoadMessageInfo() == nil {
1253+ ms.StoreMessageInfo(mi)
1254+ }
1255+ return ms
1256+ }
1257+ return mi.MessageOf(x)
1258+}
1259+
1260+// Deprecated: Use StepSummary.ProtoReflect.Descriptor instead.
1261+func (*StepSummary) Descriptor() ([]byte, []int) {
1262+ return file_exec_proto_rawDescGZIP(), []int{11}
1263+}
1264+
1265+func (x *StepSummary) GetStep() int32 {
1266+ if x != nil {
1267+ return x.Step
1268+ }
1269+ return 0
1270+}
1271+
1272+func (x *StepSummary) GetMarkdown() string {
1273+ if x != nil {
1274+ return x.Markdown
1275+ }
1276+ return ""
1277+}
1278+
953 // Log is one line of the job log, without terminator, valid UTF-8. A line of1279 // Log is one line of the job log, without terminator, valid UTF-8. A line of
954 // more than 64 KiB is cut by the executor into pieces at character boundaries;1280 // more than 64 KiB is cut by the executor into pieces at character boundaries;
955 // every piece but the first has continued set (the AppendLog rule).1281 // every piece but the first has continued set (the AppendLog rule).
@@ -965,7 +1291,7 @@ type Log struct {
965 1291
966 func (x *Log) Reset() {1292 func (x *Log) Reset() {
967 *x = Log{}1293 *x = Log{}
968- mi := &file_exec_proto_msgTypes[9]1294+ mi := &file_exec_proto_msgTypes[12]
969 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1295 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
970 ms.StoreMessageInfo(mi)1296 ms.StoreMessageInfo(mi)
971 }1297 }
@@ -977,7 +1303,7 @@ func (x *Log) String() string {
977 func (*Log) ProtoMessage() {}1303 func (*Log) ProtoMessage() {}
978 1304
979 func (x *Log) ProtoReflect() protoreflect.Message {1305 func (x *Log) ProtoReflect() protoreflect.Message {
980- mi := &file_exec_proto_msgTypes[9]1306+ mi := &file_exec_proto_msgTypes[12]
981 if x != nil {1307 if x != nil {
982 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1308 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
983 if ms.LoadMessageInfo() == nil {1309 if ms.LoadMessageInfo() == nil {
@@ -990,7 +1316,7 @@ func (x *Log) ProtoReflect() protoreflect.Message {
990 1316
991 // Deprecated: Use Log.ProtoReflect.Descriptor instead.1317 // Deprecated: Use Log.ProtoReflect.Descriptor instead.
992 func (*Log) Descriptor() ([]byte, []int) {1318 func (*Log) Descriptor() ([]byte, []int) {
993- return file_exec_proto_rawDescGZIP(), []int{9}1319+ return file_exec_proto_rawDescGZIP(), []int{12}
994 }1320 }
995 1321
996 func (x *Log) GetStep() int32 {1322 func (x *Log) GetStep() int32 {
@@ -1034,7 +1360,7 @@ type JobResult struct {
1034 1360
1035 func (x *JobResult) Reset() {1361 func (x *JobResult) Reset() {
1036 *x = JobResult{}1362 *x = JobResult{}
1037- mi := &file_exec_proto_msgTypes[10]1363+ mi := &file_exec_proto_msgTypes[13]
1038 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1364 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1039 ms.StoreMessageInfo(mi)1365 ms.StoreMessageInfo(mi)
1040 }1366 }
@@ -1046,7 +1372,7 @@ func (x *JobResult) String() string {
1046 func (*JobResult) ProtoMessage() {}1372 func (*JobResult) ProtoMessage() {}
1047 1373
1048 func (x *JobResult) ProtoReflect() protoreflect.Message {1374 func (x *JobResult) ProtoReflect() protoreflect.Message {
1049- mi := &file_exec_proto_msgTypes[10]1375+ mi := &file_exec_proto_msgTypes[13]
1050 if x != nil {1376 if x != nil {
1051 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))1377 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1052 if ms.LoadMessageInfo() == nil {1378 if ms.LoadMessageInfo() == nil {
@@ -1059,7 +1385,7 @@ func (x *JobResult) ProtoReflect() protoreflect.Message {
1059 1385
1060 // Deprecated: Use JobResult.ProtoReflect.Descriptor instead.1386 // Deprecated: Use JobResult.ProtoReflect.Descriptor instead.
1061 func (*JobResult) Descriptor() ([]byte, []int) {1387 func (*JobResult) Descriptor() ([]byte, []int) {
1062- return file_exec_proto_rawDescGZIP(), []int{10}1388+ return file_exec_proto_rawDescGZIP(), []int{13}
1063 }1389 }
1064 1390
1065 func (x *JobResult) GetConclusion() StepConclusion {1391 func (x *JobResult) GetConclusion() StepConclusion {
@@ -1095,7 +1421,7 @@ var File_exec_proto protoreflect.FileDescriptor
1095 const file_exec_proto_rawDesc = "" +1421 const file_exec_proto_rawDesc = "" +
1096 "\n" +1422 "\n" +
1097 "\n" +1423 "\n" +
1098- "exec.proto\x12\x15ermite.runner.exec.v1\"\xa5\x04\n" +1424+ "exec.proto\x12\x15ermite.runner.exec.v1\"\xc3\x05\n" +
1099 "\x05Frame\x124\n" +1425 "\x05Frame\x124\n" +
1100 "\x05hello\x18\x01 \x01(\v2\x1c.ermite.runner.exec.v1.HelloH\x00R\x05hello\x12.\n" +1426 "\x05hello\x18\x01 \x01(\v2\x1c.ermite.runner.exec.v1.HelloH\x00R\x05hello\x12.\n" +
1101 "\x03run\x18\x02 \x01(\v2\x1a.ermite.runner.exec.v1.RunH\x00R\x03run\x127\n" +1427 "\x03run\x18\x02 \x01(\v2\x1a.ermite.runner.exec.v1.RunH\x00R\x03run\x127\n" +
@@ -1106,7 +1432,10 @@ const file_exec_proto_rawDesc = "" +
1106 "\x0estep_completed\x18\a \x01(\v2$.ermite.runner.exec.v1.StepCompletedH\x00R\rstepCompleted\x12.\n" +1432 "\x0estep_completed\x18\a \x01(\v2$.ermite.runner.exec.v1.StepCompletedH\x00R\rstepCompleted\x12.\n" +
1107 "\x03log\x18\b \x01(\v2\x1a.ermite.runner.exec.v1.LogH\x00R\x03log\x12A\n" +1433 "\x03log\x18\b \x01(\v2\x1a.ermite.runner.exec.v1.LogH\x00R\x03log\x12A\n" +
1108 "\n" +1434 "\n" +
1109- "job_result\x18\t \x01(\v2 .ermite.runner.exec.v1.JobResultH\x00R\tjobResultB\x06\n" +1435+ "job_result\x18\t \x01(\v2 .ermite.runner.exec.v1.JobResultH\x00R\tjobResult\x12S\n" +
1436+ "\x10step_annotations\x18\n" +
1437+ " \x01(\v2&.ermite.runner.exec.v1.StepAnnotationsH\x00R\x0fstepAnnotations\x12G\n" +
1438+ "\fstep_summary\x18\v \x01(\v2\".ermite.runner.exec.v1.StepSummaryH\x00R\vstepSummaryB\x06\n" +
1110 "\x04body\"W\n" +1439 "\x04body\"W\n" +
1111 "\x05Hello\x12\x18\n" +1440 "\x05Hello\x12\x18\n" +
1112 "\aversion\x18\x01 \x01(\tR\aversion\x12\x18\n" +1441 "\aversion\x18\x01 \x01(\tR\aversion\x12\x18\n" +
@@ -1118,7 +1447,7 @@ const file_exec_proto_rawDesc = "" +
1118 "\x03job\x18\x03 \x01(\v2\x1e.ermite.runner.exec.v1.JobSpecR\x03job\x1a6\n" +1447 "\x03job\x18\x03 \x01(\v2\x1e.ermite.runner.exec.v1.JobSpecR\x03job\x1a6\n" +
1119 "\bEnvEntry\x12\x10\n" +1448 "\bEnvEntry\x12\x10\n" +
1120 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +1449 "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
1121- "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x8b\x03\n" +1450+ "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xdd\x03\n" +
1122 "\aJobSpec\x12#\n" +1451 "\aJobSpec\x12#\n" +
1123 "\rworkflow_path\x18\x01 \x01(\tR\fworkflowPath\x12#\n" +1452 "\rworkflow_path\x18\x01 \x01(\tR\fworkflowPath\x12#\n" +
1124 "\rworkflow_yaml\x18\x02 \x01(\tR\fworkflowYaml\x12\x17\n" +1453 "\rworkflow_yaml\x18\x02 \x01(\tR\fworkflowYaml\x12\x17\n" +
@@ -1134,7 +1463,9 @@ const file_exec_proto_rawDesc = "" +
1134 " \x01(\tR\x11runnerEnvironment\x12\x14\n" +1463 " \x01(\tR\x11runnerEnvironment\x12\x14\n" +
1135 "\x05debug\x18\v \x01(\bR\x05debug\x12\x1f\n" +1464 "\x05debug\x18\v \x01(\bR\x05debug\x12\x1f\n" +
1136 "\vdeadline_ms\x18\f \x01(\x03R\n" +1465 "\vdeadline_ms\x18\f \x01(\x03R\n" +
1137- "deadlineMs\"t\n" +1466+ "deadlineMs\x12)\n" +
1467+ "\x10send_annotations\x18\r \x01(\bR\x0fsendAnnotations\x12%\n" +
1468+ "\x0esend_summaries\x18\x0e \x01(\bR\rsendSummaries\"t\n" +
1138 "\x06Output\x129\n" +1469 "\x06Output\x129\n" +
1139 "\x06stream\x18\x01 \x01(\x0e2!.ermite.runner.exec.v1.StreamKindR\x06stream\x12\x12\n" +1470 "\x06stream\x18\x01 \x01(\x0e2!.ermite.runner.exec.v1.StreamKindR\x06stream\x12\x12\n" +
1140 "\x04data\x18\x02 \x01(\fR\x04data\x12\x1b\n" +1471 "\x04data\x18\x02 \x01(\fR\x04data\x12\x1b\n" +
@@ -1148,14 +1479,33 @@ const file_exec_proto_rawDesc = "" +
1148 "\vStepStarted\x12\x16\n" +1479 "\vStepStarted\x12\x16\n" +
1149 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +1480 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
1150 "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" +1481 "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" +
1151- "\tunix_nano\x18\x03 \x01(\x03R\bunixNano\"\x9f\x01\n" +1482+ "\tunix_nano\x18\x03 \x01(\x03R\bunixNano\"\xe0\x01\n" +
1152 "\rStepCompleted\x12\x16\n" +1483 "\rStepCompleted\x12\x16\n" +
1153 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +1484 "\x06number\x18\x01 \x01(\x05R\x06number\x12\x12\n" +
1154 "\x04name\x18\x02 \x01(\tR\x04name\x12E\n" +1485 "\x04name\x18\x02 \x01(\tR\x04name\x12E\n" +
1155 "\n" +1486 "\n" +
1156 "conclusion\x18\x03 \x01(\x0e2%.ermite.runner.exec.v1.StepConclusionR\n" +1487 "conclusion\x18\x03 \x01(\x0e2%.ermite.runner.exec.v1.StepConclusionR\n" +
1157 "conclusion\x12\x1b\n" +1488 "conclusion\x12\x1b\n" +
1158- "\tunix_nano\x18\x04 \x01(\x03R\bunixNano\"h\n" +1489+ "\tunix_nano\x18\x04 \x01(\x03R\bunixNano\x12?\n" +
1490+ "\aoutcome\x18\x05 \x01(\x0e2%.ermite.runner.exec.v1.StepConclusionR\aoutcome\"\x8a\x02\n" +
1491+ "\n" +
1492+ "Annotation\x12<\n" +
1493+ "\x05level\x18\x01 \x01(\x0e2&.ermite.runner.exec.v1.AnnotationLevelR\x05level\x12\x14\n" +
1494+ "\x05title\x18\x02 \x01(\tR\x05title\x12\x18\n" +
1495+ "\amessage\x18\x03 \x01(\tR\amessage\x12\x12\n" +
1496+ "\x04file\x18\x04 \x01(\tR\x04file\x12\x1d\n" +
1497+ "\n" +
1498+ "start_line\x18\x05 \x01(\x05R\tstartLine\x12\x19\n" +
1499+ "\bend_line\x18\x06 \x01(\x05R\aendLine\x12!\n" +
1500+ "\fstart_column\x18\a \x01(\x05R\vstartColumn\x12\x1d\n" +
1501+ "\n" +
1502+ "end_column\x18\b \x01(\x05R\tendColumn\"j\n" +
1503+ "\x0fStepAnnotations\x12\x12\n" +
1504+ "\x04step\x18\x01 \x01(\x05R\x04step\x12C\n" +
1505+ "\vannotations\x18\x02 \x03(\v2!.ermite.runner.exec.v1.AnnotationR\vannotations\"=\n" +
1506+ "\vStepSummary\x12\x12\n" +
1507+ "\x04step\x18\x01 \x01(\x05R\x04step\x12\x1a\n" +
1508+ "\bmarkdown\x18\x02 \x01(\tR\bmarkdown\"h\n" +
1159 "\x03Log\x12\x12\n" +1509 "\x03Log\x12\x12\n" +
1160 "\x04step\x18\x01 \x01(\x05R\x04step\x12\x1b\n" +1510 "\x04step\x18\x01 \x01(\x05R\x04step\x12\x1b\n" +
1161 "\tunix_nano\x18\x02 \x01(\x03R\bunixNano\x12\x12\n" +1511 "\tunix_nano\x18\x02 \x01(\x03R\bunixNano\x12\x12\n" +
@@ -1181,7 +1531,12 @@ const file_exec_proto_rawDesc = "" +
1181 "\x17CANCEL_KIND_UNSPECIFIED\x10\x00\x12\x14\n" +1531 "\x17CANCEL_KIND_UNSPECIFIED\x10\x00\x12\x14\n" +
1182 "\x10CANCEL_KIND_USER\x10\x01\x12\x17\n" +1532 "\x10CANCEL_KIND_USER\x10\x01\x12\x17\n" +
1183 "\x13CANCEL_KIND_TIMEOUT\x10\x02\x12\x18\n" +1533 "\x13CANCEL_KIND_TIMEOUT\x10\x02\x12\x18\n" +
1184- "\x14CANCEL_KIND_SHUTDOWN\x10\x03*\xc6\x01\n" +1534+ "\x14CANCEL_KIND_SHUTDOWN\x10\x03*\x8c\x01\n" +
1535+ "\x0fAnnotationLevel\x12 \n" +
1536+ "\x1cANNOTATION_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n" +
1537+ "\x17ANNOTATION_LEVEL_NOTICE\x10\x01\x12\x1c\n" +
1538+ "\x18ANNOTATION_LEVEL_WARNING\x10\x02\x12\x1c\n" +
1539+ "\x18ANNOTATION_LEVEL_FAILURE\x10\x03*\xc6\x01\n" +
1185 "\x0eStepConclusion\x12\x1f\n" +1540 "\x0eStepConclusion\x12\x1f\n" +
1186 "\x1bSTEP_CONCLUSION_UNSPECIFIED\x10\x00\x12\x1b\n" +1541 "\x1bSTEP_CONCLUSION_UNSPECIFIED\x10\x00\x12\x1b\n" +
1187 "\x17STEP_CONCLUSION_SUCCESS\x10\x01\x12\x1b\n" +1542 "\x17STEP_CONCLUSION_SUCCESS\x10\x01\x12\x1b\n" +
@@ -1202,48 +1557,57 @@ func file_exec_proto_rawDescGZIP() []byte {
1202 return file_exec_proto_rawDescData1557 return file_exec_proto_rawDescData
1203 }1558 }
1204 1559
1205-var file_exec_proto_enumTypes = make([]protoimpl.EnumInfo, 3)1560+var file_exec_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
1206-var file_exec_proto_msgTypes = make([]protoimpl.MessageInfo, 13)1561+var file_exec_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
1207 var file_exec_proto_goTypes = []any{1562 var file_exec_proto_goTypes = []any{
1208- (StreamKind)(0), // 0: ermite.runner.exec.v1.StreamKind1563+ (StreamKind)(0), // 0: ermite.runner.exec.v1.StreamKind
1209- (CancelKind)(0), // 1: ermite.runner.exec.v1.CancelKind1564+ (CancelKind)(0), // 1: ermite.runner.exec.v1.CancelKind
1210- (StepConclusion)(0), // 2: ermite.runner.exec.v1.StepConclusion1565+ (AnnotationLevel)(0), // 2: ermite.runner.exec.v1.AnnotationLevel
1211- (*Frame)(nil), // 3: ermite.runner.exec.v1.Frame1566+ (StepConclusion)(0), // 3: ermite.runner.exec.v1.StepConclusion
1212- (*Hello)(nil), // 4: ermite.runner.exec.v1.Hello1567+ (*Frame)(nil), // 4: ermite.runner.exec.v1.Frame
1213- (*Run)(nil), // 5: ermite.runner.exec.v1.Run1568+ (*Hello)(nil), // 5: ermite.runner.exec.v1.Hello
1214- (*JobSpec)(nil), // 6: ermite.runner.exec.v1.JobSpec1569+ (*Run)(nil), // 6: ermite.runner.exec.v1.Run
1215- (*Output)(nil), // 7: ermite.runner.exec.v1.Output1570+ (*JobSpec)(nil), // 7: ermite.runner.exec.v1.JobSpec
1216- (*Exit)(nil), // 8: ermite.runner.exec.v1.Exit1571+ (*Output)(nil), // 8: ermite.runner.exec.v1.Output
1217- (*Cancel)(nil), // 9: ermite.runner.exec.v1.Cancel1572+ (*Exit)(nil), // 9: ermite.runner.exec.v1.Exit
1218- (*StepStarted)(nil), // 10: ermite.runner.exec.v1.StepStarted1573+ (*Cancel)(nil), // 10: ermite.runner.exec.v1.Cancel
1219- (*StepCompleted)(nil), // 11: ermite.runner.exec.v1.StepCompleted1574+ (*StepStarted)(nil), // 11: ermite.runner.exec.v1.StepStarted
1220- (*Log)(nil), // 12: ermite.runner.exec.v1.Log1575+ (*StepCompleted)(nil), // 12: ermite.runner.exec.v1.StepCompleted
1221- (*JobResult)(nil), // 13: ermite.runner.exec.v1.JobResult1576+ (*Annotation)(nil), // 13: ermite.runner.exec.v1.Annotation
1222- nil, // 14: ermite.runner.exec.v1.Run.EnvEntry1577+ (*StepAnnotations)(nil), // 14: ermite.runner.exec.v1.StepAnnotations
1223- nil, // 15: ermite.runner.exec.v1.JobResult.OutputsEntry1578+ (*StepSummary)(nil), // 15: ermite.runner.exec.v1.StepSummary
1579+ (*Log)(nil), // 16: ermite.runner.exec.v1.Log
1580+ (*JobResult)(nil), // 17: ermite.runner.exec.v1.JobResult
1581+ nil, // 18: ermite.runner.exec.v1.Run.EnvEntry
1582+ nil, // 19: ermite.runner.exec.v1.JobResult.OutputsEntry
1224 }1583 }
1225 var file_exec_proto_depIdxs = []int32{1584 var file_exec_proto_depIdxs = []int32{
1226- 4, // 0: ermite.runner.exec.v1.Frame.hello:type_name -> ermite.runner.exec.v1.Hello1585+ 5, // 0: ermite.runner.exec.v1.Frame.hello:type_name -> ermite.runner.exec.v1.Hello
1227- 5, // 1: ermite.runner.exec.v1.Frame.run:type_name -> ermite.runner.exec.v1.Run1586+ 6, // 1: ermite.runner.exec.v1.Frame.run:type_name -> ermite.runner.exec.v1.Run
1228- 7, // 2: ermite.runner.exec.v1.Frame.output:type_name -> ermite.runner.exec.v1.Output1587+ 8, // 2: ermite.runner.exec.v1.Frame.output:type_name -> ermite.runner.exec.v1.Output
1229- 8, // 3: ermite.runner.exec.v1.Frame.exit:type_name -> ermite.runner.exec.v1.Exit1588+ 9, // 3: ermite.runner.exec.v1.Frame.exit:type_name -> ermite.runner.exec.v1.Exit
1230- 9, // 4: ermite.runner.exec.v1.Frame.cancel:type_name -> ermite.runner.exec.v1.Cancel1589+ 10, // 4: ermite.runner.exec.v1.Frame.cancel:type_name -> ermite.runner.exec.v1.Cancel
1231- 10, // 5: ermite.runner.exec.v1.Frame.step_started:type_name -> ermite.runner.exec.v1.StepStarted1590+ 11, // 5: ermite.runner.exec.v1.Frame.step_started:type_name -> ermite.runner.exec.v1.StepStarted
1232- 11, // 6: ermite.runner.exec.v1.Frame.step_completed:type_name -> ermite.runner.exec.v1.StepCompleted1591+ 12, // 6: ermite.runner.exec.v1.Frame.step_completed:type_name -> ermite.runner.exec.v1.StepCompleted
1233- 12, // 7: ermite.runner.exec.v1.Frame.log:type_name -> ermite.runner.exec.v1.Log1592+ 16, // 7: ermite.runner.exec.v1.Frame.log:type_name -> ermite.runner.exec.v1.Log
1234- 13, // 8: ermite.runner.exec.v1.Frame.job_result:type_name -> ermite.runner.exec.v1.JobResult1593+ 17, // 8: ermite.runner.exec.v1.Frame.job_result:type_name -> ermite.runner.exec.v1.JobResult
1235- 14, // 9: ermite.runner.exec.v1.Run.env:type_name -> ermite.runner.exec.v1.Run.EnvEntry1594+ 14, // 9: ermite.runner.exec.v1.Frame.step_annotations:type_name -> ermite.runner.exec.v1.StepAnnotations
1236- 6, // 10: ermite.runner.exec.v1.Run.job:type_name -> ermite.runner.exec.v1.JobSpec1595+ 15, // 10: ermite.runner.exec.v1.Frame.step_summary:type_name -> ermite.runner.exec.v1.StepSummary
1237- 0, // 11: ermite.runner.exec.v1.Output.stream:type_name -> ermite.runner.exec.v1.StreamKind1596+ 18, // 11: ermite.runner.exec.v1.Run.env:type_name -> ermite.runner.exec.v1.Run.EnvEntry
1238- 1, // 12: ermite.runner.exec.v1.Cancel.kind:type_name -> ermite.runner.exec.v1.CancelKind1597+ 7, // 12: ermite.runner.exec.v1.Run.job:type_name -> ermite.runner.exec.v1.JobSpec
1239- 2, // 13: ermite.runner.exec.v1.StepCompleted.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion1598+ 0, // 13: ermite.runner.exec.v1.Output.stream:type_name -> ermite.runner.exec.v1.StreamKind
1240- 2, // 14: ermite.runner.exec.v1.JobResult.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion1599+ 1, // 14: ermite.runner.exec.v1.Cancel.kind:type_name -> ermite.runner.exec.v1.CancelKind
1241- 15, // 15: ermite.runner.exec.v1.JobResult.outputs:type_name -> ermite.runner.exec.v1.JobResult.OutputsEntry1600+ 3, // 15: ermite.runner.exec.v1.StepCompleted.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1242- 16, // [16:16] is the sub-list for method output_type1601+ 3, // 16: ermite.runner.exec.v1.StepCompleted.outcome:type_name -> ermite.runner.exec.v1.StepConclusion
1243- 16, // [16:16] is the sub-list for method input_type1602+ 2, // 17: ermite.runner.exec.v1.Annotation.level:type_name -> ermite.runner.exec.v1.AnnotationLevel
1244- 16, // [16:16] is the sub-list for extension type_name1603+ 13, // 18: ermite.runner.exec.v1.StepAnnotations.annotations:type_name -> ermite.runner.exec.v1.Annotation
1245- 16, // [16:16] is the sub-list for extension extendee1604+ 3, // 19: ermite.runner.exec.v1.JobResult.conclusion:type_name -> ermite.runner.exec.v1.StepConclusion
1246- 0, // [0:16] is the sub-list for field type_name1605+ 19, // 20: ermite.runner.exec.v1.JobResult.outputs:type_name -> ermite.runner.exec.v1.JobResult.OutputsEntry
1606+ 21, // [21:21] is the sub-list for method output_type
1607+ 21, // [21:21] is the sub-list for method input_type
1608+ 21, // [21:21] is the sub-list for extension type_name
1609+ 21, // [21:21] is the sub-list for extension extendee
1610+ 0, // [0:21] is the sub-list for field type_name
1247 }1611 }
1248 1612
1249 func init() { file_exec_proto_init() }1613 func init() { file_exec_proto_init() }
@@ -1261,14 +1625,16 @@ func file_exec_proto_init() {
1261 (*Frame_StepCompleted)(nil),1625 (*Frame_StepCompleted)(nil),
1262 (*Frame_Log)(nil),1626 (*Frame_Log)(nil),
1263 (*Frame_JobResult)(nil),1627 (*Frame_JobResult)(nil),
1628+ (*Frame_StepAnnotations)(nil),
1629+ (*Frame_StepSummary)(nil),
1264 }1630 }
1265 type x struct{}1631 type x struct{}
1266 out := protoimpl.TypeBuilder{1632 out := protoimpl.TypeBuilder{
1267 File: protoimpl.DescBuilder{1633 File: protoimpl.DescBuilder{
1268 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),1634 GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1269 RawDescriptor: unsafe.Slice(unsafe.StringData(file_exec_proto_rawDesc), len(file_exec_proto_rawDesc)),1635 RawDescriptor: unsafe.Slice(unsafe.StringData(file_exec_proto_rawDesc), len(file_exec_proto_rawDesc)),
1270- NumEnums: 3,1636+ NumEnums: 4,
1271- NumMessages: 13,1637+ NumMessages: 16,
1272 NumExtensions: 0,1638 NumExtensions: 0,
1273 NumServices: 0,1639 NumServices: 0,
1274 },1640 },

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 4

Tags 11

↑↓ moveenter openesc close