1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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"
|