diff --git a/apis/workflows/v1/task_release.proto b/apis/workflows/v1/task_release.proto deleted file mode 100644 index e590acb..0000000 --- a/apis/workflows/v1/task_release.proto +++ /dev/null @@ -1,117 +0,0 @@ -// The externally facing API allowing users to publish and deploy workflow task releases. - -edition = "2023"; - -package workflows.v1; - -import "buf/validate/validate.proto"; -import "google/protobuf/timestamp.proto"; -import "tilebox/v1/id.proto"; -import "workflows/v1/core.proto"; - -option features.field_presence = IMPLICIT; - -// PublishReleaseRequest publishes immutable release metadata for a release task set. -message PublishReleaseRequest { - // Task identifiers included in this release. - repeated TaskIdentifier tasks = 1 [(buf.validate.field).repeated.min_items = 1]; - // URI pointing to the release artifact. - string artifact_uri = 2 [(buf.validate.field).string.min_len = 1]; - // Canonical artifact digest in format sha256:. - string artifact_digest = 3 [(buf.validate.field).string.pattern = "^sha256:[a-f0-9]{64}$"]; - // Runtime kind for this release, currently python_uv in phase 1. - string runtime_kind = 4 [(buf.validate.field).string.min_len = 1]; - // Canonical environment digest in format sha256:. - string environment_digest = 5 [(buf.validate.field).string.pattern = "^sha256:[a-f0-9]{64}$"]; - // Optional UTF-8 JSON metadata payload. - bytes metadata_json = 6 [features.field_presence = EXPLICIT]; -} - -// PublishReleaseResponse is the publish API response. -message PublishReleaseResponse { - // Immutable release id. - tilebox.v1.ID release_id = 1; - // True when this call created a new release row. - bool created = 2; - // Explicit payload changes compared to the latest comparable release. - PublishReleaseChanges changes = 4; - reserved idempotent; - reserved 3; -} - -// PublishReleaseChanges captures which release surfaces changed. -message PublishReleaseChanges { - // True when the task set (including versions) changed. - bool tasks = 1; - // True when the artifact content changed. - bool artifact = 2; - // True when the runtime environment changed. - bool environment = 3; -} - -// DeployReleaseRequest updates the cluster deployment pointer for a release. -message DeployReleaseRequest { - // Target cluster slug. - string cluster_slug = 1 [(buf.validate.field).string.min_len = 1]; - // Immutable release id. - tilebox.v1.ID release_id = 2 [(buf.validate.field).required = true]; -} - -// DeployReleaseResponse is the deploy API response. -message DeployReleaseResponse { - // Target cluster slug. - string cluster_slug = 1; - // Deployed release id. - tilebox.v1.ID release_id = 2; - // Latest cluster manifest revision after the request. - uint64 manifest_revision = 3; - // Whether this request changed the deployment pointer. - bool changed = 4; -} - -// GetClusterDeploymentManifestRequest requests the active desired state for a cluster. -message GetClusterDeploymentManifestRequest { - // Target cluster slug. - string cluster_slug = 1 [(buf.validate.field).string.min_len = 1]; - // Optional revision cursor. 0 requests a full snapshot. - uint64 since_revision = 2; -} - -// DeployedRelease describes the currently deployed release in the manifest response. -message DeployedRelease { - // Immutable release id. - tilebox.v1.ID release_id = 1; - // URI pointing to the release artifact. - string artifact_uri = 2; - // Canonical artifact digest. - string artifact_digest = 3; - // Runtime kind. - string runtime_kind = 4; - // Canonical environment digest. - string environment_digest = 5; - // Optional UTF-8 JSON metadata payload. - bytes metadata_json = 6 [features.field_presence = EXPLICIT]; - // Deployment revision at which this release pointer changed. - uint64 change_revision = 7; - // Task identifiers included in the deployed release. - repeated TaskIdentifier tasks = 8; - // Timestamp when this release pointer was deployed. - google.protobuf.Timestamp deployed_at = 9; -} - -// GetClusterDeploymentManifestResponse returns desired deployment state for a cluster. -message GetClusterDeploymentManifestResponse { - // Target cluster slug. - string cluster_slug = 1; - // Latest cluster manifest revision. - uint64 manifest_revision = 2; - // Active deployed release. Empty when nothing is deployed or when unchanged since since_revision. - DeployedRelease release = 3; -} - -// A service for managing workflows. -service TaskReleaseService { - rpc PublishRelease(PublishReleaseRequest) returns (PublishReleaseResponse); - rpc DeployRelease(DeployReleaseRequest) returns (DeployReleaseResponse); - rpc GetClusterDeploymentManifest(GetClusterDeploymentManifestRequest) returns (GetClusterDeploymentManifestResponse); -} diff --git a/apis/workflows/v1/worker.proto b/apis/workflows/v1/worker.proto new file mode 100644 index 0000000..3233567 --- /dev/null +++ b/apis/workflows/v1/worker.proto @@ -0,0 +1,40 @@ +edition = "2023"; + +package workflows.v1; + +import "buf/validate/validate.proto"; +import "google/protobuf/empty.proto"; +import "workflows/v1/core.proto"; +import "workflows/v1/task.proto"; + +// HandshakeRequest is sent by the runner to a worker runtime to discover its capabilities. +message HandshakeRequest {} + +// HandshakeResponse is the response to a handshake request, containing the task identifiers that the worker can execute. +message HandshakeResponse { + workflows.v1.TaskIdentifiers task_identifiers = 1; +} + +// ExecuteTaskResponse is the response of a worker runtime to a request to execute a task, after the task has +// been executed. +message ExecuteTaskResponse { + option (buf.validate.message).oneof = { + fields: [ + "computed_task", + "failed_task" + ] + }; + + // If the task execution succeeded, this field will be set with the computed task result. + workflows.v1.ComputedTask computed_task = 1; + + // If the task execution failed, this field will be set with details about the failure. + workflows.v1.TaskFailedRequest failed_task = 2; +} + +// WorkerService defines the RPC interface between a runner and a a worker runtime that can execute workflow tasks. +service WorkerService { + rpc Handshake(HandshakeRequest) returns (HandshakeResponse) {} + rpc ExecuteTask(workflows.v1.Task) returns (workflows.v1.ComputedTask) {} + rpc Shutdown(google.protobuf.Empty) returns (google.protobuf.Empty) {} +} diff --git a/apis/workflows/v1/workflows.proto b/apis/workflows/v1/workflows.proto index abbc6b6..7434f47 100644 --- a/apis/workflows/v1/workflows.proto +++ b/apis/workflows/v1/workflows.proto @@ -67,7 +67,7 @@ message GetWorkflowRequest { message PublishWorkflowReleaseRequest { string workflow_slug = 1 [(buf.validate.field).string.min_len = 1]; tilebox.v1.ID artifact_id = 2 [(buf.validate.field).required = true]; - repeated TaskIdentifier tasks = 3 [(buf.validate.field).repeated.min_items = 1]; + ReleaseContent content = 3 [(buf.validate.field).required = true]; } // ListWorkflowsRequest lists all workflows. @@ -98,11 +98,35 @@ message Workflow { // WorkflowRelease represents an immutable release of a workflow, which includes a set of tasks and an artifact. message WorkflowRelease { tilebox.v1.ID id = 1; - tilebox.v1.ID artifact_id = 2; - repeated TaskIdentifier tasks = 3; + Artifact artifact = 2; + ReleaseContent content = 3; google.protobuf.Timestamp created_at = 4; } +// Artifact represents the artifact associated with a workflow release, +// which is the file that contains the code and dependencies needed to execute the tasks in the release. +message Artifact { + tilebox.v1.ID id = 1; + string digest = 2 [(buf.validate.field).string.pattern = "^[a-f0-9]{64}$"]; +} + +// ReleaseContent represents the content of a workflow release, which is the set of files that are included, +// the list of task identifiers, and the command to start a worker runtime for executing the tasks in the release. +// The fingerprint is a hash of the release content. +message ReleaseContent { + string fingerprint = 1 [(buf.validate.field).string.pattern = "^[a-f0-9]{64}$"]; + repeated TaskIdentifier tasks = 2 [(buf.validate.field).repeated.min_items = 1]; + Path root = 3; + repeated string command = 4; +} + +// Path represents a file or directory path in the release content. If it is a directory, it can have child paths. +message Path { + string path = 1; + bool directory = 2; + repeated Path children = 3; +} + // DeployWorkflowReleaseRequest deploys a workflow release to a set of clusters, making the tasks available for // execution on those clusters. message DeployWorkflowReleaseRequest {