228 lines
7.2 KiB
Protocol Buffer
228 lines
7.2 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package forest.v1;
|
|
|
|
// RunnerService is exposed by the forest-server. Runners (workers) call these
|
|
// RPCs to register for work, fetch release artifacts, stream logs, and report
|
|
// completion. Authentication for all post-assignment RPCs uses a release-scoped
|
|
// opaque token rather than the regular JWT flow.
|
|
service RunnerService {
|
|
// Bidirectional stream used for runner registration and work assignment.
|
|
// The runner sends a RunnerRegister as its first message, then periodic
|
|
// RunnerHeartbeat messages. The server responds with a RegisterAck followed
|
|
// by WorkAssignment messages when releases matching the runner's capabilities
|
|
// become available.
|
|
rpc RegisterRunner(stream RunnerMessage) returns (stream ServerMessage);
|
|
|
|
// Fetch the artifact files for a release assigned to this runner.
|
|
// Scoped by the release_token received in the WorkAssignment.
|
|
rpc GetReleaseFiles(GetReleaseFilesRequest) returns (stream ReleaseFile);
|
|
|
|
// Stream log lines back to the server for real-time display.
|
|
// Each message must include the release_token for authentication.
|
|
rpc PushLogs(stream PushLogRequest) returns (PushLogResponse);
|
|
|
|
// Fetch the original spec files for a release.
|
|
// Scoped by the release_token received in the WorkAssignment.
|
|
rpc GetSpecFiles(GetSpecFilesRequest) returns (stream ReleaseFile);
|
|
|
|
// Fetch the annotation (metadata context) for a release.
|
|
rpc GetReleaseAnnotation(GetReleaseAnnotationRequest) returns (ReleaseAnnotationResponse);
|
|
|
|
// Fetch project info (organisation + project name) for a release.
|
|
rpc GetProjectInfo(GetProjectInfoRequest) returns (ProjectInfoResponse);
|
|
|
|
// Report the final outcome of a release (success or failure).
|
|
// This commits the release status and revokes the token.
|
|
rpc CompleteRelease(CompleteReleaseRequest) returns (CompleteReleaseResponse);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Connect stream: Runner → Server
|
|
// ============================================================================
|
|
|
|
message RunnerMessage {
|
|
oneof message {
|
|
RunnerRegister register = 1;
|
|
RunnerHeartbeat heartbeat = 2;
|
|
WorkAck work_ack = 3;
|
|
}
|
|
}
|
|
|
|
// First message a runner sends on the Connect stream.
|
|
message RunnerRegister {
|
|
// Runner-chosen unique identifier. If empty, the server assigns one.
|
|
string runner_id = 1;
|
|
// Destination types this runner can handle.
|
|
repeated DestinationCapability capabilities = 2;
|
|
// Maximum number of simultaneous releases this runner can process.
|
|
int32 max_concurrent = 3;
|
|
}
|
|
|
|
// Describes a destination type the runner supports.
|
|
message DestinationCapability {
|
|
string organisation = 1;
|
|
string name = 2;
|
|
uint64 version = 3;
|
|
}
|
|
|
|
// Periodic keepalive sent by the runner (recommended every 10s).
|
|
message RunnerHeartbeat {
|
|
// Current number of in-progress releases on this runner.
|
|
int32 active_releases = 1;
|
|
}
|
|
|
|
// Runner's response to a WorkAssignment.
|
|
message WorkAck {
|
|
string release_token = 1;
|
|
// false = runner rejects the work (e.g., overloaded). The server will
|
|
// reassign or fall back to in-process execution.
|
|
bool accepted = 2;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Connect stream: Server → Runner
|
|
// ============================================================================
|
|
|
|
message ServerMessage {
|
|
oneof message {
|
|
RegisterAck register_ack = 1;
|
|
WorkAssignment work_assignment = 2;
|
|
}
|
|
}
|
|
|
|
// Server response to RunnerRegister.
|
|
message RegisterAck {
|
|
// Server-confirmed (or server-assigned) runner ID.
|
|
string runner_id = 1;
|
|
bool accepted = 2;
|
|
string reason = 3;
|
|
}
|
|
|
|
// Execution mode for a work assignment.
|
|
enum ReleaseMode {
|
|
RELEASE_MODE_UNSPECIFIED = 0;
|
|
// Normal deployment execution.
|
|
RELEASE_MODE_DEPLOY = 1;
|
|
// Dry-run / plan only (e.g. terraform plan). Runner should capture
|
|
// plan output and include it in CompleteRelease.plan_output.
|
|
RELEASE_MODE_PLAN = 2;
|
|
}
|
|
|
|
// Work assignment pushed to a runner when a matching release is available.
|
|
message WorkAssignment {
|
|
// Scoped opaque auth token. Use this for GetReleaseFiles, PushLogs,
|
|
// and CompleteRelease. The token restricts access to only the data
|
|
// associated with this specific release.
|
|
string release_token = 1;
|
|
string release_id = 2;
|
|
string release_intent_id = 3;
|
|
string artifact_id = 4;
|
|
string destination_id = 5;
|
|
// Full destination configuration including metadata.
|
|
DestinationInfo destination = 6;
|
|
// Execution mode. Defaults to DEPLOY if unset.
|
|
ReleaseMode mode = 7;
|
|
}
|
|
|
|
// Destination configuration sent with the work assignment.
|
|
message DestinationInfo {
|
|
string name = 1;
|
|
string environment = 2;
|
|
map<string, string> metadata = 3;
|
|
DestinationCapability type = 4;
|
|
string organisation = 5;
|
|
}
|
|
|
|
// ============================================================================
|
|
// GetReleaseFiles
|
|
// ============================================================================
|
|
|
|
message GetReleaseFilesRequest {
|
|
string release_token = 1;
|
|
}
|
|
|
|
message ReleaseFile {
|
|
string file_name = 1;
|
|
string file_content = 2;
|
|
}
|
|
|
|
// ============================================================================
|
|
// GetSpecFiles
|
|
// ============================================================================
|
|
|
|
message GetSpecFilesRequest {
|
|
string release_token = 1;
|
|
}
|
|
|
|
// ============================================================================
|
|
// GetReleaseAnnotation
|
|
// ============================================================================
|
|
|
|
message GetReleaseAnnotationRequest {
|
|
string release_token = 1;
|
|
}
|
|
|
|
message ReleaseAnnotationResponse {
|
|
string slug = 1;
|
|
string source_username = 2;
|
|
string source_email = 3;
|
|
string context_title = 4;
|
|
string context_description = 5;
|
|
string context_web = 6;
|
|
string reference_version = 7;
|
|
string reference_commit_sha = 8;
|
|
string reference_commit_branch = 9;
|
|
string reference_commit_message = 10;
|
|
string created_at = 11;
|
|
}
|
|
|
|
// ============================================================================
|
|
// GetProjectInfo
|
|
// ============================================================================
|
|
|
|
message GetProjectInfoRequest {
|
|
string release_token = 1;
|
|
}
|
|
|
|
message ProjectInfoResponse {
|
|
string organisation = 1;
|
|
string project = 2;
|
|
}
|
|
|
|
// ============================================================================
|
|
// PushLogs
|
|
// ============================================================================
|
|
|
|
message PushLogRequest {
|
|
string release_token = 1;
|
|
// "stdout" or "stderr"
|
|
string channel = 2;
|
|
string line = 3;
|
|
uint64 timestamp = 4;
|
|
}
|
|
|
|
message PushLogResponse {}
|
|
|
|
// ============================================================================
|
|
// CompleteRelease
|
|
// ============================================================================
|
|
|
|
message CompleteReleaseRequest {
|
|
string release_token = 1;
|
|
ReleaseOutcome outcome = 2;
|
|
// Error description when outcome is FAILURE.
|
|
string error_message = 3;
|
|
// Plan output text when mode was "plan" and outcome is SUCCESS.
|
|
// Stored in release_states.plan_output for UI review.
|
|
optional string plan_output = 4;
|
|
}
|
|
|
|
enum ReleaseOutcome {
|
|
RELEASE_OUTCOME_UNSPECIFIED = 0;
|
|
RELEASE_OUTCOME_SUCCESS = 1;
|
|
RELEASE_OUTCOME_FAILURE = 2;
|
|
}
|
|
|
|
message CompleteReleaseResponse {}
|