exec.proto RawHistoryFolder
1// SPDX-License-Identifier: MIT
2
3// Internal wire format between the host process of ermite-runner and the
4// executor running inside a sandbox (vsock in a micro-VM, Unix socket in a
5// container). Frames are length-prefixed on the stream (see frame.go); this file
6// defines the payload. It is internal to ermite-runner: no compatibility is
7// promised between runner versions, which is safe because the host attaches its
8// own executable to every sandbox.
9
10syntax = "proto3";
11
12package ermite.runner.exec.v1;
13
14option go_package = "bnema.dev/ermite-runner/internal/execstream/execpb";
15
16// Frame is the only message on the stream.
17message Frame {
18 oneof body {
19 Hello hello = 1; // executor -> host, first frame
20 Run run = 2; // host -> executor, after Hello
21 Output output = 3; // executor -> host
22 Exit exit = 4; // executor -> host, last frame
23 Cancel cancel = 5; // host -> executor
24 StepStarted step_started = 6; // executor -> host
25 StepCompleted step_completed = 7; // executor -> host
26 Log log = 8; // executor -> host
27 JobResult job_result = 9; // executor -> host, before Exit
28 }
29}
30
31message Hello {
32 string version = 1; // runner version of the executor
33 string sandbox = 2; // "vm" or "container"
34 string hostname = 3;
35}
36
37// Run asks the executor to run a script or a job. Without job it is the stub
38// executor of sandbox-check: the script is run with `sh -c`; an empty script
39// means the built-in diagnostics script. With job the executor runs the job
40// like a GitHub Actions runner and reports it with StepStarted, Log,
41// StepCompleted and JobResult frames, then Exit.
42message Run {
43 string script = 1;
44 map<string, string> env = 2;
45 JobSpec job = 3;
46}
47
48// JobSpec is the job to run: the fields of the job that ermite handed to the
49// host process, minus the tokens (the sandbox never sees them).
50message JobSpec {
51 string workflow_path = 1;
52 string workflow_yaml = 2;
53 string job_key = 3;
54 string matrix = 4; // JSON object
55 string contexts = 5; // JSON object
56 string repo = 6; // repository name
57 int32 timeout_minutes = 7;
58 string runner_name = 8;
59 string runner_version = 9;
60 // runner_environment is the runner.environment value ("github-hosted" or "self-hosted").
61 string runner_environment = 10;
62 bool debug = 11; // ACTIONS_STEP_DEBUG
63 // deadline_ms is what is left of the job timeout when the host sends this
64 // Run, in milliseconds: the timeout counts from the moment the host received
65 // the job (runner.proto: Job.timeout_minutes), not from the start of the
66 // executor, and booting the sandbox takes time. 0 means "use
67 // timeout_minutes from now".
68 int64 deadline_ms = 12;
69}
70
71enum StreamKind {
72 STREAM_KIND_UNSPECIFIED = 0;
73 STREAM_KIND_STDOUT = 1;
74 STREAM_KIND_STDERR = 2;
75}
76
77message Output {
78 StreamKind stream = 1;
79 bytes data = 2;
80 int64 unix_nano = 3;
81}
82
83message Exit {
84 int32 code = 1;
85 string error = 2; // set when the executor failed to run the script at all
86}
87
88// Cancel asks the executor to stop the running script. The executor escalates
89// like the official runner: SIGINT to the script's process group at once,
90// SIGTERM 7.5 s later, SIGKILL 2.5 s after that.
91message Cancel {
92 // reason is for the job log and diagnostics ("cancelled by the user",
93 // "job timeout", ...); it never changes the behaviour.
94 string reason = 1;
95 // kind tells the job executor how the job ends: cancelled, timed out, or
96 // cancelled because the runner shuts down. The stub executor ignores it.
97 CancelKind kind = 2;
98}
99
100enum CancelKind {
101 CANCEL_KIND_UNSPECIFIED = 0; // same as USER
102 CANCEL_KIND_USER = 1;
103 CANCEL_KIND_TIMEOUT = 2;
104 CANCEL_KIND_SHUTDOWN = 3;
105}
106
107// Steps are numbered like GitHub's log: "Set up job" is 1, the steps of the
108// workflow follow, "Complete job" is last.
109message StepStarted {
110 int32 number = 1;
111 string name = 2;
112 int64 unix_nano = 3;
113}
114
115message StepCompleted {
116 int32 number = 1;
117 string name = 2;
118 StepConclusion conclusion = 3;
119 int64 unix_nano = 4;
120}
121
122enum StepConclusion {
123 STEP_CONCLUSION_UNSPECIFIED = 0;
124 STEP_CONCLUSION_SUCCESS = 1;
125 STEP_CONCLUSION_FAILURE = 2;
126 STEP_CONCLUSION_CANCELLED = 3;
127 STEP_CONCLUSION_SKIPPED = 4;
128 STEP_CONCLUSION_TIMED_OUT = 5; // jobs only
129}
130
131// Log is one line of the job log, without terminator, valid UTF-8. A line of
132// more than 64 KiB is cut by the executor into pieces at character boundaries;
133// every piece but the first has continued set (the AppendLog rule).
134message Log {
135 int32 step = 1;
136 int64 unix_nano = 2;
137 string text = 3;
138 bool continued = 4;
139}
140
141// JobResult is the outcome of the job; Exit follows.
142message JobResult {
143 StepConclusion conclusion = 1;
144 map<string, string> outputs = 2;
145 string error = 3;
146 bool runner_shutdown = 4;
147}