blob: ebd5c994392b633e32f54f665266e2839cb8e3f7 [file] [log] [blame]
// Copyright 2018 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package cq.config;
option go_package = "go.chromium.org/luci/cq/api/config/v2;config";
import "google/protobuf/duration.proto";
/* TODO(fxb/46095): Figure out why the copy in
* https://chromium.googlesource.com/infra/luci/recipes-py.git/+/master/recipe_proto/
* is not used
import "go.chromium.org/luci/common/proto/options.proto";
option (luci.file_metadata) = {
doc_url: "https://luci-config.appspot.com/schemas/projects:commit-queue.cfg";
};
*/
// This message describes a CQ configuration.
//
// The config file commit-queue.cfg should be stored in the config directory of
// your project, alongside cr-buildbucket.cfg.
message Config {
// Optional. If present, the CQ will refrain from processing any CLs,
// on which CQ was triggered after the specified time.
//
// This is an UTC RFC3339 (stiptime(tm)) string representing the time.
// For example, "2017-12-23T15:47:58Z", where Z is required.
string draining_start_time = 1;
// Optional and deprecated.
// URL of the CQ status app to push updates to.
string cq_status_host = 2 [deprecated = true];
// Optional options for how CLs should be submitted.
SubmitOptions submit_options = 3;
// At least 1 ConfigGroup is required.
repeated ConfigGroup config_groups = 4;
// DO NOT USE.
Toggle project_scoped_account = 5 [deprecated = true];
}
// SubmitOptions control how CQ submits CLs.
message SubmitOptions {
// Optional. Maximum number of successful CQ attempts completed by submitting
// corresponding Gerrit CL(s) before waiting burst_delay.
//
// This feature today applies to all attempts processed by this CQ, across all
// config_groups.
//
// Must be >0 to take effect. Requires burst_delay to be set, too.
int32 max_burst = 1;
// Optional. Delay between bursts of submissions of CQ attempts.
// See max_burst for more info.
//
// Must be >0 to take effect. Requires max_burst to be set, too.
google.protobuf.Duration burst_delay = 2;
}
// A boolean with an "unset" default value.
enum Toggle {
UNSET = 0;
YES = 1;
NO = 2;
}
// Determines how visible the results of a build for this builder are in Gerrit
// comments.
//
// This doesn't affect the buildbucket plugin (green/red chips).
enum CommentLevel {
// Currently default to full visibility.
COMMENT_LEVEL_UNSET = 0;
// The CQ reports the summary markdown and a link to the buildbucket build id
// in Milo with the builder name in the URL in a Gerrit comment.
COMMENT_LEVEL_FULL = 1;
// The CQ reports a generic "Build failed: https://ci.chromium.org/b/1234"
// with no summary markdown.
COMMENT_LEVEL_RESTRICTED = 2;
}
// ConfigGroup allows one to share single verifiers config across a set of
// Gerrit repositories, which may be in different Gerrit installations.
message ConfigGroup {
reserved 3; // allow_cq_depend.
// The human- and machine-readable name (unique within this project) of this
// config group. This is used in messages posted to users and in monitoring
// data.
string name = 6;
// Enumerates repositories on a Gerrit instance for which CQ should work.
message Gerrit {
// Gerrit URL, e.g., https://chromium-review.googlesource.com.
// No trailing slashes allowed.
string url = 1;
// Gerrit projects of this Gerrit instance to work with.
//
// At least 1 required.
repeated Project projects = 2;
message Project {
// Repository name inside Gerrit host. Required.
//
// No leading or trailing slashes allowed, no '.git' at the end.
// 'a/' prefix is also not allowed (it's used on *.googlesource.com for
// forcing authentication).
//
// Examples on https://chromium-review.googlesource.com:
// catapult
// chromium/src
// chromium/tools/depot_tools
string name = 1;
// Limit CLs in this repo to only these refs. Required.
//
// If not specified, defaults to "refs/heads/master".
//
// NOTE: your Gerrit admin must configure Gerrit ACLs such that CQ has
// read access to these refs, otherwise your users will be waiting for CQ
// to act on their CLs forever.
//
// Regular expression is validated by https://github.com/google/re2 library.
//
// NOTE: Git globs aren't supported. Convert them to a regular expression,
// e.g., Git glob "refs/heads/*" should be "refs/heads/[^/]+".
// However, users typically expect "refs/heads/.+", since expectation is
// that every typical Git branch to be CQ-able, including
// "refs/heads/experimental/foobar".
repeated string ref_regexp = 2;
}
}
// At least 1 Gerrit instance with repositories to work with is required.
repeated Gerrit gerrit = 1;
// Optional. If specified, CQ will consider sets of dependent CLs to test and
// submit at the same time.
//
// Typical use-case is testing & submitting changes to multiple repos at the
// same time, in which case all such repos must be declared up-front in
// `Gerrit` part of this config_group.
//
// Not allowed to be used together with
// submit_options.allow_submit_with_open_deps=true.
CombineCLs combine_cls = 4;
// Defines how to verify a CL before submitting it. Required.
Verifiers verifiers = 2;
// EXPERIMENTAL! TODO(tandrii, crbug/966115): add better doc or remove.
//
// If set, this ConfigGroup will be used if no other ConfigGroup matches.
//
// At most 1 config_group can be YES.
//
// Example use is to define specific config_group for refs/heads/master,
// and fallback one for refs/heads/* which will pick up all CLs on
// non-master branches.
Toggle fallback = 5;
}
// CombineCLs defines how CQ works with >1 CL per attempt.
//
// Dependencies between CLs are either implicit via Git child->parent
// relationship (e.g. stacked CLs in Gerrit) or explicit via "CQ-Depend:"
// footer in CL description (next to Change-Id:). "CQ-Depend" may span
// across repositories and even Gerrit hosts. For example, a CL on
// https://pdfium-review.googlesource.com may declare dependency on
// https://chromium-review.googlesource.com/1111111 by adding this footer:
//
// CQ-Depend: chromium:1111111
//
// The "chromium" part means that 1111111 is on the
// chromium-review.googlesource.com host. It can be omitted if dependency
// is on the same host as the CL depending on it.
//
// CQ-Depend alone or with Git dependencies may form cycles, which is useful
// to require CQ to test & submit all CLs in a cycle at the same time, never
// alone.
//
// A user must vote on CQ label on **each CL** individually. Since it can't be
// instantaneous, `stabilization_delay` controls how long CQ waits for all
// CQ+1/2 votes before computing maximal expanded set of CLs and starting the
// attempt.
//
// For any CL with CQ+1/2 vote, each of its dependency must have the same CQ
// vote and be configured for CQ **in the same config group**, else CQ would
// abort the attempt with appropriate error message.
//
// Each tryjob CQ triggers via Buildbucket will be associated with each CL of
// the attempt via `gerrit_changes` parameter of Buildbucket. These changes are
// then available to a build as it is being executed. If ran via recipes,
// the `ordered_gerrit_changes` property of
// https://chromium.googlesource.com/infra/luci/recipes-py/+/HEAD/README.recipes.md#class-cqapi_recipeapi
// can be used to CLs in the right order.
//
// WARNING: When submitting CLs, CQ can not do so atomically (all submitted or
// none submitted) because Gerrit doesn't support this even for the same repo &
// target_ref.
message CombineCLs {
// Roughly, how long CQ waits for CQ to be triggered on each of the related
// CLs.
//
// Must be greater than 10s.
// 30s is recommended.
//
// Technically precise definition is time to wait since the latest CL among
// related ones receives CQ+1/2 vote before starting actual attempt.
//
// For example, during this delay, a CQ vote may be added on another CL
// which depends on previously CQ-ed CL in this not-yet-started attempt. Then,
// CQ would extend the attempt with additional CL and reset the waiting
// counter.
//
// Additional implication is that a standalone CL w/o any other relations to
// other CLs will need to wait this much time before CQ would start processing
// it (i.e., before it triggers first tryjob).
google.protobuf.Duration stabilization_delay = 1;
}
// Verifiers are various types of checks that a Commit Queue performs on a CL.
// All verifiers must pass in order for a CL to be submitted. Configuration file
// describes types of verifiers that should be applied to each CL and their
// parameters.
message Verifiers {
// Required. GerritCQAbility ensures that a user who triggered
// this CQ attempt actually has rights to do so based on 3 factors:
// * membership of the user in committers & dryrunners group,
// * the state of CL/patchset on which CQ is triggered,
// * relationship of the user to the CL.
GerritCQAbility gerrit_cq_ability = 1;
// This verifier is used to check tree status before committing a CL. If the
// tree is closed, then the verifier will wait until it is reopened.
TreeStatus tree_status = 2;
// This verifier triggers a set of builds through Buildbucket.
//
// CQ automatically retries failed tryjobs and only allows CL to land if each
// builder has succeeded in the latest retry.
// If a given tryjob result is too old (>1 day) it is ignored.
//
// Typically, builds from Buildbucket are executed on LUCI stack, however, CQ
// is agnostic to how and where builds are executed.
Tryjob tryjob = 3;
// CQLinter is for internal CQ use only. DO NOT USE IN YOUR cq.cfg.
CQLinter cqlinter = 4;
// Fake is for internal CQ use only. DO NOT USE IN YOUR cq.cfg.
Fake fake = 5;
message GerritCQAbility {
// Required. List of chrome-infra-auth groups, whose members are authorized
// to trigger full CQ runs.
//
// Typically, such groups are named "project-<name>-committers".
repeated string committer_list = 1;
// Optional, but strongly recommended. List of chrome-infra-auth groups,
// whose members are authorized to trigger CQ dry run on Gerrit CLs they own
// (not to be confused with OWNER files) even if CL hasn't been approved.
//
// Typically, such groups are named "project-<name>-tryjob-access".
repeated string dry_run_access_list = 2;
// Optional. allow_submit_with_open_deps controls how CQ full run behaves
// when current Gerrit CL has open dependencies (not yet submitted CLs on
// which *this* CL depends).
//
// If set to false (default), CQ will abort full run attempt immediately if
// open dependencies are detected.
//
// If set to true, then CQ will not abort full run and upon passing all
// other verifiers, CQ will attempt to submit the CL regardless of open
// dependencies and whether CQ verified those open dependencies.
// In turn, if Gerrit project config allows this, Gerrit will execute submit
// of all dependent CLs first and then this CL.
bool allow_submit_with_open_deps = 3;
// See `allow_owner_if_submittable` doc below.
enum CQAction {
UNSET = 0;
DRY_RUN = 1;
// COMMIT implies ability to trigger dry run as well.
COMMIT = 2;
}
// Optional. Allow CL owner to trigger CQ dry or full run on their own CL,
// even if not a member of `committer_list` or `dry_run_access_list`.
// Defaults to no such allowance.
//
// WARNING: using this option is not recommended if you have sticky
// Code-Review label because this allows a malicious developer to upload
// an good looking patchset at first, get code review approval,
// and then upload a bad patchset and CQ it right away.
//
// CL owner is Gerrit user owning a CL, i.e., its first patchset uploader.
// not to be confused with OWNERS files.
CQAction allow_owner_if_submittable = 4;
}
message TreeStatus {
// Required. URL of the project tree status app.
string url = 1;
}
// Tryjob configures builders which CQ may trigger and/or use to verify CL(s).
message Tryjob {
// Next field number: 4
// Builders on which tryjobs should be triggered.
//
// CQ won't allow adding any builder via `CQ-Include-Trybots:` in CL
// description except those in this list.
repeated Builder builders = 1;
// Optional, defaulting to no retries whatsoever.
RetryConfig retry_config = 2;
// EXPERIMENTAL. WORK IN PROGRESS. https://crbug.com/909895.
// Optional. If YES, running or not-yet-started tryjobs will be cancelled as
// soon as substantially different patchset is uploaded to a CL.
Toggle cancel_stale_tryjobs = 3;
message Builder {
// Next field number: 11
// Required. Name of the builder as <project>/<bucket>/<builder>
//
// Examples:
// "chromium/try/linux-tester"
// "other-project/try/shared-try-builder"
string name = 1;
// If true, this builder will only be used if specified via
// `CQ-Include-Trybots:` on CL description.
//
// This is useful if you want individual CLs to opt-in to this builder,
// e.g.:
// builder {name: "win-release"} # required for all.
// builder {name: "win-debug" includable_only: true} # opt in only.
//
// Not combinable with:
// * location_regexp[_exclude]
// * experiment_percentage
// * triggered_by
bool includable_only = 9;
// Determines how visible the results of a build for this builder are in
// Gerrit for this tryjob.
//
// This doesn't affect the buildbucket plugin (green/red chips).
CommentLevel result_visibility = 10;
// Optional. If true, a fresh build will be required for each CQ attempt.
//
// Default is false, meaning CQ may re-use a successful build
// triggered before current CQ attempt started.
//
// This option is typically used for builders which run depot_tools'
// PRESUBMIT scripts, which are supposed to be quick to run and provide
// additional OWNERS, lint, etc checks which are useful to run against
// the latest revision of the CL's target branch.
bool disable_reuse = 2;
// Optional name of a builder (aka parent) which will trigger this builder
// (aka child).
//
// If `triggered_by` is not specified (default), CQ will trigger this
// builder directly.
//
// Else, CQ will wait for `triggered_by` (parent) builder to trigger
// (possibly, indirectly) this (child) builder.
// Conditions:
// * `triggered_by` (parent) builder must set a special property
// `triggered_build_ids` upon successful completion with value set
// to a list of triggered Buildbucket build IDs,
// corresponding to each triggered build. One or more of the IDs must
// correspond to this (child) builder, which will then be waited for
// by CQ.
// * parent->child relationship graph must be a forest (set of a trees).
// However, grandparent->parent->child triggering structure isn't well
// tested. Please, talk to CQ maintainers to discuss your use case if you
// actually need it.
//
// Failure/Retry semantics:
// * If `triggered_by` (parent) builder succeeds, but doesn't set
// the right `triggered_build_ids` then CQ will wait for this child
// build to complete for as long as parent build result remains valid.
// * If this (child) builder fails and CQ still has retry budget,
// CQ will retry a parent builder.
//
// For example, given config:
// builder { name: "*/m/mac_compiler" }
// builder { name: "*/m/mac_tester_10.12"
// triggered_by: "*/m/mac_compiler" }
// builder { name: "*/m/mac_tester_10.13"
// triggered_by: "*/m/mac_compiler" }
// CQ will trigger and wait for "mac_compiler" to succeed. Then, it'll
// check its `triggered_build_ids` and find which ones correspond to
// "mac_tester_10.12" and "mac_tester_10.13" and wait for each to
// complete. If say "mac_tester_10.12" fails, CQ will retry
// "mac_compiler" and expect it to trigger new builds for
// "mac_tester_10.12" and "mac_tester_10.13".
string triggered_by = 3;
// Optional. When this field is present, it marks given builder as
// experimental. It is only triggered on a given percentage of the CLs
// and the outcome does not affect the decision of whether a CL can land
// or not. This is typically used to test new builders and estimate their
// capacity requirements.
float experiment_percentage = 4;
// Optionally specified alternative builder for CQ to choose instead.
// If provided, CQ will choose only one of the equivalent builders as
// required based purely on given CL and CL's owner and **regardless** of
// the possibly already completed tryjobs.
//
// Note: none of the equivalent builders should be part of triggered_by
// chain, although CQ may eventually relax this requirement.
EquivalentBuilder equivalent_to = 5;
// Optional. Require this builder only if location_regexp matches a file in
// this CL.
//
// This means:
// * If specified and no file in a CL matches any of the location_regexp,
// then CQ will not care about this builder.
// * If a file in a CL matches any location_regexp_exclude, then this file
// won't be considered when matching location_regexp.
//
// If location_regexp is not specified (default), builder will be used
// on all CLs.
//
// The location_regexp is matches are done against the following string:
// <gerrit_url>/<gerrit_project_name>/+/<cl_file_path>
// File path must be relative to root of the repo, and it uses Unix /
// directory separators.
//
// The comparison is a full match; the pattern is implicitly anchored with
// "^" and "$", so there is no need add them.
//
// Touching a file means either adding, modifying or removing it.
//
// These options currently can not be combined with the following other options:
// * experiment_percentage
// * triggered_by
// * GerritCQAbility.allow_submit_with_open_deps
// If you need to combine them, please talk to CQ owners.
//
// Examples:
//
// location_regexp:
// "https://chromium-review.googlesource.com/chromium/src/[+]/third_party/blink/.+"
// will enable builder for all CLs touching any file in
// third_party/blink directory of the chromium/src repo, but not
// just the directory itself.
//
// location_regexp: "https://example.com/repo/[+]/.+"
// location_regexp_exclude: "https://example.com/repo/[+]/all/one.txt"
// will match a CL which touches at least one file other than
// 'one.txt' inside all/ directory of the Gerrit project "repo".
//
// location_regexp_exclude: "https://example.com/.+/[+]/one.txt"
// will match a CL which touches at least one file other than
// 'one.txt' in any repository OR belongs to any other Gerrit server.
// Note, in this case location_regexp defaults to ".*".
repeated string location_regexp = 6;
repeated string location_regexp_exclude = 7;
// If set, this builder will only be triggered if the CL owner (who first
// uploaded the CL) is a member of at least one of these groups.
repeated string owner_whitelist_group = 8;
}
message EquivalentBuilder {
// Required. Name of this builder.
// Format is the same in the same format as Builder.name.
string name = 1;
// Percentage expressing probability of CQ triggering this builder instead
// of the builder to which this builder is equivalent to.
//
// A choice itself is made deterministically based on CL alone, hereby
// all CQ attempts on all patchsets of a given CL will trigger the same
// builder, assuming CQ config doesn't change in the mean time.
//
// Note that if `owner_whitelist_group` is also specified, the choice over
// which of the two builders to trigger will be made only for CLs owned by
// whitelisted group.
//
// If not specified, defaults to 0, meaning this builder is never
// triggered by CQ, but an existing build can be re-used by CQ.
//
// To illustrate, suppose percentage=10. Then,
// Without owner_whitelist_group,
// ~10% of all CQ attempts will trigger this builder.
// With owner_whitelist_group set and, suppose, 1/5 of CQ attempts are
// ran on CLs owned by this group, then only ~(1/10)*(1/5) or
// ~2% of all CQ attempts will trigger this builder.
float percentage = 2;
// If specified, limits the builder to CL owners in this group.
string owner_whitelist_group = 3;
}
// Builder which can be included via `CQ-Include-Trybots:` in CL
// description.
message IncludableBuilder {
// Required. Name of this builder.
// Format is the same in the same format as Builder.name.
string name = 1;
}
// Collection of parameters for deciding whether to retry a single build.
// If parameter is not specified, its value defaults to 0 (per proto3).
// Thus, omitting all parameters means no retries of any kind.
message RetryConfig {
// Retry quota for a single tryjob.
int32 single_quota = 1;
// Retry quota for all tryjobs in a CL.
int32 global_quota = 2;
// The weight assigned to each tryjob failure.
int32 failure_weight = 3;
// The weight assigned to each transient failure.
int32 transient_failure_weight = 4;
// The weight assigned to tryjob timeouts.
int32 timeout_weight = 5;
}
}
// CQLinter is for internal use in CQ.
message CQLinter{}
// Fake is for internal use in CQ.
message Fake {
string name = 1;
string eventual_state = 2;
int32 delay = 3;
}
}