go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/run/storage.proto (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 syntax = "proto3"; 16 17 package cv.internal.run; 18 19 option go_package = "go.chromium.org/luci/cv/internal/run;run"; 20 21 import "google/protobuf/timestamp.proto"; 22 23 import "go.chromium.org/luci/cv/api/config/v2/config.proto"; 24 import "go.chromium.org/luci/cv/internal/gerrit/storage.proto"; 25 import "go.chromium.org/luci/cv/internal/run/eventpb/submission.proto"; 26 import "go.chromium.org/luci/cv/internal/tryjob/storage.proto"; 27 import "go.chromium.org/luci/cv/internal/tryjob/task.proto"; 28 29 // Status describes the status of a CV Run. 30 enum Status { 31 // Unspecified status. 32 STATUS_UNSPECIFIED = 0; 33 // Run is pending to start. 34 // 35 // It is either because Run Manager hasn't processed the StartEvent yet or 36 // the RunOwner has exhausted all the quota and waiting for new quota to 37 // be available. 38 PENDING = 1; 39 // Run is running. 40 RUNNING = 2; 41 // Run is waiting for submission. 42 // 43 // Run is in this status if one of the following scenario is true: 44 // 1. Tree is closed at the time Run attempts to submit. 45 // 2. There is another Run in the same LUCI Project that is currently 46 // submitting. 47 // 3. The submission is rate limited according to the submit option in 48 // Project Config. 49 // 50 // This status is cancellable. 51 WAITING_FOR_SUBMISSION = 4; 52 // Run is submitting. 53 // 54 // A Run can't be cancelled while submitting. A Run may transition from 55 // this status to either `WAITING_FOR_SUBMISSION` status or a non-cancelled 56 // terminal status. 57 SUBMITTING = 5; 58 59 // End of non-terminal status; MUST have value less than `ENDED_MASK`. 60 61 ///////////////////////////////////////////////////////////////////////////// 62 // Terminal Status 63 64 // ENDED_MASK can be used as a bitmask to check if a Run has ended. 65 // This MUST NOT be used as the status of a Run. 66 ENDED_MASK = 64; 67 // Run ends successfully. 68 SUCCEEDED = 65; 69 // Run ends unsuccessfully. 70 FAILED = 66; 71 // Run is cancelled. 72 CANCELLED = 67; 73 } 74 75 // Trigger describes who/how CV was triggered on a specific CL. 76 message Trigger { 77 reserved 5; // additional_label 78 google.protobuf.Timestamp time = 1; 79 // Mode is string value of run.Mode. 80 string mode = 2; 81 // ModeDefinition is the definition of the mode in case `mode` is not standard 82 // modes supported by LUCI CV (e.g. DRY_RUN, FULL_RUN, NEW_PATCHSET_RUN) but 83 // is provided through project configuration. 84 // 85 // This field is empty if `mode` is standard mode in LUCI CV. 86 cv.config.Mode mode_definition = 6; 87 // Triggering user email. Always known for Runs created since July 2021. 88 // 89 // Gerrit doesn't guarantee that every user has set their preferred email, 90 // but LUCI ACLs are based entirely on user emails. Thus, Project Manager will 91 // refuse starting Runs for users without the email. 92 string email = 3; 93 // Gerrit account ID. Always known. 94 int64 gerrit_account_id = 4; 95 } 96 97 // Triggers describes the triggers associated with a CL. 98 message Triggers { 99 // CQVoteTrigger is the trigger that corresponds to a vote on the 100 // `Commit-Queue` Gerrit label. 101 Trigger cq_vote_trigger = 1; 102 103 // NewPatchsetRunTrigger is the trigger that is created automatically by 104 // uploading a new patchset. 105 // 106 // This is only populated if the CL matches a config group that allows this. 107 Trigger new_patchset_run_trigger = 2; 108 } 109 110 // Submission describes the state of Run submission. 111 message Submission { 112 // The deadline of this submission. 113 // 114 // If the deadline is not set or has already expired, a RunManager task 115 // can claim the exclusive privilege by setting the deadline to a future 116 // timestamp (generally, end of task deadline). 117 google.protobuf.Timestamp deadline = 1; 118 // ID of the task that executes this submission. 119 string task_id = 2; 120 // IDs of all CLs that should be submitted in this submission. 121 // 122 // Must be ordered in submission order. 123 repeated int64 cls = 3; 124 // IDs of all CLs that have been submitted successfully already. 125 repeated int64 submitted_cls = 4; 126 // IDs of all CLs that fails to submit if any. 127 // 128 // CLs that are neither in this list nor in the `submitted_cls` should be 129 // treated as if CV has never attempted to submit them. 130 // 131 // This could be empty even when the entire submission fails, which would be 132 // typically caused by faulty infrastructure (e.g. Task Queue not executing 133 // a Run Manager task before the whole submission timeout is reached). 134 repeated int64 failed_cls = 5; 135 // If True, Tree is currently in open state. 136 bool tree_open = 10; 137 // The timestamp when the last attempt to fetch the Tree status occurred. 138 google.protobuf.Timestamp last_tree_check_time = 11; 139 // The timestamp when an attempt to fetch the Tree status first resulted in 140 // an error. 141 google.protobuf.Timestamp tree_error_since = 12; 142 143 } 144 145 // Options are Run-specific additions on top of LUCI project config. 146 message Options { 147 // If true, submitting the Run isn't blocked on open tree. 148 // 149 // If false (default), respects project configuration. 150 bool skip_tree_checks = 1; 151 152 // If true, `builders.equivalent_to{...}` sections are ignored when triggering 153 // tryjobs. 154 // 155 // If false (default), respects project configuration. 156 bool skip_equivalent_builders = 2; 157 158 // If true, no longer useful tryjobs won't be cancelled. 159 // 160 // If false (default), respects project configuration. 161 bool avoid_cancelling_tryjobs = 3; 162 163 // If true, no tryjobs will be triggered except "presubmit" regardless of 164 // project configuration. 165 // 166 // "presubmit" builders are legacy which are currently configured with 167 // "disable_reuse: true" in project config. To skip triggering them, 168 // skip_presubmit must be set to true. 169 // TODO(https://crbug.com/950074): ignore. 170 // 171 // If false (default), respects project configuration. 172 bool skip_tryjobs = 4; 173 // Deprecated per https://crbug.com/950074. 174 // See skip_tryjobs doc. 175 bool skip_presubmit = 5; 176 177 // Contains the directives to include specific builder in the Run. 178 // 179 // Its elements are strings of the form: 180 // project/bucket:builder1,builder2;project2/bucket:builder3 181 // 182 // Note that there may be duplication in the directives, it's up to the 183 // consumer of this information to handle it. 184 // 185 // Mutually exclusive with `overridden_tryjobs` option. 186 // This option is ignored if `skip_tryjobs` is true. 187 repeated string included_tryjobs = 6; 188 189 // Overrides all the Tryjobs triggered for this Run regardless of Project 190 // configuration. 191 // 192 // Its elements are strings of the form: 193 // project/bucket:builder1,builder2;project2/bucket:builder3 194 // 195 // Note that there may be duplication in the directives, it's up to the 196 // consumer of this information to handle it. 197 // 198 // Mutually exclusive with `included_tryjobs` option. 199 // This option is ignored if `skip_tryjobs` is true. 200 repeated string overridden_tryjobs = 8; 201 202 // Contains the custom Tryjob tags that should be added when launching 203 // Tryjobs for this Run. 204 // 205 // Each element SHOULD be in the format of "$tag_key:$tag_value" and the 206 // character set for tag key is [a-z0-9_\-]. 207 repeated string custom_tryjob_tags = 7; 208 } 209 210 // LogEntries contains 1+ LogEntry ordered from logically oldest to newest. 211 message LogEntries { 212 repeated LogEntry entries = 1; 213 } 214 215 // LogEntry records what changed in a Run. 216 message LogEntry { 217 // Next tag: 7. 218 219 // Time is when something was changed. 220 google.protobuf.Timestamp time = 1; 221 oneof kind { 222 // Run was created. 223 Created created = 2; 224 // Run was started. 225 Started started = 6; 226 // Run updated to a new project config version. 227 ConfigChanged config_changed = 3; 228 // Tryjobs requirement was (re-)computed. 229 TryjobsRequirementUpdated tryjobs_requirement_updated = 4; 230 // Applicable tryjobs were updated. 231 TryjobsUpdated tryjobs_updated = 5; 232 // TODO(crbug/1232158): add & implement events related to Submission and 233 // ending of the Run. 234 235 // Intended for informational logs (E.g. temporary/during migration) 236 Info info = 7; 237 // The tree is configured and was checked. 238 TreeChecked tree_checked = 8; 239 // The run has been added to the submit queue's waitlist. 240 Waitlisted waitlisted = 9; 241 // The run is current on the queue. 242 AcquiredSubmitQueue acquired_submit_queue = 10; 243 ReleasedSubmitQueue released_submit_queue = 11; 244 // CL(s) submitted successfully. 245 CLSubmitted cl_submitted = 12; 246 // Submission failed. 247 SubmissionFailure submission_failure = 13; 248 RunEnded run_ended = 14; 249 } 250 251 message Created { 252 string config_group_id = 1; 253 } 254 message Started { 255 } 256 message ConfigChanged { 257 string config_group_id = 1; 258 } 259 message TryjobsRequirementUpdated { 260 // TODO(crbug/1227363): define a Tryjobs.Requirement diff. 261 } 262 message Info { 263 // If you have the need to add fields here, consider instead adding a new 264 // dedicated kind 265 string label = 1; 266 string message = 2; 267 } 268 message TryjobsUpdated { 269 // Which tryjobs had a meaningful change (e.g. change of status). 270 repeated Tryjob tryjobs = 2; 271 } 272 message TreeChecked{ 273 bool open = 1; 274 } 275 message Waitlisted{ 276 } 277 message AcquiredSubmitQueue{ 278 } 279 message ReleasedSubmitQueue{ 280 } 281 message CLSubmitted{ 282 // The CLs that were submitted in this event. 283 repeated int64 newly_submitted_cls = 1; 284 // The number of CLs submitted for this run, so far. 285 int64 total_submitted = 2; 286 } 287 message SubmissionFailure{ 288 cv.internal.run.eventpb.SubmissionCompleted event = 1; 289 } 290 message RunEnded{ 291 } 292 } 293 294 // Tryjobs is the state of Run's tryjobs. 295 message Tryjobs { 296 // Requirement is what has to happen to verify a given Run. 297 cv.internal.tryjob.Requirement requirement = 1; 298 // StagingRequirement will be promoted to requirement. 299 // 300 // It is typically set when the existing requirement is executing and waiting 301 // to be cancelled. For example: 302 // T0: Run starts and computes the requirement. A long op task is executing 303 // the requirement. 304 // T1: A new config is ingested and results in a new requirement. RM 305 // requests a cancellation for the long op task and set the new 306 // requirement to this field. 307 // T2: The long op task is successfully cancelled. RM promotes the 308 // staging requirement to requirement and enqueue a new long op task to 309 // execute the new requirement. 310 cv.internal.tryjob.Requirement staging_requirement = 4; 311 // RequirementVersion increments by 1 every time this requirement changes. 312 // 313 // Starts with 1. 314 int32 requirement_version = 6; 315 // The timestamp when the requirement is last computed. 316 // 317 // Every requirement computation will update this field even if the result 318 // requirement is the same as the existing one. 319 google.protobuf.Timestamp requirement_computed_at = 7; 320 // Tryjobs tracks tryjobs of a Run. 321 // 322 // It may contain Tryjobs which are no longer required. 323 // It does contain all Tryjobs which weren't reused even if no longer 324 // required. 325 // 326 // TODO(crbug/1227363): replace this field in favor of `state` 327 repeated Tryjob tryjobs = 2 [deprecated = true]; 328 // The timestamp of the CQDaemon report last incorporated into `tryjobs`. 329 // 330 // TODO(crbug/1227523): delete this field. 331 google.protobuf.Timestamp cqd_update_time = 3; 332 // State is the latest state reported by Tryjob Executor task. 333 // 334 // Once the Run is ended, this state is finalized. 335 cv.internal.tryjob.ExecutionState state = 5; 336 } 337 338 // Tryjob represents a Run's view of a tryjob. 339 message Tryjob { 340 cv.internal.tryjob.Definition definition = 1; 341 342 // ID is a CV internal Tryjob ID, corresponding to a Datastore entity. 343 // 344 // During migration from CQDaemon, the ID may be not set but then ExternalID 345 // is set. 346 // TODO(crbug/1227523): make this field required. 347 int64 id = 2; 348 349 // EVersion of the Tryjob entity last observed by this Run. 350 int64 eversion = 3; 351 352 // ExternalID is the external job ID. 353 // 354 // It's kept here for ease of URL generation and to ease migration from 355 // CQDaemon. 356 // TODO(crbug/1227523): update comment above after CQDaemon migration. 357 string external_id = 4; 358 359 // Status of the Tryjob. 360 cv.internal.tryjob.Status status = 5; 361 362 // Reused is true, if this tryjob wasn't triggered by CV for this Run. 363 // 364 // In other words, either: 365 // * tryjob was triggered by CV for a previous Run 366 // * tryjob was triggered by non-CV. 367 bool reused = 6; 368 369 // If true, indicates this tryjob must pass in order for the Run to be 370 // considered successful. 371 // 372 // It is typically true when the tryjob is NOT experimental or triggered 373 // because of `Cq-Include-TryBot` git footer. 374 bool critical = 9; 375 376 // Result of the tryjob. 377 cv.internal.tryjob.Result result = 7; 378 379 // If true, this Tryjob was computed based on CQDaemon's input. 380 // 381 // TODO(crbug/1227523): delete after CQDaemon migration. 382 bool cqd_derived = 8; 383 } 384 385 // OngoingLongOps tracks ongoing long operations. 386 message OngoingLongOps { 387 message Op { 388 reserved 4; // cancel_triggers 389 // Deadline best-effort limits the lifetime of this work. 390 // 391 // Run Manager expects to receive a LongOpCompleted event by this deadline. 392 google.protobuf.Timestamp deadline = 1; 393 // If true, signals to the Long Op handler that it should stop as soon 394 // possible. 395 bool cancel_requested = 2; 396 397 message ResetTriggers { 398 // Request is to request resetting the trigger of a CL. 399 message Request { 400 // internal CLID. 401 int64 clid = 1; 402 // Message explains why trigger is reset. Will be posted to the CL. 403 string message = 2; 404 // Whom to notify. 405 repeated gerrit.Whom notify = 3; 406 // Whom to add to the attention set. 407 repeated gerrit.Whom add_to_attention = 4; 408 // Reason explains the reason of attention set change. 409 string add_to_attention_reason = 5; 410 } 411 repeated Request requests = 1; 412 // The status Run will transition to if all triggers are successfully 413 // cancelled. 414 // 415 // Must be one of the terminal statues. 416 Status run_status_if_succeeded = 2; 417 } 418 419 // ExecutePostActionPayload is the payload of a long-op task that executes 420 // a given post action. 421 message ExecutePostActionPayload { 422 reserved 1; // action 423 424 // Name of the post action. 425 // 426 // For config action, it should be the same as the name in the config 427 // action. 428 string name = 2; 429 430 message CreditRunQuota {} 431 432 oneof kind { 433 // ConfigAction is the post action defined in the config group. 434 cv.config.ConfigGroup.PostAction config_action = 3; 435 // CreditRunQuota credits the quota back to the run creator and ask 436 // next run that is blocked on the quota to start. 437 CreditRunQuota credit_run_quota = 4; 438 } 439 } 440 441 // PostGerritMessage is the payload for posting a bot message within 442 // a run's gerrit CLs. 443 message PostGerritMessage { 444 // Message to post to gerrit. The current implementation treats the 445 // message as a unique key to achieve idempotence. If multiple payloads 446 // with the same message is triggered for the same run, only one would 447 // be posted. 448 string message = 1; 449 } 450 451 oneof work { 452 // If true, posts a start message. 453 bool post_start_message = 3; 454 ResetTriggers reset_triggers = 6; 455 cv.internal.tryjob.ExecuteTryjobsPayload execute_tryjobs = 5; 456 // The PostActions from different runs can race each other in case 457 // the actions from an earlier Run transiently failed and are being 458 // retried. However, the resolution depends on the type of the post 459 // action. 460 // 461 // If the action is to export the Run records to BQ, each of the Run 462 // records should be exported, and CV should still attempt to execute post 463 // actions for all the Runs ever triggered. 464 // 465 // In contrast, if the action is to vote a label, the post action handler 466 // should check if the originated patchset is still the latest at the time 467 // of the long-op processing time, and skip the action, if the patchset 468 // is no longer the latest. 469 ExecutePostActionPayload execute_post_action = 7; 470 471 // Post a custom message to all the CLs linked to a run. 472 PostGerritMessage post_gerrit_message = 8; 473 } 474 } 475 // Ops map operation ID to details. 476 map<string, Op> ops = 1; 477 }