Skip to content

Commit 9a6b98a

Browse files
committed
package in pipe html report generator
Signed-off-by: Gaëtan Lehmann <[email protected]>
1 parent c8a6eb8 commit 9a6b98a

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

Diff for: scripts/pkg_in_pipe/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
report.html

Diff for: scripts/pkg_in_pipe/README.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Packages in pipe report generator
2+
3+
Generates an html report with the packages in the current tags.
4+
5+
# Requirements
6+
7+
You'll need a few extra python modules:
8+
* koji
9+
* requests
10+
* specfile
11+
12+
The user running the generator must have a working configuration for koji (in `~/.koji`).
13+
A plane token with enough rights to list the cards in the XCPNG project must be passed either through the `PLANE_TOKEN`
14+
environment variable or the `--plane-token` command line option.
15+
16+
An extra `--generated-info` command line option may be used to add some info about the report generation process.
17+
18+
# Run in docker
19+
20+
Before running in docker, the docker image must be built with:
21+
22+
```sh
23+
docker build -t pkg_in_pipe .
24+
```
25+
26+
Several options are required to run the generator in docker:
27+
28+
* a `PLANE_TOKEN` environment variable with the rights required to request all the cards in the XCPNG project;
29+
* a (read only) mount of a directory containing the requeried certificates to connect to koji in `/root/.koji`
30+
* a mount of the output directory in `/output`
31+
* the path of the generated report
32+
33+
```sh
34+
docker run -v ~/.koji:/root/.koji:z -e PLANE_TOKEN=<plane token> -v /out/dir:/output:z pkg_in_pipe /output/index.html
35+
```

Diff for: scripts/pkg_in_pipe/pkg_in_pipe.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
import os
5+
from datetime import datetime
6+
7+
import koji
8+
import requests
9+
10+
def print_header(out):
11+
print('''
12+
<!DOCTYPE html>
13+
<html lang="en">
14+
<head>
15+
<meta charset="UTF-8">
16+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
17+
<title>XCP-ng Package Update</title>
18+
<script src="https://cdn.tailwindcss.com"></script>
19+
</head>
20+
<body class="bg-gray-400 text-center">
21+
''', file=out)
22+
23+
def print_footer(out, generated_info):
24+
now = datetime.now()
25+
print(f'''
26+
Last generated at {now}. {generated_info or ''}
27+
</body>
28+
</html>
29+
''', file=out)
30+
31+
def print_table_header(out, tag):
32+
print(f'''
33+
<div class="px-3 py-3">
34+
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
35+
<table class="table-fixed w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
36+
<caption class="p-5 text-lg font-semibold text-left rtl:text-right text-gray-900 bg-white dark:text-white dark:bg-gray-800">
37+
{tag}
38+
</caption>
39+
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
40+
<tr>
41+
<th scope="col" class="px-6 py-3">
42+
Build
43+
</th>
44+
<th scope="col" class="px-6 py-3">
45+
Cards
46+
</th>
47+
<th scope="col" class="px-6 py-3">
48+
By
49+
</th>
50+
</tr>
51+
</thead>
52+
<tbody>
53+
''', file=out)
54+
55+
def print_table_footer(out):
56+
print('''
57+
</tbody>
58+
</table>
59+
</div>
60+
</div>
61+
''', file=out)
62+
63+
def print_table_line(out, build, link, issues, by):
64+
issues_content = '\n'.join([f'<li><a class="font-medium text-blue-600 dark:text-blue-500 hover:underline" href="https://project.vates.tech/vates-global/browse/XCPNG-{i['sequence_id']}/">XCPNG-{i['sequence_id']}</a></li>' for i in issues])
65+
print(f'''
66+
<tr class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700 border-gray-200">
67+
<th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
68+
<a class="font-medium text-blue-600 dark:text-blue-500 hover:underline" href="{link}">{build}</a>
69+
</th>
70+
<td class="px-6 py-4">
71+
<ul>
72+
{issues_content}
73+
</ul>
74+
</td>
75+
<td class="px-6 py-4">
76+
{by}
77+
</td>
78+
</tr>
79+
''', file=out)
80+
81+
parser = argparse.ArgumentParser(description='Generate a report of the packages in the pipe')
82+
parser.add_argument('output', nargs='?', help='Report output path', default='report.html')
83+
parser.add_argument('--generated-info', help="Add this message about the generation in the report")
84+
parser.add_argument('--plane-token', help="The token used to access the plane api", default=os.environ['PLANE_TOKEN'])
85+
args = parser.parse_args()
86+
87+
# open koji session
88+
config = koji.read_config("koji")
89+
session = koji.ClientSession('https://kojihub.xcp-ng.org', config)
90+
session.ssl_login(config['cert'], None, config['serverca'])
91+
92+
# load the issues from plane, so we can search for the plane card related to a build
93+
resp = requests.get('https://project.vates.tech/api/v1/workspaces/vates-global/projects/43438eec-1335-4fc2-8804-5a4c32f4932d/issues/',
94+
headers={'x-api-key': args.plane_token})
95+
project_issues = resp.json()
96+
97+
with open(args.output, 'w') as out:
98+
print_header(out)
99+
tags = [f'v{v}-{p}' for v in ['8.2', '8.3'] for p in ['incoming', 'ci', 'testing', 'candidates', 'lab']]
100+
for tag in tags:
101+
print_table_header(out, tag)
102+
for build in session.listTagged(tag):
103+
build_url = f'https://koji.xcp-ng.org/buildinfo?buildID={build['build_id']}'
104+
build_issues = [i for i in project_issues['results'] if f'href="{build_url}"' in i['description_html']]
105+
print_table_line(out, build['nvr'], build_url, build_issues, build['owner_name'])
106+
print_table_footer(out)
107+
print_footer(out, args.generated_info)

0 commit comments

Comments
 (0)