# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This recipe module allows triggering builds within the same master.

See README.md.
"""

from recipe_engine import recipe_api


class TriggerApi(recipe_api.RecipeApi):
  """APIs for triggering new builds."""

  def __init__(self, **kwargs):
    super(TriggerApi, self).__init__(**kwargs)

  def _port_from_properties_only(self, trigger_spec):
    """Convert from previous "properties-only" mode to trigger spec."""
    builder_name = trigger_spec.get('buildername')
    if not builder_name:
      return trigger_spec

    props = trigger_spec.copy()
    del props['buildername']
    return {
        'builder_name': builder_name,
        'properties': props,
    }

  def __call__(self, *trigger_specs, **kwargs):
    """Triggers new builds by builder names.

    Args:
      trigger_specs: a list of trigger dicts, where each dict specifies a build
        to trigger. Supported keys:
          builder_name (str): in BuildBot context, builder name
          bucket (str): buildbucket bucket where the triggered builds will be
            placed.
          critical (bool): if True (default) and triggering fails on the
            buildbot master side, mark entire build as failed (exception).
          properties (dict): build properties for a new build.
          buildbot_changes (list of dict): list of Buildbot changes to create.
            See below.
          tags (dict or list of str): if the trigger build is scheduled through
            buildbucket, |tags| will be appended to the buildbucket build.
      name: name of the step. If not specified, it is generated
        automatically. Its format may change in future.

    Buildbot changes:
      buildbot_changes (a list of dicts) is a list of changes for the
      triggered builds. Each change is a dict with keys (all optional):
        author (str)
        revision
        revlink (str): link to a web view of the revision.
        comment
        when_timestamp (int): timestamp of the change, in seconds since Unix
          Epoch.
        branch
        category (str): Buildbot change category
        files (list of str): list of changed filenames
      The first change is used to populate source stamp properties.

    Examples:
      Basic:
        api.trigger({
            'builder_name': 'Release',
            'properties': {
                'my_prop': 123,
            },
        })

      Using BuildBucket:
        api.trigger({
            'builder_name': 'Release',
            'bucket': 'master.tryserver.chromium.linux',
            'properties': {
                'my_prop': 123,
            },
        })
      WARNING: on buildbot, this requires certain configuration on the
      master prior first use. See ./README.md.

      Create Buildbot changes:
        api.trigger({
            'builder_name': 'Release',
            'buildbot_changes': [{
                'author': 'someone@chromium.org',
                'branch': 'master',
                'files': ['a.txt.'],
                'comments': 'Refactoring',
                'revision': 'deadbeef',
                'revlink':
                  'http://chromium.googlesource.com/chromium/src/+/deadbeef',
                'when_timestamp': 1416859562,
            }]
        })
    """
    # Backward-compatibility:
    trigger_specs = map(self._port_from_properties_only, trigger_specs)

    builder_names = set()
    for trigger in trigger_specs:
      assert isinstance(trigger, dict), ('trigger spec must be a dict: %s'
                                          % (trigger,))
      builder_name = trigger.get('builder_name')
      assert builder_name, 'builder_name is missing: %s' % (trigger,)
      builder_names.add(builder_name)

      tags = trigger.get('tags', [])
      # Convert dict tags
      if isinstance(tags, dict):
        tags = ['%s:%s' % item for item in tags.iteritems()]
        trigger['tags'] = tags

      # Validate tags.
      for t in tags:
        assert isinstance(t, basestring), t
        assert len(t) >= 3 and ':' in t, t
        key, value = t.split(':', 1)
        assert key
        assert value
        assert key != 'buildset', 'buildset tag is reserved'
        assert key != 'parent_build_id', 'parent_build_id tag is reserved'

    result = self.m.step(
        kwargs.get('name', 'trigger'),
        cmd=[],
        trigger_specs=trigger_specs,
    )
    if 'name' not in kwargs:
      result.presentation.step_text = "<br />".join(sorted(builder_names))
    return result
