diff --git a/lib/analyze_test_results.py b/lib/analyze_test_results.py index 775d0a0..0ae7d8f 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,107 @@ 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[1m") \ + .replace("", "\033[0m") + + +def export_as_image(text, output): + text = text \ + .replace("", '') \ + .replace("", '') \ + .replace("", '') \ + .replace("", '') \ + .replace("", '') + + text = f""" + + +
+{text}
+
+ +""" + + imgkit.from_string(text, output, options={"crop-w": 600, "quiet": ""}) + + 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)) +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(), 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 }