OLD | NEW |
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 recipe module allows triggering builds within the same master. | 5 """This recipe module allows triggering builds within the same master. |
6 | 6 |
7 Example: | 7 Example: |
8 api.trigger({ | 8 api.trigger({ |
9 'buildername': 'My Builder', | 9 'buildername': 'My Builder', |
10 'another_property': 'value', | 10 'another_property': 'value', |
11 }) | 11 }) |
12 | 12 |
13 # This triggers a new build on "My Builder" builder with "another_property" | 13 # This triggers a new build on "My Builder" builder with "another_property" |
14 property set to "value". | 14 property set to "value". |
15 | 15 |
16 You can trigger multiple builds in one steps: | 16 You can trigger multiple builds in one steps: |
17 api.trigger({'buildername': 'Release'}, {'buildername': 'Debug'}) | 17 api.trigger({'buildername': 'Release'}, {'buildername': 'Debug'}) |
18 """ | 18 """ |
19 | 19 |
20 from slave import recipe_api | 20 from slave import recipe_api |
21 | 21 |
22 | 22 |
23 class TriggerApi(recipe_api.RecipeApi): | 23 class TriggerApi(recipe_api.RecipeApi): |
24 """APIs for triggering new builds.""" | 24 """APIs for triggering new builds.""" |
25 | 25 |
26 def __init__(self, **kwargs): | 26 def __init__(self, **kwargs): |
27 super(TriggerApi, self).__init__(**kwargs) | 27 super(TriggerApi, self).__init__(**kwargs) |
28 | 28 |
29 def __call__(self, *propertiesList, **kwargs): | 29 def _port_from_properties_only(self, trigger_spec): |
| 30 """Convert from previous "properties-only" mode to trigger spec.""" |
| 31 builder_name = trigger_spec.get('buildername') |
| 32 if not builder_name: |
| 33 return trigger_spec |
| 34 |
| 35 props = trigger_spec.copy() |
| 36 del props['buildername'] |
| 37 return { |
| 38 'builder_name': builder_name, |
| 39 'properties': props, |
| 40 } |
| 41 |
| 42 def __call__(self, *trigger_specs, **kwargs): |
30 """Triggers new builds by builder names. | 43 """Triggers new builds by builder names. |
31 | 44 |
32 Args: | 45 Args: |
33 propertiesList: a list of build property dicts for the builds to | 46 trigger_specs: a list of trigger dicts, where each dict specifies a build |
34 trigger. Each dict triggers a build. See "Known properties" below. | 47 to trigger. Supported keys: |
35 name: (in kwargs) name of the step. If not specified, it is generated | 48 builder_name (str): in BuildBot context, builder name |
36 automatically, its format may change in future. | 49 properties (dict): build properties for a new build. |
| 50 buildbot_changes (list of dict): list of Buildbot changes to create. |
| 51 See below. |
| 52 name: name of the step. If not specified, it is generated |
| 53 automatically. Its format may change in future. |
37 | 54 |
38 Known properties: | 55 Buildbot changes: |
39 buildername (str): Buildbot-specific, required in Buildbot environment. | 56 buildbot_changes (a list of dicts) is a list of changes for the |
40 buildbot.changes (a list of dicts): Buildbot-specific, changes for the | 57 triggered builds. Each change is a dict with keys (all optional): |
41 triggered builds. Each change is a dict with keys (all optional): | 58 author (str) |
42 author (str) | 59 revision |
43 revision | 60 revlink (str): link to a web view of the revision. |
44 revlink (str): link to a web view of the revision. | 61 comment |
45 comment | 62 when_timestamp (int): timestamp of the change, in seconds since Unix |
46 when_timestamp (int): timestamp of the change, in seconds since Unix | 63 Epoch. |
47 Epoch. | 64 branch |
48 branch | 65 category (str): Buildbot change category |
49 category (str): Buildbot change category | 66 files (list of str): list of changed filenames |
50 files (list of str): list of changed filenames | 67 The first change is used to populate source stamp properties. |
51 The first change is used to populate source stamp properties. | |
52 | 68 |
53 Examples: | 69 Examples: |
| 70 Basic: |
| 71 api.trigger({ |
| 72 'builder_name': 'Release', |
| 73 'properties': { |
| 74 'my_prop': 123, |
| 75 }, |
| 76 }) |
| 77 |
54 Create Buildbot changes: | 78 Create Buildbot changes: |
55 api.trigger({ | 79 api.trigger({ |
56 'builderName': 'Release', | 80 'builder_name': 'Release', |
57 'my_prop': 123, | 81 'buildbot_changes': [{ |
58 'buildbot.changes': [{ | |
59 'author': 'someone@chromium.org', | 82 'author': 'someone@chromium.org', |
60 'branch': 'master', | 83 'branch': 'master', |
61 'files': ['a.txt.'], | 84 'files': ['a.txt.'], |
62 'comments': 'Refactoring', | 85 'comments': 'Refactoring', |
63 'revision': 'deadbeef', | 86 'revision': 'deadbeef', |
64 'revlink': | 87 'revlink': |
65 'http://chromium.googlesource.com/chromium/src/+/deadbeef', | 88 'http://chromium.googlesource.com/chromium/src/+/deadbeef', |
66 'when_timestamp': 1416859562, | 89 'when_timestamp': 1416859562, |
67 }] | 90 }] |
68 }) | 91 }) |
69 """ | 92 """ |
70 builder_names = [] | 93 # Backward-compatibility: |
71 for properties in propertiesList: | 94 trigger_specs = map(self._port_from_properties_only, trigger_specs) |
72 assert isinstance(properties, dict), ('properties must be a dict: %s' | |
73 % (properties,)) | |
74 builder_name = properties.get('buildername') | |
75 assert builder_name, 'buildername property is missing: %s' % (properties,) | |
76 if builder_name not in builder_names: | |
77 builder_names.append(builder_name) | |
78 | 95 |
79 name = kwargs.get('name') or ('trigger %s' % ', '.join(builder_names)) | 96 builder_names = set() |
80 trigger_specs = [ | 97 for trigger in trigger_specs: |
81 { | 98 assert isinstance(trigger, dict), ('trigger spec must be a dict: %s' |
82 'properties': properties, | 99 % (trigger,)) |
83 } for properties in propertiesList | 100 builder_name = trigger.get('builder_name') |
84 ] | 101 assert builder_name, 'builder_name is missing: %s' % (trigger,) |
| 102 builder_names.add(builder_name) |
| 103 |
| 104 name = ( |
| 105 kwargs.get('name') or ('trigger %s' % ', '.join(sorted(builder_names)))) |
85 return self.m.step( | 106 return self.m.step( |
86 name, | 107 name, |
87 cmd=[], | 108 cmd=[], |
88 trigger_specs=trigger_specs, | 109 trigger_specs=trigger_specs, |
89 ) | 110 ) |
OLD | NEW |