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 generated file: collapsed

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