# Copyright 2023 The Pigweed 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
#
#     https://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.
"""Retrigger builds where the latest build failed.

If the most recent build of a builder failed, retrigger it. Exceptions:

* A build of the builder is currently scheduled or started (e.g., about to run,
  or already running)
* No recent builds of the builder passed (e.g., this is a true failure and not
  a flake)

This will allow other tooling to check the latest build in ci and evaluate
whether it's passing. There are three cases: it's passing, it's failing because
of a flake, and it's failing because it's broken. This should reduce the impact
of the second case because the builder will be retried several times, until
there's a passing build, or there are 10 failing builds in a row.

Tools should check to see if any of the most recent 10 builds passed, and if so
assume the builder is passing. If the builder is broken, the passing build will
be bumped from the 10 most recent builds before long.
"""

import collections
import fnmatch
from typing import Sequence, Tuple

from PB.recipe_engine import result as result_pb2
from PB.go.chromium.org.luci.buildbucket.proto import (
    build as build_pb2,
    builds_service as builds_service_pb2,
    common as common_pb2,
    project_config as bb_pb2,
)
from PB.go.chromium.org.luci.scheduler.appengine.messages import (
    config as scheduler_pb2,
)
from PB.recipes.pigweed.rerunner import InputProperties
from PB.recipe_engine import result
from recipe_engine import post_process, recipe_api

DEPS = [
    'fuchsia/builder_status',
    'fuchsia/luci_config',
    'recipe_engine/buildbucket',
    'recipe_engine/properties',
    'recipe_engine/scheduler',
    'recipe_engine/step',
    'recipe_engine/time',
]

PROPERTIES = InputProperties


def include_bucket(props: InputProperties, bucket: str) -> bool:
    if not props.excluded_buckets and not props.included_buckets:
        props.included_buckets.append('*.ci')
        props.included_buckets.append('ci')

    for excluded_bucket in props.excluded_buckets:
        if fnmatch.fnmatch(bucket, excluded_bucket):
            return False

    for included_bucket in props.included_buckets:
        if fnmatch.fnmatch(bucket, included_bucket):
            return True

    return False


def RunSteps(api: recipe_api.RecipeApi, props: InputProperties):
    bb_cfg: bb_pb2.BuildbucketCfg = api.luci_config.buildbucket()

    builds_to_launch: list[tuple[str, str]] = []

    for bucket in bb_cfg.buckets:
        if not include_bucket(props, bucket.name):
            api.step(
                f'excluding {len(bucket.swarming.builders)} builders in '
                f'bucket {bucket.name}',
                None,
            )
            continue

        with api.step.nest(bucket.name):
            for builder in bucket.swarming.builders:
                num_builds: int = props.num_builds or 10

                with api.step.nest(builder.name):
                    # Don't DoS buildbucket. (And there's no need for this
                    # builder to run quickly.)
                    api.time.sleep(1)

                    status: BuilderStatus = api.builder_status.retrieve(
                        bucket=bucket.name, builder=builder.name, n=num_builds
                    )

                    # If the builder is currently running, don't start a new
                    # build.
                    if api.builder_status.is_incomplete(status):
                        api.step('is incomplete', None)
                        continue

                    # If the builder is currently passing, don't start a new
                    # build.
                    if api.builder_status.is_passing(status):
                        api.step('is passing', None)
                        continue

                    # If the builder hasn't recently passed, this probably isn't
                    # a flake and we should not start a new build.
                    if not api.builder_status.has_recently_passed(status):
                        api.step('no recent passes', None)
                        continue

                    api.step('scheduling', None)

                    builds_to_launch.append((bucket.name, builder.name))

    if not builds_to_launch:
        api.step('nothing to launch', None)
        return result_pb2.RawResult(
            summary_markdown='nothing to launch', status=common_pb2.SUCCESS,
        )

    sched_cfg: scheduler_pb2.ProjectConfig = api.luci_config.scheduler()
    jobs: dict[str, list[str]] = collections.defaultdict(list)
    for job in sched_cfg.job:
        bucket_builder = (job.buildbucket.bucket, job.buildbucket.builder)
        jobs[bucket_builder].append(job.id)

    bb_requests: list[builds_service_pb2.ScheduleBuildRequest] = []
    sched_ids: list[str] = []

    for bucket_builder in builds_to_launch:
        if bucket_builder in jobs and len(jobs[bucket_builder]) == 1:
            sched_ids.append(jobs[bucket_builder][0])

        else:
            bb_requests.append(
                api.buildbucket.schedule_request(
                    bucket=bucket_builder[0], builder=bucket_builder[1],
                )
            )

    def scheduler_link(job_id):
        project: str = api.buildbucket.build.builder.project
        return f'https://luci-scheduler.appspot.com/jobs/{project}/{job_id}'

    if props.dry_run:
        with api.step.nest('dry-run, not launching builds'):
            links: list[tuple[str, str]] = [
                (x, scheduler_link(x)) for x in sched_ids
            ]

            for req in bb_requests:
                bucket_builder: str = (
                    f'{req.builder.bucket}/{req.builder.builder}'
                )
                api.step(bucket_builder, None)
                links.append(
                    (
                        bucket_builder,
                        f'https://ci.chromium.org/ui/p/{req.builder.project}/'
                        f'builders/{bucket_builder}',
                    )
                )

        links_combined: str = ''.join(
            f'<br/>[{name}]({link})' for name, link in links
        )

        return result_pb2.RawResult(
            summary_markdown=f'dry-run, would have launched: {links_combined}',
            status=common_pb2.SUCCESS,
        )

    with api.step.nest('launch') as pres:
        links: list[tuple[str, str]] = []

        if sched_ids:
            api.scheduler.emit_trigger(
                api.scheduler.BuildbucketTrigger(),
                api.buildbucket.build.builder.project,
                sched_ids,
            )
            links.extend((x, scheduler_link(x)) for x in sched_ids)

        if bb_requests:
            builds: list[build_pb2.Build] = api.buildbucket.schedule(
                bb_requests
            )
            for build in builds:
                bucket_builder: str = (
                    f'{build.builder.bucket}/{build.builder.builder}'
                )
                link: str = api.buildbucket.build_url(build_id=build.id)
                pres.links[bucket_builder] = link
                links.append((bucket_builder, link))

        links_combined: str = ''.join(
            f'<br/>[{name}]({link})' for name, link in links
        )

        return result_pb2.RawResult(
            summary_markdown=f'launched: {links_combined}',
            status=common_pb2.SUCCESS,
        )


def GenTests(api):  # pylint: disable=invalid-name
    def properties(
        *,
        included_buckets: Sequence[str] = (),
        excluded_buckets: Sequence[str] = (),
        dry_run: bool = False,
    ):
        props = InputProperties(dry_run=dry_run)
        props.included_buckets.extend(included_buckets)
        props.excluded_buckets.extend(excluded_buckets)
        return api.properties(props)

    def test(name):
        return api.test(name) + api.buildbucket.ci_build(project='pigweed')

    def buildbucket_config(buckets: bb_pb2.Bucket):
        cfg = bb_pb2.BuildbucketCfg()
        cfg.buckets.extend(buckets)
        return cfg

    def bucket_config(
        name: str, builders: Sequence[bb_pb2.BuilderConfig],
    ):
        cfg = bb_pb2.Bucket(name=name)
        cfg.swarming.builders.extend(builders)
        return cfg

    def builder_config(name: str):
        return bb_pb2.BuilderConfig(name=name)

    def mock_buildbucket_config(
        *buckets_builders: Sequence[Tuple[str, Sequence[str]]],
    ):
        buckets: List[bb_pb2.Bucket] = []
        for bucket_name, builder_names in buckets_builders:
            builders: List[bb_pb2.BuilderConfig] = []
            for builder in builder_names:
                builders.append(builder_config(builder))
            buckets.append(bucket_config(bucket_name, builders))
        return api.luci_config.mock_config(
            project='pigweed',
            config_name='cr-buildbucket.cfg',
            data=buildbucket_config(buckets),
        )

    def mock_scheduler_config(
        *buckets_builders: Sequence[Tuple[str, Sequence[str]]],
    ):
        cfg = scheduler_pb2.ProjectConfig()
        for bucket_name, builder_names in buckets_builders:
            for builder_name in builder_names:
                cfg.job.append(
                    scheduler_pb2.Job(
                        id=f'{bucket_name}-{builder_name}',
                        buildbucket=scheduler_pb2.BuildbucketTask(
                            bucket=bucket_name, builder=builder_name,
                        ),
                    )
                )
        return api.luci_config.mock_config(
            project='pigweed', config_name='luci-scheduler.cfg', data=cfg,
        )

    def excluding(bucket, num):
        return api.post_process(
            post_process.MustRun,
            f'excluding {num} builders in bucket {bucket}',
        )

    def including(bucket):
        return api.post_process(post_process.MustRun, bucket)

    def build_status(*statuses: str, prefix: str = ''):
        step_name = None
        if prefix:
            step_name = f'{prefix}.buildbucket.search'
        return api.buildbucket.simulated_search_results(
            [getattr(api.builder_status, x)() for x in statuses],
            step_name=step_name,
        )

    def assert_skip_is_incomplete(prefix):
        return api.post_process(post_process.MustRun, f'{prefix}.is incomplete')

    def assert_skip_is_passing(prefix):
        return api.post_process(post_process.MustRun, f'{prefix}.is passing')

    def assert_skip_no_recent_passes(prefix):
        return api.post_process(
            post_process.MustRun, f'{prefix}.no recent passes',
        )

    def assert_scheduling(prefix):
        return api.post_process(post_process.MustRun, f'{prefix}.scheduling')

    def assert_buildbucket_scheduled():
        return api.post_process(
            post_process.MustRun, f'launch.buildbucket.schedule',
        )

    def assert_scheduler_triggered():
        return api.post_process(
            post_process.MustRun, 'launch.luci-scheduler.EmitTriggers',
        )

    def assert_nothing_to_launch():
        return api.post_process(post_process.MustRun, f'nothing to launch',)

    def assert_dry_run():
        return api.post_process(
            post_process.MustRun, f'dry-run, not launching builds',
        )

    def drop_expectations_must_be_last():
        # No need for expectation files, everything of note here is tested by
        # assertions. This must be the last thing added to the test.
        return api.post_process(post_process.DropExpectation)

    yield (
        test('default-ci-only')
        + mock_buildbucket_config(('try', ('foo', 'bar', 'baz')))
        + excluding('try', 3)
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('ci-only')
        + properties(included_buckets=("*.ci", "ci"))
        + mock_buildbucket_config(('try', ('foo', 'bar', 'baz')))
        + excluding('try', 3)
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('ignore-abc')
        + properties(
            included_buckets=("*.ci", "ci"), excluded_buckets=("abc.*"),
        )
        + mock_buildbucket_config(('abc.ci', ('foo', 'bar', 'baz')))
        + excluding('abc.ci', 3)
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('scheduled')
        + mock_buildbucket_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('scheduled', prefix='abc.ci.foo')
        + assert_skip_is_incomplete('abc.ci.foo')
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('running')
        + mock_buildbucket_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('running', prefix='abc.ci.foo')
        + assert_skip_is_incomplete('abc.ci.foo')
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('passed')
        + mock_buildbucket_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('passed', prefix='abc.ci.foo')
        + assert_skip_is_passing('abc.ci.foo')
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('no_recent_passes')
        + mock_buildbucket_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('failure', 'failure', 'failure', prefix='abc.ci.foo')
        + assert_skip_no_recent_passes('abc.ci.foo')
        + assert_nothing_to_launch()
        + drop_expectations_must_be_last()
    )

    yield (
        test('recent_passes')
        + mock_buildbucket_config(('abc.ci', ('foo', 'bar')))
        + mock_scheduler_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('failure', 'failure', 'passed', prefix='abc.ci.foo')
        + build_status('failure', 'failure', 'passed', prefix='abc.ci.bar')
        + assert_scheduling('abc.ci.foo')
        + assert_scheduling('abc.ci.bar')
        + assert_buildbucket_scheduled()
        + assert_scheduler_triggered()
        + drop_expectations_must_be_last()
    )

    yield (
        test('dry_run')
        + properties(dry_run=True)
        + mock_buildbucket_config(('abc.ci', ('foo', 'bar')))
        + mock_scheduler_config(('abc.ci', ('foo',)))
        + including('abc.ci')
        + build_status('failure', 'failure', 'passed', prefix='abc.ci.foo')
        + build_status('failure', 'failure', 'passed', prefix='abc.ci.bar')
        + assert_scheduling('abc.ci.foo')
        + assert_scheduling('abc.ci.bar')
        + assert_dry_run()
        + drop_expectations_must_be_last()
    )
