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

"""Build stages specific to factory builds.

Factory builds use a mix of standard stages, and custom stages
related to how build artifacts are generated and published.
"""

import datetime
import json
import logging
import os
import shutil

from chromite.cbuildbot import cbuildbot_alerts
from chromite.cbuildbot import commands
from chromite.cbuildbot.stages import generic_stages
from chromite.cbuildbot.stages import workspace_stages
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import portage_util
from chromite.lib import timeout_util
from chromite.utils import gs_urls_util
from chromite.utils import pformat


class UnsafeBuildForPushImage(Exception):
    """Raised if push_image is run against a non-signable build."""


class WorkspaceArchiveBase(
    workspace_stages.WorkspaceStageBase,
    generic_stages.BoardSpecificBuilderStage,
    generic_stages.ArchivingStageMixin,
):
    """Base class for workspace archive stages.

    The expectation is that the archive stages will be creating a "branch"
    upload that looks like an older style branched infrastructure build would
    have generated in addition to a factory branch set of archive results.
    """

    BRANCH_NAME = "branch"

    @property
    def branch_config(self):
        """Uniqify the name across boards."""
        if self._run.options.debug:
            return "%s-%s-tryjob" % (self._current_board, self.BRANCH_NAME)
        else:
            return "%s-%s" % (self._current_board, self.BRANCH_NAME)

    @property
    def branch_version(self):
        """Uniqify the name across boards."""
        workspace_version_info = self.GetWorkspaceVersionInfo()

        if self._run.options.debug:
            build_identifier, _ = self._run.GetCIDBHandle()
            build_id = build_identifier.cidb_id
            return "R%s-%s-b%s" % (
                workspace_version_info.chrome_branch,
                workspace_version_info.VersionString(),
                build_id,
            )
        else:
            return "R%s-%s" % (
                workspace_version_info.chrome_branch,
                workspace_version_info.VersionString(),
            )

    @property
    def branch_archive_url(self):
        """Uniqify the name across boards."""
        return self.UniqifyArchiveUrl(config_lib.GetSiteParams().ARCHIVE_URL)

    def UniqifyArchiveUrl(self, archive_url):
        """Return an archive url unique to the current board.

        Args:
            archive_url: The base archive URL (e.g. 'chromeos-image-archive').

        Returns:
            The unique archive URL.
        """
        return os.path.join(
            archive_url, self.branch_config, self.branch_version
        )

    def GetBranchArchiveUrls(self):
        """Returns upload URLs for branch artifacts based on artifacts.json."""
        upload_urls = [self.branch_archive_url]
        artifacts_file = portage_util.ReadOverlayFile(
            "scripts/artifacts.json",
            board=self._current_board,
            buildroot=self._build_root,
        )
        if artifacts_file is not None:
            artifacts_json = json.loads(artifacts_file)
            extra_upload_urls = artifacts_json.get("extra_upload_urls", [])
            upload_urls += [
                self.UniqifyArchiveUrl(url) for url in extra_upload_urls
            ]
        return upload_urls

    def UploadBranchArtifact(self, path) -> None:
        """Upload artifacts to the branch build results."""
        logging.info("UploadBranchArtifact: %s", path)
        with osutils.TempDir(prefix="branch") as tempdir:
            artifact_path = os.path.join(
                tempdir, "%s/%s" % (self._current_board, os.path.basename(path))
            )

            logging.info("Rename: %s -> %s", path, artifact_path)
            os.mkdir(os.path.join(tempdir, self._current_board))
            shutil.copyfile(path, artifact_path)

            logging.info("Main artifact from: %s", artifact_path)
            self.UploadArtifact(artifact_path, archive=True)

        gs_context = gs.GSContext(dry_run=self._run.options.debug_forced)
        for url in self.GetBranchArchiveUrls():
            logging.info("Uploading branch artifact to %s...", url)
            with timeout_util.Timeout(20 * 60):
                logging.info("Branch artifact from: %s", path)
                gs_context.CopyInto(path, url, parallel=True, recursive=True)

    def PushBoardImage(self) -> None:
        """Helper to run push_image against the branch boards artifacts."""
        # This helper script is only available on internal manifests currently.
        if not self._run.config["internal"]:
            raise UnsafeBuildForPushImage(
                "Can't use push_image on external builds."
            )

        logging.info(
            "Use pushimage to publish signing artifacts for: %s",
            self._current_board,
        )

        # Push build artifacts to gs://chromeos-releases for signing and
        # release. This runs TOT pushimage against the build artifacts for the
        # branch.
        commands.PushImages(
            board=self._current_board,
            archive_url=self.branch_archive_url,
            dryrun=self._run.options.debug
            or not self._run.config["push_image"],
            profile=self._run.options.profile or self._run.config["profile"],
            sign_types=self._run.config["sign_types"] or [],
            buildroot=self._build_root,
        )

    def CreateBranchMetadataJson(self) -> None:
        """Create/publish the factory build artifact for the current board."""
        workspace_version_info = self.GetWorkspaceVersionInfo()

        # Use the metadata for the main build, with selected fields modified.
        board_metadata = self._run.attrs.metadata.GetDict()
        board_metadata["boards"] = [self._current_board]
        board_metadata["branch"] = self._run.config.workspace_branch
        board_metadata["version_full"] = self.branch_version
        board_metadata[
            "version_milestone"
        ] = workspace_version_info.chrome_branch
        board_metadata[
            "version_platform"
        ] = workspace_version_info.VersionString()
        board_metadata["version"] = {
            "platform": workspace_version_info.VersionString(),
            "full": self.branch_version,
            "milestone": workspace_version_info.chrome_branch,
        }

        current_time = datetime.datetime.now()
        current_time_stamp = cros_build_lib.UserDateTimeFormat(
            timeval=current_time
        )

        # We report the build as passing, since we can't get here if isn't.
        board_metadata["status"] = {
            "status": "pass",
            "summary": "",
            "current-time": current_time_stamp,
        }

        with osutils.TempDir(prefix="metadata") as tempdir:
            metadata_path = os.path.join(tempdir, constants.METADATA_JSON)
            logging.info("Writing metadata to %s.", metadata_path)
            osutils.WriteFile(
                metadata_path, pformat.json(board_metadata), atomic=True
            )

            self.UploadBranchArtifact(metadata_path)


class FactoryArchiveStage(WorkspaceArchiveBase):
    """Generates and publishes factory specific build artifacts."""

    BRANCH_NAME = "factory"

    def CreateFactoryZip(self) -> None:
        """Create/publish the firmware build artifact for the current board."""
        logging.info("Create factory_image.zip")

        # TODO: Move this image creation logic back into WorkspaceBuildImages.

        factory_install_symlink = None
        if "factory_install" in self._run.config["images"]:
            alias = commands.BuildFactoryInstallImage(
                self._build_root,
                self._current_board,
                extra_env=self._portage_extra_env,
            )

            factory_install_symlink = self.GetImageDirSymlink(
                alias, self._build_root
            )
            if self._run.config["factory_install_netboot"]:
                commands.MakeNetboot(
                    self._build_root,
                    self._current_board,
                    factory_install_symlink,
                )

        # Build and upload factory zip if needed.
        assert self._run.config["factory_toolkit"]

        with osutils.TempDir(prefix="factory_zip") as zip_dir:
            filename = commands.BuildFactoryZip(
                self._build_root,
                self._current_board,
                zip_dir,
                factory_install_symlink,
                self.branch_version,
            )

            self.UploadBranchArtifact(os.path.join(zip_dir, filename))

    def CreateTestImageTar(self) -> None:
        """Create and upload chromiumos_test_image.tar.xz.

        This depends on the WorkspaceBuildImage stage having previously created
        chromiumos_test_image.bin.
        """
        with osutils.TempDir(prefix="test_image_dir") as tempdir:
            tarball_path = os.path.join(tempdir, constants.TEST_IMAGE_TAR)

            cros_build_lib.CreateTarball(
                tarball_path,
                inputs=[constants.TEST_IMAGE_BIN],
                cwd=self.GetImageDirSymlink(
                    pointer="latest", buildroot=self._build_root
                ),
                compression=cros_build_lib.CompressionType.XZ,
            )

            self.UploadBranchArtifact(tarball_path)

    def CreateFactoryProjectToolkitsZip(self) -> None:
        """Create/publish the factory project toolkits for the current board."""
        toolkits_src_path = os.path.join(
            path_util.FromChrootPath(
                commands.FACTORY_PACKAGE_CHROOT_PATH
                % {"board": self._current_board},
                source_path=self._build_root,
            ),
            "project_toolkits",
            commands.FACTORY_PROJECT_PACKAGE,
        )
        if os.path.exists(toolkits_src_path):
            self.UploadBranchArtifact(toolkits_src_path)

    def BuildAutotestTarballs(self) -> None:
        """Build the autotest tarballs."""
        with osutils.TempDir(prefix="cbuildbot-autotest") as tempdir:
            cwd = os.path.abspath(
                path_util.FromChrootPath(
                    os.path.join(
                        os.path.sep,
                        "build",
                        self._current_board,
                        constants.AUTOTEST_BUILD_PATH,
                        "..",
                    ),
                    source_path=self._build_root,
                )
            )
            logging.debug(
                "Running BuildAutotestTarballsForHWTest root %s cwd %s"
                " target %s",
                self._build_root,
                cwd,
                tempdir,
            )
            for tarball in commands.BuildAutotestTarballsForHWTest(
                self._build_root, cwd, tempdir
            ):
                self.UploadBranchArtifact(tarball)

    def BuildTastTarball(self) -> None:
        """Build the tarball containing private Tast test bundles."""
        with osutils.TempDir(prefix="cbuildbot-tast") as tempdir:
            cwd = os.path.abspath(
                path_util.FromChrootPath(
                    os.path.join(
                        os.path.sep,
                        "build",
                        self._current_board,
                        "build",
                    ),
                    source_path=self._build_root,
                )
            )
            logging.debug("Running commands.BuildTastBundleTarball")
            tarball = commands.BuildTastBundleTarball(
                self._build_root, cwd, tempdir
            )
            if tarball:
                self.UploadBranchArtifact(tarball)

    def PerformStage(self) -> None:
        """Archive and publish the factory build artifacts."""
        logging.info("Factory version: %s", self.branch_version)
        logging.info("Archive build as: %s", self.branch_config)

        # Link branch build artifacts from build.
        branch_http_url = gs_urls_util.GsUrlToHttp(
            self.branch_archive_url, public=False, directory=True
        )

        label = "%s factory [%s]" % (self._current_board, self.branch_version)
        cbuildbot_alerts.PrintBuildbotLink(label, branch_http_url)

        # factory_image.zip
        self.CreateFactoryZip()
        self.CreateFactoryProjectToolkitsZip()
        self.CreateTestImageTar()
        self.CreateBranchMetadataJson()
        self.PushBoardImage()

        # Upload any needed HWTest artifacts.
        if (
            self._run.ShouldBuildAutotest()
            and self._run.config.upload_hw_test_artifacts
        ):
            self.BuildAutotestTarballs()
            self.BuildTastTarball()
