# Copyright 2015 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 simple builders."""

import collections
import logging

from chromite.cbuildbot.builders import generic_builders
from chromite.cbuildbot.stages import android_stages
from chromite.cbuildbot.stages import artifact_stages
from chromite.cbuildbot.stages import build_stages
from chromite.cbuildbot.stages import completion_stages
from chromite.cbuildbot.stages import report_stages
from chromite.cbuildbot.stages import scheduler_stages
from chromite.cbuildbot.stages import sync_stages
from chromite.cbuildbot.stages import test_stages
from chromite.lib import chromeos_version
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import failures_lib
from chromite.lib import parallel
from chromite.lib import results_lib


# TODO: SimpleBuilder needs to be broken up big time.


BoardConfig = collections.namedtuple("BoardConfig", ["board", "name"])


class SimpleBuilder(generic_builders.Builder):
    """Builder that performs basic vetting operations."""

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.sync_stage = None

    def GetSyncInstance(self):
        """Sync to lkgm or TOT as necessary.

        Returns:
            The instance of the sync stage to run.
        """
        if self._run.options.force_version:
            sync_stage = self._GetStageInstance(
                sync_stages.ManifestVersionedSyncStage
            )
        else:
            sync_stage = self._GetStageInstance(sync_stages.SyncStage)

        self.sync_stage = sync_stage
        return sync_stage

    def GetVersionInfo(self):
        """Returns the CrOS version info from the chromiumos-overlay."""
        return chromeos_version.VersionInfo.from_repo(self._run.buildroot)

    def _RunDebugSymbolStages(self, builder_run, board) -> None:
        """Run debug-related stages for the specified board.

        Args:
            builder_run: BuilderRun object for these background stages.
            board: Board name.
        """
        # These stages should run sequentially.
        self._RunStage(
            android_stages.DownloadAndroidDebugSymbolsStage,
            board,
            builder_run=builder_run,
        )
        self._RunStage(
            artifact_stages.DebugSymbolsStage, board, builder_run=builder_run
        )

    def _RunBackgroundStagesForBoardAndMarkAsSuccessful(
        self, builder_run, board
    ) -> None:
        """Run background board-specific stages for the specified board.

        After finishing the build, mark it as successful.

        Args:
            builder_run: BuilderRun object for these background stages.
            board: Board name.
        """
        self._RunBackgroundStagesForBoard(builder_run, board)
        board_runattrs = builder_run.GetBoardRunAttrs(board)
        board_runattrs.SetParallel("success", True)

    def _RunBackgroundStagesForBoard(self, builder_run, board) -> None:
        """Run background board-specific stages for the specified board.

        Used by _RunBackgroundStagesForBoardAndMarkAsSuccessful. Callers should
        use that method instead.

        Args:
            builder_run: BuilderRun object for these background stages.
            board: Board name.
        """
        config = builder_run.config

        # TODO(mtennant): This is the last usage of self.archive_stages.  We can
        # kill it once we migrate its uses to BuilderRun so that none of the
        # stages below need it as an argument.
        archive_stage = self.archive_stages[BoardConfig(board, config.name)]

        # While this stage list is run in parallel, the order here dictates the
        # order that things will be shown in the log.  So group things together
        # that make sense when read in order.  Also keep in mind that, since we
        # gather output manually, early slow stages will prevent any output from
        # later stages showing up until it finishes.
        early_stage_list = [
            [test_stages.UnitTestStage, board],
        ]

        stage_list = []

        stage_list += [
            [artifact_stages.UploadPrebuiltsStage, board],
        ]

        if config.run_build_configs_export:
            stage_list += [[artifact_stages.BuildConfigsExportStage, board]]

        # This is what adds the autotest/tast uploads to the image.
        early_stage_list += [[artifact_stages.UploadTestArtifactsStage, board]]

        early_stage_objs = [
            self._GetStageInstance(*x, builder_run=builder_run)
            for x in early_stage_list
        ]

        stage_objs = [
            self._GetStageInstance(*x, builder_run=builder_run)
            for x in stage_list
        ]

        # Build the image first before running the steps.
        with self._build_image_lock:
            self._RunStage(
                build_stages.BuildImageStage,
                board,
                builder_run=builder_run,
                afdo_use=True,
            )

        # Run the debug symbols stage before the UnitTestStage to avoid
        # generating debug symbols from the altered, test symbols.
        self._RunDebugSymbolStages(builder_run, board)
        # Run UnitTestStage & UploadTestArtifactsStage in a separate pass before
        # any of the other parallel stages to prevent races with the image
        # construction in the ArchiveStage.
        # http://crbug.com/1000374
        self._RunParallelStages(early_stage_objs)

        parallel.RunParallelSteps(
            [
                lambda: self._RunParallelStages(stage_objs + [archive_stage]),
            ]
        )

    def BoardsForSimpleBuilder(self, builder_run):
        """All boards for this builder."""
        return builder_run.config.boards

    def RunSetupBoard(self) -> None:
        """Run the SetupBoard stage for all child configs and boards."""
        for builder_run in [self._run]:
            for board in self.BoardsForSimpleBuilder(builder_run):
                self._RunStage(
                    build_stages.SetupBoardStage, board, builder_run=builder_run
                )

    def RunEarlySyncAndSetupStages(self) -> None:
        """Runs through the early sync and board setup stages."""
        # If there are slave builders, schedule them.
        if self._run.config.slave_configs:
            self._RunStage(
                scheduler_stages.ScheduleSlavesStage, self.sync_stage
            )
        self._RunStage(build_stages.UprevStage)
        self._RunStage(build_stages.InitSDKStage)
        self._RunStage(build_stages.UpdateSDKStage)
        self._RunStage(build_stages.RegenPortageCacheStage)
        self.RunSetupBoard()
        self._RunStage(android_stages.AndroidMetadataStage)

    def RunBuildStages(self) -> None:
        """Runs through the stages to perform the build and resulting tests."""
        # Prepare stages to run in background.
        tasks = []
        for builder_run in [self._run]:
            # Prepare a local archive directory for each "run".
            builder_run.GetArchive().SetupArchivePath()

            for board in self.BoardsForSimpleBuilder(builder_run):
                archive_stage = self._GetStageInstance(
                    artifact_stages.ArchiveStage,
                    board,
                    builder_run=builder_run,
                    chrome_version=self._run.attrs.chrome_version,
                )
                board_config = BoardConfig(board, builder_run.config.name)
                self.archive_stages[board_config] = archive_stage
                tasks.append((builder_run, board))

        # Set up a process pool to run test/archive stages in the background.
        # This process runs task(board) for each board added to the queue.
        task_runner = self._RunBackgroundStagesForBoardAndMarkAsSuccessful
        with parallel.BackgroundTaskRunner(task_runner) as queue:
            for builder_run, board in tasks:
                # Run BuildPackages in the foreground.
                self._RunStage(
                    build_stages.BuildPackagesStage,
                    board,
                    update_metadata=True,
                    builder_run=builder_run,
                    afdo_use=True,
                )

                # Kick off our background stages.
                queue.put([builder_run, board])

    def _RunDefaultTypeBuild(self) -> None:
        """Runs through the stages of a non-special-type build."""
        self.RunEarlySyncAndSetupStages()
        self.RunBuildStages()

    def RunStages(self) -> None:
        """Runs through build process."""
        self._RunDefaultTypeBuild()


class DistributedBuilder(SimpleBuilder):
    """Build class that has special logic to handle distributed builds.

    These builds sync using git/manifest logic in manifest_versions.  In general
    they use a non-distributed builder code for the bulk of the work.
    """

    def __init__(self, *args, **kwargs) -> None:
        """Initializes a buildbot builder.

        Extra variables:
          completion_stage_class:  Stage used to complete a build.  Set in the
          Sync stage.
        """
        super().__init__(*args, **kwargs)
        self.completion_stage_class = None
        self.sync_stage = None
        self._completion_stage = None

    def GetSyncInstance(self):
        """Syncs the tree using one of the distributed sync logic paths.

        Returns:
            The instance of the sync stage to run.
        """
        # Determine sync class to use.  CQ overrides PFQ bits so should check it
        # first.
        if config_lib.IsCanaryType(self._run.config.build_type):
            sync_stage = self._GetStageInstance(
                sync_stages.ManifestVersionedSyncStage
            )
            self.completion_stage_class = (
                completion_stages.CanaryCompletionStage
            )
        elif config_lib.IsPFQType(
            self._run.config.build_type
        ) or self._run.config.build_type in (constants.FULL_TYPE,):
            sync_stage = self._GetStageInstance(
                sync_stages.MasterSlaveLKGMSyncStage
            )
            self.completion_stage_class = (
                completion_stages.MasterSlaveSyncCompletionStage
            )
        else:
            sync_stage = self._GetStageInstance(
                sync_stages.ManifestVersionedSyncStage
            )
            self.completion_stage_class = (
                completion_stages.ManifestVersionedSyncCompletionStage
            )

        self.sync_stage = sync_stage
        return self.sync_stage

    def GetCompletionInstance(self):
        """Returns completion_stage_class instance that was used for this build.

        Returns:
            None if the completion_stage instance was not yet created (this
            occurs during Publish).
        """
        return self._completion_stage

    def Complete(self, was_build_successful, build_finished) -> None:
        """Completes build by publishing any required information.

        Args:
            was_build_successful: Whether the build succeeded.
            build_finished: Whether the build completed. A build can be
                successful without completing if it raises ExitEarlyException.
        """
        self._completion_stage = self._GetStageInstance(
            self.completion_stage_class, self.sync_stage, was_build_successful
        )
        completion_successful = False
        try:
            self._completion_stage.Run()
            completion_successful = True
        except failures_lib.StepFailure:
            raise
        finally:
            self._Publish(
                was_build_successful, build_finished, completion_successful
            )

    def _Publish(
        self, was_build_successful, build_finished, completion_successful
    ) -> None:
        """Updates and publishes uprevs.

        Args:
            was_build_successful: Whether the build succeeded.
            build_finished: Whether the build completed. A build can be
                successful without completing if it raises ExitEarlyException.
            completion_successful: Whether the compeletion_stage succeeded.
        """
        if self._run.config.master:
            self._RunStage(report_stages.SlaveFailureSummaryStage)

        if config_lib.IsCanaryMaster(self._run) or (
            self._run.config.master
            and self._run.config.build_type == constants.FULL_TYPE
        ):
            if build_finished:
                self._RunStage(completion_stages.UpdateChromeosLKGMStage)
            else:
                logging.info(
                    "Skipping UpdateChromeosLKGMStage, "
                    "build_successful=%d completion_successful=%d "
                    "build_finished=%d",
                    was_build_successful,
                    completion_successful,
                    build_finished,
                )

        if self._run.config.push_overlays:
            publish = (
                was_build_successful
                and completion_successful
                and build_finished
            )
            # CQ and Master Chrome PFQ no longer publish uprevs. For Master
            # Chrome PFQ this is because this duty is being transitioned to the
            # Chrome PUpr in the PCQ world. See http://go/pupr. There is no easy
            # way to disable this in ChromeOS config, so hack the check here.

            self._RunStage(
                completion_stages.PublishUprevChangesStage,
                self.sync_stage,
                publish,
            )

    def RunStages(self) -> None:
        """Runs simple builder logic and publishes information to overlays."""
        was_build_successful = False
        build_finished = False
        try:
            super().RunStages()
            build_identifier, _ = self._run.GetCIDBHandle()
            buildbucket_id = build_identifier.buildbucket_id
            was_build_successful = results_lib.Results.BuildSucceededSoFar(
                self.buildstore, buildbucket_id
            )
            build_finished = True
        except failures_lib.ExitEarlyException as ex:
            # If a stage throws ExitEarlyException, it's exiting with success,
            # so that means we should mark ourselves as successful.
            logging.info("Detected exception %s", ex)
            was_build_successful = True
            raise
        finally:
            self.Complete(was_build_successful, build_finished)
