aboutsummaryrefslogtreecommitdiffstats
path: root/.github/scripts/tests/generate-summary.py
blob: 33d61b01f1addd88a8ee01a0980c944d1d6f5154 (plain) (blame)
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
#!/usr/bin/env python3
import argparse
import os
import dataclasses
import sys
from typing import Optional, List
from junit_utils import get_property_value, iter_xml_files


@dataclasses.dataclass
class SummaryEntry:
    target: str
    log_url: Optional[str]
    reason = ""
    is_failure: bool = False
    is_error: bool = False
    is_muted: bool = False
    is_skipped: bool = False

    @property
    def display_status(self):
        if self.is_error:
            return "Error"
        elif self.is_failure:
            return "Failure"
        elif self.is_muted:
            return "Muted"
        elif self.is_skipped:
            return "Skipped"

        return "?"


def parse_junit(folder_or_file):
    result = []
    for fn, suite, case in iter_xml_files(folder_or_file):
        is_failure = case.find("failure") is not None
        is_error = case.find("error") is not None
        is_muted = get_property_value(case, "mute") is not None
        is_skipped = is_muted is False and case.find("skipped") is not None

        if any([is_failure, is_muted, is_skipped, is_error]):
            cls, method = case.attrib["classname"], case.attrib["name"]
            log_url = get_property_value(case, "url:Log")
            target = f"{ cls }::{ method }" if cls != method else cls

            result.append(
                SummaryEntry(
                    target=target,
                    log_url=log_url,
                    is_skipped=is_skipped,
                    is_muted=is_muted,
                    is_failure=is_failure,
                    is_error=is_error,
                )
            )
    return result


def generate_summary(summary: List[SummaryEntry]):
    log_icon = ":floppy_disk:"
    mute_icon = ":white_check_mark:"

    text = [
        "| Test  | Muted | Log |",
        "| ----: | :---: | --: |",
    ]

    for entry in summary:
        if entry.log_url:
            log_url = f"[{log_icon}]({entry.log_url})"
        else:
            log_url = ""

        mute_target = mute_icon if entry.is_muted else ""

        text.append(f"| {entry.target} | {mute_target} |  {log_url} |")

    return text


def write_summary(title, lines: List[str]):
    summary_fn = os.environ.get("GITHUB_STEP_SUMMARY")
    if summary_fn:
        fp = open(summary_fn, "at")
    else:
        fp = sys.stdout

    if title:
        fp.write(f"{title}\n")
    for line in lines:
        fp.write(f"{line}\n")
    fp.write("\n")

    if summary_fn:
        fp.close()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--title")
    parser.add_argument("folder_or_file")

    args = parser.parse_args()

    summary = parse_junit(args.folder_or_file)

    if summary:
        text = generate_summary(summary)
        write_summary(args.title, text)


if __name__ == "__main__":
    main()