summaryrefslogtreecommitdiff
path: root/squad_client/commands/submit_tuxbuild.py
blob: f562bed193c5da517efa1af002b128d79907428f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import hashlib
import json
import jsonschema
import logging
from squad_client.shortcuts import submit_results
from squad_client.core.command import SquadClientCommand

logger = logging.getLogger()

tuxbuild_schema = {
    "type": "object",
    "properties": {
        "build_status": {
            "type": "string",
            "enum": ["fail", "pass"],
        },
        "git_describe": {
            "type": "string",
        },
        "kconfig": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": True,
            "items": [{"type": "string"}],
        },
        "target_arch": {
            "type": "string",
        },
        "toolchain": {
            "type": "string",
        },
    },
    "required": [
        "build_status",
        "git_describe",
        "kconfig",
        "target_arch",
        "toolchain",
    ],
}


class SubmitTuxbuildCommand(SquadClientCommand):
    command = "submit-tuxbuild"
    help_text = "submit tuxbuild results to SQUAD"

    def register(self, subparser):
        parser = super(SubmitTuxbuildCommand, self).register(subparser)
        parser.add_argument(
            "--group", help="SQUAD group where results are stored", required=True
        )
        parser.add_argument(
            "--project", help="SQUAD project where results are stored", required=True
        )
        parser.add_argument(
            "tuxbuild",
            help="File with tuxbuild results to submit",
        )

    def _load_builds(self, path):
        builds = None
        try:
            with open(path) as f:
                builds = json.load(f)

        except json.JSONDecodeError as jde:
            logger.error("Failed to load json: %s", jde)

        except OSError as ose:
            logger.error("Failed to open file: %s", ose)

        return builds

    def _get_test_name(self, kconfig, toolchain):
        if len(kconfig[1:]):
            kconfig_hash = "%s-%s" % (
                kconfig[0],
                hashlib.sha1(json.dumps(kconfig[1:]).encode()).hexdigest()[0:8],
            )
        else:
            kconfig_hash = kconfig[0]

        return "build/%s-%s" % (toolchain, kconfig_hash)

    def run(self, args):
        builds = self._load_builds(args.tuxbuild)

        # log
        if builds is None:
            return False

        data = {}
        for build in builds:
            try:
                jsonschema.validate(instance=build, schema=tuxbuild_schema)

                arch = build["target_arch"]
                description = build["git_describe"]
                kconfig = build["kconfig"]
                status = build["build_status"]
                toolchain = build["toolchain"]
                test = self._get_test_name(kconfig, toolchain)

                multi_key = "%s.%s" % (description, arch)
                if multi_key not in data:
                    data[multi_key] = {}

                data[multi_key].update({test: status})

            except jsonschema.exceptions.ValidationError as ve:
                logger.error("Failed to validate tuxbuild data: %s", ve)
                return False

        for key, result in data.items():
            description, arch = key.split(".", 1)
            submit_results(
                group_project_slug="%s/%s" % (args.group, args.project),
                build_version=description,
                env_slug=arch,
                tests=result,
                metrics={},
                log={},
                metadata={},
            )

        return True