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

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: rebase 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
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
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 kwargs.setdefault('always_run', True)
301 return self.m.python( 305 return self.m.python(
302 name=self._get_step_name('swarming', task), 306 name=self._get_step_name('swarming', task),
303 script=self.m.swarming_client.path.join('swarming.py'), 307 script=self.m.swarming_client.path.join('swarming.py'),
304 args=self._get_collect_cmd_args(task), 308 args=self._get_collect_cmd_args(task),
305 always_run=True, 309 **kwargs)
306 followup_fn=followup_fn)
307 310
308 def _gtest_collect_step(self, merged_test_output, task, followup_fn): 311 def _gtest_collect_step(self, merged_test_output, task, **kwargs):
309 """Produces a step that collects and processes a result of gtest task.""" 312 """Produces a step that collects and processes a result of gtest task."""
313 # By default wait for all tasks to finish even if some of them failed.
314 kwargs.setdefault('always_run', True)
315
310 # Shim script's own arguments. 316 # Shim script's own arguments.
311 args = [ 317 args = [
312 '--swarming-client-dir', self.m.swarming_client.path, 318 '--swarming-client-dir', self.m.swarming_client.path,
313 '--temp-root-dir', self.m.path['tmp_base'], 319 '--temp-root-dir', self.m.path['tmp_base'],
314 ] 320 ]
315 321
316 # Where to put combined summary to, consumed by recipes. Also emit 322 # Where to put combined summary to, consumed by recipes. Also emit
317 # test expectation only if |merged_test_output| is really used. 323 # test expectation only if |merged_test_output| is really used.
318 step_test_data = None 324 step_test_data = None
319 if merged_test_output: 325 if merged_test_output:
320 args.extend(['--merged-test-output', merged_test_output]) 326 args.extend(['--merged-test-output', merged_test_output])
321 step_test_data = lambda: self.m.json.test_api.canned_gtest_output(True) 327 step_test_data = lambda: self.m.json.test_api.canned_gtest_output(True)
322 328
323 # Arguments for actual 'collect' command. 329 # Arguments for actual 'collect' command.
324 args.append('--') 330 args.append('--')
325 args.extend(self._get_collect_cmd_args(task)) 331 args.extend(self._get_collect_cmd_args(task))
326 332
327 # Always wait for all tasks to finish even if some of them failed. Allow 333 # 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. 334 # collect_gtest_task.py to emit all necessary annotations itself.
329 return self.m.python( 335 return self.m.python(
330 name=self._get_step_name('swarming', task), 336 name=self._get_step_name('swarming', task),
331 script=self.resource('collect_gtest_task.py'), 337 script=self.resource('collect_gtest_task.py'),
332 args=args, 338 args=args,
333 always_run=True,
334 allow_subannotations=True, 339 allow_subannotations=True,
335 followup_fn=followup_fn, 340 step_test_data=step_test_data,
336 step_test_data=step_test_data) 341 **kwargs)
337 342
338 def _get_step_name(self, prefix, task): 343 def _get_step_name(self, prefix, task):
339 """SwarmingTask -> name of a step of a waterfall. 344 """SwarmingTask -> name of a step of a waterfall.
340 345
341 Will take a task title (+ step name prefix) and optionally append 346 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 347 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 348 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 349 common case of triggering a task on the same OS as one that recipe
345 is running on. 350 is running on.
346 351
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 isolated tests based on gtest. Swarming uses GTEST_SHARD_INDEX 402 isolated tests based on gtest. Swarming uses GTEST_SHARD_INDEX
398 and GTEST_TOTAL_SHARDS environment variables to tell the executable 403 and GTEST_TOTAL_SHARDS environment variables to tell the executable
399 what shard to run. 404 what shard to run.
400 builder: buildbot builder this task was triggered from. 405 builder: buildbot builder this task was triggered from.
401 build_number: build number of a build this task was triggered from. 406 build_number: build number of a build this task was triggered from.
402 profile: True to enable swarming profiling. 407 profile: True to enable swarming profiling.
403 suffix: string suffix to append to task ID. 408 suffix: string suffix to append to task ID.
404 extra_args: list of command line arguments to pass to isolated tasks. 409 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 410 collect_step_builder: callback that will be called to generate recipe step
406 that collects and processes results of task execution, signature is 411 that collects and processes results of task execution, signature is
407 collect_step_builder(task, followup_fn). 412 collect_step_builder(task, **step_kwargs).
408 """ 413 """
409 assert 'os' in dimensions 414 assert 'os' in dimensions
410 self.title = title 415 self.title = title
411 self.isolated_hash = isolated_hash 416 self.isolated_hash = isolated_hash
412 self.dimensions = dimensions.copy() 417 self.dimensions = dimensions.copy()
413 self.env = env.copy() 418 self.env = env.copy()
414 self.priority = priority 419 self.priority = priority
415 self.shards = shards 420 self.shards = shards
416 self.builder = builder 421 self.builder = builder
417 self.build_number = build_number 422 self.build_number = build_number
418 self.profile = profile 423 self.profile = profile
419 self.suffix = suffix 424 self.suffix = suffix
420 self.extra_args = tuple(extra_args or []) 425 self.extra_args = tuple(extra_args or [])
421 self.collect_step_builder = collect_step_builder 426 self.collect_step_builder = collect_step_builder
422 427
423 @property 428 @property
424 def task_id(self): 429 def task_id(self):
425 """ID of this task, derived from its other properties. 430 """ID of this task, derived from its other properties.
426 431
427 Task ID identifies what task is doing and what machine configuration it 432 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 433 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 434 service figures out that a task with given ID has successfully finished
430 before, it will reuse the result right away, without even running 435 before, it will reuse the result right away, without even running
431 the task again. 436 the task again.
432 """ 437 """
433 return '%s/%s/%s/%s/%d%s' % ( 438 return '%s/%s/%s/%s/%d%s' % (
434 self.title, self.dimensions['os'], self.isolated_hash, 439 self.title, self.dimensions['os'], self.isolated_hash,
435 self.builder, self.build_number, self.suffix) 440 self.builder, self.build_number, self.suffix)
OLDNEW
« no previous file with comments | « scripts/slave/recipe_modules/isolate/test_api.py ('k') | scripts/slave/recipe_modules/test_utils/api.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698