# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for testing LUCI configs."""

import re

from recipe_engine import post_process

from PB.go.chromium.org.luci.buildbucket.proto import (
    builder_common as builder_common_pb2,
    project_config as project_config_pb2,
)
from PB.go.chromium.org.luci.cv.api.config.v2 import config as cv_config_pb2
from PB.recipes.fuchsia.luci_config import InputProperties

DEPS = [
    "fuchsia/buildbucket_util",
    "fuchsia/git_checkout",
    "fuchsia/luci_config",
    "fuchsia/sso",
    "recipe_engine/cipd",
    "recipe_engine/file",
    "recipe_engine/path",
    "recipe_engine/properties",
    "recipe_engine/step",
]

PROPERTIES = InputProperties

NEW_BUILDERS_IN_CQ_MSG = """\
The following builder(s) are referenced in commit-queue.cfg but aren't yet
known to Buildbucket. Create the builder(s) in a separate change before adding
them to commit-queue.cfg.
"""

CQ_BUILDERS_DELETED_MSG = """\
The following builder(s) are running in CQ but missing from
cr-buildbucket.cfg. Remove the builder(s) from CQ in a separate change before
deleting them.
"""

# lucicfg version used when the `lucicfg_ensure_file` property is not set.
# TODO(olivernewman): Convert each repository that uses this recipe to declare a
# compatible lucicfg version in a cipd.ensure checked into the repo that this
# recipe can use. Then remove support for installing a default version.
DEFAULT_LUCICFG_VERSION = "git_revision:23d142175f4dc17791ff85df9b8af144377d73a1"
LUCICFG_CIPD_PACKAGE = "infra/tools/luci/lucicfg/${platform}"


def RunSteps(api, props):
    assert props.starlark_paths, "starlark_paths must not be empty"

    checkout_root, _ = api.git_checkout(api.sso.sso_to_https(props.remote))

    if props.lucicfg_ensure_file:
        # TODO(olivernewman): The cleanup directory is supposed to already
        # exist, so we shouldn't need to re-ensure it in order to call
        # `mkdtemp()`. Figure out why the cleanup directory doesn't already
        # exist, and remove this step if possible.
        api.file.ensure_directory("ensure cleanup dir", api.path["cleanup"])
        lucicfg_dir = api.path.mkdtemp("lucicfg")
        api.cipd.ensure(
            lucicfg_dir,
            checkout_root.join(props.lucicfg_ensure_file),
            "install lucicfg",
        )
        # Assumes that the ensure file installs lucicfg in the root of the CIPD
        # directory.
        lucicfg_path = lucicfg_dir.join("lucicfg")
    else:
        lucicfg_path = api.cipd.ensure_tool(
            LUCICFG_CIPD_PACKAGE, DEFAULT_LUCICFG_VERSION
        )

    with api.step.nest("validate"), api.step.defer_results():
        for relative_path in props.starlark_paths:
            abs_path = checkout_root.join(relative_path)
            api.step(
                str(relative_path),
                [lucicfg_path, "validate", "-strict", "-fail-on-warnings", abs_path],
            )

    # The LUCI Config service tracks the "main" branch of all config repos, so
    # we should skip the race condition check if we're running on a branch other
    # than "main" because:
    #   1. Comparing the local (non-main) configs to the deployed (main) configs
    #      will likely return spurious failures, e.g. if the local
    #      commit-queue.cfg file references builders that have been deleted at
    #      HEAD.
    #   2. It doesn't matter if there are any race conditions in config changes
    #      on non-main branches, because the changes won't be deployed to LUCI
    #      Config anyway; config changes on non-main branches are only necessary
    #      to modify generated files that are consumed by other parts of the
    #      infrastructure.
    if props.generated_dir and api.buildbucket_util.triggering_branch == "main":
        with api.step.nest("check for config deployment race conditions"):
            check_for_deployment_race_conditions(
                api, checkout_root.join(props.generated_dir)
            )


def check_for_deployment_race_conditions(api, generated_dir):
    """
    There are some types of LUCI config changes that introduce race
    conditions in the process of deploying the updated config files to their
    corresponding services.

    For example, it's not safe to simultaneously create a new builder and add
    it to CQ, because CQ might ingest the updated configs before Buildbucket
    and try to trigger the builder before Buildbucket even knows it exists.
    This causes CQ to error out and add confusing comments to CLs.

    To avoid this specific race condition, we compare the modified version of
    commit-queue.cfg with the live version of cr-buildbucket.cfg to make sure
    that even if CQ ingests the updated configs before Buildbucket does, CQ
    won't try to trigger any builders that don't yet exist.

    We also check that the live version of commit-queue.cfg doesn't reference
    any builders that will soon be deleted, which would cause the same issue
    if Buildbucket ingests the config changes before CQ does.

    There are other race conditions that we don't bother checking here; for
    example, it's technically not safe to immediately start running a new
    builder in CI by adding it to luci-scheduler.cfg. However, LUCI scheduler
    trigger failures don't produce user-visible error messages like CQ
    trigger failures, so it's not as big a deal. Also, adding new builders to
    CI is a very common workflow (adding builders to CQ is somewhat more
    rare) and it would be annoying if that always required two separate
    changes.
    """
    api.path.mock_add_directory(generated_dir.join("fuchsia"))
    api.path.mock_add_directory(generated_dir.join("fuchsia_internal"))

    # Our luci configs are set up such that each LUCI project's config files
    # are in a subdirectory of the "generated" directory whose name is the same
    # as the project name.
    project_dirs = [
        path
        for path in api.file.listdir(
            "find projects",
            generated_dir,
            test_data=["fuchsia", "fuchsia_internal", "foo.txt"],
        )
        if api.path.isdir(path)
    ]

    all_live_builders = set()
    all_local_builders = set()

    for project_dir in project_dirs:
        project = api.path.basename(project_dir)

        live_bb_config = api.luci_config.buildbucket(project=project)
        all_live_builders.update(all_builder_names(api, project, live_bb_config))

        local_bb_config = api.luci_config.buildbucket(
            project=project, local_dir=project_dir.join("luci")
        )
        all_local_builders.update(all_builder_names(api, project, local_bb_config))

    for project_dir in project_dirs:
        project = api.path.basename(project_dir)

        cq_config_path = project_dir.join("luci", "commit-queue.cfg")
        api.path.mock_add_paths(cq_config_path)
        if not api.path.exists(cq_config_path):  # pragma: no cover
            # Skip projects that don't have CQ set up.
            continue

        local_cq_config = api.luci_config.commit_queue(
            project=project, local_dir=project_dir.join("luci")
        )

        # Make sure that the new CQ config won't try to trigger non-existent builders.
        nonexistent_builders = nonexistent_cq_builders(
            local_cq_config, all_live_builders
        )
        if nonexistent_builders:
            msg = NEW_BUILDERS_IN_CQ_MSG + "".join(
                ["\n- %s" % b for b in nonexistent_builders]
            )
            raise api.step.StepFailure(msg)

        live_cq_config = api.luci_config.commit_queue(project=project)
        # Make sure that the existing CQ config won't try to trigger builders
        # that we're deleting.
        nonexistent_builders = nonexistent_cq_builders(
            live_cq_config, all_local_builders
        )
        if nonexistent_builders:
            msg = CQ_BUILDERS_DELETED_MSG + "".join(
                ["\n- %s" % b for b in nonexistent_builders]
            )
            raise api.step.StepFailure(msg)


def all_builder_names(api, project_name, bb_config):
    for bucket in bb_config.buckets:
        for builder in bucket.swarming.builders:
            yield api.buildbucket_util.full_builder_name(
                builder_common_pb2.BuilderID(
                    project=project_name,
                    bucket=bucket.name,
                    builder=builder.name,
                )
            )


def nonexistent_cq_builders(cq_config, all_known_builders):
    """Checks that all builders in cq_config are known to Buildbucket.

    Returns the names of any CQ builders that aren't in the list of builders
    known to Buildbucket.
    """
    nonexistent_builders = set()
    for group in cq_config.config_groups:
        for builder in group.verifiers.tryjob.builders:
            # Includable-only builders are only run if a special footer is in a
            # change's commit message. Usage of the footer is rare enough that
            # we're willing to allow errors in that case, in exchange for making
            # it easier to add and remove builders from CQ.
            if builder.includable_only:
                continue
            if builder.name not in all_known_builders:
                nonexistent_builders.add(builder.name)
    return sorted(nonexistent_builders)


def GenTests(api):
    remote = "https://fuchsia.googlesource.com/infra/config"

    def properties(**kwargs):
        return api.properties(
            InputProperties(
                remote=remote,
                starlark_paths=["main.star", "dev.star"],
                generated_dir="generated",
                **kwargs,
            )
        )

    nesting = "check for config deployment race conditions"

    def cq_config(builders, includable_only=False):
        return cv_config_pb2.Config(
            config_groups=[
                dict(
                    verifiers=dict(
                        tryjob=dict(
                            builders=[
                                dict(name=builder_name, includable_only=includable_only)
                                for builder_name in builders
                            ]
                        )
                    )
                )
            ]
        )

    yield (
        api.buildbucket_util.test("starlark", git_repo=remote)
        # Cover the logic for installing lucicfg from a checked-in CIPD ensure
        # file.
        + properties(lucicfg_ensure_file="cipd.ensure")
        # Cover the logic that reads builder names from cr-buildbucket.cfg.
        + api.luci_config.mock_local_config(
            "fuchsia",
            "cr-buildbucket.cfg",
            project_config_pb2.BuildbucketCfg(
                buckets=[
                    dict(
                        name="try",
                        swarming=dict(builders=[dict(name="core.x64-asan")]),
                    )
                ]
            ),
            nesting=nesting,
        )
    )

    # The second file should be validated even if the first one fails.
    yield (
        api.buildbucket_util.test(
            "first_file_invalid", tryjob=True, git_repo=remote, status="failure"
        )
        + properties()
        + api.step_data("validate.main.star", retcode=1)
        + api.post_process(post_process.MustRun, "validate.dev.star")
        # Make sure we patch in the triggering change, since this is a tryjob.
        + api.post_process(post_process.MustRun, "checkout.git rebase")
    )

    yield (
        api.buildbucket_util.test(
            "cq_new_builder", tryjob=True, git_repo=remote, status="failure"
        )
        + properties()
        + api.luci_config.mock_local_config(
            "fuchsia",
            "commit-queue.cfg",
            cq_config(["fuchsia/try/core.x64-asan"]),
            nesting=nesting,
        )
        + api.post_process(
            post_process.ResultReasonRE, re.escape(NEW_BUILDERS_IN_CQ_MSG)
        )
    )

    yield (
        api.buildbucket_util.test(
            "deleting_cq_builder", tryjob=True, git_repo=remote, status="failure"
        )
        + properties()
        + api.luci_config.mock_config(
            "fuchsia",
            "commit-queue.cfg",
            cq_config(["fuchsia/try/core.x64-asan"]),
            nesting=nesting,
        )
        + api.post_process(
            post_process.ResultReasonRE, re.escape(CQ_BUILDERS_DELETED_MSG)
        )
    )

    # It should be considered safe to delete an includable_only builder even if
    # it's still referenced in commit-queue.cfg.
    yield (
        api.buildbucket_util.test(
            "deleting_includable_only_builder", tryjob=True, git_repo=remote
        )
        + properties()
        + api.luci_config.mock_config(
            "fuchsia",
            "commit-queue.cfg",
            cq_config(["fuchsia/try/core.x64-asan"], includable_only=True),
            nesting=nesting,
        )
    )

    yield (
        api.buildbucket_util.test("non_main_branch", tryjob=True)
        + properties()
        + api.buildbucket_util.tryjob_branch("non-main-branch")
        # Race condition check should be skipped on branches other than "main".
        + api.post_process(
            post_process.DoesNotRun, "check for config deployment race conditions"
        )
    )
