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  }