blob: 97b8fc56ee50c87352ebdb923e2141f2899493cc [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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package cv.config;
option go_package = ";cfgpb";
import "google/protobuf/duration.proto";
import "validate/validate.proto";
import "";
import "";
option (luci.file_metadata) = {
doc_url: "";
// 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.
// Pro-tip: a command line tool exists to validate a locally generated .cfg
// file and verify that it matches arbitrary given CLs as expected.
// See
message Config {
// Deprecated. Ignored. Do not use.
// See also to implement an alternative.
string draining_start_time = 1 [deprecated = true];
// Optional.
// Originally, this was used to specify the URL of the CQ status app where
// users have access to their Run details. Currently, with the migration
// from CQ to LUCI CV, this field no longer serves as the same meaning,
// but is used to decide the visibility of the Run details via LUCI CV UI at
// This field accepts the following values:
// * "": all Runs in this Project are public.
// * "": all Runs in this Project are visible
// to Googler only.
// Note that the Run details page contains the name of the builders launched
// to verify CL(s). Therefore, if this Project launches internal builders for
// public repos and the builder names are confidential, please don't
// use public host.
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;
// Deprecated. Ignored. Do not use.
Toggle project_scoped_account = 5 [deprecated = true];
// ConfigGroup allows one to share single verifiers config across a set of
// Gerrit repositories, which may be in different Gerrit installations.
message ConfigGroup {
// Next field number: 10.
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. Must match regex "^[a-zA-Z][a-zA-Z0-9_-]*$".
string name = 6;
// Enumerates repositories on a Gerrit instance for which CQ should work.
message Gerrit {
// Gerrit URL, e.g.,
// 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 * for
// forcing authentication).
// Examples on
// 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 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;
// Exclude matching refs in this repo. Optional.
// If a ref is matches at least one of the ref_regexp_exclude,
// then it is ignored by this config group regardless of ref_regexp.
// The syntax is the same as for ref_regexp.
repeated string ref_regexp_exclude = 3;
// 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;
// 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/main,
// and fallback one for refs/heads/* which will pick up all CLs on
// non-main branches.
// TODO(crbug/966115): provide a better solution.
Toggle fallback = 5;
// Optional. Additional run modes supported besides standard DRY_RUN and
// If specified, the order matters. CQ will create the Run with the first
// mode for which triggering conditions are fulfilled. If there is no such
// mode, CQ will fallback to standard DRY_RUN or FULL_RUN.
// All the mode names must be unique.
// **NOTE**: As of Jan 2023, this field may be given either 1 or 0 mode, and
// the name must be "QUICK_DRY_RUN", if provided.
repeated Mode additional_modes = 7;
// Per-user limits.
// At the time of a Run creation, CV will iterate `user_limits` and apply the
// first applicable limit to the Run. If none of the limit(s) are applicable,
// CV will apply `user_limits_default` to the run.
repeated UserLimit user_limits = 8;
// Default per-user limit.
// If CV couldn't find an applicable limit from `user_limits`, this limit
// will be applied.
UserLimit user_limit_default = 9;
// Action to be performed on a Run completion.
message PostAction {
// Name of the post action.
string name = 1 [(validate.rules).string.min_len = 1];
// Condition to be met for the action to be triggered.
message TriggeringCondition {
// Name of the mode to be matched.
// the additional modes configured.
string mode = 1 [(validate.rules).string.min_len = 1];
// Statuses to trigger the action on.
// Must be terminal statuses.
// Duplicates are not allowed.
repeated cv.v1.Run.Status statuses = 2 [
(validate.rules).repeated = {
min_items: 1,
items: {enum: {defined_only: true}}
// If at least one of the conditions is met,
// the action will be triggered on a Run completion.
repeated TriggeringCondition conditions = 2 [
(validate.rules).repeated = {
min_items: 1,
items: {message: {required: true}}
// Vote Gerrit labels with given values.
message VoteGerritLabels {
message Vote {
// Gerrit label name
string name = 1 [(validate.rules).string.min_len = 1];
// Value to set on the label
int32 value = 2;
// All label names must be unique.
repeated Vote votes = 1 [(validate.rules).repeated.min_items = 1];
oneof action {
option (validate.required) = true;
VoteGerritLabels vote_gerrit_labels = 3;
// PostAction to be performed on a Run completion.
// On a Run completion, all the post actions with matching conditions will
// be executed.
// All actions must have a unique name in the list.
repeated PostAction post_actions = 10 [
(validate.rules).repeated = {
items: {message: {required: 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;
// Mode defines a CQ Run mode and how it can be triggered.
message Mode {
// Name of the mode.
// Must match regex "^[a-zA-Z][a-zA-Z0-9_-]{0,39}$".
string name = 1 [
(validate.rules).string.pattern = "^[a-zA-Z][a-zA-Z0-9-9_-]{0,39}$"
// Value of Commit-Queue label that triggers a CQ Run in the mode.
// Must be either 1 or 2.
int32 cq_label_value = 2 [(validate.rules).int32 = {in: [1, 2]}];
// Label that MUST also be voted with `triggering_value` in addition to
// "Commit-Queue" label to trigger a CQ Run in the mode.
// Must not be "Commit-Queue"
string triggering_label = 3 [
(validate.rules).string = {
min_len: 1,
not_in: ['Commit-Queue'],
// Value of the `trigerring_label` that triggers a CQ Run in the mode.
// Must be > 0
int32 triggering_value = 4 [(validate.rules) = 0];
// 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
// may declare dependency on
// by adding this footer:
// CQ-Depend: chromium:1111111
// The "chromium" part means that 1111111 is on the
// 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
// 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.
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;
// Next tag: 6.
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, but required to use auto-triggered runs on new patchset upload,
// it defines a list of chrome-infra-auth groups whose members are
// authorized to trigger a new patchset runs. That is, CV will check the
// owner of the CL when a new patchset is uploaded against these.
repeated string new_patchset_run_access_list = 5;
// 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.
// 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 (including the equivalent
// builders).
repeated Builder builders = 1;
// Optional, defaulting to no retries whatsoever.
RetryConfig retry_config = 2;
// DEPRECATED. Use per-builder `cancel_stale` instead.
Toggle cancel_stale_tryjobs = 3 [deprecated = true];
message Builder {
// Next field number: 17
reserved 3; // triggered_by
// The buildbucket host name.
// Optional. If empty, default to "".
string host = 16;
// 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.
// If false, the builder may still be included 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_filters
// * experiment_percentage
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. If YES (default), running or not-yet-started builds of this
// builder previously triggered by CQ will be cancelled as soon as
// a substantially different patchset is uploaded to a CL.
// The following paragraph is only applicable to LUCI Change Verifier (
// The successor of legacy CQ). As of 09/2020, the implementation is
// still WIP. TODO(crbug/1127991): Remove after migration is done.
// CV will snapshot the value of this option when a Run is created
// and use it throughout the lifecycle of this Run. Therefore,
// modification on this option will only take effect on newly-created
// Runs after config change is propagated to CV.
Toggle cancel_stale = 11;
// 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. May be combined with location_filters.
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: The equivalent builders can be included using
// `CQ-Include-Trybots:` footer. In this case, CQ will always try to
// trigger the equivalent builders regardless of the equivalent
// percentage.
EquivalentBuilder equivalent_to = 5;
// Optional. Require this builder only if a file in the CL is included
// by location_filters.
// location_filters is an ordered list of LocationFilter messages, where
// each message includes regular expressions for the matching Gerrit
// host, Gerrit project and file path, as well as a boolean field to
// specify whether the filter is an exclude filter or not.
// Files "in the CL" means all files touched, i.e. added, modified or
// deleted.
// The Gerrit host, Gerrit project and file path are matched against the
// respective patterns in the LocationFilter. The last LocationFilter
// that match all patterns (host, project, and path) determines whether
// the file is considered included, i.e. if the last matching
// LocationFilter has exclude set to false, then it's included; else
// included.
// If none of the LocationFilters match, then the file is considered
// included if the first rule is an exclude rule; else the file is
// excluded.
// If host, project or path are empty, then they will match anything
// (".*") by default. The comparison is a full match; the pattern is
// implicitly anchored with "^" and "$", so there is no need add them.
// The syntax for regular expressions is Google's re2 syntax for regexp,
// documented here:
// If location_filters is non-empty, and no file in a CL is included by
// location_filters, then this builder will not be triggered. If
// location_filters is empty or not specified, then the builder will be
// triggered by default, subject to other conditions, e.g.
// mode_allowlist.
// This option currently can not be combined with the
// `GerritCQAbility.allow_submit_with_open_deps` option.
// If you need to combine, please talk to LUCI CV owners.
// (
// Examples:
// location_filters: {path_regexp: "excluded/.+", exclude: true}
// location_filters: {path_regexp: "excluded/exception", exclude: false}
// Result: files outside of the "excluded" directory will be
// included, and so will "excluded/exception" will, but other files
// in the "excluded" directory will not match.
// location_filters: {path_regexp: ".*", exclude: false} // include all by default
// location_filters: {host_regexp: "",
// project_regexp: "repo",
// exclude: true}
// location_filters: {host_regexp: "",
// project_regexp: "repo",
// path_regexp: "all/one.txt",
// exclude: false}
// Result: files in the specified host and repo will not be included,
// except all/one.txt which will be included; files outside of the
// given host/repo will be included.
message LocationFilter {
// Pattern to match Gerrit host. Does not include scheme, which is
// always assumed to be "https://".
string gerrit_host_regexp = 1;
// Pattern to match Gerrit project, e.g. "infra/luci/luci-go".
string gerrit_project_regexp = 2;
// Pattern to match file path. This is a relative path from repo root
// (no starting slash).
string path_regexp = 3;
// If exclude is true, then if this filter matches a file, the file is
// considered not included. (If all files are not included, then the
// builder is not triggered.)
bool exclude = 4;
repeated LocationFilter location_filters = 15;
// 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;
reserved 12, 13; // mode_regexp[_exclude]
// If set, require this builder only if the Run mode matches
// one of the modes in this list. If unset, it implies that only FULL_RUN
// and DRY_RUN are allowed, and temporarily QUICK_DRY_RUN. Optional.
repeated string mode_allowlist = 14;
message EquivalentBuilder {
// Required. Name of this builder.
// Format is the same in the same format as
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
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.
// CQ's retry logic is as follows:
// All builds triggered during the lifetime of a CQ attempt for a tryjob are
// weighted according to the failure type, as described below. The resulting
// weights are then added together. Call this number W. If W > single_quota,
// then no more builds are scheduled for that tryjob.
// W for every tryjob is then summed up. If that result is strictly greater
// than global_quota, then the CQ attempt fails, and no more builds are
// scheduled for the attempt.
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. A failure is as a
// buildbucket build whose result == 'FAILURE'.
int32 failure_weight = 3;
// The weight assigned to each transient failure. A transient failure is a
// buildbucket build which has result == 'FAILURE' and 'failure_reason' in
int32 transient_failure_weight = 4;
// The weight assigned to tryjob timeouts. A tryjob timeout is as a
// buildbucket build with result == 'CANCELED' and cancelation_reason ==
int32 timeout_weight = 5;
// CQLinter is for internal use in CQ.
// Deprecated. Do not use.
// TODO(crbug/1127991): Remove after migration off CQDaemon is completed.
message CQLinter{}
// Fake is for internal use in CQ.
// Deprecated. Do not use.
// TODO(crbug/1127991): Remove after migration off CQDaemon is completed.
message Fake {
string name = 1;
string eventual_state = 2;
int32 delay = 3;
// 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.
// 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.
// The CQ reports a generic "Build failed:"
// with no summary markdown.
// A boolean with an "unset" default value.
enum Toggle {
UNSET = 0;
YES = 1;
NO = 2;
// UserLimit specifies Run and Tryjob limits per user.
message UserLimit {
// Name of the limit. Must be unique across all the policies
// with the LUCI project.
// Required. Must match regex '^[0-9A-Za-z][0-9A-Za-z\.\-@_+]{0,511}$'
string name = 1;
// Principals to apply the limits to.
// Each entry can be either an identity string "user:<email>"
// or a LUCI group reference "group:<name>"
repeated string principals = 2;
message Limit {
// Required. value must be > 0, unless unlimited is set to True.
oneof limit {
int64 value = 1;
bool unlimited = 2;
message Run {
// Maximum number of active runs that the user can have at any moment.
// Required. Active Run is a Run that has started but not ended yet.
Limit max_active = 1;
message Tryjob {
// Maximum number of active tryjobs that the user can have at any
// moment.
// Active tryjob is a tryjob that CV has successfully launched,
// and has not ended yet from CV's point of view. Also, optional
// tryjobs, which are experimental tryjobs that were not explicitly
// requested via the git footer, are not counted as active tryjobs.
// Note that counting active tryjobs and launching tryjobs are not
// atomic operations. So, # of active tryjobs may not match # of
// the successfully launched tryjobs for a short period, but will
// match eventually.
// If not specified, an unlimited number of active Tryjobs are allowed.
Limit max_active = 1;
// Run limits. Required.
Run run = 5;
// Tryjob limits. Required
Tryjob tryjob = 6;