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

Side by Side Diff: scripts/slave/recipe_modules/swarming/api.py

Issue 313693003: Swarming: conditionally run tests on swarming in chromium_trybot recipe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 6 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 | Annotate | Revision Log
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 from slave import recipe_api 5 from slave import recipe_api
6 6
7 7
8 # Minimally supported version of swarming.py script (reported by --version). 8 # Minimally supported version of swarming.py script (reported by --version).
9 MINIMAL_SWARMING_VERSION = (0, 4, 8) 9 MINIMAL_SWARMING_VERSION = (0, 4, 8)
10 10
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 x.startswith('--test-launcher-summary-output=') for x in extra_args) 201 x.startswith('--test-launcher-summary-output=') for x in extra_args)
202 if bad_args: # pragma: no cover 202 if bad_args: # pragma: no cover
203 raise ValueError('--test-launcher-summary-output should not be used.') 203 raise ValueError('--test-launcher-summary-output should not be used.')
204 204
205 # Append it. output.json name is expected by collect_gtest_task.py. 205 # Append it. output.json name is expected by collect_gtest_task.py.
206 extra_args.append( 206 extra_args.append(
207 '--test-launcher-summary-output=${ISOLATED_OUTDIR}/output.json') 207 '--test-launcher-summary-output=${ISOLATED_OUTDIR}/output.json')
208 208
209 # Make a task, configure it to be collected through shim script. 209 # Make a task, configure it to be collected through shim script.
210 task = self.task(title, isolated_hash, make_unique, shards, extra_args) 210 task = self.task(title, isolated_hash, make_unique, shards, extra_args)
211 task.collect_step_builder = lambda *args: ( 211 task.collect_step_builder = lambda *args, **kwargs: (
212 self._gtest_collect_step(test_launcher_summary_output, *args)) 212 self._gtest_collect_step(test_launcher_summary_output, *args, **kwargs))
213 return task 213 return task
214 214
215 def check_client_version(self): 215 def check_client_version(self):
216 """Yields steps to verify compatibility with swarming_client version.""" 216 """Yields steps to verify compatibility with swarming_client version."""
217 yield self.m.swarming_client.ensure_script_version( 217 yield self.m.swarming_client.ensure_script_version(
218 'swarming.py', MINIMAL_SWARMING_VERSION) 218 'swarming.py', MINIMAL_SWARMING_VERSION)
219 219
220 def trigger(self, tasks): 220 def trigger(self, tasks, **kwargs):
221 """Asynchronously launches a set of tasks on Swarming. 221 """Asynchronously launches a set of tasks on Swarming.
222 222
223 This steps justs posts the tasks and immediately returns. Use 'collect' to 223 This steps justs posts the tasks and immediately returns. Use 'collect' to
224 wait for a task to finish and grab its result. 224 wait for a task to finish and grab its result.
225 225
226 Args: 226 Args:
227 tasks: an enumerable of SwarmingTask instances. 227 tasks: an enumerable of SwarmingTask instances.
228 kwargs: passed to recipe step constructor as is, may contain
M-A Ruel 2014/06/04 00:52:53 as-is
Vadim Sh. 2014/06/04 02:58:26 Done.
229 always_run, can_fail_build, etc.
228 """ 230 """
229 # TODO(vadimsh): Trigger multiple tasks as a single step. 231 # TODO(vadimsh): Trigger multiple tasks as a single step.
230 assert all(isinstance(t, SwarmingTask) for t in tasks) 232 assert all(isinstance(t, SwarmingTask) for t in tasks)
231 steps = [] 233 steps = []
232 for task in tasks: 234 for task in tasks:
233 assert task.task_id not in self._pending_tasks, ( 235 assert task.task_id not in self._pending_tasks, (
234 'Triggered same task twice: %s' % task.task_id) 236 'Triggered same task twice: %s' % task.task_id)
235 self._pending_tasks.add(task.task_id) 237 self._pending_tasks.add(task.task_id)
236 238
237 # Trigger parameters. 239 # Trigger parameters.
(...skipping 21 matching lines...) Expand all
259 261
260 # Additional command line args for isolated command. 262 # Additional command line args for isolated command.
261 if task.extra_args: 263 if task.extra_args:
262 args.append('--') 264 args.append('--')
263 args.extend(task.extra_args) 265 args.extend(task.extra_args)
264 266
265 # Build corresponding step. 267 # Build corresponding step.
266 steps.append(self.m.python( 268 steps.append(self.m.python(
267 name=self._get_step_name('trigger', task), 269 name=self._get_step_name('trigger', task),
268 script=self.m.swarming_client.path.join('swarming.py'), 270 script=self.m.swarming_client.path.join('swarming.py'),
269 args=args)) 271 args=args,
272 **kwargs))
270 273
271 return steps 274 return steps
272 275
273 def collect(self, tasks, followup_fn=None): 276 def collect(self, tasks, **kwargs):
274 """Waits for a set of Swarming tasks to finish. 277 """Waits for a set of Swarming tasks to finish.
275 278
276 Always waits for all task results. Failed tasks will be marked as such 279 Always waits for all task results. Failed tasks will be marked as such
277 but would not abort the build (corresponds to always_run=True step 280 but would not abort the build (corresponds to always_run=True step
278 property). 281 property).
279 282
280 Args: 283 Args:
281 tasks: an enumerable of SwarmingTask instances. All of them should have 284 tasks: an enumerable of SwarmingTask instances. All of them should have
282 been triggered previously with 'trigger' method. 285 been triggered previously with 'trigger' method.
283 followup_fn: if given, will be called with each step result before step is 286 kwargs: passed to recipe step constructor as is, may contain
M-A Ruel 2014/06/04 00:52:53 as-is
Vadim Sh. 2014/06/04 02:58:26 Done.
284 finalized. Can be used to customize step appearance. 287 always_run, can_fail_build, followup_fn, etc.
285 """ 288 """
286 # TODO(vadimsh): Implement "wait for any" to wait for first finished task. 289 # TODO(vadimsh): Implement "wait for any" to wait for first finished task.
287 # TODO(vadimsh): Update |tasks| in-place with results of task execution. 290 # TODO(vadimsh): Update |tasks| in-place with results of task execution.
288 # TODO(vadimsh): Add timeouts. 291 # TODO(vadimsh): Add timeouts.
289 assert all(isinstance(t, SwarmingTask) for t in tasks) 292 assert all(isinstance(t, SwarmingTask) for t in tasks)
290 steps = [] 293 steps = []
291 for task in tasks: 294 for task in tasks:
292 assert task.task_id in self._pending_tasks, ( 295 assert task.task_id in self._pending_tasks, (
293 'Trying to collect a task that was not triggered: %s' % task.task_id) 296 'Trying to collect a task that was not triggered: %s' % task.task_id)
294 self._pending_tasks.remove(task.task_id) 297 self._pending_tasks.remove(task.task_id)
295 steps.append(task.collect_step_builder(task, followup_fn)) 298 steps.append(task.collect_step_builder(task, **kwargs))
296 return steps 299 return steps
297 300
298 def _default_collect_step(self, task, followup_fn): 301 def _default_collect_step(self, task, **kwargs):
299 """Produces a step that collects a result of an arbitrary task.""" 302 """Produces a step that collects a result of an arbitrary task."""
300 # Always wait for all tasks to finish even if some of them failed. 303 # By default wait for all tasks to finish even if some of them failed.
304 if 'always_run' not in kwargs:
M-A Ruel 2014/06/04 00:52:53 setdefault, everywhere
Vadim Sh. 2014/06/04 02:58:26 Done.
305 kwargs['always_run'] = True
301 return self.m.python( 306 return self.m.python(
302 name=self._get_step_name('swarming', task), 307 name=self._get_step_name('swarming', task),
303 script=self.m.swarming_client.path.join('swarming.py'), 308 script=self.m.swarming_client.path.join('swarming.py'),
304 args=self._get_collect_cmd_args(task), 309 args=self._get_collect_cmd_args(task),
305 always_run=True, 310 **kwargs)
306 followup_fn=followup_fn)
307 311
308 def _gtest_collect_step(self, merged_test_output, task, followup_fn): 312 def _gtest_collect_step(self, merged_test_output, task, **kwargs):
309 """Produces a step that collects and processes a result of gtest task.""" 313 """Produces a step that collects and processes a result of gtest task."""
314 # By default wait for all tasks to finish even if some of them failed.
315 if 'always_run' not in kwargs:
316 kwargs['always_run'] = True
317
310 # Shim script's own arguments. 318 # Shim script's own arguments.
311 args = [ 319 args = [
312 '--swarming-client-dir', self.m.swarming_client.path, 320 '--swarming-client-dir', self.m.swarming_client.path,
313 '--temp-root-dir', self.m.path['tmp_base'], 321 '--temp-root-dir', self.m.path['tmp_base'],
314 ] 322 ]
315 323
316 # Where to put combined summary to, consumed by recipes. Also emit 324 # Where to put combined summary to, consumed by recipes. Also emit
317 # test expectation only if |merged_test_output| is really used. 325 # test expectation only if |merged_test_output| is really used.
318 step_test_data = None 326 step_test_data = None
319 if merged_test_output: 327 if merged_test_output:
320 args.extend(['--merged-test-output', merged_test_output]) 328 args.extend(['--merged-test-output', merged_test_output])
321 step_test_data = lambda: self.m.json.test_api.canned_gtest_output(True) 329 step_test_data = lambda: self.m.json.test_api.canned_gtest_output(True)
322 330
323 # Arguments for actual 'collect' command. 331 # Arguments for actual 'collect' command.
324 args.append('--') 332 args.append('--')
325 args.extend(self._get_collect_cmd_args(task)) 333 args.extend(self._get_collect_cmd_args(task))
326 334
327 # Always wait for all tasks to finish even if some of them failed. Allow 335 # Always wait for all tasks to finish even if some of them failed. Allow
328 # collect_gtest_task.py to emit all necessary annotations itself. 336 # collect_gtest_task.py to emit all necessary annotations itself.
329 return self.m.python( 337 return self.m.python(
330 name=self._get_step_name('swarming', task), 338 name=self._get_step_name('swarming', task),
331 script=self.resource('collect_gtest_task.py'), 339 script=self.resource('collect_gtest_task.py'),
332 args=args, 340 args=args,
333 always_run=True,
334 allow_subannotations=True, 341 allow_subannotations=True,
335 followup_fn=followup_fn, 342 step_test_data=step_test_data,
336 step_test_data=step_test_data) 343 **kwargs)
337 344
338 def _get_step_name(self, prefix, task): 345 def _get_step_name(self, prefix, task):
339 """SwarmingTask -> name of a step of a waterfall. 346 """SwarmingTask -> name of a step of a waterfall.
340 347
341 Will take a task title (+ step name prefix) and optionally append 348 Will take a task title (+ step name prefix) and optionally append
342 OS dimension to it in case the task is triggered on OS that is different 349 OS dimension to it in case the task is triggered on OS that is different
343 from OS this recipe is running on. It shortens step names for the most 350 from OS this recipe is running on. It shortens step names for the most
344 common case of triggering a task on the same OS as one that recipe 351 common case of triggering a task on the same OS as one that recipe
345 is running on. 352 is running on.
346 353
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 isolated tests based on gtest. Swarming uses GTEST_SHARD_INDEX 404 isolated tests based on gtest. Swarming uses GTEST_SHARD_INDEX
398 and GTEST_TOTAL_SHARDS environment variables to tell the executable 405 and GTEST_TOTAL_SHARDS environment variables to tell the executable
399 what shard to run. 406 what shard to run.
400 builder: buildbot builder this task was triggered from. 407 builder: buildbot builder this task was triggered from.
401 build_number: build number of a build this task was triggered from. 408 build_number: build number of a build this task was triggered from.
402 profile: True to enable swarming profiling. 409 profile: True to enable swarming profiling.
403 suffix: string suffix to append to task ID. 410 suffix: string suffix to append to task ID.
404 extra_args: list of command line arguments to pass to isolated tasks. 411 extra_args: list of command line arguments to pass to isolated tasks.
405 collect_step_builder: callback that will be called to generate recipe step 412 collect_step_builder: callback that will be called to generate recipe step
406 that collects and processes results of task execution, signature is 413 that collects and processes results of task execution, signature is
407 collect_step_builder(task, followup_fn). 414 collect_step_builder(task, **step_kwargs).
408 """ 415 """
409 assert 'os' in dimensions 416 assert 'os' in dimensions
410 self.title = title 417 self.title = title
411 self.isolated_hash = isolated_hash 418 self.isolated_hash = isolated_hash
412 self.dimensions = dimensions.copy() 419 self.dimensions = dimensions.copy()
413 self.env = env.copy() 420 self.env = env.copy()
414 self.priority = priority 421 self.priority = priority
415 self.shards = shards 422 self.shards = shards
416 self.builder = builder 423 self.builder = builder
417 self.build_number = build_number 424 self.build_number = build_number
418 self.profile = profile 425 self.profile = profile
419 self.suffix = suffix 426 self.suffix = suffix
420 self.extra_args = tuple(extra_args or []) 427 self.extra_args = tuple(extra_args or [])
421 self.collect_step_builder = collect_step_builder 428 self.collect_step_builder = collect_step_builder
422 429
423 @property 430 @property
424 def task_id(self): 431 def task_id(self):
425 """ID of this task, derived from its other properties. 432 """ID of this task, derived from its other properties.
426 433
427 Task ID identifies what task is doing and what machine configuration it 434 Task ID identifies what task is doing and what machine configuration it
428 expects. It is used as a key in table of a cached results. If Swarming 435 expects. It is used as a key in table of a cached results. If Swarming
429 service figures out that a task with given ID has successfully finished 436 service figures out that a task with given ID has successfully finished
430 before, it will reuse the result right away, without even running 437 before, it will reuse the result right away, without even running
431 the task again. 438 the task again.
432 """ 439 """
433 return '%s/%s/%s/%s/%d%s' % ( 440 return '%s/%s/%s/%s/%d%s' % (
434 self.title, self.dimensions['os'], self.isolated_hash, 441 self.title, self.dimensions['os'], self.isolated_hash,
435 self.builder, self.build_number, self.suffix) 442 self.builder, self.build_number, self.suffix)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698