index_generator.py (2974B)
1 #!/usr/bin/env python3 2 3 import os 4 import re 5 import shlex 6 import subprocess 7 from pathlib import Path 8 9 from ansi2html import Ansi2HTMLConverter 10 from jinja2 import Environment, FileSystemLoader, select_autoescape 11 12 orig_cwd = os.getcwd() 13 qmk_firmware_dir = Path(os.path.realpath(__file__)).parents[2] 14 build_dir = qmk_firmware_dir / ".build" 15 16 KEYBOARD_PATTERN = re.compile("CI Metadata: KEYBOARD=(?P<keyboard>.*)\r?\n") 17 KEYMAP_PATTERN = re.compile("CI Metadata: KEYMAP=(?P<keymap>.*)\r?\n") 18 19 env = Environment( 20 loader=FileSystemLoader(Path(os.path.realpath(__file__)).parent / "templates"), 21 autoescape=select_autoescape(), 22 ) 23 24 25 def _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 40 def _ansi2html(value): 41 return Ansi2HTMLConverter().convert(value, full=False) 42 43 44 def _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 51 def _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 58 def _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 65 def _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 72 env.filters["ansi2html"] = _ansi2html 73 74 binaries = [] 75 binaries.extend(qmk_firmware_dir.glob("*.bin")) 76 binaries.extend(qmk_firmware_dir.glob("*.hex")) 77 binaries.extend(qmk_firmware_dir.glob("*.uf2")) 78 binaries = list(sorted(binaries)) 79 80 failures = [] 81 for 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 99 template = env.get_template("index.html.j2") 100 print(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 ))