/* * Copyright (C) 2024 The Android Open Source Project * * 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 luci.resultdb.v1; import "google/api/field_behavior.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import public "tools/tradefederation/core/proto/resultdb/invocation.proto"; import public "tools/tradefederation/core/proto/resultdb/artifact.proto"; import public "tools/tradefederation/core/proto/resultdb/test_result.proto"; option go_package = "go.chromium.org/luci/resultdb/proto/v1;resultpb"; option java_package = "com.android.resultdb.proto"; option java_multiple_files = true; option java_generic_services = true; // Service to record test results. // // CreateInvocation response includes a metadata key "update-token". // It MUST be passed to all other mutation RPCs, such as CreateTestResult. // Otherwise the request will fail with UNAUTHENTICATED error code. // // RPCs that mutate an invocation return FAILED_PRECONDITION error code if the // invocation is finalized. service Recorder { // == Invocations ============================================================ // Creates a new invocation. // The request specifies the invocation id and its contents. // // The response header metadata contains "update-token" required for future // updates, including finalization. // // If invocation with the given ID already exists, returns ALREADY_EXISTS // error code. rpc CreateInvocation(CreateInvocationRequest) returns (Invocation) {}; // Creates multiple invocations in a single rpc. // // The response header metadata contains a multi-valued "update-token" // required for future updates, including finalization. The tokens will be // given in the same order as BatchCreateInvocationRequest.requests. rpc BatchCreateInvocations(BatchCreateInvocationsRequest) returns (BatchCreateInvocationsResponse) {}; // Updates an existing non-finalized invocation. rpc UpdateInvocation(UpdateInvocationRequest) returns (Invocation) {}; // Transitions the given invocation to the state FINALIZED. rpc FinalizeInvocation(FinalizeInvocationRequest) returns (Invocation) {}; // Updates inclusions for a non-finalized invocation. rpc UpdateIncludedInvocations(UpdateIncludedInvocationsRequest) returns (google.protobuf.Empty) {}; // Recursively marks all test variants associated with the invocation as // submitted, merging them into the invocation's associated baseline. rpc MarkInvocationSubmitted(MarkInvocationSubmittedRequest) returns (google.protobuf.Empty) {}; // == Test results =========================================================== // Appends a test result to a non-finalized invocation. rpc CreateTestResult(CreateTestResultRequest) returns (TestResult) {}; // Atomically appends a batch of test results to a non-finalized invocation. rpc BatchCreateTestResults(BatchCreateTestResultsRequest) returns (BatchCreateTestResultsResponse) {}; // Appends a test exoneration to a non-finalized invocation. rpc CreateTestExoneration(CreateTestExonerationRequest) returns (TestExoneration) {}; // Atomically appends a batch of test exonerations to a non-finalized // invocation. rpc BatchCreateTestExonerations(BatchCreateTestExonerationsRequest) returns (BatchCreateTestExonerationsResponse) {}; // == Artifacts ============================================================== // Create multiple artifacts. // // An artifact can be either invocation-level or test-result-level. // See Artifact.name for more info. rpc BatchCreateArtifacts(BatchCreateArtifactsRequest) returns (BatchCreateArtifactsResponse) {}; } // == Invocations ============================================================== // A request message for CreateInvocation. message CreateInvocationRequest { // Invocation identifier, becomes a part of the invocation.name. // LUCI systems MAY create invocations with nicely formatted IDs, such as // "build-1234567890". All other clients MUST use GUIDs. // // Regex: ^[a-z][a-z0-9_\-]*$. string invocation_id = 1 [ (google.api.field_behavior) = REQUIRED ]; // Invocation data to insert. Invocation invocation = 2; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided. string request_id = 3; } // A request message for BatchCreateInvocations message BatchCreateInvocationsRequest { // requests[i].request_id MUST be either empty or equal to request_id in // this message. // // Up to 500 requests. repeated CreateInvocationRequest requests = 1; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided, so it is // strongly recommended to populate this field. string request_id = 2; } // A response message for BatchCreateInvocations RPC. message BatchCreateInvocationsResponse { // Invocations created. repeated Invocation invocations = 1; // One token per each created invocation. // These are passed in the response instead of as metadata, because large // batches increase the size of the response headers beyond allowed limits and // cause failures like crbug.com/1064496 // update_tokens[i] corresponds to invocations[i]. // *Do not log these values*. repeated string update_tokens = 2; } // A request message for UpdateInvocation RPC. message UpdateInvocationRequest { // Invocation to update. Invocation invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // The list of fields to be updated. google.protobuf.FieldMask update_mask = 2; } // A request message for FinalizeInvocation RPC. message FinalizeInvocationRequest { // Name of the invocation to finalize. string name = 1 [ (google.api.field_behavior) = REQUIRED ]; } // A request message for UpdateIncludedInvocations RPC. message UpdateIncludedInvocationsRequest { // Name of the invocation to add/remove inclusions to/from, // see Invocation.name. // For example, name of the buildbucket build invocation that should include // a swarming task invocation. string including_invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // Names of the invocations to include, see Invocation.name. // If any of these invocations are already included, they will be silently // ignored for idempotency. repeated string add_invocations = 2; // Deprecated: Removing invocations is no longer supported. Do not use. repeated string remove_invocations = 3; } // A request message for MarkInvocationSubmitted RPC. // To use this RPC, callers need: // - resultdb.invocations.setSubmitted in the realm the :@project, where // project is the project of the nominated invocation. message MarkInvocationSubmittedRequest { // Name of the invocation, e.g. "invocations/{id}". string invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; } // A request message for CreateTestResult RPC. message CreateTestResultRequest { // Name of the parent invocation, see Invocation.name. string invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // The test result to create. // Test id and result id are used to dedupe requests, i.e. // if a test result with the same test id and result id already exists in // the invocation, then the requests succeeds as opposed to returns with // ALREADY_EXISTS error. TestResult test_result = 2 [ (google.api.field_behavior) = REQUIRED ]; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided, so it is // strongly recommended to populate this field. // // Impl note: this field is used to compute the spanner-level result id, which // will encode tuple (request_id, index_of_request)", where // - request_id is a random GUID if not provided by the user // - index_of_request is 0 in CreateTestResult RPC, or index of the request // in BatchCreateTestResultsRequest in the batch RPC. // TODO(jchinlee): remove this impl note when it is converted into code. string request_id = 3; } // == Test results ============================================================= // A request message for BatchCreateTestResults RPC. message BatchCreateTestResultsRequest { // Name of the parent invocation, see Invocation.name. string invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // Requests to create test results. // requests[i].invocation MUST be either empty or equal to invocation in this // message. // requests[i].request_id MUST be either empty or equal to request_id in // this message. // // Up to 500 requests. repeated CreateTestResultRequest requests = 2; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided, so it is // strongly recommended to populate this field. // string request_id = 3; } // A response message for BatchCreateTestResults RPC. message BatchCreateTestResultsResponse { // Test results created. repeated TestResult test_results = 1; } // A request message for CreateTestExoneration RPC. message CreateTestExonerationRequest { // Name of the parent invocation, see Invocation.name. string invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // The TestExoneration to create. TestExoneration test_exoneration = 2 [ (google.api.field_behavior) = REQUIRED ]; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided. string request_id = 3; } // A request message for BatchCreateTestExonerations RPC. message BatchCreateTestExonerationsRequest { // Name of the parent invocation, see Invocation.name. string invocation = 1 [ (google.api.field_behavior) = REQUIRED ]; // Requests to create TestExonerations. // requests[i].invocation MUST be either empty or equal to invocation in this // message. // requests[i].request_id MUST be either empty or equal to request_id in // this message. // // Up to 500 requests. repeated CreateTestExonerationRequest requests = 2; // A unique identifier for this request. Restricted to 36 ASCII characters. // A random UUID is recommended. // This request is only idempotent if a `request_id` is provided, so it is // strongly recommended to populate this field. string request_id = 3; } // A response message for BatchCreateTestExonerations RPC. message BatchCreateTestExonerationsResponse { // Test exonerations created. repeated TestExoneration test_exonerations = 1; } // == Artifacts ================================================================ // A request message for CreateArtifactRequest. message CreateArtifactRequest { // Name of the parent resource where the artifact will be created. // // For invocation-level artifacts, it is the invocation name. // For test-result-level artifacts, it is the TestResult name. string parent = 1 [ (google.api.field_behavior) = REQUIRED ]; // Artifact to upload. // The length of the artifact contents MUST be <= 512KiB. // artifact.artifact_id MUST be set. // artifact.name will be ignored. Artifact artifact = 2 [ (google.api.field_behavior) = REQUIRED ]; } // A request message for BatchCreateArtifactsRequest. message BatchCreateArtifactsRequest { // Requests to create Artifacts. // The sum of the content lengths MUST be <= 10MiB. // The parents of all the requests must be derived from the same invocation. // // Up to 500 requests. repeated CreateArtifactRequest requests = 2; } message BatchCreateArtifactsResponse { // Artifacts created. repeated Artifact artifacts = 1; }