Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: appengine/cr-buildbucket/swarming/swarming.py

Issue 2090343006: swarmbucket: support for repository property (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: swarmbucket: support for repository property Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | appengine/cr-buildbucket/swarming/test/swarming_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """This module integrates buildbucket with swarming. 5 """This module integrates buildbucket with swarming.
6 6
7 A bucket config may have "swarming" field that specifies how a builder 7 A bucket config may have "swarming" field that specifies how a builder
8 is mapped to a recipe. If build is scheduled for a bucket/builder 8 is mapped to a recipe. If build is scheduled for a bucket/builder
9 with swarming configuration, the integration overrides the default behavior. 9 with swarming configuration, the integration overrides the default behavior.
10 10
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 task_template = yield get_task_template_async() 93 task_template = yield get_task_template_async()
94 if task_template and isinstance(build.parameters, dict): # pragma: no branch 94 if task_template and isinstance(build.parameters, dict): # pragma: no branch
95 builder = build.parameters.get(BUILDER_PARAMETER) 95 builder = build.parameters.get(BUILDER_PARAMETER)
96 if builder: # pragma: no branch 96 if builder: # pragma: no branch
97 result = yield _is_for_swarming_async(build.bucket, builder) 97 result = yield _is_for_swarming_async(build.bucket, builder)
98 raise ndb.Return(result) 98 raise ndb.Return(result)
99 99
100 100
101 def validate_build_parameters(builder_name, params): 101 def validate_build_parameters(builder_name, params):
102 """Raises errors.InvalidInputError if build parameters are invalid.""" 102 """Raises errors.InvalidInputError if build parameters are invalid."""
103
104 def bad(fmt, *args):
105 raise errors.InvalidInputError(fmt % args)
106
103 properties = params.get(PARAM_PROPERTIES) 107 properties = params.get(PARAM_PROPERTIES)
104 if properties is not None: 108 if properties is not None:
105 if not isinstance(properties, dict): 109 if not isinstance(properties, dict):
106 raise errors.InvalidInputError('properties param must be an object') 110 bad('properties parameter must be an object')
107 if properties.get('buildername', builder_name) != builder_name: 111 if properties.get('buildername', builder_name) != builder_name:
108 raise errors.InvalidInputError('inconsistent builder name') 112 bad('inconsistent builder name')
109 113
110 swarming = params.get(PARAM_SWARMING) 114 swarming = params.get(PARAM_SWARMING)
111 if swarming is not None: 115 if swarming is not None:
112 if not isinstance(swarming, dict): 116 if not isinstance(swarming, dict):
113 raise errors.InvalidInputError('swarming param must be an object') 117 bad('swarming parameter must be an object')
114 swarming = copy.deepcopy(swarming) 118 swarming = copy.deepcopy(swarming)
115 if 'recipe' in swarming: 119 if 'recipe' in swarming:
116 recipe = swarming.pop('recipe') 120 recipe = swarming.pop('recipe')
117 if not isinstance(recipe, dict): 121 if not isinstance(recipe, dict):
118 raise errors.InvalidInputError( 122 bad('swarming.recipe parameter must be an object')
119 'swarming.recipe param must be an object')
120 if 'revision' in recipe: 123 if 'revision' in recipe:
121 revision = recipe.pop('revision') 124 revision = recipe.pop('revision')
122 if not isinstance(revision, basestring): 125 if not isinstance(revision, basestring):
123 raise errors.InvalidInputError( 126 bad('swarming.recipe.revision parameter must be a string')
124 'swarming.recipe.revision must be a string')
125 if recipe: 127 if recipe:
126 raise errors.InvalidInputError( 128 bad('unrecognized keys in swarming.recipe: %r', recipe)
127 'Unrecognized keys in swarming.recipe: %r' % recipe)
128 129
129 if swarming: 130 if swarming:
130 raise errors.InvalidInputError('Unrecognized keys: %r', swarming) 131 bad('unrecognized keys: %r', swarming)
132
133 changes = params.get(PARAM_CHANGES)
134 if changes is not None:
135 if not isinstance(changes, list):
136 bad('changes param must be an array')
137 for c in changes: # pragma: no branch
138 if not isinstance(c, dict):
139 bad('changes param must contain only objects')
140 repo_url = c.get('repo_url')
141 if repo_url is not None and not isinstance(repo_url, basestring):
142 bad('change repo_url must be a string')
143 author = c.get('author')
144 if not isinstance(author, dict):
145 bad('change author must be an object')
146 email = author.get('email')
147 if not isinstance(email, basestring):
148 bad('change author email must be a string')
149 if not email:
150 bad('change author email not specified')
131 151
132 152
133 def merge_recipe(r1, r2): 153 def merge_recipe(r1, r2):
134 """Merges two Recipe messages. Values in r2 overwrite values in r1.""" 154 """Merges two Recipe messages. Values in r2 overwrite values in r1."""
135 if not r1: # pragma: no branch 155 if not r1: # pragma: no branch
136 return r2 # pragma: no cover 156 return r2 # pragma: no cover
137 r1_props = dict(p.split(':', 1) for p in r1.properties) 157 r1_props = dict(p.split(':', 1) for p in r1.properties)
138 r2_props = dict(p.split(':', 1) for p in r2.properties) 158 r2_props = dict(p.split(':', 1) for p in r2.properties)
139 r1_props.update(r2_props) 159 r1_props.update(r2_props)
140 return project_config_pb2.Swarming.Recipe( 160 return project_config_pb2.Swarming.Recipe(
(...skipping 26 matching lines...) Expand all
167 } 187 }
168 188
169 is_recipe = ( 189 is_recipe = (
170 builder_cfg.HasField('recipe') or swarming_cfg.HasField('common_recipe')) 190 builder_cfg.HasField('recipe') or swarming_cfg.HasField('common_recipe'))
171 if is_recipe: # pragma: no branch 191 if is_recipe: # pragma: no branch
172 recipe = merge_recipe(swarming_cfg.common_recipe, builder_cfg.recipe) 192 recipe = merge_recipe(swarming_cfg.common_recipe, builder_cfg.recipe)
173 revision = swarming_param.get('recipe', {}).get('revision') or '' 193 revision = swarming_param.get('recipe', {}).get('revision') or ''
174 194
175 build_properties = dict( 195 build_properties = dict(
176 p.split(':', 1) for p in recipe.properties or []) 196 p.split(':', 1) for p in recipe.properties or [])
177 build_properties.update(build.parameters.get(PARAM_PROPERTIES) or {})
178 build_properties['buildername'] = builder_cfg.name 197 build_properties['buildername'] = builder_cfg.name
179 198
180 # Convert changes in build to blamelist property, like Buildbot-Buildbucket
181 # integration. In Buildbot the property value is a list of emails.
182 changes = params.get(PARAM_CHANGES) 199 changes = params.get(PARAM_CHANGES)
183 if changes: # pragma: no branch 200 if changes: # pragma: no branch
201 # Buildbucket-Buildbot integration passes repo_url of the first change in
202 # build parameter "changes" as "repository" attribute of SourceStamp.
203 # https://chromium.googlesource.com/chromium/tools/build/+/2c6023d/scripts /master/buildbucket/changestore.py#140
204 # Buildbot passes repository of the build source stamp as "repository"
205 # build property. Recipes, in partiular bot_update recipe module, rely on
206 # "repository" property and it is an almost sane property to support in
207 # swarmbucket.
208 repo_url = changes[0].get('repo_url')
209 if repo_url: # pragma: no branch
210 build_properties['repository'] = repo_url
211
212 # Buildbot-Buildbucket integration converts emails in changes to blamelist
213 # property.
184 emails = [c.get('author', {}).get('email') for c in changes] 214 emails = [c.get('author', {}).get('email') for c in changes]
185 build_properties['blamelist'] = filter(None, emails) 215 build_properties['blamelist'] = filter(None, emails)
186 216
217 # Properties specified in build parameters must override any values derived
218 # by swarmbucket.
219 build_properties.update(build.parameters.get(PARAM_PROPERTIES) or {})
220
187 task_template_params.update({ 221 task_template_params.update({
188 'repository': recipe.repository, 222 'repository': recipe.repository,
189 'revision': revision, 223 'revision': revision,
190 'recipe': recipe.name, 224 'recipe': recipe.name,
191 'properties_json': json.dumps(build_properties, sort_keys=True), 225 'properties_json': json.dumps(build_properties, sort_keys=True),
192 }) 226 })
193 227
194 task_template_params = { 228 task_template_params = {
195 k: v or '' for k, v in task_template_params.iteritems()} 229 k: v or '' for k, v in task_template_params.iteritems()}
196 task = format_obj(task_template, task_template_params) 230 task = format_obj(task_template, task_template_params)
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 def _extend_unique(target, items): 667 def _extend_unique(target, items):
634 for x in items: 668 for x in items:
635 if x not in target: # pragma: no branch 669 if x not in target: # pragma: no branch
636 target.append(x) 670 target.append(x)
637 671
638 672
639 class TaskToken(tokens.TokenKind): 673 class TaskToken(tokens.TokenKind):
640 expiration_sec = 60 * 60 * 24 # 24 hours. 674 expiration_sec = 60 * 60 * 24 # 24 hours.
641 secret_key = auth.SecretKey('swarming_task_token', scope='local') 675 secret_key = auth.SecretKey('swarming_task_token', scope='local')
642 version = 1 676 version = 1
OLDNEW
« no previous file with comments | « no previous file | appengine/cr-buildbucket/swarming/test/swarming_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698