5.1 KiB · text 5af55d9
// Forgejo runner protocol message shapes.
//
// Mirrors `code.forgejo.org/forgejo/actions-proto-def/runner/v1`. We
// re-host them here because we serve the protocol, not because we
// generate clients from them.
//
// Compatibility tracks the *runner* side: forgejo-runner is the
// source of truth for what fields exist and what's required.
syntax = "proto3";
package runner.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/struct.proto";
// ── Ping ─────────────────────────────────────────────────────────────
message PingRequest {
string data = 1;
}
message PingResponse {
string data = 1;
}
// ── Runner registration / declaration ────────────────────────────────
message Runner {
int64 id = 1;
string uuid = 2;
string name = 3;
string token = 4;
string address = 5;
// 6 reserved
repeated string labels = 7;
// 8 reserved
string version = 9;
}
message RegisterRequest {
string name = 1;
// The one-shot registration token the operator issues.
string token = 2;
string version = 3;
// Deprecated; runners that still send this set both. Honor both.
repeated string agent_labels = 5;
repeated string labels = 6;
}
message RegisterResponse {
Runner runner = 1;
}
message DeclareRequest {
string version = 1;
repeated string labels = 2;
}
message DeclareResponse {
Runner runner = 1;
}
// ── Task fetch / update ──────────────────────────────────────────────
enum Result {
RESULT_UNSPECIFIED = 0;
RESULT_SUCCESS = 1;
RESULT_FAILURE = 2;
RESULT_CANCELLED = 3;
RESULT_SKIPPED = 4;
}
// Per-need state — the runner needs the parent-job result to drive
// `needs.<id>.result` and the parent's outputs map.
message TaskNeed {
Result result = 1;
map<string, string> outputs = 2;
}
message Task {
int64 id = 1;
// gzip-compressed YAML of the job definition the runner should execute.
bytes workflow_payload = 2;
// Context the runner injects into `${{ github.* }}` etc. Forgejo's
// proto switched this from `map<string,string>` to a Struct so values
// can carry richer types (nested objects, numbers, bools). String
// values are still the common case for us.
google.protobuf.Struct context = 3;
// Repo / org secrets the job can read via `${{ secrets.* }}`.
map<string, string> secrets = 4;
// 5 = `machine` (deprecated upstream, leave unset).
string machine = 5;
// `needs.<job_id>` lookups. Each prior job's result + its declared
// outputs are available; this map is keyed by the upstream job's id.
map<string, TaskNeed> needs = 6;
// Repo / org variables (non-secret); `${{ vars.* }}`.
map<string, string> vars = 7;
}
message FetchTaskRequest {
int64 tasks_version = 1;
// How many tasks the runner can accept in one batch (`task` plus
// `additional_tasks`). Upstream Forgejo treats this as optional;
// we cap at one until concurrency support lands.
optional int64 task_capacity = 2;
}
message FetchTaskResponse {
Task task = 1;
int64 tasks_version = 2;
// Bonus tasks beyond `task` when the runner can run more than one
// job in parallel and `task_capacity > 1`. Same wire shape as
// `task`; the runner spins up one workflow execution per entry.
repeated Task additional_tasks = 3;
}
// Targeted FetchTask used by newer runners for recovery — same as
// FetchTask but constrained to a single job, optionally identified
// by `handle`. We treat it as a constrained FetchTask in our impl.
message FetchSingleTaskRequest {
int64 tasks_version = 1;
optional string handle = 2;
}
message FetchSingleTaskResponse {
int64 tasks_version = 1;
Task task = 2;
}
message StepState {
int64 id = 1;
Result result = 2;
google.protobuf.Timestamp started_at = 3;
google.protobuf.Timestamp stopped_at = 4;
// Upstream `runner.v1.StepState.log_index` is int64 (varint wire
// type), not string. We had it as string previously, which made the
// runner's final UpdateTask (carrying populated step state with
// log_index/log_length) fail to decode with `invalid_argument`.
int64 log_index = 5;
int64 log_length = 6;
}
message TaskState {
int64 id = 1;
Result result = 2;
google.protobuf.Timestamp started_at = 3;
google.protobuf.Timestamp stopped_at = 4;
repeated StepState steps = 5;
}
message UpdateTaskRequest {
TaskState state = 1;
map<string, string> outputs = 2;
}
message UpdateTaskResponse {
TaskState state = 1;
repeated string sent_outputs = 2;
}
// ── Log streaming ────────────────────────────────────────────────────
message LogRow {
google.protobuf.Timestamp time = 1;
string content = 2;
}
message UpdateLogRequest {
int64 task_id = 1;
int64 index = 2;
repeated LogRow rows = 3;
bool no_more = 4;
}
message UpdateLogResponse {
int64 ack_index = 1;
}