repo requests web ui

* new page for request details
* new page for querying requests
* add links in taginfo and taskinfo pages
* show more data in repoinfo page
This commit is contained in:
Mike McLean 2024-11-11 12:18:34 -05:00 committed by Tomas Kopecek
parent 573bd41654
commit 357587a57c
9 changed files with 300 additions and 15 deletions

View file

@ -797,6 +797,10 @@ def taskinfo(environ, taskID):
else:
values['perms'] = []
values['requests'] = []
if task['method'] == 'newRepo':
values['requests'] = server.repo.queryQueue([['task_id', '=', task['id']]], ['id'])
values['koji'] = koji
values['S'] = SafeValue
@ -1051,8 +1055,9 @@ def taginfo(environ, tagID, all='0', packageOrder='package_name', packageStart=N
values['srcTargets'] = srcTargets
values['destTargets'] = destTargets
values['all'] = all
values['repo'] = server.getRepo(tag['id'], state=koji.REPO_READY)
values['repo'] = server.repo.get(tag['id'])
values['external_repos'] = server.getExternalRepoList(tag['id'])
values['request_count'] = server.repo.queryQueue([['tag_id', '=', tag['id']]], opts={'countOnly': True})
child = None
if childID is not None:
@ -2696,13 +2701,72 @@ def repoinfo(environ, repoID):
else:
values['repo_json'] = os.path.join(
pathinfo.repo(repo_info['id'], repo_info['tag_name']), 'repo.json')
num_buildroots = len(server.listBuildroots(repoID=repoID)) or 0
values['numBuildroots'] = num_buildroots
num_buildroots = server.listBuildroots(repoID=repoID, queryOpts={'countOnly': True})
values['numBuildroots'] = num_buildroots
values['requests'] = server.repo.queryQueue([['repo_id', '=', repoID]], ['id'])
values['state_name'] = kojiweb.util.repoState(repo_info['state'])
values['create_time'] = kojiweb.util.formatTimeLong(repo_info['create_ts'])
return _genHTML(environ, 'repoinfo.html.j2')
def reporequest(environ, reqID):
values = _initValues(environ, 'Repo Request', 'tags')
server = _getServer(environ)
req_id = int(reqID)
values['req_id'] = req_id
rows = server.repo.queryQueue([['id', '=', req_id]], '**')
if not rows:
raise koji.GenericError("No such repo request: %s" % req_id)
req = rows[0]
if req['at_event']:
values['at_event'] = server.getEvent(req['at_event'])
elif req['min_event']:
values['min_event'] = server.getEvent(req['min_event'])
else:
# invalid, but technically not blocked in db
values['min_event'] = None
values['req'] = req
return _genHTML(environ, 'reporequest.chtml')
def reporequests(environ, active="true", tag=None, start=None, order=None):
values = _initValues(environ, 'Repo Requests', 'tags')
server = _getServer(environ)
clauses = []
desc_parts = []
if active.lower() == 'all':
desc_parts.append('Recent repo requests')
elif active.lower() in ('false', 'no', '0'):
desc_parts.append('Inactive repo requests')
clauses.append(["active", False])
active = 'false'
else:
desc_parts.append('Active repo requests')
clauses.append(["active", True])
active = 'true'
if tag:
taginfo = server.getTag(_convert_if_int(tag), strict=True, event='auto')
clauses.append(["tag_id", taginfo['id']])
desc_parts.append('for tag %(name)s' % taginfo)
tag = taginfo['name']
else:
tag = None
if order is None:
order = '-id'
values['desc'] = ' '.join(desc_parts)
values['order'] = order
values['active'] = active
values['tag'] = tag
kojiweb.util.paginateMethod(server, values, 'repo.queryQueue',
args=(clauses, '**'),
start=start, dataName='reqs', prefix='req', order=order,
optsarg='opts')
return _genHTML(environ, 'reporequests.chtml')
def activesession(environ, start=None, order=None):
values = _initValues(environ, 'Active sessions', 'activesession')
server = _getServer(environ)

View file

@ -0,0 +1,41 @@
#import json
#import koji
#from kojiweb import util
#include "includes/header.chtml"
<h4>Information for repo request $req_id</h4>
#if not $req
Repo request $req_id not found.
#else
<table>
<tr><th>ID</th><td>$req.id</td><th></tr>
<tr><th>Active</th><td>$req.active</td><th></tr>
<tr><th>Priority</th><td>$req.priority</td><th></tr>
<tr><th>Tag</th><td><a href="taginfo?tagID=$req.tag_id">$req.tag_name</a></td></tr>
#if $req.at_event
<tr><th>At specific event</th><td>$at_event.id ($util.formatTimeLong($at_event.ts))</td><th></tr>
#elif $req.min_event
<tr><th>Minimum event</th><td>$min_event.id ($util.formatTimeLong($min_event.ts))</td><th></tr>
#else
<tr><th>Invalid event</th><td>Unable to determine event for request</td><th></tr>
#end if
#if $req.opts
<th>Options</th><td class="usertext">$json.dumps($req.opts, indent=4)</td>
#end if
#if $req.repo_id
<tr><th>Fulfilled by repo</th><td><a href="repoinfo?repoID=$req.repo_id">$req.repo_id</a</td></tr>
#end if
#if $req.task_id
<tr><th>Task ID</th><td><a href="taskinfo?taskID=$req.task_id">$req.task_id</a> ($util.taskState($req.task_state))</td></tr>
<tr><th>Tries</th><td>$req.tries</td></tr>
#end if
<tr><th>Owner</th><td><a href="userinfo?userID=$req.owner">$req.owner_name</a></td></tr>
<tr><th>Created</th><td>$util.formatTimeLong($req.create_ts)</td></tr>
<tr><th>Updated</th><td>$util.formatTimeLong($req.update_ts)</td></tr>
</table>
#end if
#include "includes/footer.chtml"

View file

@ -0,0 +1,129 @@
#encoding UTF-8
#from kojiweb import util
#from kojiweb.util import passthrough as P
#include "includes/header.chtml"
#set $Pvars = ('active', 'tag', 'order')
<h4>$desc</h4>
<table class="data-list">
<td colspan="6">
<form action="">
<table class="nested">
<tr><td>
<strong>Active</strong>:
</td><td>
<select name="active" class="filterlist" onchange="javascript: window.location = 'reporequests?active=' + this.value + '$P($self, 'tag', 'order')';">
<option value="true" #if $active == 'true' then 'selected' else ''#>true</option>
<option value="false" #if $active == 'false' then 'selected' else ''#>false</option>
<option value="all" #if $active == 'all' then 'selected' else ''#>all</option>
</select>
</td>
<td>
<strong>Tag</strong>:
</td><td>
<input type="text" name="tag" value="$tag"/>
</td>
</tr>
</table>
</form>
</td>
</tr>
<tr>
<td class="paginate" colspan="6">
#if $len($reqPages) > 1
<form class="pageJump" action="">
Page:
<select onchange="javascript: window.location = 'reporequests?start=' + this.value * $reqRange + '$P($self, *Pvars)';">
#for $pageNum in $reqPages
<option value="$pageNum"#if $pageNum == $reqCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>
#end for
</select>
</form>
#end if
#if $reqStart > 0
<a href="reporequests?start=#echo $reqStart - $reqRange #$P($self, *Pvars)">&lt;&lt;&lt;</a>
#end if
#if $totalReqs != 0
<strong>Requests #echo $reqStart + 1 # through #echo $reqStart + $reqCount # of $totalReqs</strong>
#end if
#if $reqStart + $reqCount < $totalReqs
<a href="reporequests?start=#echo $reqStart + $reqRange#$P($self, *Pvars)">&gt;&gt;&gt;</a>
#end if
</td>
</tr>
<tr class="list-header">
<th><a href="reporequests?$P($self, *Pvars, toggleOrder='id', prefix='')">ID</a> $util.sortImage($self, 'id')</th>
<th><a href="reporequests?$P($self, *Pvars, toggleOrder='priority', prefix='')">Priority</a> $util.sortImage($self, 'priority')</th>
<th><a href="reporequests?$P($self, *Pvars, toggleOrder='tag_name', prefix='')">Tag</a> $util.sortImage($self, 'tag_name')</th>
<th>Task</th>
<th>Repo</th>
<th>Status</th>
</tr>
#if $len($reqs) > 0
#for $req in $reqs
<tr class="$util.rowToggle($self)">
<td><a href="reporequest?reqID=$req.id">$req.id</a></td>
<td>$req.priority</td>
<td>
<a href="taginfo?tagID=$req.tag_id">$req.tag_name</a>
#if not $tag
<a href="reporequests?tag=$req.tag_id$P($self, 'active', 'order')" title="Filter by tag"><img src="$util.themePath('images/funnel.svg')"></a>
#end if
</td>
#if $req.task_id
<td><a href="taskinfo?taskID=$req.task_id">$req.task_id</a></td>
#else
<td>...</td>
#end if
#if $req.repo_id
<td><a href="repoinfo?repoID=$req.repo_id">$req.repo_id</a></td>
#else
<td>...</td>
#end if
<td>
## simulate a more helpful status
#if $req.active
$util.imageTag('waiting')
#elif $req.repo_id
$util.imageTag('yes')
#else
$util.imageTag('no')
#end if
</td>
</tr>
#end for
#else
<tr class="row-odd">
<td colspan="2">No repo requests</td>
</tr>
#end if
<tr>
<td class="paginate" colspan="2">
#if $len($reqPages) > 1
<form class="pageJump" action="">
Page:
<select onchange="javascript: window.location = 'reporequests?start=' + this.value * $reqRange + '$P($self, *Pvars)';">
#for $pageNum in $reqPages
<option value="$pageNum"#if $pageNum == $reqCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>
#end for
</select>
</form>
#end if
#if $reqStart > 0
<a href="reporequests?start=#echo $reqStart - $reqRange #$P($self, *Pvars)">&lt;&lt;&lt;</a>
#end if
#if $totalReqs != 0
<strong>Reqs #echo $reqStart + 1 # through #echo $reqStart + $reqCount # of $totalReqs</strong>
#end if
#if $reqStart + $reqCount < $totalReqs
<a href="reporequests?start=#echo $reqStart + $reqRange#$P($self, *Pvars)">&gt;&gt;&gt;</a>
#end if
</td>
</tr>
</table>
#include "includes/footer.chtml"

View file

@ -7,16 +7,35 @@
<tr><th>ID</th><td>{{ repo.id }}</td><th></tr>
<tr><th>Tag</th><td><a href="taginfo?tagID={{ repo.tag_id }}">{{ repo.tag_name }}</a></td></tr>
{% if repo.task_id %}
<tr><th>Task ID</th><td><a href="taskinfo?taskID={{ repo.task_id }}">{{ repo.task_id }}</a></td></tr>
<tr><th>Task ID</th><td><a href="taskinfo?taskID={{ repo.task_id }}">{{ repo.task_id }}</a> ({{ util.taskState(repo.task_state) }})</td></tr>
{% endif %}
<tr><th>State</th><td class="repo{{ state_name }}">{{ state_name }}</td></tr>
<tr><th>Event</th><td>{{ repo.create_event }} ({{ create_time }})</td></tr>
<tr><th>Created</th><td>{{ util.formatTimeLong(repo.creation_ts) }}</td></tr>
<tr><th>State changed</th><td>{{ util.formatTimeLong(repo.state_ts) }}</td></tr>
<tr><th>Created from Event</th><td>{{ repo.create_event }} ({{ util.formatTimeLong(repo.create_ts) }})</td></tr>
{%- if repo.begin_event %}
{%- if repo.end_event %}
<tr><th>Event range</th><td>{{ repo.begin_event }} ... {{ repo.end_event }}</td></tr>
{%- else %}
<tr><th>Event range</th><td>{{ repo.begin_event }} ... </td></tr>
{%- endif %}
{%- endif %}
{%- if state_name != 'deleted' %}
<tr><th>URL</th><td><a href="{{ url }}">repodata</a></td></tr>
<tr><th>Repo json</th><td><a href="{{ repo_json }}">repo.json</a></td></tr>
{%- endif %}
#if repo.custom_opts
<th>Custom Opts</th><td class="usertext">{{ json.dumps(repo.custom_opts, indent=4) }}</td>
#endif
<tr><th>Dist repo?</th><td class="{{ repo.dist | lower }}">{{ 'yes' if repo.dist else 'no' }}</td></tr>
<tr><th>Number of buildroots: </th><td><a href="buildroots?repoID={{ repo.id }}">{{ numBuildroots }}</a></td></tr>
#if requests
<tr><th>Fulfills requests:</th><td>
#for req in requests
<a href="reporequest?reqID={{ req.id }}">{{ req.id }}</a>
#endfor
</td/></tr>
#endif
</table>
{% else %}
Repo {{ repo_id }} not found.

View file

@ -117,6 +117,10 @@
#endif
</td>
</tr>
<tr>
<th>Repo&nbsp;requests</th>
<td><a href="reporequests?active=all&tag={{ tag.id }}">{{ request_count }}</a></td>
</tr>
<tr>
<th>Packages</th>
<td><a href="packages?blocked=0&tagID={{ tag.id }}">{{ numPackages }}</a></td>

View file

@ -140,6 +140,14 @@ None
</tr>
#endfor
#endif
#if requests
<tr><th>For request:</th><td>
## we only expect one, but if we get more print them all
#for req in requests
<a href="reporequest?reqID={{ req.id }}">{{ req.id }}</a>
#endfor
</td/></tr>
#endif
<tr>
<th>Created</th><td>{{ util.formatTimeLong(task.create_ts) }}</td>
</tr>