index_generator.py
2974 bytes
1#!/usr/bin/env python3
2
3import os
4import re
5import shlex
6import subprocess
7from pathlib import Path
8
9from ansi2html import Ansi2HTMLConverter
10from jinja2 import Environment, FileSystemLoader, select_autoescape
11
12orig_cwd = os.getcwd()
13qmk_firmware_dir = Path(os.path.realpath(__file__)).parents[2]
14build_dir = qmk_firmware_dir / ".build"
15
16KEYBOARD_PATTERN = re.compile("CI Metadata: KEYBOARD=(?P<keyboard>.*)\r?\n")
17KEYMAP_PATTERN = re.compile("CI Metadata: KEYMAP=(?P<keymap>.*)\r?\n")
18
19env = Environment(
20 loader=FileSystemLoader(Path(os.path.realpath(__file__)).parent / "templates"),
21 autoescape=select_autoescape(),
22)
23
24
25def _run(command, capture_output=True, combined_output=False, text=True, **kwargs):
26 if isinstance(command, str):
27 command = shlex.split(command)
28 if capture_output:
29 kwargs["stdout"] = subprocess.PIPE
30 kwargs["stderr"] = subprocess.PIPE
31 if combined_output:
32 kwargs["stderr"] = subprocess.STDOUT
33 if "stdin" in kwargs and kwargs["stdin"] is None:
34 del kwargs["stdin"]
35 if text:
36 kwargs["universal_newlines"] = True
37 return subprocess.run(command, **kwargs)
38
39
40def _ansi2html(value):
41 return Ansi2HTMLConverter().convert(value, full=False)
42
43
44def _ansi2html_styles():
45 from ansi2html.style import get_styles
46
47 styles = get_styles(scheme="dracula")
48 return "\n".join([str(s) for s in styles])
49
50
51def _git_log(count=4):
52 os.chdir(qmk_firmware_dir)
53 ret = _run(f"git log -n {count} --color=always --no-merges --topo-order --stat").stdout.strip()
54 os.chdir(orig_cwd)
55 return ret
56
57
58def _git_describe():
59 os.chdir(qmk_firmware_dir)
60 ret = _run("git describe --tags --always --dirty").stdout.strip()
61 os.chdir(orig_cwd)
62 return ret
63
64
65def _git_revision():
66 os.chdir(qmk_firmware_dir)
67 ret = _run("git rev-parse HEAD").stdout.strip()
68 os.chdir(orig_cwd)
69 return ret
70
71
72env.filters["ansi2html"] = _ansi2html
73
74binaries = []
75binaries.extend(qmk_firmware_dir.glob("*.bin"))
76binaries.extend(qmk_firmware_dir.glob("*.hex"))
77binaries.extend(qmk_firmware_dir.glob("*.uf2"))
78binaries = list(sorted(binaries))
79
80failures = []
81for mdfile in list(sorted(build_dir.glob("failed.log.*"))):
82 txt = Path(mdfile).read_text()
83
84 m_kb = KEYBOARD_PATTERN.search(txt)
85 if not m_kb:
86 raise Exception("Couldn't determine the keyboard from the failure output")
87 m_km = KEYMAP_PATTERN.search(txt)
88 if not m_km:
89 raise Exception("Couldn't determine the keymap from the failure output")
90
91 txt = KEYBOARD_PATTERN.sub("", KEYMAP_PATTERN.sub("", txt)).strip()
92
93 failures.append({
94 "stdout": txt,
95 "keyboard": m_kb.group("keyboard"),
96 "keymap": m_km.group("keymap"),
97 })
98
99template = env.get_template("index.html.j2")
100print(template.render(
101 ansi2html_styles=_ansi2html_styles(),
102 git_log=_git_log(),
103 git_describe=_git_describe(),
104 git_revision=_git_revision(),
105 binaries=binaries,
106 failures=failures,
107))