def CancelBuilds(buildbucket_ids, buildbucket_client,
                 debug=True, config=None):
  """Cancel Buildbucket builds in a set.

  Args:
    buildbucket_ids: A list of build_ids (strings).
    buildbucket_client: Instance of buildbucket_lib.buildbucket_client.
    debug: Boolean indicating whether it's a dry run. Default to True.
    config: Instance of config_lib.BuildConfig. Config dict for the master
      build initiating the cancel. Optional.
  """
  if buildbucket_ids:
    logging.info('Canceling buildbucket_ids: %s', buildbucket_ids)
    if (not debug) and config:
      fields = {'build_type': config.build_type,
                'build_name': config.name}
      metrics.Counter(constants.MON_BB_CANCEL_BATCH_BUILDS_COUNT).increment(
          fields=fields)
    cancel_results = buildbucket_client.CancelBatchBuildsRequest(
        buildbucket_ids,
        dryrun=debug)
    result_map = buildbucket_lib.GetResultMap(cancel_results)
    for buildbucket_id, result in result_map.items():
      # Check for error messages
      if buildbucket_lib.GetNestedAttr(result, ['error']):
        # TODO(nxia): Get build url and log url in the warnings.
        logging.warning('Error cancelling build %s with reason: %s. '
                        'Please check the status of the build.',
                        buildbucket_id,
                        buildbucket_lib.GetErrorReason(result))
Пример #2
0
  def _PutConfigToBuildBucket(self, buildbucket_client, dryrun):
    """Put the tryjob request to buildbucket.

    Args:
      buildbucket_client: The buildbucket client instance.
      dryrun: bool controlling dryrun behavior.

    Returns:
      ScheduledBuild describing the scheduled build.

    Raises:
      RemoteRequestFailure.
    """
    request_body = self._GetRequestBody()
    content = buildbucket_client.PutBuildRequest(
        json.dumps(request_body), dryrun)

    if buildbucket_lib.GetNestedAttr(content, ['error']):
      raise RemoteRequestFailure(
          'buildbucket error.\nReason: %s\n Message: %s' %
          (buildbucket_lib.GetErrorReason(content),
           buildbucket_lib.GetErrorMessage(content)))

    buildbucket_id = buildbucket_lib.GetBuildId(content)
    url = TryJobUrl(buildbucket_id)
    created_ts = buildbucket_lib.GetBuildCreated_ts(content)

    result = ScheduledBuild(buildbucket_id, self.build_config, url, created_ts)

    logging.info(self.BUILDBUCKET_PUT_RESP_FORMAT, result)

    return result
    def testRetryBuildRequest(self):
        """Test RetryBuild."""
        buildbucket_id = '001'
        buildbucket_id_2 = '002'

        content = json.dumps({
            'build': {
                'status': 'SCHEDULED',
                'id': buildbucket_id_2,
                'retry_of': buildbucket_id
            }
        })

        self.mock_http.request.return_value = (self.success_response, content)
        result_content = self.client.RetryBuildRequest(buildbucket_id, False)
        self.assertEqual(buildbucket_lib.GetBuildId(result_content),
                         buildbucket_id_2)

        reason = 'BUILD_NOT_FOUND'
        message = 'Build 001 not found'
        content = json.dumps({'error': {'message': message, 'reason': reason}})

        self.mock_http.request.return_value = (self.success_response, content)
        result_content = self.client.RetryBuildRequest(buildbucket_id, False)
        self.assertEqual(buildbucket_lib.GetErrorReason(result_content),
                         reason)
        self.assertEqual(buildbucket_lib.GetErrorMessage(result_content),
                         message)

        # Test dryrun
        result_content = self.client.RetryBuildRequest(buildbucket_id, True)
        self.assertIsNone(result_content)
    def testCancelBatchBuildsRequest(self):
        """Test CancelBatchBuilds."""
        buildbucket_id_1 = 'test_buildbucket_id_1'
        buildbucket_id_2 = 'test_buildbucket_id_2'
        status = 'COMPLETED'
        result = 'CANCELED'
        error_reason = 'BUILD_IS_COMPLETED'
        content = json.dumps({
            'results': [{
                'build_id': buildbucket_id_1,
                'build': {
                    'status': status,
                    'result': result,
                }
            }, {
                'build_id': buildbucket_id_2,
                'error': {
                    'message': 'Cannot cancel a completed build',
                    'reason': error_reason,
                }
            }]
        })
        self.mock_http.request.return_value = (self.success_response, content)
        result_content = self.client.CancelBatchBuildsRequest(
            [buildbucket_id_1, buildbucket_id_2], False)

        result_map = buildbucket_lib.GetResultMap(result_content)
        self.assertIsNotNone(
            buildbucket_lib.GetNestedAttr(result_map[buildbucket_id_1],
                                          ['build']))
        self.assertIsNotNone(
            buildbucket_lib.GetNestedAttr(result_map[buildbucket_id_2],
                                          ['error']))
        self.assertEqual(
            buildbucket_lib.GetBuildStatus(result_map[buildbucket_id_1]),
            status)
        self.assertEqual(
            buildbucket_lib.GetErrorReason(result_map[buildbucket_id_2]),
            error_reason)

        # Test dryrun
        result_content_2 = self.client.CancelBatchBuildsRequest(
            [buildbucket_id_1, buildbucket_id_2], True)
        self.assertIsNone(result_content_2)
    def testGetNestedAttr(self):
        """Test GetNestedAttr."""
        buildbucket_id_1 = 'test_buildbucket_id_1'
        buildbucket_id_2 = 'test_buildbucket_id_2'
        content = {
            'kind':
            'kind',
            'etag':
            'etag',
            'builds': [{
                'bucket': 'master.chromiumios.tryserver',
                'status': 'COMPLETED',
                'id': buildbucket_id_1,
            }, {
                'bucket': 'master.chromiumios.tryserver',
                'status': 'COMPLETED',
                'id': buildbucket_id_2,
            }],
            'result': {
                'status': 'COMPLETED'
            }
        }

        etag = buildbucket_lib.GetNestedAttr(content, ['etag'],
                                             default='default_etag')
        self.assertEqual(etag, 'etag')

        status = buildbucket_lib.GetNestedAttr(content, ['result', 'status'])
        self.assertEqual('COMPLETED', status)

        test_attr = buildbucket_lib.GetNestedAttr(content, ['test_attr'],
                                                  default='default_test_attr')
        self.assertEqual(test_attr, 'default_test_attr')

        test_etag_attr = buildbucket_lib.GetNestedAttr(
            content, ['etag', 'test_attr'], default='default_etag_test_attr')
        self.assertEqual(test_etag_attr, 'default_etag_test_attr')

        build_ids = buildbucket_lib.ExtractBuildIds(
            buildbucket_lib.GetNestedAttr(content, ['builds'], default=[]))
        self.assertTrue(buildbucket_id_1 in build_ids
                        and buildbucket_id_2 in build_ids)

        build_ids = buildbucket_lib.GetBuildIds(content)
        self.assertTrue(buildbucket_id_1 in build_ids
                        and buildbucket_id_2 in build_ids)

        content = {
            'results': [{
                'build_id': buildbucket_id_1,
                'error': {
                    'message': 'Cannot cancel a completed build',
                    'reason': 'error_reason',
                }
            }]
        }
        results = buildbucket_lib.GetNestedAttr(content, ['results'],
                                                default=[])

        for r in results:
            reason = buildbucket_lib.GetErrorReason(r)
            self.assertEqual(reason, 'error_reason')