# Path: tasks/packaging/model.py
# class DockerImageRecipe:
#     enabled: bool
#     architecture: str
#     flavors: List[str]
#     base_distribution: str
#     base_image: str
#     platform: str
# 
# class PackageSpecification:
#     """
#     Data structure for holding information about individual distribution
#     packages.
#     """
# 
#     # Package flavor, e.g. minimal, standard, full.
#     flavor: str
# 
#     # Package version.
#     version: str
# 
#     # Distribution name, e.g. stretch, buster.
#     distribution: str
# 
#     # Architecture, e.g. amd64, arm64v8, arm32v7.
#     architecture: str
# 
#     # Computed package name, taking `flavor` into account.
#     name: str = None
# 
#     # List of Python `extra` labels, taking `flavor` into account.
#     features: str = None
# 
#     # Map architecture labels to Debian distribution package architecture name.
#     debian_architecture_map: ClassVar = {
#         "arm64v8": "arm64",
#         "arm32v7": "armhf",
#     }
# 
#     def __post_init__(self):
#         self.resolve()
#         self.validate()
# 
#     def validate(self):
#         """
#         Sanity checks. All designated specification fields must be set and not
#         be empty.
#         """
#         for field in dataclasses.fields(self):
#             value = getattr(self, field.name)
#             if value is None:
#                 raise ValueError(
#                     f'Package specification field "{field.name}" is required.'
#                 )
# 
#     def resolve(self):
#         """
#         Resolve the designated package flavor to a list of Python package
#         `extra` labels.
#         """
#         if self.flavor == "minimal":
#             self.name = "kotori-minimal"
#             self.features = "daq"
#         elif self.flavor == "standard":
#             self.name = "kotori-standard"
#             self.features = "daq,daq_geospatial,export"
#         elif self.flavor == "full":
#             self.name = "kotori"
#             self.features = "daq,daq_geospatial,export,plotting,firmware,scientific"
#         else:
#             raise ValueError("Unknown package flavor")
# 
#     @property
#     def debian_architecture(self):
#         """
#         Resolve the architecture label to a Debian package architecture suffix.
#         """
#         return self.debian_architecture_map.get(self.architecture, self.architecture)
# 
#     def deb_name(self):
#         """
#         Compute the full name of the Debian `.deb` package.
#         """
#         return f"{self.name}_{self.version}-1~{self.distribution}_{self.debian_architecture}.deb"
# 
# Path: tasks/util.py
# def print_header(label, char="-"):
#     length = max(len(label), 42)
#     print(char * length)
#     print(label.center(length))
#     print(char * length)
# 
# def run_commands(commands):
#     if isinstance(commands, str):
#         commands = [commands]
#     for command in commands:
#         command = command.strip()
#         print(command)
#         exitcode = os.system(command)
#         if exitcode != 0:
#             raise SystemExit("Command failed")
# 
# def task(f: F) -> F:
#     f.__annotations__ = {}
#     return invoke.task(f)


import dataclasses
import os
import requests
import sh
from datetime import datetime
from pathlib import Path
from typing import List
from invoke import Context
from tasks.packaging.model import DockerImageRecipe, PackageSpecification
from tasks.util import print_header, run_commands, task
    def qa(self, tag: str = None):
        for recipe in self.recipes:

            if not recipe.enabled:
                continue

            for flavor in recipe.flavors:

                # TODO: This is currently only needed to resolve the "name" from the "flavor". Refactor it!
                spec = PackageSpecification(
                    distribution=recipe.base_distribution,
                    architecture=recipe.architecture,
                    flavor=flavor,
                    version="n/a",
                )

                image_name = f"daqzilla/{spec.name}"
                if tag:
                    image_name += f":{tag}"

                print_header(
                    f"Running QA for Docker image {image_name} on {recipe.platform}"
                )

                command = f"docker run -it --rm --platform={recipe.platform} {image_name} kotori --version"
                run_commands(command)

                print()



# Path: tasks/packaging/model.py
# class DockerImageRecipe:
#     enabled: bool
#     architecture: str
#     flavors: List[str]
#     base_distribution: str
#     base_image: str
#     platform: str
# 
# class PackageSpecification:
#     """
#     Data structure for holding information about individual distribution
#     packages.
#     """
# 
#     # Package flavor, e.g. minimal, standard, full.
#     flavor: str
# 
#     # Package version.
#     version: str
# 
#     # Distribution name, e.g. stretch, buster.
#     distribution: str
# 
#     # Architecture, e.g. amd64, arm64v8, arm32v7.
#     architecture: str
# 
#     # Computed package name, taking `flavor` into account.
#     name: str = None
# 
#     # List of Python `extra` labels, taking `flavor` into account.
#     features: str = None
# 
#     # Map architecture labels to Debian distribution package architecture name.
#     debian_architecture_map: ClassVar = {
#         "arm64v8": "arm64",
#         "arm32v7": "armhf",
#     }
# 
#     def __post_init__(self):
#         self.resolve()
#         self.validate()
# 
#     def validate(self):
#         """
#         Sanity checks. All designated specification fields must be set and not
#         be empty.
#         """
#         for field in dataclasses.fields(self):
#             value = getattr(self, field.name)
#             if value is None:
#                 raise ValueError(
#                     f'Package specification field "{field.name}" is required.'
#                 )
# 
#     def resolve(self):
#         """
#         Resolve the designated package flavor to a list of Python package
#         `extra` labels.
#         """
#         if self.flavor == "minimal":
#             self.name = "kotori-minimal"
#             self.features = "daq"
#         elif self.flavor == "standard":
#             self.name = "kotori-standard"
#             self.features = "daq,daq_geospatial,export"
#         elif self.flavor == "full":
#             self.name = "kotori"
#             self.features = "daq,daq_geospatial,export,plotting,firmware,scientific"
#         else:
#             raise ValueError("Unknown package flavor")
# 
#     @property
#     def debian_architecture(self):
#         """
#         Resolve the architecture label to a Debian package architecture suffix.
#         """
#         return self.debian_architecture_map.get(self.architecture, self.architecture)
# 
#     def deb_name(self):
#         """
#         Compute the full name of the Debian `.deb` package.
#         """
#         return f"{self.name}_{self.version}-1~{self.distribution}_{self.debian_architecture}.deb"
# 
# Path: tasks/util.py
# def print_header(label, char="-"):
#     length = max(len(label), 42)
#     print(char * length)
#     print(label.center(length))
#     print(char * length)
# 
# def run_commands(commands):
#     if isinstance(commands, str):
#         commands = [commands]
#     for command in commands:
#         command = command.strip()
#         print(command)
#         exitcode = os.system(command)
#         if exitcode != 0:
#             raise SystemExit("Command failed")
# 
# def task(f: F) -> F:
#     f.__annotations__ = {}
#     return invoke.task(f)


# Path: tasks/packaging/docker.py
import dataclasses
import os
import requests
import sh
from datetime import datetime
from pathlib import Path
from typing import List
from invoke import Context
from tasks.packaging.model import DockerImageRecipe, PackageSpecification
from tasks.util import print_header, run_commands, task

    def qa(self, tag: str = None):
        for recipe in self.recipes:

            if not recipe.enabled:
                continue

            for flavor in recipe.flavors:

                # TODO: This is currently only needed to resolve the "name" from the "flavor". Refactor it!
                spec = PackageSpecification(
                    distribution=recipe.base_distribution,
                    architecture=recipe.architecture,
                    flavor=flavor,
                    version="n/a",
                )

                image_name = f"daqzilla/{spec.name}"
                if tag:
                    image_name += f":{tag}"

                print_header(
                    f"Running QA for Docker image {image_name} on {recipe.platform}"
                )

                command = f"docker run -it --rm --platform={recipe.platform} {image_name} kotori --version"
                run_commands(command)

                print()



@task