| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Build triggering via buildbucket.""" |
| 6 |
| 7 import json |
| 8 |
| 9 from twisted.internet import defer |
| 10 |
| 11 from . import client |
| 12 from . import common |
| 13 |
| 14 |
| 15 class TriggeringService(object): |
| 16 """Schedules new builds on buildbucket.""" |
| 17 |
| 18 def __init__(self, buildbucket_service): |
| 19 self.buildbucket_service = buildbucket_service |
| 20 |
| 21 @classmethod |
| 22 @defer.inlineCallbacks |
| 23 def create(cls, active_master): |
| 24 buildbucket_service = yield client.create_buildbucket_service(active_master) |
| 25 defer.returnValue(cls(active_master, buildbucket_service)) |
| 26 |
| 27 def start(self): |
| 28 self.buildbucket_service.start() |
| 29 |
| 30 def stop(self): |
| 31 self.buildbucket_service.stop() |
| 32 |
| 33 @staticmethod |
| 34 def get_buildset(build_def): |
| 35 tags = build_def.get('tags', []) |
| 36 PREFIX = 'buildset:' |
| 37 for t in tags: |
| 38 if t.startswith(PREFIX): |
| 39 return t[len(PREFIX):] |
| 40 return None |
| 41 |
| 42 @defer.inlineCallbacks |
| 43 def trigger( |
| 44 self, source_build, bucket_name, builder_name, properties, changes=None): |
| 45 """Schedules a build on buildbucket.""" |
| 46 info = source_build.getProperties().getProperty(common.INFO_PROPERTY) or {} |
| 47 build_def = info.get(common.BUILD_PROPERTY) or {} |
| 48 bucket_name = bucket_name or build_def.get('bucket') |
| 49 if not bucket_name: |
| 50 # This function should not be called in this case. |
| 51 raise common.Error( |
| 52 'Neither bucket_name is specified, nor the build is from buildbucket') |
| 53 |
| 54 tags = [] |
| 55 if build_def: |
| 56 tags.append('parent_build_id:%s' % build_def['id']) |
| 57 buildset = self.get_buildset(build_def) |
| 58 if buildset: |
| 59 tags.append('buildset:%s' % buildset) |
| 60 |
| 61 result = yield self.buildbucket_service.api.put(body={ |
| 62 'bucket': bucket_name, |
| 63 'tags': tags, |
| 64 'parameters_json': json.dumps({ |
| 65 'builder_name': builder_name, |
| 66 'properties': properties, |
| 67 'changes': changes or [], |
| 68 }), |
| 69 }) |
| 70 defer.returnValue(result) |
| 71 |
| 72 |
| 73 _master_triggering_service_map = {} |
| 74 |
| 75 |
| 76 def get_triggering_service(active_master): |
| 77 """Returns a TriggeringService instance for active_master as Deferred.""" |
| 78 d = _master_triggering_service_map.get(active_master) |
| 79 if not d: |
| 80 d = TriggeringService.create(active_master) |
| 81 def start(service): |
| 82 service.start() |
| 83 return service |
| 84 d.addCallback(start) |
| 85 _master_triggering_service_map[active_master] = d |
| 86 return d |
| 87 |
| 88 |
| 89 def change_from_change_spec(self, change): |
| 90 """Converts a change in change_spec format to buildbucket format. |
| 91 |
| 92 For more info on change_spec format, see |
| 93 master.chromium_step.AnnotationObserver.insertSourceStamp. |
| 94 |
| 95 Buildbucket change format is described in README.md. |
| 96 """ |
| 97 create_ts = None |
| 98 if 'when_timestamp' in change: |
| 99 # Convert from seconds to milliseconds since Unix Epoch. |
| 100 assert isinstance(change['when_timestamp'], (int, float)) |
| 101 create_ts = change['when_timestamp'] * 1000 |
| 102 |
| 103 return { |
| 104 'revision': change.get('revision'), |
| 105 'author': { |
| 106 # Assuming author is email. |
| 107 'email': change.get('author'), |
| 108 }, |
| 109 'create_ts': create_ts, |
| 110 'files': [{'path': f} for f in change.get('files', [])], |
| 111 'message': change.get('comments'), |
| 112 'branch': change.get('branch'), |
| 113 'url': change.get('revlink'), |
| 114 'project': change.get('project'), |
| 115 } |
| 116 |
| OLD | NEW |