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 }