# Copyright 2019 The LUCI Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load('@stdlib//internal/graph.star', 'graph')
load('@stdlib//internal/validate.star', 'validate')

load('@stdlib//internal/luci/common.star', 'keys', 'triggerer')


def gitiles_poller(
      name=None,
      bucket=None,
      repo=None,
      refs=None,
      refs_regexps=None,
      schedule=None,
      triggers=None,
  ):
  """Defines a gitiles poller which can trigger builders on git commits.

  It periodically examines the state of watched refs in the git repository. On
  each iteration it triggers builders if either:

    * A watched ref's tip has changed since the last iteration (e.g. a new
      commit landed on a ref). Each new detected commit results in a separate
      triggering request, so if for example 10 new commits landed on a ref since
      the last poll, 10 new triggering requests will be submitted to the
      builders triggered by this poller. How they are converted to actual builds
      depends on `triggering_policy` of a builder. For example, some builders
      may want to have one build per commit, others don't care and just want to
      test the latest commit. See core.builder(...) and scheduler.policy(...)
      for more details.

      *** note
      **Caveat**: When a large number of commits are pushed on the ref between
      iterations of the poller, only the most recent 50 commits will result in
      triggering requests. Everything older is silently ignored. This is a
      safeguard against mistaken or deliberate but unusual git push actions,
      which typically don't have intent of triggering a build for each such
      commit.
      ***

    * A ref belonging to the watched set has just been created. This produces
      a single triggering request.

  The watched ref set is defined via `refs` and `refs_regexps` fields. One is
  just a simple enumeration of refs, and another allows to use regular
  expressions to define what refs belong to the watched set. Both fields can
  be used at the same time. If neither is set, the gitiles_poller defaults to
  watching `refs/heads/master`.

  Args:
    name: name of the poller, to refer to it from other rules. Required.
    bucket: name of the bucket the poller belongs to. Required.
    repo: URL of a git repository to poll, starting with `https://`. Required.
    refs: a list of fully qualified refs to watch, e.g. `refs/heads/master` or
        `refs/tags/v1.2.3`.
    refs_regexps: a list of regular expressions that define the watched set of
        refs, e.g. `refs/heads/[^/]+` or `refs/branch-heads/\d+\.\d+`. The
        regular expression should have a literal prefix with at least two
        slashes present, e.g. `refs/release-\d+/foobar` is *not allowed*,
        because the literal prefix `refs/release-` contains only one slash. The
        regexp should not start with `^` or end with `$` as they will be added
        automatically.
    schedule: string with a schedule that describes when to run one iteration
        of the poller. See [Defining cron schedules](#schedules_doc) for the
        expected format of this field. Note that it is rare to use custom
        schedules for pollers. By default, the poller will run each 30 sec.
    triggers: names of builders to trigger whenever the poller detects a new git
        commit on any ref in the watched ref set.
  """
  name = validate.string('name', name)
  bucket = validate.string('bucket', bucket)

  refs = validate.list('refs', refs)
  for r in refs:
    validate.string('refs', r)

  refs_regexps = validate.list('refs_regexps', refs_regexps)
  for r in refs_regexps:
    validate.string('refs_regexps', r)

  if not refs and not refs_regexps:
    refs = ['refs/heads/master']

  # Node that carries the full definition of the poller.
  poller_key = keys.gitiles_poller(bucket, name)
  graph.add_node(poller_key, props = {
      'name': name,
      'bucket': bucket,
      'repo': validate.string('repo', repo, regexp=r'https://.+'),
      'refs': refs,
      'refs_regexps': refs_regexps,
      'schedule': validate.string('schedule', schedule, required=False),
  })
  graph.add_edge(keys.bucket(bucket), poller_key)

  # Setup nodes that indicate this poller can be referenced in 'triggered_by'
  # relations (either via its bucket-scoped name or via its global name).
  triggerer_key = triggerer.add(poller_key)

  # Link to builders triggered by this builder.
  for t in validate.list('triggers', triggers):
    graph.add_edge(
        parent = triggerer_key,
        child = keys.builder_ref(validate.string('triggers', t)),
        title = 'triggers',
    )
