From f06040486b63e8e3b586f259995a2c734393acbf Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 10 Sep 2021 23:07:04 +0200 Subject: [PATCH 1/4] yolo: Export test summary as image --- lib/analyze_test_results.py | 159 ++++++++++++++++++++++-------------- 1 file changed, 97 insertions(+), 62 deletions(-) diff --git a/lib/analyze_test_results.py b/lib/analyze_test_results.py index 775d0a0..a73a7f7 100644 --- a/lib/analyze_test_results.py +++ b/lib/analyze_test_results.py @@ -2,7 +2,7 @@ import sys import json import os import time - +import imgkit def load_tests(test_folder): @@ -26,19 +26,19 @@ def test_notes(test): return if test["test_type"] == "PACKAGE_LINTER" and test['results']['main_result'] == 'success' and test['results'].get("warning"): - yield '\033[93m%s warnings\033[0m' % len(test['results'].get("warning")) + yield '%s warnings' % len(test['results'].get("warning")) if test['results'].get("witness"): - yield '\033[91mMissing witness file\033[0m' + yield 'Missing witness file' if test['results'].get("alias_traversal"): - yield '\033[91mNginx path traversal issue\033[0m' + yield 'Nginx path traversal issue' if test['results'].get("too_many_warnings"): - yield '\033[93mBad UX because shitload of warnings\033[0m' + yield 'Bad UX because shitload of warnings' if test['results'].get("install_dir_permissions"): - yield '\033[91mUnsafe install dir permissions\033[0m' + yield 'Unsafe install dir permissions' levels = [] @@ -184,67 +184,102 @@ def level_9(tests): and "App.qualify_for_level_9" in linter_tests[0]["results"]["success"] +def make_summary(): + + test_types = { + "PACKAGE_LINTER": "Package linter", + "TEST_INSTALL": "Install", + "TEST_UPGRADE": "Upgrade", + "TEST_BACKUP_RESTORE": "Backup/restore", + "TEST_CHANGE_URL": "Change url", + "TEST_PORT_ALREADY_USED": "Port already used", + "ACTIONS_CONFIG_PANEL": "Config/panel" + } + + latest_test_serie = "default" + yield "" + for test in tests: + test_display_name = test_types[test["test_type"]] + if test["test_arg"]: + test_display_name += " (%s)" % test["test_arg"][:8] + test_display_name += ":" + if test["test_serie"] != latest_test_serie: + latest_test_serie = test["test_serie"] + yield "------------- %s -------------" % latest_test_serie + + result = " OK" if test["results"]["main_result"] == "success" else "fail" + + if test["notes"]: + result += "(%s)" % ', '.join(test["notes"]) + + yield "{test: <30}{result}".format(test=test_display_name, result=result) + + yield "" + yield "Level results" + yield "=============" + + stop_global_level_bump = False + + global global_level + global_level = level_0 + + for level in levels[1:]: + level.passed = level(tests) + + if not level.passed: + stop_global_level_bump = True + + if not stop_global_level_bump: + global_level = level + display = "OK" + else: + display = " ok " if level.passed else "" + + yield "Level {i} {descr: <40} {result}".format(i=level.level, + descr="(%s)" % level.descr[:38], + result=display) + + yield "" + yield "Global level for this application: %s (%s)" % (global_level.level, global_level.descr) + yield "" + + +def render_for_terminal(text): + return text \ + .replace("", "\033[1m\033[92m") \ + .replace("", "\033[93m") \ + .replace("", "\033[91m") \ + .replace("", "\033[0m") + + +def export_as_image(text, output): + text = text \ + .replace("", '') \ + .replace("", '') \ + .replace("", '') \ + .replace("", '') + + text = f""" + + +
+{text}
+
+ +""" + + imgkit.from_string(text, output) + + test_context = sys.argv[1] tests = list(load_tests(test_context)) -test_types = { - "PACKAGE_LINTER": "Package linter", - "TEST_INSTALL": "Install", - "TEST_UPGRADE": "Upgrade", - "TEST_BACKUP_RESTORE": "Backup/restore", - "TEST_CHANGE_URL": "Change url", - "TEST_PORT_ALREADY_USED": "Port already used", - "ACTIONS_CONFIG_PANEL": "Config/panel" -} +global_level = None -OK = ' \033[1m\033[92mOK\033[0m ' -FAIL = '\033[91mfail\033[0m' - -latest_test_serie = "default" -print() -for test in tests: - test_display_name = test_types[test["test_type"]] - if test["test_arg"]: - test_display_name += " (%s)" % test["test_arg"][:8] - test_display_name += ":" - if test["test_serie"] != latest_test_serie: - latest_test_serie = test["test_serie"] - print("------------- %s -------------" % latest_test_serie) - - result = OK if test["results"]["main_result"] == "success" else FAIL - - if test["notes"]: - result += "(%s)" % ', '.join(test["notes"]) - - print("{test: <30}{result}".format(test=test_display_name, result=result)) - -print() -print("Level results") -print("=============") - -stop_global_level_bump = False - -global_level = level_0 - -for level in levels[1:]: - level.passed = level(tests) - - if not level.passed: - stop_global_level_bump = True - - if not stop_global_level_bump: - global_level = level - display = OK - else: - display = " ok " if level.passed else "" - - print("Level {i} {descr: <40} {result}".format(i=level.level, - descr="(%s)"%level.descr[:38], result=display)) - -print() -print("\033[1mGlobal level for this application: %s (%s)\033[0m" % (global_level.level, global_level.descr)) -print() +summary = '\n'.join(make_summary()) +print(render_for_terminal(summary)) +export_as_image(summary, test_context + "/summary.jpg") summary = { "app": open(test_context + "/app_id").read().strip(), From 589a85bdb41331ee01e15facb763124c8a712f38 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 10 Sep 2021 23:12:12 +0200 Subject: [PATCH 2/4] Magically install imgkit --- lib/common.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/common.sh b/lib/common.sh index a658a81..931db29 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -213,10 +213,11 @@ function fetch_or_upgrade_package_linter() then log_info "Installing Package linter" git clone --quiet $git_repository "./package_linter" - pip3 install pyparsing six + pip3 install pyparsing six imgkit else git -C "./package_linter" fetch origin --quiet git -C "./package_linter" reset --hard origin/master --quiet + python3 -c "import imgkit" 2>/dev/null || pip3 install imgkit fi } From a43463522d9ae5182437a442aa76fed713ae9615 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Fri, 10 Sep 2021 23:13:29 +0200 Subject: [PATCH 3/4] Improve imgkit export options --- lib/analyze_test_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/analyze_test_results.py b/lib/analyze_test_results.py index a73a7f7..af3c787 100644 --- a/lib/analyze_test_results.py +++ b/lib/analyze_test_results.py @@ -268,7 +268,7 @@ def export_as_image(text, output): """ - imgkit.from_string(text, output) + imgkit.from_string(text, output, options={"crop-w": 600, "quiet": ""}) test_context = sys.argv[1] From e1cbb22f4984938ff927a16586c68f43cf699131 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 22 Sep 2021 22:36:21 +0200 Subject: [PATCH 4/4] Misc fixes /o\ --- lib/analyze_test_results.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/analyze_test_results.py b/lib/analyze_test_results.py index af3c787..0ae7d8f 100644 --- a/lib/analyze_test_results.py +++ b/lib/analyze_test_results.py @@ -210,7 +210,7 @@ def make_summary(): result = " OK" if test["results"]["main_result"] == "success" else "fail" if test["notes"]: - result += "(%s)" % ', '.join(test["notes"]) + result += " (%s)" % ', '.join(test["notes"]) yield "{test: <30}{result}".format(test=test_display_name, result=result) @@ -231,7 +231,7 @@ def make_summary(): if not stop_global_level_bump: global_level = level - display = "OK" + display = " OK" else: display = " ok " if level.passed else "" @@ -249,6 +249,7 @@ def render_for_terminal(text): .replace("", "\033[1m\033[92m") \ .replace("", "\033[93m") \ .replace("", "\033[91m") \ + .replace("", "\033[1m") \ .replace("", "\033[0m") @@ -257,6 +258,7 @@ def export_as_image(text, output): .replace("", '') \ .replace("", '') \ .replace("", '') \ + .replace("", '') \ .replace("", '') text = f""" @@ -279,7 +281,10 @@ global_level = None summary = '\n'.join(make_summary()) print(render_for_terminal(summary)) -export_as_image(summary, test_context + "/summary.jpg") +if os.path.exists("/usr/bin/wkhtmltoimage"): + export_as_image(summary, test_context + "/summary.jpg") +else: + print("(Protip™ for CI admin: you should 'apt install wkhtmltopdf --no-install-recommends' to enable result summary export to .jpg)") summary = { "app": open(test_context + "/app_id").read().strip(),