go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/tryjob/storage.proto (about)

     1  // Copyright 2021 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.tryjob;
    18  
    19  option go_package = "go.chromium.org/luci/cv/internal/tryjob;tryjob";
    20  
    21  import "google/protobuf/timestamp.proto";
    22  
    23  import "go.chromium.org/luci/buildbucket/proto/build.proto";
    24  import "go.chromium.org/luci/buildbucket/proto/builder_common.proto";
    25  import "go.chromium.org/luci/buildbucket/proto/common.proto";
    26  
    27  import "go.chromium.org/luci/cv/api/config/v2/config.proto";
    28  import "go.chromium.org/luci/cv/api/recipe/v1/cq.proto";
    29  
    30  // Definition defines what a Tryjob should do.
    31  //
    32  // It must be sufficient to trigger a new tryjob.
    33  message Definition {
    34    reserved 7; // experimental
    35  
    36    oneof backend {
    37      // For buildbucket, it's just a builder.
    38      Buildbucket buildbucket = 1;
    39    }
    40  
    41    message Buildbucket {
    42      string host = 1;
    43      buildbucket.v2.BuilderID builder = 2;
    44    }
    45  
    46    // If set, existing tryjob matching this definition is deemed equivalent
    47    // to the primary Definition.
    48    //
    49    // Note that recursive `equivalent_to` is not supported. Also, this doesn't
    50    // affect triggering a new tryjob.
    51    Definition equivalent_to = 2;
    52  
    53    // If true, trigger a new tryjob using this Definition regardless of whether
    54    // reusable tryjobs exist.
    55    bool disable_reuse = 3;
    56  
    57    // If true, CV should let this Tryjob run even if it becomes stale,
    58    // e.g. by a new non-trivial patchset on one of this Tryjob's CLs.
    59    //
    60    // If the Tryjob is not triggered by CV, then this is value is ignored and in
    61    // effect it's assumed true. That is, we don't cancel tryjobs not triggered
    62    // by CV.
    63    bool skip_stale_check = 4;
    64  
    65    // If true, the Tryjob is deemed critical for the Run to succeed, i.e. the
    66    // Run will fail unless one of the attempts of this Tryjob is successful.
    67    bool critical = 5;
    68  
    69    // If true, the Tryjob will be marked as optional.
    70    //
    71    // Optional Tryjobs are generally not critical. However, an optional Tryjob
    72    // could be critical iff it is requested explicitly (i.e. via git footer).
    73    bool optional = 8;
    74  
    75    // If set to restricted, CV should only post generic messages such as
    76    //   "Build failed: https://ci.chromium.org/b/1234"
    77    // and no summary markdown about tryjobs with this definition.
    78    cv.config.CommentLevel result_visibility = 6;
    79  
    80    // Experiments to enable when launching Tryjob.
    81    repeated string experiments = 9;
    82  }
    83  
    84  // Requirement is what has to happen to verify a specific Run.
    85  //
    86  // It is computed based on the Project Config and specifics of the Run.
    87  message Requirement {
    88    // Definitions is the definitions of all Tryjobs that should be triggered
    89    // to verify a specific Run.
    90    repeated Definition definitions = 1;
    91    // RetryConfig specifies retries allowed in case of Tryjob failure.
    92    //
    93    // No retry allowed if nil.
    94    cv.config.Verifiers.Tryjob.RetryConfig retry_config = 2;
    95  }
    96  
    97  // Status is a high level status of a Tryjob from CV implementation PoV.
    98  enum Status {
    99    // STATUS_UNSPECIFIED is never used.
   100    STATUS_UNSPECIFIED = 0;
   101  
   102    // PENDING means Tryjob is being triggered by CV, i.e. it has not yet been
   103    // triggered, but CV will try to trigger it.
   104    //
   105    // *may* not yet have an external ID.
   106    // *must* have no Result.
   107    PENDING = 1;
   108  
   109    // TRIGGERED means Tryjob was triggered.
   110    //
   111    // *must* have an External ID.
   112    // *may* have been triggered not by CV, but by another user, service, etc.
   113    // *may* have a Result, which *may* still change.
   114    TRIGGERED = 2;
   115  
   116    // ENDED means the Tryjob completed. Final status.
   117    //
   118    // *must* have an External ID.
   119    // *must* have a Result, whose Status is not UNKNOWN.
   120    ENDED = 3;
   121    // CANCELLED means Tryjob was cancelled by CV. Final status.
   122    //
   123    // *must* have an External ID.
   124    // *must* have no Result.
   125    CANCELLED = 4;
   126    // UNTRIGGERED means Tryjob was never triggered. Final state.
   127    //
   128    // *must* have no External ID.
   129    // *must* have no Result.
   130    //
   131    // This status is an implementation detail of CV, used for Tryjobs which
   132    // weren't actually triggered.
   133    UNTRIGGERED = 5;
   134  }
   135  
   136  // Result of a Tryjob.
   137  //
   138  // It's interpreted by the Run Manager.
   139  message Result {
   140    // Next tag: 6.
   141  
   142    // Status of the Result.
   143    //
   144    // This is the verdict of verification of Run's CLs by this Tryjob.
   145    Status status = 1;
   146    enum Status {
   147      // RESULT_STATUS_UNSPECIFIED is never used.
   148      RESULT_STATUS_UNSPECIFIED = 0;
   149      // UNKNOWN means Tryjob didn't reach a conclusion.
   150      //
   151      // *must* be used only if Tryjob.Status is TRIGGERED and the Tryjob
   152      // hasn't made a decision yet.
   153      UNKNOWN = 1;
   154      // SUCCEEDED means that Run's CLs are considered OK by this Tryjob.
   155      SUCCEEDED = 2;
   156      // FAILED_PERMANENTLY means that Run's CLs are most likely not good.
   157      FAILED_PERMANENTLY = 3;
   158      // FAILED_TRANSIENTLY means that Run's CLs are most likely not to blame
   159      // for the failure.
   160      // TODO(crbug/1227363): consider removing transiency aspect if possible.
   161      FAILED_TRANSIENTLY = 4;
   162      // TIMEOUT means the Tryjob ran over some deadline and did not make a
   163      // decision about this Run's CLs.
   164      TIMEOUT = 5;
   165    }
   166  
   167    // Time when the Tryjob was created in the backend.
   168    //
   169    // This is used by CV to determine if the Tryjob is fresh enough to be used
   170    // to verify a Run.
   171    google.protobuf.Timestamp create_time = 2;
   172    // Time when the Tryjob was last updated in the backend.
   173    //
   174    // This is used by CV to determine if it needs to refresh Tryjob's Result by
   175    // querying its backend.
   176    google.protobuf.Timestamp update_time = 3;
   177  
   178    // Output is a rich result of a Tryjob.
   179    // This includes details related to retry and reuse.
   180    //
   181    // It's typically set by LUCI recipes.
   182    cq.recipe.Output output = 4;
   183  
   184    // Backend houses backend-specific output.
   185    oneof backend {
   186      Buildbucket buildbucket = 5;
   187    }
   188  
   189    message Buildbucket {
   190      int64 id = 1;
   191      buildbucket.v2.BuilderID builder = 4;
   192      buildbucket.v2.Status status = 2;
   193      // SummaryMarkdown is a field containing a human readable summary of the
   194      // build's result.
   195      string summary_markdown = 3;
   196  
   197      // Infra metadata from Buildbucket.
   198      //
   199      // NOTE: This ONLY supports ResultDB metadata and excludes the rest.
   200      // See go/src/go.chromium.org/luci/buildbucket/proto/build.proto.
   201      buildbucket.v2.BuildInfra infra = 5;
   202    }
   203  }
   204  
   205  // ExecutionState is the state of executing Tryjobs requirement.
   206  message ExecutionState {
   207    reserved 4; // failure_reason
   208    reserved 7; // failure_reason_tmpl
   209    // Execution tracks the execution state of each individual Tryjob requirement.
   210    message Execution {
   211      // Attempt represents each attempt to complete an execution.
   212      //
   213      // Failed attempt will trigger a retry attempt if quota allows.
   214      message Attempt {
   215        // TryjobId is the ID of this attempt of the Tryjob.
   216        int64 tryjob_id = 1;
   217        // ExternalID is the external ID of this attempt of the Tryjob
   218        string external_id = 2;
   219        // Status is the status of this attempt of the Tryjob.
   220        cv.internal.tryjob.Status status = 3;
   221        // Result of this attempt of the Tryjob.
   222        cv.internal.tryjob.Result result = 4;
   223        // Reused indicates the current attempt of the Tryjob wasn't triggered
   224        // by CV for this Run specifically.
   225        //
   226        // In other words, either:
   227        //  * the Tryjob was triggered by CV for a previous Run, or
   228        //  * the Tryjob was triggered by non-CV (e.g. `git cl try`).
   229        bool reused = 5;
   230      }
   231      // Attempts records all attempts (including retries) to verify the Run with
   232      // this Tryjob Execution.
   233      repeated Attempt attempts = 2;
   234      // UsedQuota is the quota consumed for retrying the execution of this
   235      // Tryjob.
   236      int32 used_quota = 3;
   237    }
   238     // Status describes the summarized status of the overall Tryjob execution.
   239    enum Status {
   240      // Unspecified is never used.
   241      STATUS_UNSPECIFIED = 0;
   242      // At least one critical Tryjob is not yet finished so its result is
   243      // unknown.
   244      RUNNING = 1;
   245      // At least one critical Tryjob in the state failed and cannot be retried.
   246      FAILED = 2;
   247      // All the critical Tryjobs in the execution state succeeded.
   248      SUCCEEDED = 3;
   249    }
   250    // Failures describe why the Tryjobs execution fails.
   251    message Failures {
   252      // LaunchFailure describes why a Tryjob fails to launch. For example, CV
   253      // doesn't have the permission to launch the Tryjob.
   254      message LaunchFailure {
   255        Definition definition = 1;
   256        string reason = 2;
   257      }
   258      // UnsuccessfulResult contains the ID of the tryjob that ends with
   259      // non-successful result status (i.e. Build failure).
   260      message UnsuccessfulResult {
   261        int64 tryjob_id = 1;
   262      }
   263      repeated LaunchFailure launch_failures = 1;
   264      repeated UnsuccessfulResult unsuccessful_results = 2;
   265    }
   266    // Executions track the execution state of all required Tryjobs.
   267    //
   268    // It is one to one mapped to `requirement.definitions`
   269    repeated Execution executions = 1;
   270    // Requirement is the requirement that is currently being worked on.
   271    Requirement requirement = 2;
   272    // The version of the requirement that is currently being worked on.
   273    int32 requirement_version = 5;
   274    // Status will be set to SUCCEEDED if all Tryjobs succeed,
   275    // FAILED if at least one Tryjob fails and cannot be retried,
   276    // or RUNNING otherwise.
   277    Status status = 3;
   278    // Failures describe why the Tryjob execution has failed.
   279    //
   280    // Must set if status == FAILED.
   281    Failures failures = 8;
   282    // The time when the executions end with a terminal status
   283    google.protobuf.Timestamp end_time = 6;
   284  }
   285  
   286  // ExecutionLogEntries contains a list of log entries ordered by time.
   287  message ExecutionLogEntries {
   288    repeated ExecutionLogEntry entries = 1;
   289  }
   290  
   291  // ExecutionLogEntry records what happened during Tryjob Execution.
   292  message ExecutionLogEntry {
   293    reserved 6;
   294    // Time is when the event occurs.
   295    google.protobuf.Timestamp time = 1;
   296    oneof kind {
   297      RequirementChanged requirement_changed = 2;
   298      TryjobsLaunched tryjobs_launched = 3;
   299      TryjobsLaunchFailed tryjobs_launch_failed = 4;
   300      TryjobsReused tryjobs_reused = 5;
   301      TryjobsEnded tryjobs_ended = 8;
   302      TryjobDiscarded tryjob_discarded = 7;
   303      RetryDenied retry_denied = 9;
   304    }
   305  
   306    message RequirementChanged {
   307      // TODO(yiwzhang): provide more detail on the config revision change
   308      // that cause the requirement change.
   309    }
   310  
   311    message TryjobSnapshot {
   312      int64 id = 1;
   313      string external_id = 2;
   314      Definition definition = 3;
   315      Status status = 4;
   316      Result result = 5;
   317      bool reused = 6;
   318    }
   319  
   320    message TryjobsLaunched {
   321      reserved 1;
   322      repeated TryjobSnapshot tryjobs = 2;
   323    }
   324  
   325    message TryjobsLaunchFailed {
   326      repeated TryjobLaunchFailed tryjobs = 1;
   327    }
   328  
   329    message TryjobLaunchFailed {
   330      Definition definition = 1;
   331      string reason = 2;
   332    }
   333  
   334    message TryjobsReused {
   335      reserved 1;
   336      repeated TryjobSnapshot tryjobs = 2;
   337    }
   338  
   339    message TryjobsEnded {
   340      reserved 1;
   341      repeated TryjobSnapshot tryjobs = 2;
   342    }
   343  
   344    message TryjobDiscarded{
   345      TryjobSnapshot snapshot = 1;
   346      string reason = 2;
   347    }
   348  
   349    message RetryDenied {
   350      repeated TryjobSnapshot tryjobs =1;
   351      string reason = 2;
   352    }
   353  }
   354  
   355  // TryjobUpdatedEvent describes which Tryjob entity is updated.
   356  message TryjobUpdatedEvent {
   357    int64 tryjob_id = 1;
   358  }
   359  
   360  // TryjobUpdatedEvents is a batch of TryjobUpdatedEvent.
   361  message TryjobUpdatedEvents {
   362    repeated TryjobUpdatedEvent events = 1;
   363  }