# Copyright 2013 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module containing the completion stages."""

import logging
import os

from chromite.cbuildbot import cbuildbot_alerts
from chromite.cbuildbot import commands
from chromite.cbuildbot import prebuilts
from chromite.cbuildbot.stages import generic_stages
from chromite.cbuildbot.stages import sync_stages
from chromite.lib import buildbucket_v2
from chromite.lib import builder_status_lib
from chromite.lib import chroot_lib
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import failures_lib
from chromite.service import binhost as binhost_service


# Percentage of child builders that need to complete to update LKGM
# TODO(b/232822787): Delete when cbuildbot has been removed.
LKGM_THRESHOLD = 101

# Metadata key to indicate whether a build is self-destructed.
SELF_DESTRUCTED_BUILD = "self_destructed_build"

# Metadata key to indicate whether a build is self-destructed with success.
SELF_DESTRUCTED_WITH_SUCCESS_BUILD = "self_destructed_with_success_build"


def GetBuilderSuccessMap(builder_run, overall_success):
    """Get the pass/fail status of all builders.

    A builder is marked as passed if all of its steps ran all of the way to
    completion. We determine this by looking at whether all of the steps for
    all of the constituent boards ran to completion.

    In cases where a builder does not have any boards, or has child boards, we
    fall back and instead just look at whether the entire build was successful.

    Args:
        builder_run: The builder run we wish to get the status of.
        overall_success: The overall status of the build.

    Returns:
        A dict, mapping the builder names to whether they succeeded.
    """
    success_map = {}
    for run in [builder_run]:
        if run.config.boards:
            success_map[run.config.name] = True
            for board in run.config.boards:
                board_runattrs = run.GetBoardRunAttrs(board)
                if not board_runattrs.HasParallel("success"):
                    success_map[run.config.name] = False
        else:
            # If a builder does not have boards, or if it has child configs, we
            # will just use the overall status instead.
            success_map[run.config.name] = overall_success
    return success_map


class ManifestVersionedSyncCompletionStage(
    generic_stages.ForgivingBuilderStage
):
    """Stage that records board specific results for a unique manifest file."""

    option_name = "sync"
    category = constants.CI_INFRA_STAGE

    def __init__(
        self, builder_run, buildstore, sync_stage, success, **kwargs
    ) -> None:
        super().__init__(builder_run, buildstore, **kwargs)
        self.sync_stage = sync_stage
        self.success = success
        # Message that can be set that well be sent along with the status in
        # UpdateStatus.
        self.message = None

    def PerformStage(self) -> None:
        if not self.success:
            self.message = self.GetBuildFailureMessage()

        if not config_lib.IsPFQType(self._run.config.build_type):
            # Update the pass/fail status in the manifest-versions
            # repo. Suite scheduler checks the build status to schedule
            # suites.
            self._run.attrs.manifest_manager.UpdateStatus(
                success_map=GetBuilderSuccessMap(self._run, self.success),
                message=self.message,
            )


class ImportantBuilderFailedException(failures_lib.StepFailure):
    """Exception thrown when an important build fails to build."""


class MasterSlaveSyncCompletionStage(ManifestVersionedSyncCompletionStage):
    """Stage that records whether we passed or failed to build/test manifest."""

    category = constants.CI_INFRA_STAGE

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        # TODO(nxia): rename to _build_statuses as it contains local status and
        # slave statuses for master builds
        self._slave_statuses = {}
        self._experimental_build_statuses = {}
        self._fatal = False
        self.buildbucket_client = buildbucket_v2.BuildbucketV2()

    def _WaitForSlavesToComplete(
        self, manager, build_identifier, builders_array, timeout
    ):
        """Wait for slave builds to complete.

        Args:
            manager: An instance of BuildSpecsManager.
            build_identifier: The BuildIdentifier instance of the master build.
            builders_array: A list of builder names (strings) of slave builds.
            timeout: Number of seconds to wait for the results.
        """
        return manager.WaitForSlavesToComplete(
            build_identifier, builders_array, timeout=timeout
        )

    def _GetBuilderStatusesFetcher(self):
        """Construct and return the BuilderStatusesFetcher instance.

        If this build is a master, wait for slaves to complete or timeout before
        constructing and returning the BuilderStatusesFetcher instance.

        Returns:
            A instance of builder_status_lib.BuilderStatusesFetcher.
        """
        # Wait for slaves if we're a master, in production or mock-production.
        # Otherwise just look at our own status.
        build_identifier, _ = self._run.GetCIDBHandle()
        builders_array = None
        if not self._run.config.master:
            # The slave build returns its own status.
            logging.warning("The build is not a master.")
        elif self._run.options.mock_slave_status or not self._run.options.debug:
            # The master build.
            builders = self._GetSlaveConfigs()
            builders_array = [b.name for b in builders]
            timeout = self._run.config.build_timeout

            if self._run.options.debug:
                # For debug runs, wait for three minutes to ensure most code
                # paths are executed.
                logging.info(
                    "Waiting for 3 minutes only for debug run. "
                    "Would have waited for %s seconds.",
                    timeout,
                )
                timeout = 3 * 60

            manager = self._run.attrs.manifest_manager
            if sync_stages.MasterSlaveLKGMSyncStage.external_manager:
                manager = sync_stages.MasterSlaveLKGMSyncStage.external_manager

            self._WaitForSlavesToComplete(
                manager, build_identifier, builders_array, timeout
            )

        # Set exclude_experimental to False to fetch the BuilderStatus for
        # builds which are important in config but marked as experimental in
        # the tree status.
        builder_statuses_fetcher = builder_status_lib.BuilderStatusesFetcher(
            build_identifier,
            self.buildstore,
            self.success,
            self.message,
            self._run.config,
            self._run.attrs.metadata,
            self.buildbucket_client,
            builders_array=builders_array,
            exclude_experimental=False,
            dry_run=self._run.options.debug,
        )

        return builder_statuses_fetcher

    def _HandleStageException(self, exc_info):
        """Decide whether an exception should be treated as fatal."""
        # Besides the master, the completion stages also run on slaves, to
        # report their status back to the master. If the build failed, they
        # throw an exception here. For slave builders, marking this stage 'red'
        # would be redundant, since the build itself would already be red. In
        # this case, report a warning instead.
        # pylint: disable=protected-access
        exc_type = exc_info[0]
        if (
            issubclass(exc_type, ImportantBuilderFailedException)
            and not self._run.config.master
        ):
            return self._HandleExceptionAsWarning(exc_info)
        else:
            # In all other cases, exceptions should be treated as fatal. To
            # implement this, we bypass ForgivingStage and call
            # generic_stages.BuilderStage._HandleStageException explicitly.
            return generic_stages.BuilderStage._HandleStageException(
                self, exc_info
            )

    def HandleSuccess(self) -> None:
        """Handle a successful build.

        This function is called whenever the cbuildbot run is successful.
        For the master, this will only be called when all slave builders
        are also successful. This function may be overridden by subclasses.
        """
        # We only promote for the pfq, not chrome pfq.
        # TODO(build): Run this logic in debug mode too.
        if (
            not self._run.options.debug
            and config_lib.IsPFQType(self._run.config.build_type)
            and self._run.config.master
            and self._run.manifest_branch in ("main", "master")
        ):
            self._run.attrs.manifest_manager.PromoteCandidate()
            if sync_stages.MasterSlaveLKGMSyncStage.external_manager:
                # pylint: disable-next=line-too-long
                sync_stages.MasterSlaveLKGMSyncStage.external_manager.PromoteCandidate()

    def HandleFailure(
        self, failing, inflight, no_stat, self_destructed
    ) -> None:
        """Handle a build failure.

        This function is called whenever the cbuildbot run fails.
        For the master, this will be called when any slave fails or times
        out. This function may be overridden by subclasses.

        Args:
            failing: The names of the failing builders.
            inflight: The names of the builders that are still running.
            no_stat: Set of builder names of slave builders that had status
                None.
            self_destructed: Boolean indicating whether the master build
                destructed itself and stopped waiting completion of its slaves.
        """
        if failing or inflight or no_stat:
            cbuildbot_alerts.PrintBuildbotStepWarnings()

        if failing:
            logging.warning(
                "\n".join(
                    [
                        "The following builders failed with this manifest:",
                        ", ".join(sorted(failing)),
                        (
                            "Please check the logs of the failing builders for"
                            " details."
                        ),
                    ]
                )
            )

        if not self_destructed and inflight:
            logging.warning(
                "\n".join(
                    [
                        "The following builders took too long to finish:",
                        ", ".join(sorted(inflight)),
                        "Please check the logs of these builders for details.",
                    ]
                )
            )

        if no_stat:
            logging.warning(
                "\n".join(
                    [
                        (
                            "The following builders did not start or failed"
                            " prematurely:"
                        ),
                        ", ".join(sorted(no_stat)),
                        "Please check the logs of these builders for details.",
                    ]
                )
            )

    def PerformStage(self) -> None:
        super().PerformStage()

        builder_statusess_fetcher = self._GetBuilderStatusesFetcher()
        (
            self._slave_statuses,
            self._experimental_build_statuses,
        ) = builder_statusess_fetcher.GetBuilderStatuses()

        no_stat = builder_status_lib.BuilderStatusesFetcher.GetNostatBuilds(
            self._slave_statuses
        )
        failing = builder_status_lib.BuilderStatusesFetcher.GetFailingBuilds(
            self._slave_statuses
        )
        inflight = builder_status_lib.BuilderStatusesFetcher.GetInflightBuilds(
            self._slave_statuses
        )

        self_destructed = self._run.attrs.metadata.GetValueWithDefault(
            SELF_DESTRUCTED_BUILD, False
        )

        self._fatal = self._IsFailureFatal(
            failing, inflight, no_stat, self_destructed=self_destructed
        )

        # Always annotate unsuccessful builders.
        self._AnnotateFailingBuilders(
            failing,
            inflight,
            no_stat,
            self._slave_statuses,
            self._experimental_build_statuses,
            self_destructed,
        )

        if self._fatal:
            self.HandleFailure(failing, inflight, no_stat, self_destructed)
            raise ImportantBuilderFailedException()
        else:
            self.HandleSuccess()

    def _IsFailureFatal(
        self, failing, inflight, no_stat, self_destructed=False
    ):
        """Returns a boolean indicating whether the build should fail.

        Args:
            failing: Set of build config names of builders that failed.
            inflight: Set of build config names of builders that are inflight
            no_stat: Set of build config names of builders that had status None.
            self_destructed: Boolean indicating whether it's a master build
                which destructed itself and stopped waiting its slaves to
                complete.

        Returns:
            True if any of the failing, in-flight or no_stat builders are not
            sanity checker builders and not ignored by self-destruction;
            else, False.
        """
        not_passed_builders = failing | inflight | no_stat

        if self_destructed:
            # This build must be a master build if self_destructed is True.
            self_destructed_with_success = (
                self._run.attrs.metadata.GetValueWithDefault(
                    SELF_DESTRUCTED_WITH_SUCCESS_BUILD, False
                )
            )
            if self_destructed_with_success:
                # If the master build itself didn't pass, report fatal.
                return self._run.config.name in not_passed_builders

            build_identifier, _ = self._run.GetCIDBHandle()
            if self.buildstore.AreClientsReady():
                aborted_slaves = (
                    builder_status_lib.GetSlavesAbortedBySelfDestructedMaster(
                        build_identifier, self.buildstore
                    )
                )
                # Ignore the slaves aborted by self-destruction.
                not_passed_builders -= aborted_slaves

        # Fatal if any not_passed_builders remain.
        return bool(not_passed_builders)

    def _PrintBuildMessage(self, text, url=None) -> None:
        """Print the build message.

        Args:
            text: Text (string) to print.
            url: URL (string) to link to the text, default to None.
        """
        if url is not None:
            cbuildbot_alerts.PrintBuildbotLink(text, url)
        else:
            cbuildbot_alerts.PrintBuildbotStepText(text)

    def _AnnotateNoStatBuilders(self, no_stat) -> None:
        """Annotate the build statuses fetched from the Buildbucket.

        Some builds may fail to upload statuses to GS. If the builds were
        scheduled by Buildbucket, get the build statuses and annotate the
        results.

        Args:
            no_stat: Config names of the slave builds with None status.
        """
        buildbucket_info_dict = buildbucket_v2.GetBuildInfoDict(
            self._run.attrs.metadata
        )

        for config_name in no_stat:
            if config_name in buildbucket_info_dict:
                buildbucket_id = buildbucket_info_dict[
                    config_name
                ].buildbucket_id
                assert buildbucket_id is not None, "buildbucket_id is None"
                try:
                    build = self.buildbucket_client.GetBuild(
                        buildbucket_id,
                        properties=["id", "status", "summary_markdown"],
                    )

                    status = build.status
                    text = "%s: [status] %s" % (config_name, status)

                    if status in [
                        constants.BUILDBUCKET_BUILDER_STATUS_FAILURE,
                        constants.BUILDBUCKET_BUILDER_STATUS_INFRA_FAILURE,
                    ]:
                        failure_reason = build.summary_markdown
                        if failure_reason:
                            text += " [failure_reason] %s" % failure_reason
                    elif (
                        status == constants.BUILDBUCKET_BUILDER_STATUS_CANCELED
                    ):
                        cancel_reason = build.summary_markdown
                        if cancel_reason:
                            text += " [cancelation_reason] %s" % cancel_reason

                    dashboard_url = constants.CHROMEOS_MILO_HOST + str(build.id)
                    if dashboard_url:
                        cbuildbot_alerts.PrintBuildbotLink(text, dashboard_url)
                    else:
                        cbuildbot_alerts.PrintBuildbotStepText(text)
                except buildbucket_v2.BuildbucketResponseException as e:
                    logging.error(
                        "Cannot get status for %s: %s", config_name, e
                    )
                    cbuildbot_alerts.PrintBuildbotStepText(
                        "No status found for build %s buildbucket_id %s"
                        % (config_name, buildbucket_id)
                    )
            else:
                cbuildbot_alerts.PrintBuildbotStepText(
                    "%s wasn't scheduled by master." % config_name
                )

    def _AnnotateFailingBuilders(
        self,
        failing,
        inflight,
        no_stat,
        statuses,
        experimental_statuses,
        self_destructed,
    ) -> None:
        """Annotate failing, inflight and no_stat builds with text and links.

        Add text and buildbot links to build dashboards for failing builds and
        in-flight builds. For master builds using Buildbucket schdeduler, add
        text and buildbot links for the no_stat builds; for other master builds,
        add step text for the no_stat builds.

        Args:
            failing: Set of builder names of slave builders that failed.
            inflight: Set of builder names of slave builders that are inflight.
            no_stat: Set of builder names of slave builders that had status
                None.
            statuses: A builder-name->status dictionary, which will provide the
                dashboard_url values for any links.
            experimental_statuses: A builder-name->status dictionary for all
                slaves that were set as experimental through the tree status.
            self_destructed: Boolean indicating whether the master build
                destructed itself and stopped waiting completion of its slaves.
        """
        for build in failing:
            if statuses[build].message:
                self._PrintBuildMessage(
                    "%s: %s" % (build, statuses[build].message.reason),
                    statuses[build].dashboard_url,
                )
            else:
                self._PrintBuildMessage(
                    "%s: failed due to unknown reasons" % build,
                    statuses[build].dashboard_url,
                )

        if not self_destructed:
            for build in inflight:
                self._PrintBuildMessage(
                    "%s: timed out" % build, statuses[build].dashboard_url
                )

            self._AnnotateNoStatBuilders(no_stat)
        else:
            cbuildbot_alerts.PrintBuildbotStepText(
                "The master destructed itself and stopped waiting for the "
                "following slaves:"
            )
            for build in inflight:
                self._PrintBuildMessage(
                    "%s: still running" % build, statuses[build].dashboard_url
                )

            self._AnnotateNoStatBuilders(no_stat)

        for build, status in experimental_statuses.items():
            if not status.Passed():
                self._PrintBuildMessage(
                    "%s: set as experimental through tree status" % build,
                    status.dashboard_url,
                )

    def GetSlaveStatuses(self):
        """Returns cached slave status results.

        Cached results are populated during PerformStage, so this function
        should only be called after PerformStage has returned.

        Returns:
            A dictionary from build names to builder_status_lib.BuilderStatus
            builder status objects.
        """
        return self._slave_statuses


class CanaryCompletionStage(MasterSlaveSyncCompletionStage):
    """Collect build slave statuses and handle the failures."""

    category = constants.CI_INFRA_STAGE

    def HandleFailure(
        self, failing, inflight, no_stat, self_destructed
    ) -> None:
        """Handle a build failure or timeout in the Canary builders.

        Args:
            failing: Names of the builders that failed.
            inflight: Names of the builders that timed out.
            no_stat: Set of builder names of slave builders that had status
                None.
            self_destructed: Boolean indicating whether the master build
                destructed itself and stopped waiting completion of its slaves.
        """
        # Print out the status about what builds failed or not.
        MasterSlaveSyncCompletionStage.HandleFailure(
            self, failing, inflight, no_stat, self_destructed
        )

        if self._run.config.master:
            self.CanaryMasterHandleFailure(failing, inflight, no_stat)

    def SendCanaryFailureAlert(self, failing, inflight, no_stat) -> None:
        """Send an alert email to summarize canary failures.

        Args:
            failing: The names of the failing builders.
            inflight: The names of the builders that are still running.
            no_stat: The names of the builders that had status None.
        """
        builder_name = "Canary Master"
        title = "%s has detected build failures:" % builder_name
        msgs = [
            str(x)
            for x in builder_status_lib.GetFailedMessages(
                self._slave_statuses, failing
            )
        ]
        slaves = builder_status_lib.GetBuildersWithNoneMessages(
            self._slave_statuses, failing
        )
        msgs += ["%s failed with unknown reason." % x for x in slaves]
        msgs += ["%s timed out" % x for x in inflight]
        msgs += ["%s did not start" % x for x in no_stat]
        msgs.insert(0, title)
        msgs.append(
            "You can also view the summary of the slave failures from "
            "the %s stage of %s. Click on the failure message to go "
            "to an individual slave's build status page: %s"
            % (self.name, builder_name, self.ConstructDashboardURL())
        )
        msg = "\n\n".join(msgs)
        logging.warning(msg)

    def CanaryMasterHandleFailure(self, failing, inflight, no_stat) -> None:
        """Handles the failure by sending out an alert email.

        Args:
            failing: Names of the builders that failed.
            inflight: Names of the builders that timed out.
            no_stat: Set of builder names of slave builders that had status
                None.
        """
        if self._run.manifest_branch in ("main", "master"):
            self.SendCanaryFailureAlert(failing, inflight, no_stat)
            # Note: We used to throttle the tree here. As of
            # https://chromium-review.googlesource.com/#/c/325821/ we no longer
            # do.

    def _HandleStageException(self, exc_info):
        """Decide whether an exception should be treated as fatal."""
        # Canary master already updates the tree status for slave
        # failures. There is no need to mark this stage red. For slave
        # builders, the build itself would already be red. In this case,
        # report a warning instead.
        # pylint: disable=protected-access
        exc_type = exc_info[0]
        if issubclass(exc_type, ImportantBuilderFailedException):
            return self._HandleExceptionAsWarning(exc_info)
        else:
            # In all other cases, exceptions should be treated as fatal.
            return super()._HandleStageException(exc_info)


class UpdateChromeosLKGMStage(generic_stages.BuilderStage):
    """Update the CHROMEOS_LKGM file in the chromium repository."""

    category = constants.CI_INFRA_STAGE

    def PerformStage(self) -> None:
        if not self._build_threshold_successful():
            logging.info(
                "Insufficient number of successful builders. "
                "Skipping LKGM update."
            )
            return

        manager = self._run.attrs.manifest_manager
        cmd = [
            "chrome_chromeos_lkgm",
            "--debug",
            "--lkgm=%s" % manager.current_version,
        ]
        if self._run.options.buildbucket_id:
            cmd += ["--buildbucket-id", self._run.options.buildbucket_id]
        # Always do a dryrun for now so that we can check the output and ensure
        # it is doing the correct thing.
        if self._run.options.debug:
            cmd.append("--dryrun")
        commands.RunBuildScript(self._build_root, cmd, chromite_cmd=True)

    def _build_threshold_successful(self):
        """True if percentage of successful child builders exceeds threshold."""
        ids = self.GetScheduledSlaveBuildbucketIds()
        num_builds = 0
        num_failures = 0
        for status in self.buildstore.GetBuildStatuses(buildbucket_ids=ids):
            if status.get("important"):
                num_builds += 1
                if status.get("status") != constants.BUILDER_STATUS_PASSED:
                    num_failures += 1
        logging.info(
            "%d of %d important builds failed.", num_failures, num_builds
        )
        if num_builds > 0:
            pct_succeeded = 100.0 * (
                (num_builds - num_failures) / float(num_builds)
            )
            return pct_succeeded >= LKGM_THRESHOLD
        return False


class PublishUprevChangesStage(generic_stages.BuilderStage):
    """Makes CQ uprev changes live for developers.

    Push local commits for uprevs, binhost, and portage cache. We resync to the
    latest version of repos as they exist in GoB.  We can't rely on the commits
    we pulled originally because our CL submit stage might have failed in some
    way (GoB sometimes flakes), or we don't want to submit all the CLs (we
    pushed some repos, but rejected others based on CQ repo settings). There
    might also be commits pushed independently (chumped by sheriffs or the precq
    submitted).
    """

    category = constants.CI_INFRA_STAGE

    def __init__(
        self, builder_run, buildstore, sync_stage, success, **kwargs
    ) -> None:
        """Constructor.

        Args:
            builder_run: BuilderRun object.
            buildstore: BuildStore instance to make DB calls with.
            sync_stage: An instance of sync stage.
            success: Boolean indicating whether the build succeeded.
        """
        super().__init__(builder_run, buildstore, **kwargs)
        self.sync_stage = sync_stage
        self.success = success

    def PerformStage(self) -> None:
        # Either has to be a master or not have any push overlays.
        assert self._run.config.master
        assert self._run.config.push_overlays

        # If we're a commit queue, we should clean out our local changes,
        # resync, and reapply our uprevs. This is necessary so that 1) we are
        # sure to point at the remote SHA1s, not our local SHA1s; 2) we can
        # avoid doing a rebase; 3) in the case of failure and staging_branch is
        # None, we don't submit the changes that were committed locally.
        #
        # If we're not a commit queue and the build succeeded, we can skip the
        # cleanup here. This is a cheap trick so that the Chrome PFQ pushes its
        # earlier uprev from the SyncChrome stage (it would be a bit tricky to
        # replicate the uprev here, so we'll leave it alone).

        # If we're not a commit queue and staging_branch is not None, we can
        # skip the cleanup here. When staging_branch is not None, we're going to
        # push the local commits generated in AFDOUpdateEbuild stage to the
        # staging_branch, cleaning up repository here will wipe out the local
        # commits.
        if not self.success:
            repo = self.GetRepoRepository()

            # Clean up our root and sync down the latest changes that were
            # submitted.
            repo.BuildRootGitCleanup(self._build_root)

            # Sync down the latest changes we have submitted.
            if self._run.options.sync:
                next_manifest = self._run.config.manifest
                repo.Sync(next_manifest)

            # Commit uprev and portage cache regeneration locally.
            if self._run.options.uprev and self._run.config.uprev:
                commands.UprevPackages(
                    self._build_root,
                    self._boards,
                    overlay_type=self._run.config.overlays,
                )
                chroot = chroot_lib.Chroot(
                    path=os.path.join(
                        self._build_root, constants.DEFAULT_CHROOT_PATH
                    )
                )
                binhost_service.RegenBuildCache(
                    chroot,
                    self._run.config.push_overlays,
                    buildroot=self._build_root,
                )

        # When prebuilts is True, if it's a successful run, update binhost conf.
        if self._run.config.prebuilts and self.success:
            confwriter = prebuilts.BinhostConfWriter(self._run)
            confwriter.Perform()

        # Push the uprev, portage cache, and binhost commits.
        commands.UprevPush(
            self._build_root,
            overlay_type=self._run.config.push_overlays,
            dryrun=self._run.options.debug,
        )
