| // 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. | 
 | } |