# 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 building and testing cobalt-registry.

Uses Cobalt's cobaltb.py script to build the config_parser tool, then
runs it on Cobalt's `config` repo.
"""

from urllib.parse import urlparse

from PB.recipes.fuchsia.cobalt_config import InputProperties

DEPS = [
    "fuchsia/build",
    "fuchsia/buildbucket_util",
    "fuchsia/checkout",
    "fuchsia/jiri",
    "fuchsia/sso",
    "recipe_engine/buildbucket",
    "recipe_engine/context",
    "recipe_engine/path",
    "recipe_engine/properties",
    "recipe_engine/raw_io",
    "recipe_engine/step",
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    # Check out the project from the specified manifest.
    checkout = api.checkout.fuchsia_with_options(
        manifest=props.manifest, remote=props.remote
    )

    with api.context(cwd=checkout.root_dir):
        cobalt_config_projects = api.jiri.project(
            ["cobalt-registry"],
            test_data=[
                {
                    "name": "cobalt-registry",
                    "path": str(checkout.root_dir / "cobalt-registry"),
                    "remote": "https://fuchsia.googlesource.com/cobalt-registry",
                },
                {
                    "name": "cobalt-registry",
                    "path": str(checkout.root_dir / "other/cobalt-registry"),
                    "remote": "https://not-fuchsia.googlesource.com/cobalt-registry",
                },
            ],
        ).json.output

    # Filter config repos based on input.
    changes = api.buildbucket.build.input.gerrit_changes
    if changes and changes[0].project == "cobalt-registry":
        cobalt_config_projects = [
            p
            for p in cobalt_config_projects
            if urlparse(api.sso.sso_to_https(p["remote"])).netloc
            == urlparse(changes[0].host).path.replace("-review", "")
        ]

    build_results = api.build.with_options(
        checkout=checkout, fint_params_path=props.fint_params_path
    )

    # Root of the cobalt repo as checked out by the manifest.
    cobalt_src_dir = checkout.root_dir / "third_party/cobalt"

    for cobalt_config_project in cobalt_config_projects:
        # Root of the config repo as checked out by the manifest.
        config_src_dir = api.path.abs_to_path(cobalt_config_project["path"])

        config_parser_bin = build_results.tool("config_parser")
        # Run config_parser on the config repo checkout.
        api.step(
            "check config",
            [
                config_parser_bin,
                "--output_file",
                checkout.root_dir / "new_config",
                "--config_dir",
                config_src_dir,
                "--allow_empty_output",
            ],
        )

        with api.context(cwd=config_src_dir):
            api.step("checkout parent", ["git", "checkout", "HEAD^"])

        api.step(
            "check parent config",
            [
                config_parser_bin,
                "--output_file",
                checkout.root_dir / "old_config",
                "--config_dir",
                config_src_dir,
                "--allow_empty_output",
                "--skip_validation",
            ],
        )

        commit_msg = ""
        with api.context(cwd=config_src_dir):
            api.step("checkout head", ["git", "checkout", "-"])
            commit_msg = api.step(
                "read commit message",
                ["git", "show", "-s", "--format=%b"],
                stdout=api.raw_io.output_text(),
            ).stdout

        api.step(
            "validate change",
            [
                build_results.tool("config_change_validator"),
                "--old_config",
                checkout.root_dir / "old_config",
                "--new_config",
                checkout.root_dir / "new_config",
                "--commit_msg",
                commit_msg,
            ],
        )


def GenTests(api):
    def properties():
        return api.properties(
            remote="https://fuchsia.googlesource.com/manifest",
            manifest="config.manifest",
            fint_params_path="foo/cobalt_config.textproto",
        )

    yield api.buildbucket_util.test("ci", repo="cobalt-registry") + properties()
    yield (
        api.buildbucket_util.test("cq_try", tryjob=True, repo="cobalt-registry")
        + properties()
    )
    yield (
        api.buildbucket_util.test(
            "cq_try_not_cobalt_config", tryjob=True, repo="cobalt"
        )
        + properties()
    )
