Skip to content

Commit d41d1c4

Browse files
mbuechsegarloff
andauthored
improve usability: add report view (#799)
Signed-off-by: Matthias Büchse <[email protected]> Signed-off-by: Kurt Garloff <[email protected]> Co-authored-by: Kurt Garloff <[email protected]>
1 parent 1d621ec commit d41d1c4

File tree

4 files changed

+107
-8
lines changed

4 files changed

+107
-8
lines changed

compliance-monitor/monitor.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ class ViewType(Enum):
9696
fragment = "fragment"
9797

9898

99+
VIEW_REPORT = {
100+
ViewType.markdown: 'report.md',
101+
ViewType.fragment: 'report.md',
102+
ViewType.page: 'overview.html',
103+
}
99104
VIEW_DETAIL = {
100105
ViewType.markdown: 'details.md',
101106
ViewType.fragment: 'details.md',
@@ -111,7 +116,7 @@ class ViewType(Enum):
111116
ViewType.fragment: 'scope.md',
112117
ViewType.page: 'overview.html',
113118
}
114-
REQUIRED_TEMPLATES = tuple(set(fn for view in (VIEW_DETAIL, VIEW_TABLE, VIEW_SCOPE) for fn in view.values()))
119+
REQUIRED_TEMPLATES = tuple(set(fn for view in (VIEW_REPORT, VIEW_DETAIL, VIEW_TABLE, VIEW_SCOPE) for fn in view.values()))
115120

116121

117122
# do I hate these globals, but I don't see another way with these frameworks
@@ -544,14 +549,23 @@ async def get_status(
544549
return convert_result_rows_to_dict2(rows2, get_scopes(), include_report=True)
545550

546551

552+
def _build_report_url(base_url, report, *args, **kwargs):
553+
if kwargs.get('download'):
554+
return f"{base_url}reports/{report}"
555+
url = f"{base_url}page/report/{report}"
556+
if len(args) == 2: # version, testcase_id --> add corresponding fragment specifier
557+
url += f"#{args[0]}_{args[1]}"
558+
return url
559+
560+
547561
def render_view(view, view_type, detail_page='detail', base_url='/', title=None, **kwargs):
548562
media_type = {ViewType.markdown: 'text/markdown'}.get(view_type, 'text/html')
549563
stage1 = stage2 = view[view_type]
550564
if view_type is ViewType.page:
551565
stage1 = view[ViewType.fragment]
552566
def scope_url(uuid): return f"{base_url}page/scope/{uuid}" # noqa: E306,E704
553567
def detail_url(subject, scope): return f"{base_url}page/{detail_page}/{subject}/{scope}" # noqa: E306,E704
554-
def report_url(report): return f"{base_url}reports/{report}" # noqa: E306,E704
568+
def report_url(report, *args, **kwargs): return _build_report_url(base_url, report, *args, **kwargs) # noqa: E306,E704
555569
fragment = templates_map[stage1].render(detail_url=detail_url, report_url=report_url, scope_url=scope_url, **kwargs)
556570
if view_type != ViewType.markdown and stage1.endswith('.md'):
557571
fragment = markdown(fragment, extensions=['extra'])
@@ -560,6 +574,23 @@ def report_url(report): return f"{base_url}reports/{report}" # noqa: E306,E704
560574
return Response(content=fragment, media_type=media_type)
561575

562576

577+
@app.get("/{view_type}/report/{report_uuid}")
578+
async def get_report_view(
579+
request: Request,
580+
account: Annotated[Optional[tuple[str, str]], Depends(auth)],
581+
conn: Annotated[connection, Depends(get_conn)],
582+
view_type: ViewType,
583+
report_uuid: str,
584+
):
585+
with conn.cursor() as cur:
586+
specs = db_get_report(cur, report_uuid)
587+
if not specs:
588+
raise HTTPException(status_code=404)
589+
spec = specs[0]
590+
check_role(account, spec['subject'], ROLES['read_any'])
591+
return render_view(VIEW_REPORT, view_type, report=spec, base_url=settings.base_url, title=f'Report {report_uuid}')
592+
593+
563594
@app.get("/{view_type}/detail/{subject}/{scopeuuid}")
564595
async def get_detail(
565596
request: Request,

compliance-monitor/templates/details.md.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ No recent test results available.
2424
{% set res = version_result.results[testcase_id] if testcase_id in version_result.results else dict(result=0) -%}
2525
| {% if res.result != 1 %}⚠️ {% endif %}{{ testcase.id }} |
2626
{#- #} {% if res.report -%}
27-
[{{ res.result | verdict_check }}]({{ report_url(res.report) }})
27+
[{{ res.result | verdict_check }}]({{ report_url(res.report, version, testcase_id) }})
2828
{%- else -%}
2929
{{ res.result | verdict_check }}
3030
{%- endif -%}
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<!DOCTYPE html>
22
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>{{ title or 'SCS compliance overview' }}</title>
6+
</head>
7+
<body>
38
<style type="text/css">
49
table {border-collapse:collapse;}
510
table td, table th {vertical-align:top;padding:0.75rem;border:1px solid #dadde1;}
611
table th {font-weight:700;background-color:#00000008;}
712
html {text-rendering:optimizelegibility;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";}
13+
li {margin:0.33em 0;}
14+
pre.line {margin: 0;}
815
</style>
9-
<head>
10-
<meta charset="utf-8">
11-
<title>{{ title or 'SCS compliance overview' }}</title>
12-
</head>
13-
<body>
1416
{% if title %}<h1>{{title}}</h1>
1517
{% endif %}{{fragment}}</body>
1618
</html>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## General info
2+
3+
- uuid: [{{ report.run.uuid }}]({{ report_url(report.run.uuid, download=True) }})
4+
- subject: {{ report.subject }}
5+
- scope: [{{ report.spec.name }}]({{ scope_url(report.spec.uuid) }})
6+
- checked at: {{ report.checked_at }}
7+
8+
## Results
9+
10+
{% for version, version_results in report.versions.items() %}{% if version_results %}
11+
### {{ version }}
12+
13+
| test case | result | invocation |
14+
|---|---|---|
15+
{% for testcase_id, result_data in version_results.items() -%}
16+
| {{ testcase_id }} {: #{{ version + '_' + testcase_id }} } | {{ result_data.result | verdict_check }} | [{{ result_data.invocation }}](#{{ result_data.invocation }}) |
17+
{% endfor %}
18+
{% endif %}{% endfor %}
19+
20+
## Run
21+
22+
### Variable assignment
23+
24+
| key | value |
25+
|---|---|
26+
{% for key, value in report.run.assignment.items() -%}
27+
| `{{ key }}` | `{{ value }}` |
28+
{% endfor %}
29+
30+
### Check tool invocations
31+
32+
{% for invid, invdata in report.run.invocations.items() %}
33+
#### Invocation {{invid}} {: #{{ invid }} }
34+
35+
- cmd: `{{ invdata.cmd }}`
36+
- rc: {{ invdata.rc }}
37+
- channel summary
38+
{%- for channel in ('critical', 'error', 'warning') %}
39+
{%- if invdata[channel] %}
40+
- **{{ channel }}: {{ invdata[channel] }}**
41+
{%- else %}
42+
- {{ channel }}: –
43+
{%- endif %}
44+
{%- endfor %}
45+
- results
46+
{%- for resultid, result in invdata.results.items() %}
47+
- {{ resultid }}: {{ result | verdict_check }}
48+
{%- endfor %}
49+
50+
{% if invdata.stdout -%}
51+
<details><summary>Captured stdout</summary>
52+
```text
53+
{{ '\n'.join(invdata.stdout) }}
54+
```
55+
</details>
56+
{%- endif %}
57+
58+
{% if invdata.stderr -%}
59+
<details {% if invdata.warning or invdata.error or invdata.critical %}open{% endif %}><summary>Captured stderr</summary>
60+
{%- for line in invdata.stderr %}
61+
<pre class="line">{% if line.split(':', 1)[0].lower() in ('warning', 'error', 'critical') %}{{ '<strong>' + line + '</strong>' }}{% else %}{{ line }}{% endif %}</pre>
62+
{%- endfor %}
63+
</details>
64+
{%- endif %}
65+
66+
{% endfor %}

0 commit comments

Comments
 (0)