summaryrefslogtreecommitdiffstats
path: root/taskcluster/taskgraph/util/attributes.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--taskcluster/taskgraph/util/attributes.py163
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"