# Copyright 2021 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.

"""Ensure the platform version in fuchsia.git is up-to-date.

The platform version should always be one ahead of the latest milestone branch's
milestone number.
"""

import json

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.recipe_engine.result import RawResult
from PB.recipes.fuchsia.release.platform_version_roller import InputProperties

DEPS = [
    "fuchsia/auto_roller",
    "fuchsia/build",
    "fuchsia/checkout",
    "fuchsia/git",
    "fuchsia/git_checkout",
    "fuchsia/gitiles",
    "fuchsia/release",
    "fuchsia/sso",
    "fuchsia/status_check",
    "recipe_engine/context",
    "recipe_engine/properties",
    "recipe_engine/step",
]

PROPERTIES = InputProperties
COMMIT_MESSAGE = """[roll] Update platform version from {current} to {target}"""


def RunSteps(api, props):
    # This should be a minimal checkout only so that we can read the state of
    # the integration repository's branches.
    with api.step.nest("checkout integration"):
        integration_dir, _ = api.git_checkout(api.sso.sso_to_https(props.remote))

    with api.step.nest("resolve target platform version"), api.context(
        cwd=integration_dir
    ):
        api.git.fetch(all_remotes=True)
        branches = api.release.get_branches(repo_path=integration_dir, remotes=True)
        if not branches:
            return RawResult(
                summary_markdown="%s does not have any release branches" % props.remote,
                status=common_pb2.FAILURE,
            )
        # The target API level is always 1 ahead of the latest milestone
        # branch's milestone number.
        target_platform_version = 1 + (
            max(api.release.get_milestone_from_branch(b) for b in branches)
        )

    with api.step.nest("resolve current platform version"):
        # Use the Gitiles API to resolve the platform version, as this is much
        # faster than doing a full checkout. A full checkout will be performed
        # later if we realize that an update is needed.
        file_content = api.gitiles.fetch(
            "fuchsia.googlesource.com",
            "fuchsia",
            "build/config/fuchsia/platform_version.json",
        ).decode()
        current_platform_version = json.loads(file_content)["current_fuchsia_api_level"]
        if current_platform_version == target_platform_version:
            api.step.empty("nothing to roll", step_text="platform version up-to-date")
            return api.auto_roller.nothing_to_roll()

        # If the target platform version isn't equal to or exactly 1 greater
        # than the current platform version, either the current platform version
        # and/or the latest milestone branch are invalid. Raise an exception and
        # do not roll.
        if current_platform_version + 1 != target_platform_version:
            return RawResult(
                summary_markdown="invalid platform versions: target platform "
                "version %d is not an increment of the current platform "
                "version %d" % (target_platform_version, current_platform_version),
                status=common_pb2.INFRA_FAILURE,
            )

    # At this point we've determined that we need to attempt a roll, so perform
    # a full checkout.
    checkout = api.checkout.fuchsia_with_options(
        manifest=props.manifest,
        remote=props.remote,
    )

    # Build Fuchsia to generate the golden files for API level N.
    build_results = api.build.with_options(
        checkout=checkout, fint_params_path=props.fint_params_path
    )

    # Run update_platform_version.py which bumps the platform version and updates the golden
    # files used for compatibility testing
    # TODO Drop the explict call to update_platform_version.py once single GN target is implemented.
    with api.context(cwd=checkout.root_dir):
        api.step(
            "update platform version",
            [
                build_results.gn_results.tool("python3"),
                checkout.root_dir.join(
                    "scripts",
                    "versioning",
                    "update_platform_version.py",
                ),
                "--fuchsia-api-level",
                target_platform_version,
            ],
        )

    change = api.auto_roller.attempt_roll(
        props.roll_options,
        repo_dir=checkout.root_dir,
        commit_message=COMMIT_MESSAGE.format(
            current=current_platform_version, target=target_platform_version
        ),
    )
    return api.auto_roller.raw_result(change)


def GenTests(api):
    default_props = api.properties(
        project="integration",
        manifest="flower",
        remote="https://fuchsia.googlesource.com/integration",
        fint_params_path="fint_params/platform-version-roller.textproto",
        roll_options=api.auto_roller.Options(
            remote="https://fuchsia.googlesource.com/fuchsia",
        ),
    )
    yield api.status_check.test("no_branches", status="failure") + default_props

    yield api.status_check.test("roll") + api.release.get_branches(
        ["releases/foo", "releases/f1", "releases/f2"],
        nesting="resolve target platform version",
    ) + api.auto_roller.success() + api.gitiles.fetch(
        "resolve current platform version.fetch",
        '{"current_fuchsia_api_level": 2}',
    ) + default_props

    yield api.status_check.test("nothing_to_roll") + api.release.get_branches(
        ["releases/foo", "releases/f1"],
        nesting="resolve target platform version",
    ) + api.gitiles.fetch(
        "resolve current platform version.fetch", '{"current_fuchsia_api_level": 2}'
    ) + default_props

    yield api.status_check.test(
        "invalid_platform_version", status="infra_failure"
    ) + api.release.get_branches(
        ["releases/foo", "releases/f1"],
        nesting="resolve target platform version",
    ) + api.gitiles.fetch(
        "resolve current platform version.fetch",
        '{"current_fuchsia_api_level": 5}',
    ) + default_props
