/* * 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/struct.proto"; import "google/protobuf/timestamp.proto"; import public "tools/tradefederation/core/proto/resultdb/common.proto"; import public "tools/tradefederation/core/proto/resultdb/instruction.proto"; import public "tools/tradefederation/core/proto/resultdb/predicate.proto"; option go_package = "go.chromium.org/luci/resultdb/proto/v1;resultpb"; option java_package = "com.android.resultdb.proto"; option java_multiple_files = true; // A conceptual container of results. Immutable once finalized. // It represents all results of some computation; examples: swarming task, // buildbucket build, CQ attempt. // Composable: can include other invocations, see inclusion.proto. // // Next id: 25. message Invocation { reserved 3; // bool interrupted, crbug.com/1078696. reserved 17,18; // step and test instructions. // Can be used to refer to this invocation, e.g. in ResultDB.GetInvocation // RPC. // Format: invocations/{INVOCATION_ID} // See also https://aip.dev/122. // // Output only. string name = 1 [ (google.api.field_behavior) = OUTPUT_ONLY, (google.api.field_behavior) = IMMUTABLE ]; enum State { // The default value. This value is used if the state is omitted. STATE_UNSPECIFIED = 0; // The invocation was created and accepts new results. ACTIVE = 1; // The invocation is in the process of transitioning into FINALIZED state. // This will happen automatically soon after all of its directly or // indirectly included invocations become inactive. FINALIZING = 2; // The invocation is immutable and no longer accepts new results nor // inclusions directly or indirectly. FINALIZED = 3; } // Current state of the invocation. // // At creation time this can be set to FINALIZING e.g. if this invocation is // a simple wrapper of another and will itself not be modified. // // Otherwise this is an output only field. State state = 2; // When the invocation was created. // Output only. google.protobuf.Timestamp create_time = 4 [ (google.api.field_behavior) = OUTPUT_ONLY, (google.api.field_behavior) = IMMUTABLE ]; // Invocation-level string key-value pairs. // A key can be repeated. repeated StringPair tags = 5; // == Finalization =========================================================== // When the invocation started to finalize, i.e. transitioned to FINALIZING // state. This means the invocation is immutable but directly or indirectly // included invocations may not be. // // Output only. google.protobuf.Timestamp finalize_start_time = 19 [ (google.api.field_behavior) = OUTPUT_ONLY ]; // When the invocation was finalized, i.e. transitioned to FINALIZED state. // If this field is set, implies that the invocation is finalized. This // means the invocation and directly or indirectly included invocations // are immutable. // // Output only. google.protobuf.Timestamp finalize_time = 6 [ (google.api.field_behavior) = OUTPUT_ONLY ]; // Timestamp when the invocation will be forcefully finalized. // Can be extended with UpdateInvocation until finalized. google.protobuf.Timestamp deadline = 7; // Names of invocations included into this one. Overall results of this // invocation is a UNION of results directly included into this invocation // and results from the included invocations, recursively. // For example, a Buildbucket build invocation may include invocations of its // child swarming tasks and represent overall result of the build, // encapsulating the internal structure of the build. // // The graph is directed. // There can be at most one edge between a given pair of invocations. // The shape of the graph does not matter. What matters is only the set of // reachable invocations. Thus cycles are allowed and are noop. // // QueryTestResults returns test results from the transitive closure of // invocations. // // This field can be set under Recorder.CreateInvocationsRequest to include // existing invocations at the moment of invocation creation. // New invocations created in the same batch (via // Recorder.BatchCreateInvocationsRequest) are also allowed. // Otherwise, this field is to be treated as Output only. // // To modify included invocations, use Recorder.UpdateIncludedInvocations in // all other cases. repeated string included_invocations = 8; // Whether this invocation is a root of the invocation graph for export purposes. // // To help downstream systems (like LUCI Analysis) make sense of test results, // and gather overall context for a result, ResultDB data export is centered // around export roots. // The export roots typically represent a top-level buildbucket build, like a // postsubmit build or presubmit tryjob. Test results are only exported if // they are included from a root. They may be exported multiple times of they // are included by multiple roots (e.g. in case of re-used test results). // Re-used test results can be identified because the parent invocation of the // test result will be the same even though the export root will be different. // // N.B. Export roots do not affect legacy BigQuery exports configured by the // BigQueryExports field. bool is_export_root = 21; // bigquery_exports indicates what BigQuery table(s) that results in this // invocation should export to. // // Legacy feature: Prefer to use LUCI Analysis exports instead. repeated BigQueryExport bigquery_exports = 9; // LUCI identity (e.g. "user:") who created the invocation. // Typically, a LUCI service account (e.g. // "user:cr-buildbucket@appspot.gserviceaccount.com"), but can also be a user // (e.g. "user:johndoe@example.com"). // // Output only. string created_by = 10 [ (google.api.field_behavior) = OUTPUT_ONLY ]; // Full name of the resource that produced results in this invocation. // See also https://aip.dev/122#full-resource-names // Typical examples: // - Swarming task: "//chromium-swarm.appspot.com/tasks/deadbeef" // - Buildbucket build: "//cr-buildbucket.appspot.com/builds/1234567890". string producer_resource = 11; // Realm that the invocation exists under. // See https://chromium.googlesource.com/infra/luci/luci-py/+/refs/heads/master/appengine/auth_service/proto/realms_config.proto string realm = 12; // Deprecated. Values specified here are ignored. HistoryOptions history_options = 13; // Arbitrary JSON object that contains structured, domain-specific properties // of the invocation. // // The serialized size must be <= 16 KB. google.protobuf.Struct properties = 14; // The code sources which were tested by this invocation. // This is used to index test results for test history, and for // related analyses (e.g. culprit analysis / changepoint analyses). // // The sources specified here applies only to: // - the test results directly contained in this invocation, and // - any directly included invocations which set their source_spec.inherit to // true. // // Clients should be careful to ensure the uploaded source spec is consistent // between included invocations that upload the same test variants. // Verdicts are associated with the sources of *any* of their constituent // test results, so if there is inconsistency between included invocations, // the position of the verdict becomes not well defined. // // Note that the sources specified here are shared with included invocations // regardless of the realm of those included invocations. // // Attempting to update this field to a value other than its current value // after is_source_spec_final is set will generate an error. SourceSpec source_spec = 15; // Whether the code sources specified by source_spec are final (immutable). // // To facilitate rapid export of invocations inheriting sources from this // invocation, this property should be set to true as soon as possible // after the invocation's sources are fixed. In most cases, clients // will want to set this property to true at the same time as they set // source_spec. // // This field is client owned. Consistent with https://google.aip.dev/129, // it will not be forced to true when the invocation starts to finalize, even // if its effective value will always be true at that point. bool is_source_spec_final = 20; // A user-specified baseline identifier that maps to a set of test variants. // Often, this will be the source that generated the test result, such as the // builder name for Chromium. For example, the baseline identifier may be // try:linux-rel. The supported syntax for a baseline identifier is // ^[a-z0-9\-_.]{1,100}:[a-zA-Z0-9\-_.\(\) ]{1,128}`$. This syntax was selected // to allow : as a valid // baseline ID. // See go/src/go.chromium.org/luci/buildbucket/proto/builder_common.proto for // character lengths for buildbucket bucket name and builder name. // // Baselines are used to identify new tests; a subtraction between the set of // test variants for a baseline in the Baselines table and test variants from // a given invocation determines whether a test is new. // // The caller must have `resultdb.baselines.put` to be able to // modify this field. string baseline_id = 16; // Instructions for the steps and test results in this invocation. // It may also contain instructions for test results in included invocations. Instructions instructions = 23; // Union of all variants of test results directly included by the invocation. // This field will be populated by ResultDB during test result creation time. Variant TestResultVariantUnion = 24 [ (google.api.field_behavior) = OUTPUT_ONLY ]; // Additional JSON object(s) that contain additional structured data about the // invocation. Unlike `properties` this field is not included (denormalized) // in the test results export, it is only available in the finalized // invocations BigQuery export. // // All google.protobuf.Struct values must contain a field '@type' which is // a URL/resource name that uniquely identifies the type of the source // protocol buffer message. This string must contain at least // one "/" character. The last segment of the URL's path must represent the // fully qualified name of the type (e.g. foo.com/x/some.package.MyMessage) // // ResultDB will not validate the contents with respect to this schema, but // downstream systems may depend on the '@type' field to inform how the // contents are interpreted. // // Each key is limited to 63 characters matching // ^[a-z]([a-z0-9_]{0,61}[a-z0-9])?$. // The size of each value is limited to <= 20,000 bytes. // The total size of the map (as measured by proto.Size()) // is limited to <= 100,000 bytes. // // The following paths can be used for field masks: // * "extended_properties" to target the whole extended_properties, // * "extended_properties.some_key" to target one key of extended_properties. map extended_properties = 22; } // BigQueryExport indicates that results in this invocation should be exported // to BigQuery after finalization. message BigQueryExport { // Name of the BigQuery project. string project = 1 [ (google.api.field_behavior) = REQUIRED ]; // Name of the BigQuery Dataset. string dataset = 2 [ (google.api.field_behavior) = REQUIRED ]; // Name of the BigQuery Table. string table = 3 [ (google.api.field_behavior) = REQUIRED ]; // TestResults indicates that test results should be exported. message TestResults { // Use predicate to query test results that should be exported to // BigQuery table. TestResultPredicate predicate = 1; } // TextArtifacts indicates that text artifacts should be exported. message TextArtifacts { // Use predicate to query artifacts that should be exported to // BigQuery table. // // Sub-field predicate.content_type_regexp defaults to "text/.*". ArtifactPredicate predicate = 1; } oneof result_type { TestResults test_results = 4; TextArtifacts text_artifacts = 6; } } // HistoryOptions indicates how the invocations should be indexed, so that their // results can be queried over a range of time or of commits. // Deprecated: do not use. message HistoryOptions { // Set this to index the results by the containing invocation's create_time. bool use_invocation_timestamp = 1; // Set this to index by commit position. // It's up to the creator of the invocation to set this consistently over // time across the same test variant. CommitPosition commit = 2; } // Specifies the source code that was tested in an invocation, either directly // (via the sources field) or indirectly (via inherit_sources). message SourceSpec { // Specifies the source position that was tested. // Either this or inherit_sources may be set, but not both. Sources sources = 1; // Specifies that the source position of the invocation is inherited // from the parent invocation it is included in. // // # Use case // This is useful in situations where the testing infrastructure deduplicates // execution of tests on identical binaries (e.g. using swarming's task // deduplication feature). // // Let A be the invocation for a swarming task that receives only a // test binary as input, with task deduplication enabled. // Let B be the invocation for a buildbucket build which built the // binary from sources (or at the very least knew the sources) // and triggered invocation A. // Invocation B includes invocation A. // // By setting A's source_spec to inherit, and specifying the sources // on invocation B, the test results in A will be associated with // the sources specified on invocation B, when queried via invocation B. // // This allows further invocations B2, B3 ... BN to be created which also // re-use the test results in A but associate them with possibly different // sources when queried via B2 ... BN (this is valid so long as the sources // produce a binary-identical testing input). // // # Multiple inclusion paths // It is possible for an invocation A to be included in the reachable // invocation graph for an invocation C in more than one way. // // For example, we may have: // A -> B1 -> C // A -> B2 -> C // as two paths of inclusion. // // If A sets inherit to true, the commit position assigned to its // test results will be selected via *one* of the paths of inclusion // into C (i.e. from B1 or B2). // // However, which path is selected is not guaranteed, so if clients // must include the same invocation multiple times, they should // make the source position via all paths the same. bool inherit = 2; } // Specifies the source code that was tested. message Sources { // The base version of code sources checked out. Mandatory. // If necessary, we could add support for non-gitiles sources here in // future, using a oneof statement. E.g. // oneof system { // GitilesCommit gitiles_commit = 1; // SubversionRevision svn_revision = 4; // ... // } GitilesCommit gitiles_commit = 1; // The changelist(s) which were applied upon the base version of sources // checked out. E.g. in commit queue tryjobs. // // At most 10 changelist(s) may be specified here. If there // are more, only include the first 10 and set is_dirty. repeated GerritChange changelists = 2; // Whether there were any changes made to the sources, not described above. // For example, a version of a dependency was upgraded before testing (e.g. // in an autoroller recipe). // // Cherry-picking a changelist on top of the base checkout is not considered // making the sources dirty as it is reported separately above. bool is_dirty = 3; }