1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17syntax = "proto3";
18
19package luci.resultdb.v1;
20
21import "google/api/field_behavior.proto";
22import "google/protobuf/struct.proto";
23import "google/protobuf/timestamp.proto";
24import public "tools/tradefederation/core/proto/resultdb/common.proto";
25import public "tools/tradefederation/core/proto/resultdb/instruction.proto";
26import public "tools/tradefederation/core/proto/resultdb/predicate.proto";
27
28
29option go_package = "go.chromium.org/luci/resultdb/proto/v1;resultpb";
30option java_package = "com.android.resultdb.proto";
31option java_multiple_files = true;
32
33// A conceptual container of results. Immutable once finalized.
34// It represents all results of some computation; examples: swarming task,
35// buildbucket build, CQ attempt.
36// Composable: can include other invocations, see inclusion.proto.
37//
38// Next id: 25.
39message Invocation {
40  reserved 3; // bool interrupted, crbug.com/1078696.
41  reserved 17,18; // step and test instructions.
42
43  // Can be used to refer to this invocation, e.g. in ResultDB.GetInvocation
44  // RPC.
45  // Format: invocations/{INVOCATION_ID}
46  // See also https://aip.dev/122.
47  //
48  // Output only.
49  string name = 1 [
50    (google.api.field_behavior) = OUTPUT_ONLY,
51    (google.api.field_behavior) = IMMUTABLE
52  ];
53
54  enum State {
55    // The default value. This value is used if the state is omitted.
56    STATE_UNSPECIFIED = 0;
57
58    // The invocation was created and accepts new results.
59    ACTIVE = 1;
60
61    // The invocation is in the process of transitioning into FINALIZED state.
62    // This will happen automatically soon after all of its directly or
63    // indirectly included invocations become inactive.
64    FINALIZING = 2;
65
66    // The invocation is immutable and no longer accepts new results nor
67    // inclusions directly or indirectly.
68    FINALIZED = 3;
69  }
70
71  // Current state of the invocation.
72  //
73  // At creation time this can be set to FINALIZING e.g. if this invocation is
74  // a simple wrapper of another and will itself not be modified.
75  //
76  // Otherwise this is an output only field.
77  State state = 2;
78
79  // When the invocation was created.
80  // Output only.
81  google.protobuf.Timestamp create_time = 4 [
82    (google.api.field_behavior) = OUTPUT_ONLY,
83    (google.api.field_behavior) = IMMUTABLE
84  ];
85
86  // Invocation-level string key-value pairs.
87  // A key can be repeated.
88  repeated StringPair tags = 5;
89
90  // == Finalization ===========================================================
91
92  // When the invocation started to finalize, i.e. transitioned to FINALIZING
93  // state. This means the invocation is immutable but directly or indirectly
94  // included invocations may not be.
95  //
96  // Output only.
97  google.protobuf.Timestamp finalize_start_time = 19
98      [ (google.api.field_behavior) = OUTPUT_ONLY ];
99
100  // When the invocation was finalized, i.e. transitioned to FINALIZED state.
101  // If this field is set, implies that the invocation is finalized. This
102  // means the invocation and directly or indirectly included invocations
103  // are immutable.
104  //
105  // Output only.
106  google.protobuf.Timestamp finalize_time = 6
107      [ (google.api.field_behavior) = OUTPUT_ONLY ];
108
109  // Timestamp when the invocation will be forcefully finalized.
110  // Can be extended with UpdateInvocation until finalized.
111  google.protobuf.Timestamp deadline = 7;
112
113  // Names of invocations included into this one. Overall results of this
114  // invocation is a UNION of results directly included into this invocation
115  // and results from the included invocations, recursively.
116  // For example, a Buildbucket build invocation may include invocations of its
117  // child swarming tasks and represent overall result of the build,
118  // encapsulating the internal structure of the build.
119  //
120  // The graph is directed.
121  // There can be at most one edge between a given pair of invocations.
122  // The shape of the graph does not matter. What matters is only the set of
123  // reachable invocations. Thus cycles are allowed and are noop.
124  //
125  // QueryTestResults returns test results from the transitive closure of
126  // invocations.
127  //
128  // This field can be set under Recorder.CreateInvocationsRequest to include
129  // existing invocations at the moment of invocation creation.
130  // New invocations created in the same batch (via
131  // Recorder.BatchCreateInvocationsRequest) are also allowed.
132  // Otherwise, this field is to be treated as Output only.
133  //
134  // To modify included invocations, use Recorder.UpdateIncludedInvocations in
135  // all other cases.
136  repeated string included_invocations = 8;
137
138  // Whether this invocation is a root of the invocation graph for export purposes.
139  //
140  // To help downstream systems (like LUCI Analysis) make sense of test results,
141  // and gather overall context for a result, ResultDB data export is centered
142  // around export roots.
143  // The export roots typically represent a top-level buildbucket build, like a
144  // postsubmit build or presubmit tryjob. Test results are only exported if
145  // they are included from a root. They may be exported multiple times of they
146  // are included by multiple roots (e.g. in case of re-used test results).
147  // Re-used test results can be identified because the parent invocation of the
148  // test result will be the same even though the export root will be different.
149  //
150  // N.B. Export roots do not affect legacy BigQuery exports configured by the
151  // BigQueryExports field.
152  bool is_export_root = 21;
153
154  // bigquery_exports indicates what BigQuery table(s) that results in this
155  // invocation should export to.
156  //
157  // Legacy feature: Prefer to use LUCI Analysis exports instead.
158  repeated BigQueryExport bigquery_exports = 9;
159
160  // LUCI identity (e.g. "user:<email>") who created the invocation.
161  // Typically, a LUCI service account (e.g.
162  // "user:[email protected]"), but can also be a user
163  // (e.g. "user:[email protected]").
164  //
165  // Output only.
166  string created_by = 10 [ (google.api.field_behavior) = OUTPUT_ONLY ];
167
168  // Full name of the resource that produced results in this invocation.
169  // See also https://aip.dev/122#full-resource-names
170  // Typical examples:
171  // - Swarming task: "//chromium-swarm.appspot.com/tasks/deadbeef"
172  // - Buildbucket build: "//cr-buildbucket.appspot.com/builds/1234567890".
173  string producer_resource = 11;
174
175  // Realm that the invocation exists under.
176  // See https://chromium.googlesource.com/infra/luci/luci-py/+/refs/heads/master/appengine/auth_service/proto/realms_config.proto
177  string realm = 12;
178
179  // Deprecated. Values specified here are ignored.
180  HistoryOptions history_options = 13;
181
182  // Arbitrary JSON object that contains structured, domain-specific properties
183  // of the invocation.
184  //
185  // The serialized size must be <= 16 KB.
186  google.protobuf.Struct properties = 14;
187
188  // The code sources which were tested by this invocation.
189  // This is used to index test results for test history, and for
190  // related analyses (e.g. culprit analysis / changepoint analyses).
191  //
192  // The sources specified here applies only to:
193  // - the test results directly contained in this invocation, and
194  // - any directly included invocations which set their source_spec.inherit to
195  //   true.
196  //
197  // Clients should be careful to ensure the uploaded source spec is consistent
198  // between included invocations that upload the same test variants.
199  // Verdicts are associated with the sources of *any* of their constituent
200  // test results, so if there is inconsistency between included invocations,
201  // the position of the verdict becomes not well defined.
202  //
203  // Note that the sources specified here are shared with included invocations
204  // regardless of the realm of those included invocations.
205  //
206  // Attempting to update this field to a value other than its current value
207  // after is_source_spec_final is set will generate an error.
208  SourceSpec source_spec = 15;
209
210  // Whether the code sources specified by source_spec are final (immutable).
211  //
212  // To facilitate rapid export of invocations inheriting sources from this
213  // invocation, this property should be set to true as soon as possible
214  // after the invocation's sources are fixed. In most cases, clients
215  // will want to set this property to true at the same time as they set
216  // source_spec.
217  //
218  // This field is client owned. Consistent with https://google.aip.dev/129,
219  // it will not be forced to true when the invocation starts to finalize, even
220  // if its effective value will always be true at that point.
221  bool is_source_spec_final = 20;
222
223  // A user-specified baseline identifier that maps to a set of test variants.
224  // Often, this will be the source that generated the test result, such as the
225  // builder name for Chromium. For example, the baseline identifier may be
226  // try:linux-rel. The supported syntax for a baseline identifier is
227  // ^[a-z0-9\-_.]{1,100}:[a-zA-Z0-9\-_.\(\) ]{1,128}`$. This syntax was selected
228  // to allow <buildbucket bucket name>:<buildbucket builder name> as a valid
229  // baseline ID.
230  // See go/src/go.chromium.org/luci/buildbucket/proto/builder_common.proto for
231  // character lengths for buildbucket bucket name and builder name.
232  //
233  // Baselines are used to identify new tests; a subtraction between the set of
234  // test variants for a baseline in the Baselines table and test variants from
235  // a given invocation determines whether a test is new.
236  //
237  // The caller must have `resultdb.baselines.put` to be able to
238  // modify this field.
239  string baseline_id = 16;
240
241  // Instructions for the steps and test results in this invocation.
242  // It may also contain instructions for test results in included invocations.
243  Instructions instructions = 23;
244
245  // Union of all variants of test results directly included by the invocation.
246  // This field will be populated by ResultDB during test result creation time.
247  Variant TestResultVariantUnion = 24 [ (google.api.field_behavior) = OUTPUT_ONLY ];
248
249  // Additional JSON object(s) that contain additional structured data about the
250  // invocation. Unlike `properties` this field is not included (denormalized)
251  // in the test results export, it is only available in the finalized
252  // invocations BigQuery export.
253  //
254  // All google.protobuf.Struct values must contain a field '@type' which is
255  // a URL/resource name that uniquely identifies the type of the source
256  // protocol buffer message. This string must contain at least
257  // one "/" character. The last segment of the URL's path must represent the
258  // fully qualified name of the type (e.g. foo.com/x/some.package.MyMessage)
259  //
260  // ResultDB will not validate the contents with respect to this schema, but
261  // downstream systems may depend on the '@type' field to inform how the
262  // contents are interpreted.
263  //
264  // Each key is limited to 63 characters matching
265  // ^[a-z]([a-z0-9_]{0,61}[a-z0-9])?$.
266  // The size of each value is limited to <= 20,000 bytes.
267  // The total size of the map (as measured by proto.Size())
268  // is limited to <= 100,000 bytes.
269  //
270  // The following paths can be used for field masks:
271  // * "extended_properties" to target the whole extended_properties,
272  // * "extended_properties.some_key" to target one key of extended_properties.
273  map<string, google.protobuf.Struct> extended_properties = 22;
274}
275
276// BigQueryExport indicates that results in this invocation should be exported
277// to BigQuery after finalization.
278message BigQueryExport {
279  // Name of the BigQuery project.
280  string project = 1 [ (google.api.field_behavior) = REQUIRED ];
281
282  // Name of the BigQuery Dataset.
283  string dataset = 2 [ (google.api.field_behavior) = REQUIRED ];
284
285  // Name of the BigQuery Table.
286  string table = 3 [ (google.api.field_behavior) = REQUIRED ];
287
288  // TestResults indicates that test results should be exported.
289  message TestResults {
290    // Use predicate to query test results that should be exported to
291    // BigQuery table.
292    TestResultPredicate predicate = 1;
293  }
294
295  // TextArtifacts indicates that text artifacts should be exported.
296  message TextArtifacts {
297    // Use predicate to query artifacts that should be exported to
298    // BigQuery table.
299    //
300    // Sub-field predicate.content_type_regexp defaults to "text/.*".
301    ArtifactPredicate predicate = 1;
302  }
303
304  oneof result_type {
305    TestResults test_results = 4;
306    TextArtifacts text_artifacts = 6;
307  }
308}
309
310// HistoryOptions indicates how the invocations should be indexed, so that their
311// results can be queried over a range of time or of commits.
312// Deprecated: do not use.
313message HistoryOptions {
314  // Set this to index the results by the containing invocation's create_time.
315  bool use_invocation_timestamp = 1;
316
317  // Set this to index by commit position.
318  // It's up to the creator of the invocation to set this consistently over
319  // time across the same test variant.
320  CommitPosition commit = 2;
321}
322
323// Specifies the source code that was tested in an invocation, either directly
324// (via the sources field) or indirectly (via inherit_sources).
325message SourceSpec {
326   // Specifies the source position that was tested.
327   // Either this or inherit_sources may be set, but not both.
328   Sources sources = 1;
329
330   // Specifies that the source position of the invocation is inherited
331   // from the parent invocation it is included in.
332   //
333   // # Use case
334   // This is useful in situations where the testing infrastructure deduplicates
335   // execution of tests on identical binaries (e.g. using swarming's task
336   // deduplication feature).
337   //
338   // Let A be the invocation for a swarming task that receives only a
339   // test binary as input, with task deduplication enabled.
340   // Let B be the invocation for a buildbucket build which built the
341   // binary from sources (or at the very least knew the sources)
342   // and triggered invocation A.
343   // Invocation B includes invocation A.
344   //
345   // By setting A's source_spec to inherit, and specifying the sources
346   // on invocation B, the test results in A will be associated with
347   // the sources specified on invocation B, when queried via invocation B.
348   //
349   // This allows further invocations B2, B3 ... BN to be created which also
350   // re-use the test results in A but associate them with possibly different
351   // sources when queried via B2 ... BN (this is valid so long as the sources
352   // produce a binary-identical testing input).
353   //
354   // # Multiple inclusion paths
355   // It is possible for an invocation A to be included in the reachable
356   // invocation graph for an invocation C in more than one way.
357   //
358   // For example, we may have:
359   //   A -> B1 -> C
360   //   A -> B2 -> C
361   // as two paths of inclusion.
362   //
363   // If A sets inherit to true, the commit position assigned to its
364   // test results will be selected via *one* of the paths of inclusion
365   // into C (i.e. from B1 or B2).
366   //
367   // However, which path is selected is not guaranteed, so if clients
368   // must include the same invocation multiple times, they should
369   // make the source position via all paths the same.
370   bool inherit = 2;
371}
372
373// Specifies the source code that was tested.
374message Sources {
375    // The base version of code sources checked out. Mandatory.
376    // If necessary, we could add support for non-gitiles sources here in
377    // future, using a oneof statement. E.g.
378    // oneof system {
379    //    GitilesCommit gitiles_commit = 1;
380    //    SubversionRevision svn_revision = 4;
381    //    ...
382    // }
383    GitilesCommit gitiles_commit = 1;
384
385    // The changelist(s) which were applied upon the base version of sources
386    // checked out. E.g. in commit queue tryjobs.
387    //
388    // At most 10 changelist(s) may be specified here. If there
389    // are more, only include the first 10 and set is_dirty.
390    repeated GerritChange changelists = 2;
391
392    // Whether there were any changes made to the sources, not described above.
393    // For example, a version of a dependency was upgraded before testing (e.g.
394    // in an autoroller recipe).
395    //
396    // Cherry-picking a changelist on top of the base checkout is not considered
397    // making the sources dirty as it is reported separately above.
398    bool is_dirty = 3;
399}
400