Skip to content

Commit

Permalink
Add remote output service proto
Browse files Browse the repository at this point in the history
  • Loading branch information
coeuvre committed Jan 30, 2024
1 parent ec0878f commit db9fa3e
Show file tree
Hide file tree
Showing 3 changed files with 428 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/main/protobuf/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,42 @@ java_library_srcs(
deps = [":remote_scrubbing_java_proto"],
)

proto_library(
name = "bazel_output_service_proto",
srcs = ["bazel_output_service.proto"],
deps = [
"@com_google_protobuf//:any_proto",
],
)

java_proto_library(
name = "bazel_output_service_java_proto",
deps = [":bazel_output_service_proto"],
)

java_library_srcs(
name = "bazel_output_service_java_proto_srcs",
deps = [":bazel_output_service_java_proto"],
)

proto_library(
name = "bazel_output_service_rev2_proto",
srcs = ["bazel_output_service_rev2.proto"],
deps = [
"@remoteapis//:build_bazel_remote_execution_v2_remote_execution_proto",
],
)

java_proto_library(
name = "bazel_output_service_rev2_java_proto",
deps = [":bazel_output_service_rev2_proto"],
)

java_library_srcs(
name = "bazel_output_service_rev2_java_proto_srcs",
deps = [":bazel_output_service_rev2_java_proto"],
)

proto_library(
name = "spawn_proto",
srcs = ["spawn.proto"],
Expand Down
330 changes: 330 additions & 0 deletions src/main/protobuf/bazel_output_service.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
// Copyright 2024 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.
//
// This file contains the protocol buffer representation of a list of supported
// flags for Bazel commands.
syntax = "proto3";

package bazel_output_service;

import "google/protobuf/any.proto";

option java_package = "com.google.devtools.build.lib.remote";
option java_outer_classname = "BazelOutputServiceProto";
option go_package = "bazeloutputservice";

// The Bazel Output Service may be used by users of the Remote Execution API to
// construct a directory on the local system that contains all output files of a
// build.
//
// Primitive implementations of this API may simply download files from the
// Content Addressable Storage (CAS) and store them at their designated
// location. Complex implementations may use a pseudo file system (e.g., FUSE)
// to support deduplication, lazy loading and snapshotting.
//
// Details:
// https://github.com/bazelbuild/proposals/blob/master/designs/2021-02-09-remote-output-service.md
// https://groups.google.com/g/remote-execution-apis/c/qOSWWwBLPzo
// https://groups.google.com/g/bazel-dev/c/lKzENsNd1Do
// https://docs.google.com/document/d/1W6Tqq8cndssnDI0yzFSoj95oezRKcIhU57nwLHaN1qk/edit
service BazelOutputService {
// Clean all data associated with a single output path, so that the
// next invocation of StartBuild() yields an empty output path. This
// may be implemented in a way that's faster than removing all of the
// files from the file system manually.
rpc Clean(CleanRequest) returns (CleanResponse);

// Signal that a new build is about to start.
//
// Bazel uses this call to obtain a directory where outputs of the build may
// be stored, called the output path. Based on the parameters provided, server
// may provide an empty output path, or one that has contents from a previous
// build of the same workspace.
//
// In case the output path contains data from a previous build, server is
// responsible for calling ContentAddressableStorage.FindMissingBlobs() for
// all of the objects that are stored remotely. This ensures that these
// objects don't disappear from the Content Addressable Storage while the
// build is running. Any files that are absent must be removed from the output
// path and reported through InitialOutputPathContents.modified_paths.
rpc StartBuild(StartBuildRequest) returns (StartBuildResponse);

// Stage build artifacts at the given paths with digests that are known to the
// Content Addressable Storage. Contents of these files can be lazily staged.
// The files may be later modified via FUSE operations.
//
// If any of the digests or paths are invalid an error is returned without
// modifying anything. If some digests are unavailable, the corresponding
// StageArtifactsResponse.Response.unavailable flag should be set.
rpc StageArtifacts(StageArtifactsRequest) returns (StageArtifactsResponse);

// Notifies server that a set of files will no longer be modified by Bazel or
// local build actions. Server should unset "dirty" bit for these files if it
// tracks file modifications under output path. If these paths are modified
// via FUSE operations later, they should be reported back to Bazel in the
// next InitialOutputPathContents.modified_paths for the same workspace.
rpc FinalizeArtifacts(FinalizeArtifactsRequest) returns (FinalizeArtifactsResponse);

// Signal that a build has been completed.
rpc FinalizeBuild(FinalizeBuildRequest) returns (FinalizeBuildResponse);

// Obtain the status of one or more files, directories or symbolic
// links that are stored in the output path.
rpc BatchStat(BatchStatRequest) returns (BatchStatResponse);
}

message CleanRequest {
// The workspace identifier that was provided to
// StartBuildRequest.output_base_id whose data needs to be removed.
string output_base_id = 1;
}

message CleanResponse {
// Intentionally empty for future extensibility.
}

message StartBuildRequest {
// The version of the protocol Bazel currently uses. The service MUST return
// an error if it doesn't recognize the version.
//
// A future Bazel version may introduce incompatible changes and increment
// this version number. The incompatible change will be first made in the
// development tree for the next major Bazel release, and the new version thus
// introduced should be considered unstable until that major Bazel release
// occurs. At that time, the new version becomes stable, and the old one is
// immediately retired.
//
// In particular, version 1 must not be considered stable until Bazel 8.0.0 is
// released.
//
// Current version: 1 (experimental).
int32 version = 1;

// A client-chosen value for the output service to uniquely identify the
// workspace the build is being started. This value must be set to ensure that
// the remote output service is capable of managing builds for distinct
// workspaces concurrently.
//
// By default, Bazel sets this value to the MD5 sum of the absolute path of
// the output base.
//
// Starting a build finalizes any previous build with the same output_base_id
// that has not been finalized yet as if a FinalizeBuildRequest had been sent
// with build_successful set to false.
string output_base_id = 2;

// A client-chosen value that uniquely identifies this build. This value must
// be provided to most other methods to ensure that operations are targeted
// against the right output path.
//
// Bazel sets this value to --invocation_id.
string build_id = 3;

// Additional arguments to pass depending on how Bazel communicate with the
// Content Addressable Storage.
google.protobuf.Any args = 4;

// The absolute path at which the remote output service exposes its output
// paths, as seen from the perspective of the client.
//
// This value needs to be provided by the client, because file system
// namespace virtualization may cause this directory to appear at a location
// that differs from the one used by the service.
//
// The purpose of this field is to ensure that the remote output service is
// capable of expanding symbolic links containing absolute paths.
//
// If this is not set, or an empty string, the service must determine where to
// expose its output path and return an absolute path in
// StartBuildResponse.output_path_suffix.
string output_path_prefix = 5;

// A map of paths on the system that will become symbolic links pointing to
// locations inside the output path. Similar to output_path_prefix, this
// option is used to ensure the remote output service is capable of expanding
// symbolic links.
//
// Map keys are absolute paths, while map values are paths that are
// relative to the output path.
map<string, string> output_path_aliases = 6;
}

message StartBuildResponse {
// If set, the contents of the output path are almost entirely identical on
// the results of a previous build. This information may be used by Bazel to
// prevent unnecessary scanning of the file system.
//
// The server MUST leave this field unset in case the contents of the output
// path are empty, not based on a previous build, if no tracking of this
// information is performed, or if the number of changes made to the output
// path is too large to be expressed.
InitialOutputPathContents initial_output_path_contents = 1;

// A path that the client must append to StartBuildRequest.output_path_prefix
// to obtain the full path at which outputs of the build are stored.
//
// Bazel replaces bazel-out/ with a symlink targeting this path.
string output_path_suffix = 2;
}

message InitialOutputPathContents {
// The identifier of a previously finalized build whose results are stored in
// the output path.
string build_id = 1;

// Output files that have been modified (either the content or metadata) or
// removed since the build was finalized.
//
// If directories as a whole are modified/removed, the server needs to
// recursively list all modified paths underneath.
//
// If the remote output service freezes the contents of the output files after
// FinalizeArtifacts, this field can be left empty.
repeated string modified_files = 2;
}

// A content digest. A digest for a given blob consists of the size of the blob
// and its hash. The hash algorithm to use is --digest_function.
message Digest {
// The hash, represented as a lowercase hex string including any leading
// zeroes.
string hash = 1;

// The size of the blob, in bytes.
int64 size_bytes = 2;
}

message StageArtifactsRequest {
message Artifact {
// path is relative to StartBuildResponse.output_path.
string path = 1;
// Describe how to stage the artifact.
google.protobuf.Any locator = 2;
}

// The identifier of the build. Server uses this to determine which output
// path needs to be modified.
string build_id = 1;

repeated Artifact artifacts = 2;
}

message StageArtifactsResponse {
message Response {
// True if the server does not have the requested digest leased.
bool unavailable = 1;
}

// The response for each of the requested artifacts, using the same order as
// requested. This means that this list has the same length as
// StageArtifactsRequest.artifacts.
repeated Response responses = 1;
}

message FinalizeArtifactsRequest {
message Artifact {
// path is relative to StartBuildResponse.output_path.
string path = 1;
// Expected digest for this file. This allows server to detect if the file
// has been changed after Bazel finished creating the file and the
// corresponding FinalizeArtifactsRequest is processed. This field is
// optional for regular files, and should be omitted for directories and
// symlinks.
Digest digest = 2;
}

// The identifier of the build. Server uses this to determine which output
// path needs to be modified.
string build_id = 1;

repeated Artifact artifacts = 2;
}

message FinalizeArtifactsResponse {
// Intentionally empty for future extensibility.
}

message FinalizeBuildRequest {
// The identifier of the build that should be finalized.
string build_id = 1;

// Whether the build completed successfully. The remote output service may,
// for example, use this option to apply different retention policies that
// take the outcome of the build into account.
bool build_successful = 2;
}

message FinalizeBuildResponse {
// Intentionally empty for future extensibility.
}

message BatchStatRequest {
// The identifier of the build. The remote output service uses this to
// determine which output path needs to be inspected.
string build_id = 1;

// Paths whose status needs to be obtained. The server MUST resolve the path
// using lstat semantic, i.e. components except the last one must be resolved
// if they are symlinks.
//
// Path is relative to StartBuildResponse.output_path.
repeated string paths = 2;
}

message BatchStatResponse {
message StatResponse {
// The status of the file. If the file corresponding with the requested path
// does not exist, this field will be null.
FileStat file_stat = 1;
}

message FileStat {
message File {
// The hash and size of the file.
Digest digest = 1;
}

message Symlink {
// The target of the symbolic link.
string target = 1;
}

message Directory {
}

message Special {
}

// If the path resolves to a location outside the output path where the
// server is unable to obtain its status, none of the file_type will be set.
oneof file_type {
// The path resolves to a regular file.
File file = 1;

// The path resolves to a symbolic link.
Symlink symlink = 2;

// The path resolves to a directory.
Directory directory = 3;

// The path resolves to a special file.
Special special = 4;
}
}

// The status response for each of the requested paths, using the same
// order as requested. This means that this list has the same length
// as BatchStatRequest.paths.
repeated StatResponse responses = 1;
}

0 comments on commit db9fa3e

Please sign in to comment.