yocto-autobuilder-helper/scripts/generate-testresult-index.py
sakib.sajal@windriver.com bbe9741d01 summarize_top_output.py: add script, use it and publish summary
summarize_top_output.py is used to summarize the top
output that is captured during autobuilder intermittent
failures.

Use the script to summarize the host top output and
publish the summary that is created instead of
the raw logfile.

Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2021-06-24 14:24:54 +01:00

185 lines
5.5 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Copyright (c) 2019, Linux Foundation
#
# SPDX-License-Identifier: GPL-2.0-only
#
import argparse
import os
import glob
import json
import subprocess
from jinja2 import Template
index_templpate = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index of autobuilder test results</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
</head>
<body>
<table class="table is-narrow is-striped">
<thead>
<tr>
<th>Build</th>
<th>Type</th>
<th>Branch</th>
<th>Test Results Report</th>
<th>Performance Reports</th>
<th>ptest Logs</th>
<th>Buildhistory</th>
<th>Host Data</th>
</tr>
</thead>
<tdata>
{% for entry in entries %}
<tr>
<td><a href="{{entry[1]}}">{{entry[0]}}</a></td>
<td>{% if entry[2] %} {{entry[2]}}{% endif %}</td>
<td>{% if entry[4] %} {{entry[4]}}{% endif %}</td>
<td> {% if entry[3] %}<a href="{{entry[3]}}">Report</a>{% endif %} </td>
<td>
{% for perfrep in entry[6] %}
<a href="{{perfrep[0]}}">{{perfrep[1]}}</a>
{% endfor %}
</td>
<td>
{% for ptest in entry[7] %}
<a href="{{ptest[0]}}">{{ptest[1]}}</a>
{% endfor %}
</td>
<td>
{% for bh in entry[5] %}
<a href="{{bh[0]}}">{{bh[1]}}</a>
{% endfor %}
</td>
<td>
{% for hd in entry[8] %}
<a href="{{hd[0]}}">{{hd[1]}}</a>
{% endfor %}
</td>
</tr>
{% endfor %}
</tdata>
</table>
</body>
</html>
"""
def parse_args(argv=None):
"""Parse command line arguments"""
parser = argparse.ArgumentParser(
description="Generate an html index for a directory of autobuilder results",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('path', help='path to directory to index')
return parser.parse_args(argv)
args = parse_args()
path = os.path.abspath(args.path)
entries = []
def get_build_branch(p):
for root, dirs, files in os.walk(p):
for name in files:
if name == "testresults.json":
f = os.path.join(root, name)
with open(f, "r") as filedata:
data = json.load(filedata)
for build in data:
try:
return data[build]['configuration']['LAYERS']['meta']['branch']
except KeyError:
continue
return ""
# Pad so 20190601-1 becomes 20190601-000001 and sorts correctly
def keygen(k):
if "-" not in k:
return k
k1, k2 = k.split("-")
return k1 + "-" + k2.rjust(6, '0')
for build in sorted(os.listdir(path), key=keygen, reverse=True):
buildpath = os.path.join(path, build, "testresults")
if not os.path.exists(buildpath):
# No test results
continue
reldir = "./" + build + "/"
btype = "other"
files = os.listdir(buildpath)
if os.path.exists(buildpath + "/a-full-posttrigger") or \
os.path.exists(buildpath + "/a-full"):
btype = "full"
elif os.path.exists(buildpath + "/a-quick-posttrigger") or \
os.path.exists(buildpath + "/a-quick"):
btype = "quick"
elif len(files) == 1:
btype = files[0]
testreport = ""
if os.path.exists(buildpath + "/testresult-report.txt"):
testreport = reldir + "testresults/testresult-report.txt"
ptestlogs = []
ptestseen = []
for p in glob.glob(buildpath + "/*-ptest/*.log"):
if p.endswith("resulttool-done.log"):
continue
buildname = os.path.basename(os.path.dirname(p))
if buildname not in ptestseen:
ptestlogs.append((reldir + "testresults/" + buildname + "/", buildname.replace("-ptest","")))
ptestseen.append(buildname)
perfreports = []
for p in glob.glob(buildpath + "/buildperf*/*.html"):
perfname = os.path.basename(os.path.dirname(p))
perfreports.append((reldir + "testresults/" + perfname + "/" + os.path.basename(p), perfname.replace("buildperf-","")))
buildhistory = []
if os.path.exists(buildpath + "/qemux86-64/buildhistory.txt"):
buildhistory.append((reldir + "testresults/qemux86-64/buildhistory.txt", "qemux86-64"))
if os.path.exists(buildpath + "/qemuarm/buildhistory.txt"):
buildhistory.append((reldir + "testresults/qemuarm/buildhistory.txt", "qemuarm"))
hd = []
counter = 0
# do we really need the loop?
for p in glob.glob(buildpath + "/*/*/host_stats*top_summary.txt"):
n_split = p.split(build)
res = reldir[0:-1] + n_split[1]
hd.append((res, str(counter)))
counter += 1
branch = get_build_branch(buildpath)
entries.append((build, reldir, btype, testreport, branch, buildhistory, perfreports, ptestlogs, hd))
# Also ensure we have saved out log data for ptest runs to aid debugging
if "ptest" in btype or btype in ["full", "quick"]:
for root, dirs, files in os.walk(buildpath):
for name in dirs:
if "ptest" in name:
f = os.path.join(root, name)
logs = glob.glob(f + "/*.log")
if logs:
continue
subprocess.check_call(["resulttool", "log", f, "--dump-ptest", f])
# Ensure we don't rerun every time with a dummy log
with open(f + "/resulttool-done.log", "a+") as tf:
tf.write("\n")
t = Template(index_templpate)
with open(os.path.join(path, "index.html"), 'w') as f:
f.write(t.render(entries = entries))