diff options
Diffstat (limited to '')
-rw-r--r-- | taskcluster/taskgraph/util/attributes.py | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/taskcluster/taskgraph/util/attributes.py b/taskcluster/taskgraph/util/attributes.py new file mode 100644 index 0000000000..6a446d6fa7 --- /dev/null +++ b/taskcluster/taskgraph/util/attributes.py @@ -0,0 +1,163 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import absolute_import, print_function, unicode_literals + +import re + +import six + + +INTEGRATION_PROJECTS = { + "autoland", +} + +TRUNK_PROJECTS = INTEGRATION_PROJECTS | {"mozilla-central", "comm-central"} + +RELEASE_PROJECTS = { + "mozilla-central", + "mozilla-beta", + "mozilla-release", + "mozilla-esr78", + "comm-central", + "comm-beta", + "comm-esr78", + "oak", +} + +RELEASE_PROMOTION_PROJECTS = { + "jamun", + "maple", + "try", + "try-comm-central", +} | RELEASE_PROJECTS + +TEMPORARY_PROJECTS = set( + { + # When using a "Disposeabel Project Branch" you can specify your branch here. e.g.: + # 'oak', + } +) + +ALL_PROJECTS = RELEASE_PROMOTION_PROJECTS | TRUNK_PROJECTS | TEMPORARY_PROJECTS + +RUN_ON_PROJECT_ALIASES = { + # key is alias, value is lambda to test it against + "all": lambda project: True, + "integration": lambda project: project in INTEGRATION_PROJECTS, + "release": lambda project: project in RELEASE_PROJECTS, + "trunk": lambda project: project in TRUNK_PROJECTS, +} + +_COPYABLE_ATTRIBUTES = ( + "accepted-mar-channel-ids", + "artifact_map", + "artifact_prefix", + "build_platform", + "build_type", + "l10n_chunk", + "locale", + "mar-channel-id", + "nightly", + "required_signoffs", + "shippable", + "shipping_phase", + "shipping_product", + "signed", + "stub-installer", + "update-channel", +) + + +def attrmatch(attributes, **kwargs): + """Determine whether the given set of task attributes matches. The + conditions are given as keyword arguments, where each keyword names an + attribute. The keyword value can be a literal, a set, or a callable. A + literal must match the attribute exactly. Given a set, the attribute value + must be in the set. A callable is called with the attribute value. If an + attribute is specified as a keyword argument but not present in the + attributes, the result is False.""" + for kwkey, kwval in six.iteritems(kwargs): + if kwkey not in attributes: + return False + attval = attributes[kwkey] + if isinstance(kwval, set): + if attval not in kwval: + return False + elif callable(kwval): + if not kwval(attval): + return False + elif kwval != attributes[kwkey]: + return False + return True + + +def keymatch(attributes, target): + """Determine if any keys in attributes are a match to target, then return + a list of matching values. First exact matches will be checked. Failing + that, regex matches and finally a default key. + """ + # exact match + if target in attributes: + return [attributes[target]] + + # regular expression match + matches = [v for k, v in six.iteritems(attributes) if re.match(k + "$", target)] + if matches: + return matches + + # default + if "default" in attributes: + return [attributes["default"]] + + return [] + + +def match_run_on_projects(project, run_on_projects): + """Determine whether the given project is included in the `run-on-projects` + parameter, applying expansions for things like "integration" mentioned in + the attribute documentation.""" + aliases = RUN_ON_PROJECT_ALIASES.keys() + run_aliases = set(aliases) & set(run_on_projects) + if run_aliases: + if any(RUN_ON_PROJECT_ALIASES[alias](project) for alias in run_aliases): + return True + + return project in run_on_projects + + +def match_run_on_hg_branches(hg_branch, run_on_hg_branches): + """Determine whether the given project is included in the `run-on-hg-branches` + parameter. Allows 'all'.""" + if "all" in run_on_hg_branches: + return True + + for expected_hg_branch_pattern in run_on_hg_branches: + if re.match(expected_hg_branch_pattern, hg_branch): + return True + + return False + + +def copy_attributes_from_dependent_job(dep_job, denylist=()): + return { + attr: dep_job.attributes[attr] + for attr in _COPYABLE_ATTRIBUTES + if attr in dep_job.attributes and attr not in denylist + } + + +def sorted_unique_list(*args): + """Join one or more lists, and return a sorted list of unique members""" + combined = set().union(*args) + return sorted(combined) + + +def release_level(project): + """ + Whether this is a staging release or not. + + :return six.text_type: One of "production" or "staging". + """ + return "production" if project in RELEASE_PROJECTS else "staging" |