Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/results.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ Example:
kci-dev results tests --giturl 'https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git' --branch master --commit d1486dca38afd08ca279ae94eb3a397f10737824
```

### test

Obtains a single test result.

Example:

```sh
kci-dev results test --id 'maestro:67d3e293f378f0c5986d3309' --download-logs --json
```

## Common parameters

### --origin
Expand Down
5 changes: 5 additions & 0 deletions kcidev/libs/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ def dashboard_fetch_tests(origin, giturl, branch, commit, arch):
return dashboard_api_fetch(endpoint, params)


def dashboard_fetch_test(test_id):
endpoint = f"test/{test_id}"
return dashboard_api_fetch(endpoint, {})


def dashboard_fetch_tree_list(origin):
params = {
"origin": origin,
Expand Down
25 changes: 25 additions & 0 deletions kcidev/libs/files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import gzip
import os
import re

import requests
from libs.common import kci_err

INVALID_FILE_CHARS = re.compile(r'[\\/:"*?<>|]+')


def to_valid_filename(filename):
return INVALID_FILE_CHARS.sub("", filename)


def download_logs_to_file(log_url, log_file):
try:
log_gz = requests.get(log_url)
log = gzip.decompress(log_gz.content)
log_file = to_valid_filename(log_file)
with open(log_file, mode="wb") as file:
file.write(log)
log_path = "file://" + os.path.join(os.getcwd(), log_file)
return log_path
except:
kci_err(f"Failed to fetch log {log_url}.")
37 changes: 33 additions & 4 deletions kcidev/subcommands/results/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
dashboard_fetch_boots,
dashboard_fetch_builds,
dashboard_fetch_summary,
dashboard_fetch_test,
dashboard_fetch_tests,
)
from libs.git_repo import set_giturl_branch_commit
from subcommands.results.parser import (
cmd_builds,
cmd_list_trees,
cmd_single_test,
cmd_summary,
cmd_tests,
)
Expand Down Expand Up @@ -63,7 +65,7 @@ def wrapper(*args, **kwargs):
return wrapper


def build_and_test_options(func):
def builds_and_tests_options(func):
@click.option(
"--download-logs",
is_flag=True,
Expand All @@ -90,6 +92,25 @@ def wrapper(*args, **kwargs):
return wrapper


def single_build_and_test_options(func):
@click.option(
"--id",
"op_id",
required=True,
help="Pass an id filter to get specific results",
)
@click.option(
"--download-logs",
is_flag=True,
help="Select desired results action",
)
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)

return wrapper


@click.group(help="[Experimental] Get results from the dashboard")
def results():
"""Commands related to results."""
Expand Down Expand Up @@ -121,7 +142,7 @@ def trees(origin, use_json):

@results.command()
@common_options
@build_and_test_options
@builds_and_tests_options
def builds(
origin,
git_folder,
Expand All @@ -146,7 +167,7 @@ def builds(

@results.command()
@common_options
@build_and_test_options
@builds_and_tests_options
def boots(
origin,
git_folder,
Expand All @@ -171,7 +192,7 @@ def boots(

@results.command()
@common_options
@build_and_test_options
@builds_and_tests_options
def tests(
origin,
git_folder,
Expand All @@ -194,5 +215,13 @@ def tests(
cmd_tests(data["tests"], commit, download_logs, status, filter, count, use_json)


@results.command()
@single_build_and_test_options
@results_display_options
def test(op_id, download_logs, use_json):
data = dashboard_fetch_test(op_id)
cmd_single_test(data, download_logs, use_json)


if __name__ == "__main__":
main_kcidev()
110 changes: 64 additions & 46 deletions kcidev/subcommands/results/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import requests
import yaml
from libs.dashboard import dashboard_fetch_tree_list
from libs.files import download_logs_to_file

from kcidev.libs.common import *

Expand Down Expand Up @@ -69,11 +70,16 @@ def create_test_json(test, log_path):
test_status = "FAIL"
else:
test_status = f"INCONCLUSIVE (status: {test['status']})"
config_name = "No config available"
if "config" in test:
config_name = test["config"]
elif "config_name" in test:
config_name = test["config_name"]
return {
"test_path": test["path"],
"hardware": test["environment_misc"]["platform"],
"compatibles": test.get("environment_compatible", []),
"config": test["config"],
"config": config_name,
"arch": test["architecture"],
"status": test_status,
"start_time": test["start_time"],
Expand Down Expand Up @@ -251,59 +257,71 @@ def cmd_tests(data, commit, download_logs, status_filter, filter, count, use_jso

log_path = test["log_url"]
if download_logs:
try:
log_gz = requests.get(test["log_url"])
log = gzip.decompress(log_gz.content)
log_file = f"{test['misc']['platform']}__{test['path']}__{test['config']}-{test['architecture']}-{test['compiler']}-{commit}.log"
with open(log_file, mode="wb") as file:
file.write(log)
log_path = "file://" + os.path.join(os.getcwd(), log_file)
except:
kci_err(f"Failed to fetch log {test['log_url']}.")
pass
log_file = f"{test['misc']['platform']}__{test['path']}__{test['config']}-{test['architecture']}-{test['compiler']}-{commit}.log"
log_path = download_logs_to_file(test["log_url"], log_file)
if count:
filtered_tests += 1
elif use_json:
tests.append(create_test_json(test, log_path))
else:
kci_msg_nonl("- test path: ")
kci_msg_cyan_nonl(test["path"])
kci_msg("")

kci_msg_nonl(" hardware: ")
kci_msg_cyan_nonl(test["environment_misc"]["platform"])
kci_msg("")

if test["environment_compatible"]:
kci_msg_nonl(" compatibles: ")
kci_msg_cyan_nonl(" | ".join(test["environment_compatible"]))
kci_msg("")

kci_msg_nonl(" config: ")
kci_msg_cyan_nonl(test["config"])
kci_msg_nonl(" arch: ")
kci_msg_cyan_nonl(test["architecture"])
kci_msg_nonl(" compiler: ")
kci_msg_cyan_nonl(test["compiler"])
kci_msg("")

kci_msg_nonl(" status:")
if test["status"] == "PASS":
kci_msg_green_nonl("PASS")
elif test["status"] == "FAIL":
kci_msg_red_nonl("FAIL")
else:
kci_msg_yellow_nonl(f"INCONCLUSIVE (status: {test['status']})")
kci_msg("")

kci_msg(f" log: {log_path}")
kci_msg(f" start time: {test['start_time']}")
kci_msg(f" id: {test['id']}")
kci_msg(f" dashboard: https://dashboard.kernelci.org/test/{test['id']}")
kci_msg("")
print_test(test, log_path)
if count and use_json:
kci_msg(f'{{"count":{filtered_tests}}}')
elif count:
kci_msg(filtered_tests)
elif use_json:
kci_msg(json.dumps(tests))


def print_test(test, log_path):
kci_msg_nonl("- test path: ")
kci_msg_cyan_nonl(test["path"])
kci_msg("")

kci_msg_nonl(" hardware: ")
kci_msg_cyan_nonl(test["environment_misc"]["platform"])
kci_msg("")

if test["environment_compatible"]:
kci_msg_nonl(" compatibles: ")
kci_msg_cyan_nonl(" | ".join(test["environment_compatible"]))
kci_msg("")

kci_msg_nonl(" config: ")
if "config" in test:
kci_msg_cyan_nonl(test["config"])
elif "config_name" in test:
kci_msg_cyan_nonl(test["config_name"])
else:
kci_msg_cyan_nonl("No config available")
kci_msg_nonl(" arch: ")
kci_msg_cyan_nonl(test["architecture"])
kci_msg_nonl(" compiler: ")
kci_msg_cyan_nonl(test["compiler"])
kci_msg("")

kci_msg_nonl(" status:")
if test["status"] == "PASS":
kci_msg_green_nonl("PASS")
elif test["status"] == "FAIL":
kci_msg_red_nonl("FAIL")
else:
kci_msg_yellow_nonl(f"INCONCLUSIVE (status: {test['status']})")
kci_msg("")

kci_msg(f" log: {log_path}")
kci_msg(f" start time: {test['start_time']}")
kci_msg(f" id: {test['id']}")
kci_msg(f" dashboard: https://dashboard.kernelci.org/test/{test['id']}")
kci_msg("")


def cmd_single_test(test, download_logs, use_json):
log_path = test["log_url"]
if download_logs:
log_file = f"{test['environment_misc']['platform']}__{test['path']}__{test['config_name']}-{test['architecture']}-{test['compiler']}-{test['id']}.log"
log_path = download_logs_to_file(test["log_url"], log_file)
if use_json:
kci_msg(create_test_json(test, log_path))
else:
print_test(test, log_path)