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
1 change: 1 addition & 0 deletions tests/fedora-review/main.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@
require:
- fedora-review
test: python3 ./run-fedora-review.py
result: custom
131 changes: 118 additions & 13 deletions tests/fedora-review/run-fedora-review.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,120 @@
import subprocess
import shutil
from pathlib import Path
from enum import Enum
import json
import yaml


def main(args: argparse.Namespace) -> None:
# Expose these to the users
FEDORA_REVIEW_RESULTS = [
"fedora-review.log.gz",
"files.dir",
"licensecheck.txt",
"review.json",
"review.txt",
"rpmlint.txt",
]


class Result(Enum):
INFO = "info"
FAIL = "fail"
PASS = "pass"


def dump_results_yaml(issues: int):
"""
https://tmt.readthedocs.io/en/stable/spec/results.html
"""
result = Result.FAIL if issues else Result.PASS
data = [
{
"name": "/",
"result": result.value,
"note": [f"{issues} issues"],
"log": ["viewer.html"] + FEDORA_REVIEW_RESULTS,
}
]
Comment thread
LecrisUT marked this conversation as resolved.
path = os.path.join(os.environ.get("TMT_TEST_DATA"), "results.yaml")
print(f"Creating: {path}")
with open(path, "w+") as fp:
yaml.dump(data, fp)


def copy_fedora_review_results(spec_file, workdir):
"""
Copy fedora-review logs and results to the result directory
"""
package_name = Path(spec_file).stem
fedora_review_resultdir = workdir / f"review-{package_name}"
test_resultdir = Path(os.environ["TMT_TEST_DATA"])
print(os.listdir(fedora_review_resultdir))
for name in FEDORA_REVIEW_RESULTS:
src = fedora_review_resultdir / name
dst = test_resultdir / name
print(src)
if src.exists():
print(f"Copying {name} to the test results")
shutil.copy(src, dst)


def copy_viewer_html():
"""
Copy viewer.html from plan data to the result directory
"""
viewer = "viewer.html"
print(f"Copying {viewer} to the test results")
shutil.copy(viewer, Path(os.environ["TMT_TEST_DATA"]) / viewer)


def copy_data_into_data():
"""
There is a weird bug that we discovered with @LecrisUT. For some reason,
when a plan has `result: custom`, the `viewer.html` stops rendering in
Testing Farm. It is because for some reason, Oculus starts looking for it
in `data/data/viewer.html` instead of just `data/viewer.html`.
This is IMHO a bug but either way, until it gets resolved, we can copy the
data there as well.
See https://gitlab.com/testing-farm/general/-/work_items/111
"""
shutil.copytree(
Path(os.environ["TMT_TEST_DATA"]),
Path(os.environ["TMT_TEST_DATA"]) / "data",
)
Comment thread
LecrisUT marked this conversation as resolved.


def fedora_review(spec_file, workdir):
"""
Run fedora-review
"""
env = os.environ.copy()
env["REVIEW_NO_MOCKGROUP_CHECK"] = "true"

name = Path(spec_file).stem
cmd = ["fedora-review", "--prebuilt", "-n", name]
print(f"Running: {" ".join(cmd)}")
subprocess.run(cmd, cwd=workdir, env=env, check=True)

path = os.path.join(workdir, "review-" + name, "review.json")
if not os.path.exists(path):
raise RuntimeError(f"Result JSON doesn't exist: {path}")
print("Result: {0}".format(path))

with open(path, "r") as fp:
review = json.load(fp)
return review


def count_issues(review):
issues = review.get("issues", [])
return len(issues)


def main(args: argparse.Namespace) -> None:
"""
Run fedora-review plan
"""
if not args.spec_file:
raise RuntimeError("No spec file provided")

Expand All @@ -22,19 +130,16 @@ def main(args: argparse.Namespace) -> None:
# we just need to copy the .spec next to them
shutil.copy(args.spec_file, args.workdir)

env = os.environ.copy()
env["REVIEW_NO_MOCKGROUP_CHECK"] = "true"

name = Path(args.spec_file).stem
cmd = ["fedora-review", "--prebuilt", "-n", name]
print(f"Running: {" ".join(cmd)}")
subprocess.run(cmd, cwd=args.workdir, env=env, check=True)
review = fedora_review(args.spec_file, args.workdir)
issues = count_issues(review)
dump_results_yaml(issues)
copy_fedora_review_results(args.spec_file, args.workdir)
copy_viewer_html()
copy_data_into_data()

result = os.path.join(args.workdir, "review-" + name, "review.json")
if not os.path.exists(result):
raise RuntimeError(f"Result JSON doesn't exist: {result}")

print("Result: {0}".format(result))
print(f"Found {issues} issues")
if issues:
sys.exit(1)


if __name__ == "__main__":
Expand Down
126 changes: 126 additions & 0 deletions tests/fedora-review/viewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!doctype html>
<html lang="en">
<head>
<title>fedora-review report viewer</title>
<meta charset="utf-8" />

<style>
.flexgap {
display: flex;
align-items: center;
gap: 1em;
}
.result {
padding: 1ex;
margin: 3ex;
background-color: #f2f2f2;
box-shadow: 2px 2px 2px lightgrey;
}
#summary {
gap: 2px;
margin: 5ex;
max-width: 100ex;
flex-wrap: wrap;
}
.result-SKIP {
background-color: white;
border-width: 1px;
border-color: lightgray;
border-style: solid;
}
.result-OK {
background-color: #e8ffe8;
}
.result-INFO {
background-color: lightblue;
}
.result-VERIFY {
background-color: darkorange;
font-weight: bold;
}
.result-BAD {
background-color: #ff4d4d;
font-weight: bold;
}
</style>

<base target="_blank" />
</head>

<body>
<header class="flexgap">
<h2><a href="https://pagure.io/FedoraReview">fedora-review</a></h2>
<div>A testsuite for Fedora package reviews</div>
</header>

<main>
<div id="summary"></div>
<div id="details"></div>
</main>
</body>

<script type="module">
import {
html,
render,
} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";

function getReviewIssues(report) {
return report["issues"];
}

function renderIssue(issue) {
return html`
<details class="result" open>
<summary class="result-BAD">${issue.name}</summary>
<p>${issue.text}</p>
<p>Read more: <a href="${issue.url}">${issue.url}</a></p>
</details>
`;
}
Comment thread
LecrisUT marked this conversation as resolved.

function renderResults(report) {
const issues = getReviewIssues(report);
const summary = [];

if (issues?.length === 0) {
summary.push(html`<div class="result-OK">No issues were found</div>`);
} else {
issues.forEach((issue) => {
summary.push(renderIssue(issue));
});

summary.push(html`
<p>
See also:
<ul>
<li><a href="https://docs.fedoraproject.org/en-US/package-maintainers/Package_Review_Process/">Package Review Process</a></li>
Comment thread
LecrisUT marked this conversation as resolved.
<li><a href="https://docs.fedoraproject.org/en-US/packaging-guidelines/">Fedora Packaging Guidelines</a></li>
</ul>
</p>
`);
}
render(summary, document.getElementById("summary"));
}

const renderError = (error) =>
render(error, document.getElementById("details"));

/*
* main
*/

const url =
new URLSearchParams(window.location.search).get("url") ?? "./review.json";
try {
const response = await fetch(url);
if (response.ok) renderResults(await response.json());
else
renderError(
`Failed to fetch ${url}: ${response.status} ${response.statusText}`,
);
} catch (error) {
renderError(`Failed to fetch ${url}: ${error}`);
}
</script>
</html>