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

"""ChromeOS image pusher (from cbuildbot to signer).

This pushes files from the archive bucket to the signer bucket and marks
artifacts for signing (which a signing process will look for).
"""

import configparser
import getpass
import io
import logging
import os
import re
import textwrap

from chromite.lib import commandline
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 signing


# This will split a fully qualified ChromeOS version string up.
# R34-5126.0.0 will break into "34" and "5126.0.0".
VERSION_REGEX = r"^R([0-9]+)-([^-]+)"

# The test signers will scan this dir looking for test work.
# Keep it in sync with the signer config files [gs_test_buckets].
TEST_SIGN_BUCKET_BASE = "gs://chromeos-throw-away-bucket/signer-tests"

# Keysets that are only valid in the above test bucket.
TEST_KEYSET_PREFIX = "test-keys"
TEST_KEYSETS = {"mp", "premp", "nvidia-premp"}

# Supported image types for signing.
_SUPPORTED_IMAGE_TYPES = (
    constants.IMAGE_TYPE_RECOVERY,
    constants.IMAGE_TYPE_FACTORY,
    constants.IMAGE_TYPE_FIRMWARE,
    constants.IMAGE_TYPE_ACCESSORY_USBPD,
    constants.IMAGE_TYPE_HPS_FIRMWARE,
    constants.IMAGE_TYPE_ACCESSORY_RWSIG,
    constants.IMAGE_TYPE_BASE,
    constants.IMAGE_TYPE_GSC_FIRMWARE,
)


class PushError(Exception):
    """When an (unknown) error happened while trying to push artifacts."""


class MissingBoardInstructions(Exception):
    """Raised when a board lacks any signer instructions."""

    def __init__(self, board, image_type, input_insns):
        Exception.__init__(
            self,
            "Board %s lacks insns for %s image: %s not found"
            % (board, image_type, input_insns),
        )


class InputInsns:
    """Object to hold settings for a signable board.

    Note: The format of the instruction file pushimage outputs (and the signer
    reads) is not exactly the same as the instruction file pushimage reads.
    """

    def __init__(self, board, image_type=None, buildroot=None):
        """Initialization.

        Args:
            board: The board to look up details.
            image_type: The type of image we will be signing (see --sign-types).
            buildroot: Buildroot in which to look for signing instructions.
        """
        self.board = board
        self.buildroot = buildroot or constants.SOURCE_ROOT

        config = configparser.ConfigParser()
        with open(self.GetInsnFile("DEFAULT"), encoding="utf-8") as fp:
            config.read_file(fp)

        # What pushimage internally refers to as 'recovery', are the basic
        # signing instructions in practice, and other types are stacked on top.
        if image_type is None:
            image_type = constants.IMAGE_TYPE_RECOVERY
        self.image_type = image_type
        input_insns = self.GetInsnFile(constants.IMAGE_TYPE_RECOVERY)
        if not os.path.exists(input_insns):
            # This board doesn't have any signing instructions.
            raise MissingBoardInstructions(self.board, image_type, input_insns)
        with open(input_insns, encoding="utf-8") as fp:
            config.read_file(fp)

        if image_type != constants.IMAGE_TYPE_RECOVERY:
            input_insns = self.GetInsnFile(image_type)
            if not os.path.exists(input_insns):
                # This type doesn't have any signing instructions.
                raise MissingBoardInstructions(
                    self.board, image_type, input_insns
                )
            with open(input_insns, encoding="utf-8") as fp:
                config.read_file(fp)

        self.cfg = config

    def GetInsnFile(self, image_type):
        """Find the signer instruction files for this board/image type.

        Args:
            image_type: The type of instructions to load.  It can be a common
                file (like "DEFAULT"), or one of the --sign-types.

        Returns:
            Full path to the instruction file using |image_type| and
            |self.board|.
        """
        if image_type == image_type.upper():
            name = image_type
        elif image_type in (
            constants.IMAGE_TYPE_RECOVERY,
            constants.IMAGE_TYPE_BASE,
        ):
            name = self.board
        else:
            name = "%s.%s" % (self.board, image_type)

        return os.path.join(
            self.buildroot, signing.INPUT_INSN_DIR_REL, "%s.instructions" % name
        )

    @staticmethod
    def SplitCfgField(val):
        """Split a string into multiple elements.

        This centralizes our convention for multiple elements in the input files
        being delimited by either a space or comma.

        Args:
            val: The string to split.

        Returns:
            The list of elements from having done split the string.
        """
        return val.replace(",", " ").split()

    def GetChannels(self):
        """Return the list of channels to sign for this board.

        If the board-specific config doesn't specify a preference, we'll use the
        common settings.
        """
        return self.SplitCfgField(self.cfg.get("insns", "channel"))

    def GetKeysets(self, insns_merge=None):
        """Return the list of keysets to sign for this board.

        Args:
            insns_merge: The additional section to look at over [insns].
        """
        # First load the default value from [insns.keyset] if available.
        sections = ["insns"]
        # Then overlay the [insns.xxx.keyset] if requested.
        if insns_merge is not None:
            sections += [insns_merge]

        keyset = ""
        for section in sections:
            try:
                keyset = self.cfg.get(section, "keyset")
            except (configparser.NoSectionError, configparser.NoOptionError):
                pass

        # We do not perturb the order (e.g. using sorted() or making a set())
        # because we want the behavior stable, and we want the input insns to
        # explicitly control the order (since it has an impact on naming).
        return self.SplitCfgField(keyset)

    def GetAltInsnSets(self):
        """Return the list of alternative insn sections."""
        # We do not perturb the order (e.g. using sorted() or making a set())
        # because we want the behavior stable, and we want the input insns to
        # explicitly control the order (since it has an impact on naming).
        ret = [x for x in self.cfg.sections() if x.startswith("insns.")]
        return ret if ret else [None]

    @staticmethod
    def CopyConfigParser(config):
        """Return a copy of a ConfigParser object.

        The python folks broke the ability to use something like deepcopy:
        https://bugs.python.org/issue16058
        """
        # Write the current config to a string io object.
        data = io.StringIO()
        config.write(data)
        data.seek(0)

        # Create a new ConfigParser from the serialized data.
        ret = configparser.ConfigParser()
        ret.read_file(data)

        return ret

    def OutputInsns(
        self, output_file, sect_insns, sect_general, insns_merge=None
    ):
        """Generate the output instruction file for sending to the signer.

        The override order is (later has precedence):
          [insns]
          [insns_merge]  (should be named "insns.xxx")
          sect_insns

        Note: The format of the instruction file pushimage outputs (and the
        signer reads) is not exactly the same as the instruction file pushimage
        reads.

        Args:
            output_file: The file to write the new instruction file to.
            sect_insns: Items to set/override in the [insns] section.
            sect_general: Items to set/override in the [general] section.
            insns_merge: The alternative insns.xxx section to merge.
        """
        # Create a copy so we can clobber certain fields.
        config = self.CopyConfigParser(self.cfg)
        sect_insns = sect_insns.copy()

        # Merge in the alternative insns section if need be.
        if insns_merge is not None:
            for k, v in config.items(insns_merge):
                sect_insns.setdefault(k, v)

        # Clear channel entry in instructions file, ensuring we only get
        # one channel for the signer to look at.  Then provide all the
        # other details for this signing request to avoid any ambiguity
        # and to avoid relying on encoding data into filenames.
        for sect, fields in zip(
            ("insns", "general"), (sect_insns, sect_general)
        ):
            if not config.has_section(sect):
                config.add_section(sect)
            for k, v in fields.items():
                config.set(sect, k, v)

        # Now prune the alternative sections.
        for alt in self.GetAltInsnSets():
            config.remove_section(alt)

        output = io.StringIO()
        config.write(output)
        data = output.getvalue()
        osutils.WriteFile(output_file, data)
        logging.debug("generated insns file for %s:\n%s", self.image_type, data)


def MarkImageToBeSigned(ctx, tbs_base, insns_path, priority):
    """Mark an instructions file for signing.

    This will upload a file to the GS bucket flagging an image for signing by
    the signers.

    Args:
        ctx: A viable gs.GSContext.
        tbs_base: The full path to where the tobesigned directory lives.
        insns_path: The path (relative to |tbs_base|) of the file to sign.
        priority: Set the signing priority (lower == higher prio).

    Returns:
        The full path to the remote tobesigned file.
    """
    if priority < 0 or priority > 99:
        raise ValueError("priority must be [0, 99] inclusive")

    if insns_path.startswith(tbs_base):
        insns_path = insns_path[len(tbs_base) :].lstrip("/")

    tbs_path = "%s/tobesigned/%02i,%s" % (
        tbs_base,
        priority,
        insns_path.replace("/", ","),
    )

    # The caller will catch gs.GSContextException for us.
    ctx.Copy("-", tbs_path, input=cros_build_lib.MachineDetails())

    return tbs_path


def PushImage(
    src_path,
    board,
    versionrev=None,
    profile=None,
    priority=50,
    sign_types=None,
    dryrun=False,
    mock=False,
    force_keysets=(),
    force_channels=None,
    buildroot=constants.SOURCE_ROOT,
    dest_bucket=constants.RELEASE_BUCKET,
):
    """Push the image from the archive bucket to the release bucket.

    Args:
        src_path: Where to copy the files from; can be a local path or gs://
            URL. Should be a full path to the artifacts in either case.
        board: The board we're uploading artifacts for (e.g. $BOARD).
        versionrev: The full Chromium OS version string (e.g. R34-5126.0.0).
        profile: The board profile in use (e.g. "asan").
        priority: Set the signing priority (lower == higher prio).
        sign_types: If set, a set of types which we'll restrict ourselves to
            signing.  See the --sign-types option for more details.
        dryrun: Show what would be done, but do not upload anything.
        mock: Upload to a testing bucket rather than the real one.
        force_keysets: Set of keysets to use rather than what the inputs say.
        force_channels: Set of channels to use rather than what the inputs say.
        buildroot: Buildroot in which to look for signing instructions.
        dest_bucket: Bucket to push results to.

    Returns:
        A dictionary that maps 'channel' -> ['gs://signer_instruction_uri1',
                                            'gs://signer_instruction_uri2',
                                            ...]
    """
    # Whether we hit an unknown error.  If so, we'll throw an error, but only
    # at the end (so that we still upload as many files as possible).
    # It's implemented using a list to deal with variable scopes in nested
    # functions below.
    unknown_error = [False]

    if versionrev is None:
        # Extract milestone/version from the directory name.
        versionrev = os.path.basename(src_path)

    # We only support the latest format here.  Older releases can use pushimage
    # from the respective branch which deals with legacy cruft.
    m = re.match(VERSION_REGEX, versionrev)
    if not m:
        raise ValueError(
            "version %s does not match %s" % (versionrev, VERSION_REGEX)
        )
    milestone = m.group(1)
    version = m.group(2)

    # Normalize board to always use dashes not underscores.  This is mostly a
    # historical artifact at this point, but we can't really break it since the
    # value is used in URLs.
    boardpath = board.replace("_", "-")
    if profile is not None:
        boardpath += "-%s" % profile.replace("_", "-")

    ctx = gs.GSContext(dry_run=dryrun)

    try:
        input_insns = InputInsns(board, buildroot=buildroot)
    except MissingBoardInstructions as e:
        logging.warning("Missing base instruction file: %s", e)
        logging.warning("not uploading anything for signing")
        return

    if force_channels is None:
        channels = input_insns.GetChannels()
    else:
        # Filter out duplicates.
        channels = sorted(set(force_channels))

    # We want force_keysets as a set.
    force_keysets = set(force_keysets)

    if mock:
        logging.info("Upload mode: mock; signers will not process anything")
        tbs_base = gs_base = os.path.join(
            constants.TRASH_BUCKET, "pushimage-tests", getpass.getuser()
        )
    elif {f"{TEST_KEYSET_PREFIX}-{x}" for x in TEST_KEYSETS} & force_keysets:
        logging.info("Upload mode: test; signers will process test keys")
        # We need the tbs_base to be in the place the signer will actually scan.
        tbs_base = TEST_SIGN_BUCKET_BASE
        gs_base = os.path.join(tbs_base, getpass.getuser())
    else:
        logging.info("Upload mode: normal; signers will process the images")
        tbs_base = gs_base = dest_bucket

    sect_general = {
        "config_board": board,
        "board": boardpath,
        "version": version,
        "versionrev": versionrev,
        "milestone": milestone,
    }
    sect_insns = {}

    if dryrun:
        logging.info("DRY RUN MODE ACTIVE: NOTHING WILL BE UPLOADED")
    logging.info("Signing for channels: %s", " ".join(channels))

    instruction_urls = {}

    def _ImageNameBase(image_type=None):
        lmid = ("%s-" % image_type) if image_type else ""
        return "ChromeOS-%s%s-%s" % (lmid, versionrev, boardpath)

    # These variables are defined outside the loop so that the nested functions
    # below can access them without 'cell-var-from-loop' linter warning.
    dst_path = ""
    files_to_sign = []
    for channel in channels:
        logging.debug("\n\n#### CHANNEL: %s ####\n", channel)
        sect_insns["channel"] = channel
        sub_path = "%s-channel/%s/%s" % (channel, boardpath, version)
        dst_path = "%s/%s" % (gs_base, sub_path)
        logging.info("Copying images to %s", dst_path)

        recovery_basename = _ImageNameBase(constants.IMAGE_TYPE_RECOVERY)
        factory_basename = _ImageNameBase(constants.IMAGE_TYPE_FACTORY)
        firmware_basename = _ImageNameBase(constants.IMAGE_TYPE_FIRMWARE)
        hps_firmware_basename = _ImageNameBase(
            constants.IMAGE_TYPE_HPS_FIRMWARE
        )
        acc_usbpd_basename = _ImageNameBase(
            constants.IMAGE_TYPE_ACCESSORY_USBPD
        )
        acc_rwsig_basename = _ImageNameBase(
            constants.IMAGE_TYPE_ACCESSORY_RWSIG
        )
        gsc_firmware_basename = _ImageNameBase(
            constants.IMAGE_TYPE_GSC_FIRMWARE
        )
        test_basename = _ImageNameBase(constants.IMAGE_TYPE_TEST)
        base_basename = _ImageNameBase(constants.IMAGE_TYPE_BASE)
        hwqual_tarball = "chromeos-hwqual-%s-%s.tar.bz2" % (board, versionrev)

        # The following build artifacts, if present, are always copied
        # regardless of requested signing types.
        files_to_copy_only = (
            # (<src>, <dst>, <suffix>),
            ("image.zip", _ImageNameBase(), "zip"),
            (constants.TEST_IMAGE_TAR, test_basename, "tar.xz"),
            ("debug.tgz", "debug-%s" % boardpath, "tgz"),
            (hwqual_tarball, None, None),
            ("stateful.tgz", None, None),
            ("dlc", None, None),
            (constants.QUICK_PROVISION_PAYLOAD_KERNEL, None, None),
            (constants.QUICK_PROVISION_PAYLOAD_ROOTFS, None, None),
            (constants.QUICK_PROVISION_PAYLOAD_MINIOS, None, None),
        )

        # The following build artifacts, if present, are always copied.
        # If |sign_types| is None, all of them are marked for signing, otherwise
        # only the image types specified in |sign_types| are marked for signing.
        files_to_copy_and_maybe_sign = (
            # (<src>, <dst>, <suffix>, <signing type>),
            (
                constants.RECOVERY_IMAGE_TAR,
                recovery_basename,
                "tar.xz",
                constants.IMAGE_TYPE_RECOVERY,
            ),
            (
                "factory_image.zip",
                factory_basename,
                "zip",
                constants.IMAGE_TYPE_FACTORY,
            ),
            (
                "firmware_from_source.tar.bz2",
                firmware_basename,
                "tar.bz2",
                constants.IMAGE_TYPE_FIRMWARE,
            ),
        )

        # The following build artifacts are copied and marked for signing, if
        # they are present *and* if the image type is specified via
        # |sign_types|.
        files_to_maybe_copy_and_sign = (
            # (<src>, <dst>, <suffix>, <signing type>),
            (
                constants.BASE_IMAGE_TAR,
                base_basename,
                "tar.xz",
                constants.IMAGE_TYPE_BASE,
            ),
            (
                "firmware_from_source.tar.bz2",
                hps_firmware_basename,
                "tar.bz2",
                constants.IMAGE_TYPE_HPS_FIRMWARE,
            ),
            (
                "firmware_from_source.tar.bz2",
                acc_usbpd_basename,
                "tar.bz2",
                constants.IMAGE_TYPE_ACCESSORY_USBPD,
            ),
            (
                "firmware_from_source.tar.bz2",
                acc_rwsig_basename,
                "tar.bz2",
                constants.IMAGE_TYPE_ACCESSORY_RWSIG,
            ),
            (
                "firmware_from_source.tar.bz2",
                gsc_firmware_basename,
                "tar.bz2",
                constants.IMAGE_TYPE_GSC_FIRMWARE,
            ),
        )

        def _CopyFileToGS(src, dst=None, suffix=None):
            """Returns |dst| file name if the copying was successful."""
            if dst is None:
                dst = src
            elif suffix is not None:
                dst = "%s.%s" % (dst, suffix)
            success = False
            try:
                ctx.Copy(
                    os.path.join(src_path, src),
                    os.path.join(dst_path, dst),
                    recursive=True,
                )
                success = True
            except gs.GSNoSuchKey:
                logging.warning("Skipping %s as it does not exist", src)
            except gs.GSContextException:
                unknown_error[0] = True
                logging.error(
                    "Skipping %s due to unknown GS error", src, exc_info=True
                )
            return dst if success else None

        for src, dst, suffix in files_to_copy_only:
            _CopyFileToGS(src, dst, suffix)

        # Clear the list of files to sign before adding new artifacts.
        files_to_sign = []

        def _AddToFilesToSign(image_type, dst, suffix):
            assert dst.endswith("." + suffix), "dst: %s, suffix: %s" % (
                dst,
                suffix,
            )
            dst_base = dst[: -(len(suffix) + 1)]
            files_to_sign.append([image_type, dst_base, suffix])

        for src, dst, suffix, image_type in files_to_copy_and_maybe_sign:
            dst = _CopyFileToGS(src, dst, suffix)
            if dst and (not sign_types or image_type in sign_types):
                _AddToFilesToSign(image_type, dst, suffix)

        for src, dst, suffix, image_type in files_to_maybe_copy_and_sign:
            if sign_types and image_type in sign_types:
                dst = _CopyFileToGS(src, dst, suffix)
                if dst:
                    _AddToFilesToSign(image_type, dst, suffix)

        logging.debug("Files to sign: %s", files_to_sign)
        unused_sign_types = set(sign_types or []) - set(
            x for x, _, _ in files_to_sign
        )
        if unused_sign_types:
            logging.warning(
                "Some sign types were unused: %s", " ".join(unused_sign_types)
            )

        # Now go through the subset for signing.
        for image_type, dst_name, suffix in files_to_sign:
            try:
                input_insns = InputInsns(
                    board, image_type=image_type, buildroot=buildroot
                )
            except MissingBoardInstructions as e:
                logging.info("Nothing to sign: %s", e)
                continue

            dst_archive = "%s.%s" % (dst_name, suffix)
            sect_general["archive"] = dst_archive
            sect_general["type"] = image_type

            # In the default/automatic mode, only flag files for signing if the
            # archives were actually uploaded in a previous stage. This
            # additional check can be removed in future once |sign_types|
            # becomes a required argument.
            # TODO: Make |sign_types| a required argument.
            gs_artifact_path = os.path.join(dst_path, dst_archive)
            exists = False
            try:
                exists = ctx.Exists(gs_artifact_path)
            except gs.GSContextException:
                unknown_error[0] = True
                logging.error(
                    "Unknown error while checking %s",
                    gs_artifact_path,
                    exc_info=True,
                )
            if not exists:
                logging.info(
                    "%s does not exist.  Nothing to sign.", gs_artifact_path
                )
                continue

            first_image = True
            for alt_insn_set in input_insns.GetAltInsnSets():
                # Figure out which keysets have been requested for this type.
                # We sort the forced set so tests/runtime behavior is stable.
                keysets = sorted(force_keysets)
                if not keysets:
                    keysets = input_insns.GetKeysets(insns_merge=alt_insn_set)
                    if not keysets:
                        logging.warning(
                            "Skipping %s image signing due to no keysets",
                            image_type,
                        )

                for keyset in keysets:
                    sect_insns["keyset"] = keyset

                    # Generate the insn file for this artifact that the signer
                    # will use, and flag it for signing.
                    with cros_build_lib.UnbufferedNamedTemporaryFile(
                        prefix="pushimage.insns."
                    ) as insns_path:
                        input_insns.OutputInsns(
                            insns_path.name,
                            sect_insns,
                            sect_general,
                            insns_merge=alt_insn_set,
                        )

                        gs_insns_path = "%s/%s" % (dst_path, dst_name)
                        if not first_image:
                            gs_insns_path += "-%s" % keyset
                        first_image = False
                        gs_insns_path += ".instructions"

                        try:
                            ctx.Copy(insns_path.name, gs_insns_path)
                        except gs.GSContextException:
                            unknown_error[0] = True
                            logging.error(
                                "Unknown error while uploading insns %s",
                                gs_insns_path,
                                exc_info=True,
                            )
                            continue

                        try:
                            MarkImageToBeSigned(
                                ctx, tbs_base, gs_insns_path, priority
                            )
                        except gs.GSContextException:
                            unknown_error[0] = True
                            logging.error(
                                "Unknown error while marking for signing %s",
                                gs_insns_path,
                                exc_info=True,
                            )
                            continue
                        logging.info(
                            "Signing %s image with keyset %s at %s",
                            image_type,
                            keyset,
                            gs_insns_path,
                        )
                        instruction_urls.setdefault(channel, []).append(
                            gs_insns_path
                        )

    if unknown_error[0]:
        raise PushError("hit some unknown error(s)", instruction_urls)

    return instruction_urls


def GetParser():
    """Creates the argparse parser."""
    parser = commandline.ArgumentParser(description=__doc__, dryrun=True)

    # The type of image_dir will strip off trailing slashes (makes later
    # processing simpler and the display prettier).
    parser.add_argument(
        "image_dir",
        default=None,
        type="local_or_gs_path",
        help="full path of source artifacts to upload",
    )
    parser.add_argument(
        "--board",
        default=None,
        required=True,
        help="board to generate symbols for",
    )
    parser.add_argument(
        "--profile", default=None, help='board profile in use (e.g. "asan")'
    )
    parser.add_argument(
        "--version",
        default=None,
        help="version info (normally extracted from image_dir)",
    )
    parser.add_argument(
        "--channels",
        default=None,
        action="split_extend",
        help="override list of channels to process",
    )
    parser.add_argument(
        "-M",
        "--mock",
        default=False,
        action="store_true",
        help="upload things to a testing bucket (dev testing)",
    )
    parser.add_argument(
        "--test-sign",
        default=[],
        action="append",
        choices=TEST_KEYSETS,
        help="mung signing behavior to sign w/ test keys",
    )
    parser.add_argument(
        "--priority",
        type=int,
        default=50,
        help="set signing priority (lower == higher prio)",
    )
    parser.add_argument(
        "--sign-types",
        default=None,
        nargs="+",
        choices=_SUPPORTED_IMAGE_TYPES,
        help="only sign specified image types",
    )
    parser.add_argument(
        "--buildroot",
        default=constants.SOURCE_ROOT,
        type="path",
        help="Buildroot to use. Defaults to current.",
    )
    parser.add_argument(
        "--yes",
        action="store_true",
        default=False,
        help="answer yes to all prompts",
    )
    parser.add_argument(
        "--dest-bucket",
        default=constants.RELEASE_BUCKET,
        help="dest bucket. Default to %(default)s",
    )

    return parser


def main(argv):
    parser = GetParser()
    opts = parser.parse_args(argv)
    opts.Freeze()

    force_keysets = {f"{TEST_KEYSET_PREFIX}-{x}" for x in opts.test_sign}

    # If we aren't using mock or test or dry run mode, then let's prompt the
    # user to make sure they actually want to do this.  It's rare that people
    # want to run this directly and hit the release bucket.
    if not (opts.mock or force_keysets or opts.dryrun) and not opts.yes:
        prolog = "\n".join(
            textwrap.wrap(
                textwrap.dedent(
                    "Uploading images for signing to the *release* bucket is"
                    " not something you generally should be doing yourself."
                ),
                80,
            )
        ).strip()
        if not cros_build_lib.BooleanPrompt(
            prompt="Are you sure you want to sign these images",
            default=False,
            prolog=prolog,
        ):
            cros_build_lib.Die("better safe than sorry")

    PushImage(
        opts.image_dir,
        opts.board,
        versionrev=opts.version,
        profile=opts.profile,
        priority=opts.priority,
        sign_types=opts.sign_types,
        dryrun=opts.dryrun,
        mock=opts.mock,
        force_keysets=force_keysets,
        force_channels=opts.channels,
        buildroot=opts.buildroot,
        dest_bucket=opts.dest_bucket,
    )
