| // Copyright 2015 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| syntax = "proto3"; | |
| package google.devtools.remote_execution; | |
| option java_package = "com.google.devtools.build.lib.remote"; | |
| message ContentDigest { | |
| bytes digest = 1; // A hash of the contents of the file, blob, or tree node | |
| // (see below). The contents are digested using SHA1 (20 bytes). | |
| int64 size_bytes = 2; | |
| int32 version = 3; // Will be 0 by default, and increase if we ever change | |
| // the hash function used, etc. | |
| // And maybe other metadata later. | |
| } | |
| message FileMetadata { | |
| ContentDigest digest = 1; | |
| bool executable = 3; | |
| } | |
| // A Platform is defined by a set of opaque name-value pairs. | |
| message Platform { | |
| message Property { | |
| string name = 1; | |
| string value = 2; | |
| } | |
| // Entries are sorted by name,value to ensure a canonical form. | |
| repeated Property entry = 1; | |
| } | |
| // All the fields of this message have the following in common: they are | |
| // expected to define a result. All instructions to remote execution that do | |
| // not affect the result should be out of this message, because this message | |
| // will be used as the Execution Cache key. | |
| message Action { | |
| // The digest of the command (as an encoded proto blob). | |
| // Digested separately, because it is both long and reusable. | |
| ContentDigest command_digest = 1; | |
| // The Merkle digest of the root input directory. | |
| ContentDigest input_root_digest = 2; | |
| // Relative paths to the action's output files and directories. | |
| // The standard output and error stream contents are always returned | |
| // in addition (see ActionResult message). | |
| // Any unnamed output files will be discarded. | |
| // A path will be interpreted as a directory iff it contains a trailing | |
| // slash. | |
| // This should be sorted! | |
| repeated string output_path = 4; | |
| Platform platform = 5; | |
| // All other requirements that affect the result of the action should be | |
| // here as well. | |
| } | |
| message Command { | |
| // The argument vector. argv[0] is the binary. | |
| repeated string argv = 1; | |
| // A map of environment variables. | |
| // This is part of the command rather than Platform, because it does not | |
| // affect scheduling. | |
| message EnvironmentEntry { | |
| string variable = 1; | |
| string value = 2; | |
| } | |
| // Environment variables, sorted by variable. | |
| repeated EnvironmentEntry environment = 2; | |
| // Possibly other fields the describe the setup actions of the command. | |
| } | |
| message Output { | |
| string path = 1; | |
| // Yes, we shouldn't have to repeat paths here, but it should not be too | |
| // costly, and might help. | |
| // The actual output bodies will be stored in CAS. | |
| oneof content { | |
| // Populated for directory outputs only, contains the root FileNode digest. | |
| ContentDigest digest = 2; | |
| // Populated for file outputs only. | |
| FileMetadata file_metadata = 3; | |
| } | |
| } | |
| message ActionResult { | |
| // Relative paths to the action's output files and directories. | |
| // Any unnamed output files will be discarded. | |
| // A path will be interpreted as a directory iff it contains a trailing | |
| // slash. | |
| // This should be sorted by path. | |
| repeated Output output = 1; | |
| int32 return_code = 2; | |
| ContentDigest stdout_digest = 3; | |
| ContentDigest stderr_digest = 4; | |
| } | |
| // Status message shared by all CAS requests. | |
| message CasStatus { | |
| bool succeeded = 1; // Whether the requested action had server side errors | |
| // or not. | |
| enum ErrorCode { | |
| UNKNOWN = 0; | |
| INVALID_ARGUMENT = 1; // The client behaved incorrectly. error_detail should | |
| // have more information. | |
| MISSING_DIGEST = 2; // Missing a node on tree download. | |
| DIGEST_MISMATCH = 3; // Upload only error, when requested digest does not | |
| // match the server side computed one. | |
| NODE_PARSE_ERROR = 4; // Failed to parse digested data as node. | |
| // more errors... | |
| } | |
| ErrorCode error = 2; | |
| string error_detail = 3; // Human readable error. | |
| // These are a common part of the status for many CAS requests: | |
| repeated ContentDigest missing_digest = 4; | |
| repeated ContentDigest parse_failed_digest = 5; // Only relevant to trees. | |
| } | |
| service CasService { | |
| // Looks up given content keys in CAS, and returns success when found. | |
| // The single returned status will have the potentially missing digests, | |
| // which need to be re-uploaded. | |
| rpc Lookup(CasLookupRequest) returns (CasLookupReply) { } | |
| // Uploads a directory tree into CAS. Not streamed, because it is only tree | |
| // metadata. | |
| rpc UploadTreeMetadata(CasUploadTreeMetadataRequest) returns | |
| (CasUploadTreeMetadataReply) { } | |
| // Uploads data blob(s) into CAS. | |
| rpc UploadBlob(stream CasUploadBlobRequest) returns (CasUploadBlobReply) { } | |
| // Downoads a directory tree metadata from CAS. | |
| rpc DownloadTreeMetadata(CasDownloadTreeMetadataRequest) returns | |
| (CasDownloadTreeMetadataReply) { } | |
| // Downoads a directory tree from CAS. Returns the entire root directory. | |
| rpc DownloadTree(CasDownloadTreeRequest) returns (stream CasDownloadReply) { } | |
| // Downoads data blob(s) from CAS, returns them. | |
| rpc DownloadBlob(CasDownloadBlobRequest) returns (stream CasDownloadReply) { } | |
| } | |
| message FileNode { | |
| FileMetadata file_metadata = 1; | |
| message Child { | |
| string path = 1; | |
| ContentDigest digest = 2; | |
| } | |
| // The children should be sorted by path, and not have equal subdirectory | |
| // prefixes. | |
| repeated Child child = 2; | |
| } | |
| message CasLookupRequest { | |
| repeated ContentDigest digest = 1; | |
| } | |
| message CasLookupReply { | |
| CasStatus status = 1; | |
| } | |
| message CasUploadTreeMetadataRequest { | |
| repeated FileNode tree_node = 1; | |
| } | |
| message CasUploadTreeMetadataReply { | |
| CasStatus status = 1; | |
| } | |
| message CasDownloadTreeMetadataRequest { | |
| ContentDigest root = 1; | |
| } | |
| message CasDownloadTreeMetadataReply { | |
| CasStatus status = 1; | |
| repeated FileNode tree_node = 2; | |
| } | |
| message BlobChunk { | |
| ContentDigest digest = 1; // Present only in first chunk. | |
| int64 offset = 2; | |
| bytes data = 3; | |
| } | |
| // This will be used for batching files/blobs. | |
| message CasUploadBlobRequest { | |
| BlobChunk data = 1; | |
| } | |
| message CasUploadBlobReply { | |
| CasStatus status = 1; | |
| } | |
| message CasDownloadTreeRequest { | |
| ContentDigest root_digest = 1; | |
| } | |
| // This message is streamed. | |
| message CasDownloadReply { | |
| CasStatus status = 1; | |
| BlobChunk data = 2; | |
| // For trees, data is the entire root directory, zipped (for a single root). | |
| // For blobs, sequential chunks of multiple blobs. | |
| } | |
| message CasDownloadBlobRequest { | |
| repeated ContentDigest digest = 1; | |
| } | |
| service ExecutionCacheService { | |
| // Gets results of a cached action. | |
| rpc GetCachedResult(ExecutionCacheRequest) returns (ExecutionCacheReply) { } | |
| // Set results of a cached action. This requires reproducible builds on | |
| // connected machines! | |
| rpc SetCachedResult(ExecutionCacheSetRequest) returns | |
| (ExecutionCacheSetReply) {} | |
| } | |
| message ExecutionCacheRequest { | |
| ContentDigest action_digest = 1; | |
| } | |
| message ExecutionCacheStatus { | |
| // Whether the request had any server side errors. For a lookup (get result) | |
| // request, a true value means the result was found in the cache. | |
| bool succeeded = 1; | |
| enum ErrorCode { | |
| UNKNOWN = 0; | |
| MISSING_RESULT = 1; // The result was not found in the execution cache. | |
| UNSUPPORTED = 2; // The request is not supported by the server. | |
| // More server errors... | |
| } | |
| ErrorCode error = 2; | |
| string error_detail = 3; // Human readable error. | |
| } | |
| message ExecutionCacheReply { | |
| ExecutionCacheStatus status = 1; | |
| ActionResult result = 2; | |
| } | |
| message ExecutionCacheSetRequest { | |
| ContentDigest action_digest = 1; | |
| ActionResult result = 2; | |
| } | |
| message ExecutionCacheSetReply { | |
| ExecutionCacheStatus status = 1; | |
| } | |
| service ExecuteService { | |
| // Executes an action remotely. | |
| rpc Execute(ExecuteRequest) returns (stream ExecuteReply) { } | |
| } | |
| message ExecuteRequest { | |
| Action action = 1; | |
| bool accept_cached = 2; | |
| // Later will probably add previous attempt history, as it will be | |
| // useful for monitoring and probably scheduling as well. | |
| // These fields will be useful for scheduling, error reporting (e.g. disk | |
| // exceeded) and for log analysis. | |
| int32 total_input_file_count = 3; | |
| int64 total_input_file_bytes = 4; | |
| // Used for monitoring and scheduling. | |
| BuildInfo build_info = 5; | |
| // Timeout milliseconds for running this action. | |
| int64 timeout_millis = 6; // Maybe add io_timeout as well, per | |
| // Marc Antoine's suggestion. | |
| // Add other fields such as required cores, RAM, etc, that affect scheduling, | |
| // but not result, later. All the requirements that DO affect results should | |
| // be part of the Action. | |
| } | |
| message BuildInfo { | |
| string build_id = 1; | |
| // TBD, Fields used to identify a build action. | |
| // This will be useful for analysis purposes. | |
| // Note: we don't want to put any Bazel-specific fields in this. | |
| } | |
| message ExecutionStats { | |
| // TBD, will contain all the stats related to the execution: | |
| // time it took, resources, etc. Maybe will break into sub-messages | |
| // for various execution phases. | |
| } | |
| message ExecuteReply { | |
| ExecutionStatus status = 1; | |
| ActionResult result = 2; | |
| bool cached_result = 3; // Filled by the server on Execution Cache hit. | |
| ExecutionStats execution_stats = 4; | |
| CasStatus cas_error = 5; // A possible server-side CAS error, e.g. missing | |
| // inputs. The message contains the missing digests. | |
| // Later will introduce return AttemptHistory for monitoring and use | |
| // in requests. | |
| } | |
| message ExecutionStatus { | |
| bool executed = 1; // Whether the action was executed. | |
| bool succeeded = 2; // Whether the action succeeded. | |
| enum ErrorCode { | |
| UNKNOWN_ERROR = 0; | |
| MISSING_COMMAND = 1; // Missing command digest in CAS. | |
| MISSING_INPUT = 2; // Missing one of the inputs in CAS. | |
| DEADLINE_EXCEEDED = 3; | |
| EXEC_FAILED = 4; // Action returned non-zero. | |
| // Other server errors. Some of these errors are client-retriable, and some | |
| // not; will have to comment clearly what will happen on each error. | |
| } | |
| ErrorCode error = 3; | |
| string error_detail = 4; | |
| // These fields allow returning streaming statuses for the action progress. | |
| enum ActionStage { | |
| UNKNOWN_STAGE = 0; | |
| QUEUED = 1; | |
| EXECUTING = 2; | |
| FINISHED = 3; | |
| } | |
| ActionStage stage = 5; | |
| // Optionally will add more details pertaining to current stage, for example | |
| // time executing, or position in queue, etc. | |
| } |