| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 """buildbucket module implements buildbucket-buildbot integration. | 5 """buildbucket module implements buildbucket-buildbot integration. |
| 6 | 6 |
| 7 The main entry point is buildbucket.setup() that accepts master configuration | 7 The main entry point is buildbucket.setup() that accepts master configuration |
| 8 dict with other buildbucket parameters and configures master to run builds | 8 dict with other buildbucket parameters and configures master to run builds |
| 9 scheduled on buildbucket service. | 9 scheduled on buildbucket service. |
| 10 | 10 |
| 11 Example: | 11 Example: |
| 12 buildbucket.setup( | 12 buildbucket.setup( |
| 13 c, # Configuration object. | 13 c, # Configuration object. |
| 14 ActiveMaster, | 14 ActiveMaster, |
| 15 buckets=['qo'], | 15 buckets=['qo'], |
| 16 ) | 16 ) |
| 17 | 17 |
| 18 """ | 18 """ |
| 19 | 19 |
| 20 import functools | 20 import functools |
| 21 import os | 21 import os |
| 22 import sys | 22 import sys |
| 23 | 23 |
| 24 from .common import Error | 24 from .common import Error |
| 25 from .integration import BuildBucketIntegrator, MAX_MAX_BUILDS | 25 from .integration import BuildBucketIntegrator, MAX_MAX_BUILDS |
| 26 from .poller import BuildBucketPoller | 26 from .poller import BuildBucketPoller |
| 27 from .status import BuildBucketStatus | 27 from .status import BuildBucketStatus |
| 28 from . import changestore |
| 28 from . import client | 29 from . import client |
| 29 from . import trigger | 30 from . import trigger |
| 30 | 31 |
| 31 | 32 |
| 32 NO_LEASE_LIMIT = sys.maxint | 33 NO_LEASE_LIMIT = sys.maxint |
| 33 | 34 |
| 34 | 35 |
| 35 def setup( | 36 def setup( |
| 36 config, active_master, buckets, build_params_hook=None, | 37 config, active_master, buckets, build_params_hook=None, |
| 37 poll_interval=10, buildbucket_hostname=None, max_lease_count=None, | 38 poll_interval=10, buildbucket_hostname=None, max_lease_count=None, |
| 38 verbose=None, dry_run=None): | 39 verbose=None, dry_run=None, unique_change_urls=False): |
| 39 """Configures a master to lease, schedule and update builds on buildbucket. | 40 """Configures a master to lease, schedule and update builds on buildbucket. |
| 40 | 41 |
| 41 Requires config to have 'mergeRequests' set to False. | 42 Requires config to have 'mergeRequests' set to False. |
| 42 | 43 |
| 43 Args: | 44 Args: |
| 44 config (dict): master configuration dict. | 45 config (dict): master configuration dict. |
| 45 active_master (config.Master.Base): master site config. | 46 active_master (config.Master.Base): master site config. |
| 46 buckets (list of str): a list of buckets to poll. | 47 buckets (list of str): a list of buckets to poll. |
| 47 build_params_hook: callable with arguments (params, build) that can modify | 48 build_params_hook: callable with arguments (params, build) that can modify |
| 48 parameters (and properties via parameters['properties']) before creating | 49 parameters (and properties via parameters['properties']) before creating |
| 49 a buildset during validation. | 50 a buildset during validation. |
| 50 params: dict name->value | 51 params: dict name->value |
| 51 build: dict describing a buildbucket build. | 52 build: dict describing a buildbucket build. |
| 52 | 53 |
| 53 If a ValueError is raised, the build will be marked as an | 54 If a ValueError is raised, the build will be marked as an |
| 54 INVALID_BUILD_DEFINITION failure and the error message will be propagated | 55 INVALID_BUILD_DEFINITION failure and the error message will be propagated |
| 55 to the BuildBucket status. | 56 to the BuildBucket status. |
| 56 poll_interval (int): frequency of polling, in seconds. Defaults to 10. | 57 poll_interval (int): frequency of polling, in seconds. Defaults to 10. |
| 57 buildbucket_hostname (str): if not None, override the default buildbucket | 58 buildbucket_hostname (str): if not None, override the default buildbucket |
| 58 service url. | 59 service url. |
| 59 max_lease_count (int): maximum number of builds that can be leased at a | 60 max_lease_count (int): maximum number of builds that can be leased at a |
| 60 time. Defaults to the number of connected slaves. | 61 time. Defaults to the number of connected slaves. |
| 61 verbose (bool): log more than usual. Defaults to False. | 62 verbose (bool): log more than usual. Defaults to False. |
| 62 dry_run (bool): whether to run buildbucket in a dry-run mode. | 63 dry_run (bool): whether to run buildbucket in a dry-run mode. |
| 64 unique_change_urls (bool): if True, change URLs in builds are treated as |
| 65 change identifiers. This is True on waterfalls and typically False on |
| 66 tryservers. |
| 63 | 67 |
| 64 Raises: | 68 Raises: |
| 65 buildbucket.Error if config['mergeRequests'] is not False. | 69 buildbucket.Error if config['mergeRequests'] is not False. |
| 66 """ | 70 """ |
| 67 assert isinstance(config, dict), 'config must be a dict' | 71 assert isinstance(config, dict), 'config must be a dict' |
| 68 assert active_master | 72 assert active_master |
| 69 assert active_master.service_account_path, 'Service account is not assigned' | 73 assert active_master.service_account_path, 'Service account is not assigned' |
| 70 assert buckets, 'Buckets are not specified' | 74 assert buckets, 'Buckets are not specified' |
| 71 assert isinstance(buckets, list), 'Buckets must be a list' | 75 assert isinstance(buckets, list), 'Buckets must be a list' |
| 72 assert all(isinstance(b, basestring) for b in buckets), ( | 76 assert all(isinstance(b, basestring) for b in buckets), ( |
| 73 'all buckets must be strings') | 77 'all buckets must be strings') |
| 74 | 78 |
| 75 if dry_run is None: | 79 if dry_run is None: |
| 76 dry_run = 'POLLER_DRY_RUN' in os.environ | 80 dry_run = 'POLLER_DRY_RUN' in os.environ |
| 77 | 81 |
| 78 integrator = BuildBucketIntegrator( | 82 integrator = BuildBucketIntegrator( |
| 79 buckets, build_params_hook=build_params_hook, | 83 buckets, build_params_hook=build_params_hook, |
| 80 max_lease_count=max_lease_count) | 84 max_lease_count=max_lease_count, |
| 85 change_store_factory=lambda bb: changestore.ChangeStore( |
| 86 bb, unique_urls=unique_change_urls)) |
| 81 | 87 |
| 82 buildbucket_service = client.create_buildbucket_service( | 88 buildbucket_service = client.create_buildbucket_service( |
| 83 active_master, buildbucket_hostname, verbose) | 89 active_master, buildbucket_hostname, verbose) |
| 84 | 90 |
| 85 poller = BuildBucketPoller( | 91 poller = BuildBucketPoller( |
| 86 integrator=integrator, | 92 integrator=integrator, |
| 87 poll_interval=poll_interval, | 93 poll_interval=poll_interval, |
| 88 dry_run=dry_run) | 94 dry_run=dry_run) |
| 89 status = BuildBucketStatus( | 95 status = BuildBucketStatus( |
| 90 integrator, | 96 integrator, |
| 91 buildbucket_service, | 97 buildbucket_service, |
| 92 dry_run=dry_run) | 98 dry_run=dry_run) |
| 93 config.setdefault('change_source', []).append(poller) | 99 config.setdefault('change_source', []).append(poller) |
| 94 config.setdefault('status', []).append(status) | 100 config.setdefault('status', []).append(status) |
| OLD | NEW |