Merge branch 'master' into shadow
This commit is contained in:
commit
aa664aadd3
10 changed files with 199 additions and 91 deletions
3
Makefile
3
Makefile
|
|
@ -84,6 +84,9 @@ srpm: tarball
|
|||
rpm: tarball
|
||||
$(RPM_WITH_DIRS) $(DIST_DEFINES) -bb $(SPECFILE)
|
||||
|
||||
test-rpm: tarball
|
||||
$(RPM_WITH_DIRS) $(DIST_DEFINES) --define "testbuild 1" -bb $(SPECFILE)
|
||||
|
||||
tag::
|
||||
git tag -a $(TAG)
|
||||
@echo "Tagged with: $(TAG)"
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ def main():
|
|||
def shutdown(*args):
|
||||
raise SystemExit
|
||||
signal.signal(signal.SIGTERM,shutdown)
|
||||
taken = False
|
||||
while 1:
|
||||
try:
|
||||
tm.updateBuildroots()
|
||||
tm.updateTasks()
|
||||
tm.getNextTask()
|
||||
taken = tm.getNextTask()
|
||||
except (SystemExit,ServerExit,KeyboardInterrupt):
|
||||
logger.warn("Exiting")
|
||||
break
|
||||
|
|
@ -86,7 +87,11 @@ def main():
|
|||
# log the exception and continue
|
||||
logger.error(''.join(traceback.format_exception(*sys.exc_info())))
|
||||
try:
|
||||
time.sleep(options.sleeptime)
|
||||
if not taken:
|
||||
# Only sleep if we didn't take a task, otherwise retry immediately.
|
||||
# The load-balancing code in getNextTask() will prevent a single builder
|
||||
# from getting overloaded.
|
||||
time.sleep(options.sleeptime)
|
||||
except (SystemExit,KeyboardInterrupt):
|
||||
logger.warn("Exiting")
|
||||
break
|
||||
|
|
@ -786,7 +791,7 @@ class TaskManager(object):
|
|||
session.host.updateHost(self.task_load,self.ready)
|
||||
if not self.ready:
|
||||
self.logger.info("Not ready for task")
|
||||
return
|
||||
return False
|
||||
hosts, tasks = session.host.getLoadData()
|
||||
self.logger.debug("Load Data:")
|
||||
self.logger.debug(" hosts: %r" % hosts)
|
||||
|
|
@ -810,10 +815,10 @@ class TaskManager(object):
|
|||
self.logger.debug("bins: %r" % bins)
|
||||
if our_avail is None:
|
||||
self.logger.info("Server did not report this host. Are we disabled?")
|
||||
return
|
||||
return False
|
||||
elif not bins:
|
||||
self.logger.info("No bins for this host. Missing channel/arch config?")
|
||||
return
|
||||
return False
|
||||
#sort available capacities for each of our bins
|
||||
avail = {}
|
||||
for bin in bins.iterkeys():
|
||||
|
|
@ -828,7 +833,7 @@ class TaskManager(object):
|
|||
if self.host_id == task['host_id']:
|
||||
#assigned to us, we can take it regardless
|
||||
if self.takeTask(task['id']):
|
||||
return
|
||||
return True
|
||||
elif task['state'] == koji.TASK_STATES['FREE']:
|
||||
bin = "%(channel_id)s:%(arch)s" % task
|
||||
self.logger.debug("task is free, bin=%r" % bin)
|
||||
|
|
@ -844,14 +849,14 @@ class TaskManager(object):
|
|||
if our_avail < median:
|
||||
self.logger.debug("Skipping - available capacity in lower half")
|
||||
#decline for now and give the upper half a chance
|
||||
return
|
||||
return False
|
||||
#otherwise, we attempt to open the task
|
||||
if self.takeTask(task['id']):
|
||||
return
|
||||
return True
|
||||
else:
|
||||
#should not happen
|
||||
raise Exception, "Invalid task state reported by server"
|
||||
return
|
||||
return False
|
||||
|
||||
def _waitTask(self, task_id, pid=None):
|
||||
"""Wait (nohang) on the task, return true if finished"""
|
||||
|
|
@ -1892,7 +1897,7 @@ class BuildSRPMFromSCMTask(BaseTaskHandler):
|
|||
for allowed_scm in options.allowed_scms.split():
|
||||
scm_tuple = allowed_scm.split(':')
|
||||
if len(scm_tuple) == 2:
|
||||
if scm.host == scm_tuple[0] and scm.repository == scm_tuple[1]:
|
||||
if fnmatch(scm.host, scm_tuple[0]) and fnmatch(scm.repository, scm_tuple[1]):
|
||||
# SCM host:repository is in the allowed list
|
||||
break
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ server=http://hub.example.com/kojihub
|
|||
pkgurl=http://hub.example.com/packages
|
||||
|
||||
; A space-separated list of hostname:repository pairs that kojid is authorized to checkout from (no quotes)
|
||||
allowed_scms=scm.example.com:/cvs/example git.example.org:/example
|
||||
; Wildcards (as supported by fnmatch) are allowed
|
||||
allowed_scms=scm.example.com:/cvs/example git.example.org:/example svn.example.org:/users/*
|
||||
|
||||
; The mail host to use for sending email notifications
|
||||
smtphost=example.com
|
||||
|
|
|
|||
34
cli/koji
34
cli/koji
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# command line interface for the Koji build system
|
||||
# Copyright (c) 2005-2007 Red Hat
|
||||
# Copyright (c) 2005-2008 Red Hat
|
||||
#
|
||||
# Koji is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -97,6 +97,8 @@ def get_options():
|
|||
help=_("show debug output"))
|
||||
parser.add_option("--debug-xmlrpc", action="store_true", default=False,
|
||||
help=_("show xmlrpc debug output"))
|
||||
parser.add_option("-q", "--quiet", action="store_true", default=False,
|
||||
help=_("run quietly"))
|
||||
parser.add_option("--skip-main", action="store_true", default=False,
|
||||
help=_("don't actually run main"))
|
||||
parser.add_option("-s", "--server", help=_("url of XMLRPC server"))
|
||||
|
|
@ -143,14 +145,15 @@ def get_options():
|
|||
}
|
||||
# grab settings from /etc/koji.conf first, and allow them to be
|
||||
# overridden by user config
|
||||
progname = os.path.basename(sys.argv[0]) or 'koji'
|
||||
for configFile in ('/etc/koji.conf', os.path.expanduser(options.configFile)):
|
||||
if os.access(configFile, os.F_OK):
|
||||
f = open(configFile)
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.readfp(f)
|
||||
f.close()
|
||||
if config.has_section('koji'):
|
||||
for name, value in config.items('koji'):
|
||||
if config.has_section(progname):
|
||||
for name, value in config.items(progname):
|
||||
#note the defaults dictionary also serves to indicate which
|
||||
#options *can* be set via the config file. Such options should
|
||||
#not have a default value set in the option parser.
|
||||
|
|
@ -785,12 +788,16 @@ def handle_resubmit(options, session, args):
|
|||
parser.add_option("--nowait", action="store_true", help=_("Don't wait on task"))
|
||||
parser.add_option("--nowatch", action="store_true", dest="nowait",
|
||||
help=_("An alias for --nowait"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the task information"), default=options.quiet)
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) < 1:
|
||||
parser.error(_("Please specify a task ID"))
|
||||
assert False
|
||||
activate_session(session)
|
||||
taskID = args[0]
|
||||
if not options.quiet:
|
||||
print "Resubmitting the following task:"
|
||||
_printTaskInfo(session, int(taskID), 0, False, True)
|
||||
newID = session.resubmitTask(int(taskID))
|
||||
print "Resubmitted task %s as new task %s" % (taskID, newID)
|
||||
if _running_in_bg() or options.nowait:
|
||||
|
|
@ -1682,7 +1689,7 @@ def anon_handle_latest_pkg(options, session, args):
|
|||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--arch", help=_("List all of the latest packages for this arch"))
|
||||
parser.add_option("--all", action="store_true", help=_("List all of the latest packages for this tag"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"), default=options.quiet)
|
||||
parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) == 0:
|
||||
|
|
@ -1738,7 +1745,7 @@ def anon_handle_latest_by_tag(options, session, args):
|
|||
usage = _("usage: %prog latest-by-tag [options] package [package...]")
|
||||
usage += _("\n(Specify the --help global option for a list of other help options)")
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"), default=options.quiet)
|
||||
parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) == 0:
|
||||
|
|
@ -1807,7 +1814,7 @@ def anon_handle_list_tagged(options, session, args):
|
|||
parser.add_option("--rpms", action="store_true", help=_("Show rpms instead of builds"))
|
||||
parser.add_option("--inherit", action="store_true", help=_("Follow inheritance"))
|
||||
parser.add_option("--latest", action="store_true", help=_("Only show the latest builds/rpms"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"), default=options.quiet)
|
||||
parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
|
||||
parser.add_option("--sigs", action="store_true", help=_("Show signatures"))
|
||||
(options, args) = parser.parse_args(args)
|
||||
|
|
@ -1842,7 +1849,6 @@ def anon_handle_list_tagged(options, session, args):
|
|||
build_idx = dict([(b['id'],b) for b in builds])
|
||||
for rinfo in data:
|
||||
build = build_idx[rinfo['build_id']]
|
||||
build['name'] = build['package_name']
|
||||
builddir = pathinfo.build(build)
|
||||
if options.sigs:
|
||||
sigkey = rinfo['sigkey']
|
||||
|
|
@ -2090,7 +2096,7 @@ def anon_handle_list_hosts(options, session, args):
|
|||
parser.add_option("--not-ready", action="store_false", dest="ready", help=_("Limit to not ready hosts"))
|
||||
parser.add_option("--enabled", action="store_true", help=_("Limit to enabled hosts"))
|
||||
parser.add_option("--not-enabled", action="store_false", dest="enabled", help=_("Limit to not enabled hosts"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print header information"), default=options.quiet)
|
||||
(options, args) = parser.parse_args(args)
|
||||
opts = {}
|
||||
activate_session(session)
|
||||
|
|
@ -2142,7 +2148,7 @@ def anon_handle_list_pkgs(options, session, args):
|
|||
parser.add_option("--owner", help=_("Specify owner"))
|
||||
parser.add_option("--tag", help=_("Specify tag"))
|
||||
parser.add_option("--package", help=_("Specify package"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print header information"), default=options.quiet)
|
||||
parser.add_option("--noinherit", action="store_true", help=_("Don't follow inheritance"))
|
||||
parser.add_option("--show-blocked", action="store_true", help=_("Show blocked packages"))
|
||||
parser.add_option("--show-dups", action="store_true", help=_("Show superseded owners"))
|
||||
|
|
@ -2642,7 +2648,7 @@ def anon_handle_list_targets(options, session, args):
|
|||
usage += _("\n(Specify the --help global option for a list of other help options)")
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--name", help=_("Specify the build target name"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not print the header information"), default=options.quiet)
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) != 0:
|
||||
parser.error(_("This command takes no arguments"))
|
||||
|
|
@ -3510,7 +3516,7 @@ def handle_list_tasks(options, session, args):
|
|||
usage += _("\n(Specify the --help global option for a list of other help options)")
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("--mine", action="store_true", help=_("Just print your tasks"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not display the column headers"))
|
||||
parser.add_option("--quiet", action="store_true", help=_("Do not display the column headers"), default=options.quiet)
|
||||
(options, args) = parser.parse_args(args)
|
||||
if len(args) != 0:
|
||||
parser.error(_("This command takes no arguments"))
|
||||
|
|
@ -3794,7 +3800,8 @@ def anon_handle_download_build(options, session, args):
|
|||
parser.add_option("--latestfrom", dest="latestfrom", help=_("Download the latest build from this tag"))
|
||||
parser.add_option("--debuginfo", action="store_true", help=_("Also download -debuginfo rpms"))
|
||||
parser.add_option("--key", help=_("Download rpms signed with the given key"))
|
||||
parser.add_option("-q", "--quiet", action="store_true", help=_("Do not display progress meter"))
|
||||
parser.add_option("-q", "--quiet", action="store_true", help=_("Do not display progress meter"),
|
||||
default=options.quiet)
|
||||
(suboptions, args) = parser.parse_args(args)
|
||||
if len(args) < 1:
|
||||
parser.error(_("Please specify a package N-V-R or build ID"))
|
||||
|
|
@ -3963,7 +3970,8 @@ def list_commands(show_admin=False):
|
|||
desc = desc[8:]
|
||||
print " %-20s %s" % (alias, desc)
|
||||
print _('(Type "koji --help" for help about global options')
|
||||
print _(' or "koji <command> --help" for help about a particular command\'s options.)')
|
||||
print _(' or "koji <command> --help" for help about a particular command\'s options')
|
||||
print _(' or "koji help --admin" for help about privileged administrative commands.)')
|
||||
|
||||
def error(msg=None, code=1):
|
||||
if msg:
|
||||
|
|
|
|||
|
|
@ -911,7 +911,7 @@ def readPackageList(tagID=None, userID=None, pkgID=None, event=None, inherit=Fal
|
|||
return packages
|
||||
|
||||
|
||||
def readTaggedBuilds(tag,event=None,inherit=False,latest=False,package=None):
|
||||
def readTaggedBuilds(tag,event=None,inherit=False,latest=False,package=None,owner=None):
|
||||
"""Returns a list of builds for specified tag
|
||||
|
||||
set inherit=True to follow inheritance
|
||||
|
|
@ -954,6 +954,9 @@ def readTaggedBuilds(tag,event=None,inherit=False,latest=False,package=None):
|
|||
if package:
|
||||
q += """AND package.name = %(package)s
|
||||
"""
|
||||
if owner:
|
||||
q += """AND users.name = %(owner)s
|
||||
"""
|
||||
q += """ORDER BY tag_listing.create_event DESC
|
||||
"""
|
||||
# i.e. latest first
|
||||
|
|
@ -980,7 +983,7 @@ def readTaggedBuilds(tag,event=None,inherit=False,latest=False,package=None):
|
|||
|
||||
return builds
|
||||
|
||||
def readTaggedRPMS(tag, package=None, arch=None, event=None,inherit=False,latest=True,rpmsigs=False):
|
||||
def readTaggedRPMS(tag, package=None, arch=None, event=None,inherit=False,latest=True,rpmsigs=False,owner=None):
|
||||
"""Returns a list of rpms for specified tag
|
||||
|
||||
set inherit=True to follow inheritance
|
||||
|
|
@ -993,7 +996,7 @@ def readTaggedRPMS(tag, package=None, arch=None, event=None,inherit=False,latest
|
|||
# (however, it is fairly quick)
|
||||
taglist += [link['parent_id'] for link in readFullInheritance(tag, event)]
|
||||
|
||||
builds = readTaggedBuilds(tag, event=event, inherit=inherit, latest=latest, package=package)
|
||||
builds = readTaggedBuilds(tag, event=event, inherit=inherit, latest=latest, package=package, owner=owner)
|
||||
#index builds
|
||||
build_idx = dict([(b['build_id'],b) for b in builds])
|
||||
|
||||
|
|
@ -2875,7 +2878,13 @@ def import_rpm(fn,buildinfo=None,brootid=None):
|
|||
#figure it out for ourselves
|
||||
if rpminfo['sourcepackage'] == 1:
|
||||
buildinfo = rpminfo.copy()
|
||||
buildinfo['id'] = new_build(rpminfo)
|
||||
build_id = find_build_id(buildinfo)
|
||||
if build_id:
|
||||
# build already exists
|
||||
buildinfo['id'] = build_id
|
||||
else:
|
||||
# create a new build
|
||||
buildinfo['id'] = new_build(rpminfo)
|
||||
else:
|
||||
#figure it out from sourcerpm string
|
||||
buildinfo = get_build(koji.parse_NVRA(rpminfo['sourcerpm']))
|
||||
|
|
@ -4410,22 +4419,23 @@ class RootExports(object):
|
|||
raise koji.ActionNotAllowed, 'Cannot cancel task, not owner'
|
||||
task.cancelChildren()
|
||||
|
||||
def listTagged(self,tag,event=None,inherit=False,prefix=None,latest=False,package=None):
|
||||
def listTagged(self,tag,event=None,inherit=False,prefix=None,latest=False,package=None,owner=None):
|
||||
"""List builds tagged with tag"""
|
||||
if not isinstance(tag,int):
|
||||
#lookup tag id
|
||||
tag = get_tag_id(tag,strict=True)
|
||||
results = readTaggedBuilds(tag,event,inherit=inherit,latest=latest,package=package)
|
||||
results = readTaggedBuilds(tag,event,inherit=inherit,latest=latest,package=package,owner=owner)
|
||||
if prefix:
|
||||
prefix = prefix.lower()
|
||||
results = [build for build in results if build['package_name'].lower().startswith(prefix)]
|
||||
return results
|
||||
|
||||
def listTaggedRPMS(self,tag,event=None,inherit=False,latest=False,package=None,arch=None,rpmsigs=False):
|
||||
def listTaggedRPMS(self,tag,event=None,inherit=False,latest=False,package=None,arch=None,rpmsigs=False,owner=None):
|
||||
"""List rpms and builds within tag"""
|
||||
if not isinstance(tag,int):
|
||||
#lookup tag id
|
||||
tag = get_tag_id(tag,strict=True)
|
||||
return readTaggedRPMS(tag,event=event,inherit=inherit,latest=latest,package=package,arch=arch,rpmsigs=rpmsigs)
|
||||
return readTaggedRPMS(tag,event=event,inherit=inherit,latest=latest,package=package,arch=arch,rpmsigs=rpmsigs,owner=owner)
|
||||
|
||||
def listBuilds(self, packageID=None, userID=None, taskID=None, prefix=None, state=None,
|
||||
completeBefore=None, completeAfter=None, queryOpts=None):
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ Alias /koji "/usr/share/koji-web/scripts/"
|
|||
# General settings
|
||||
PythonDebug On
|
||||
PythonOption KojiHubURL http://hub.example.com/kojihub
|
||||
PythonOption KojiWebURL http://www.example.com/koji
|
||||
PythonOption KojiPackagesURL http://server.example.com/mnt/koji/packages
|
||||
PythonOption WebPrincipal koji/web@EXAMPLE.COM
|
||||
PythonOption WebKeytab /etc/httpd.keytab
|
||||
|
|
|
|||
|
|
@ -74,19 +74,43 @@
|
|||
<tr>
|
||||
<th>RPMs</th>
|
||||
<td class="container">
|
||||
#if $len($rpms) > 0
|
||||
#if $len($rpmsByArch) > 0
|
||||
<table class="nested">
|
||||
#for $rpm in $rpms
|
||||
#if $rpmsByArch.has_key('src')
|
||||
<tr><th>src</th><th></th></tr>
|
||||
#for $rpm in $rpmsByArch['src']
|
||||
#set $rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % $rpm
|
||||
#set $nvrpath = '%(package_name)s/%(version)s/%(release)s' % $build
|
||||
<tr>
|
||||
#set $rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % $rpm
|
||||
#set $nvrpath = '%(package_name)s/%(version)s/%(release)s' % $build
|
||||
<td></td>
|
||||
<td>$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$downloadBase/$nvrpath/$rpm.arch/$rpmfile">download</a>)</td>
|
||||
</tr>
|
||||
#end for
|
||||
#end if
|
||||
#set $arches = $rpmsByArch.keys()
|
||||
#silent $arches.sort()
|
||||
#for $arch in $arches
|
||||
#if $arch == 'src'
|
||||
#silent continue
|
||||
#end if
|
||||
<tr>
|
||||
<th>$arch</th>
|
||||
<td>
|
||||
$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$downloadBase/$nvrpath/$rpm.arch/$rpmfile">download</a>)
|
||||
#if $task and $rpm.arch != 'src'
|
||||
(<a href="$downloadBase/$nvrpath/data/logs/$rpm.arch/">build logs</a>)
|
||||
#if $task
|
||||
(<a href="$downloadBase/$nvrpath/data/logs/$arch/">build logs</a>)
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
#for $rpm in $rpmsByArch[$arch] + $debuginfoByArch.get($arch, [])
|
||||
<tr>
|
||||
#set $rpmfile = '%(name)s-%(version)s-%(release)s.%(arch)s.rpm' % $rpm
|
||||
#set $nvrpath = '%(package_name)s/%(version)s/%(release)s' % $build
|
||||
<td></td>
|
||||
<td>
|
||||
$rpmfile (<a href="rpminfo?rpmID=$rpm.id">info</a>) (<a href="$downloadBase/$nvrpath/$rpm.arch/$rpmfile">download</a>)
|
||||
</td>
|
||||
</tr>
|
||||
#end for
|
||||
#end for
|
||||
</table>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@
|
|||
|
||||
#include "includes/header.chtml"
|
||||
|
||||
<h4>#if $state != None then $util.stateName($state).capitalize() else ''# Builds#if $prefix then ' starting with "%s"' % $prefix else ''##if $user then ' by <a href="userinfo?userID=%i">%s</a>' % ($user.id, $user.name) else ''##if $tag then ' in tag <a href="taginfo?tagID=%i">%s</a>' % ($tag.id, $tag.name) else ''#</h4>
|
||||
<h4>#if $state != None then $util.stateName($state).capitalize() else ''# Builds#if $package then ' of <a href="packageinfo?packageID=%i">%s</a>' % ($package.id, $package.name) else ''##if $prefix then ' starting with "%s"' % $prefix else ''##if $user then ' by <a href="userinfo?userID=%i">%s</a>' % ($user.id, $user.name) else ''##if $tag then ' in tag <a href="taginfo?tagID=%i">%s</a>' % ($tag.id, $tag.name) else ''#</h4>
|
||||
|
||||
<table class="data-list">
|
||||
#if $tag
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
#if $inherited
|
||||
<a href="builds?inherited=0$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'state')">Hide inherited builds</a>
|
||||
<a href="builds?inherited=0$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'state')">Hide inherited builds</a>
|
||||
#else
|
||||
<a href="builds?${util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'state')[1:]}">Show inherited builds</a>
|
||||
<a href="builds?${util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'state')[1:]}">Show inherited builds</a>
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
<tr>
|
||||
<td colspan="#if $tag then '6' else '5'#">
|
||||
<strong>State</strong>:
|
||||
<select name="state" class="filterlist" onchange="javascript: window.location = 'builds?state=' + this.value + '$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited')';">
|
||||
<select name="state" class="filterlist" onchange="javascript: window.location = 'builds?state=' + this.value + '$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited')';">
|
||||
<option value="all">all</option>
|
||||
#for $stateOpt in ['BUILDING', 'COMPLETE', 'FAILED', 'CANCELED']
|
||||
<option value="$koji.BUILD_STATES[$stateOpt]" #if $state == $koji.BUILD_STATES[$stateOpt] then 'selected="selected"' else ''#>$stateOpt.lower()</option>
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
<br/>
|
||||
<strong>Built by</strong>:
|
||||
#if $user
|
||||
<a href="builds?${util.passthrough($self, 'tagID', 'order', 'prefix', 'inherited', 'state')[1:]}">everyone</a>
|
||||
<a href="builds?${util.passthrough($self, 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')[1:]}">everyone</a>
|
||||
#else
|
||||
<strong>everyone</strong>
|
||||
#end if
|
||||
|
|
@ -46,11 +46,11 @@
|
|||
#if $user and $user.id == $loggedInUser.id
|
||||
<strong>me</strong>
|
||||
#else
|
||||
<a href="builds?userID=$loggedInUser.name$util.passthrough($self, 'tagID', 'order', 'prefix', 'inherited', 'state')">me</a>
|
||||
<a href="builds?userID=$loggedInUser.name$util.passthrough($self, 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')">me</a>
|
||||
#end if
|
||||
#end if
|
||||
|
|
||||
<select name="userID" class="filterlist" onchange="javascript: window.location = 'builds?userID=' + this.value + '$util.passthrough($self, 'tagID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
<select name="userID" class="filterlist" onchange="javascript: window.location = 'builds?userID=' + this.value + '$util.passthrough($self, 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
<option value="">(select)</option>
|
||||
#for $userOption in $users
|
||||
<option value="$userOption.name" #if $userOption.name == ($user and $user.name or None) then 'selected="selected"' else ''#>$userOption.name</option>
|
||||
|
|
@ -64,12 +64,12 @@
|
|||
#if $prefix == $char
|
||||
<strong>$char</strong>
|
||||
#else
|
||||
<a href="builds?prefix=$char$util.passthrough($self, 'userID', 'tagID', 'order', 'inherited', 'state')">$char</a>
|
||||
<a href="builds?prefix=$char$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'inherited', 'state')">$char</a>
|
||||
#end if
|
||||
|
|
||||
#end for
|
||||
#if $prefix
|
||||
<a href="builds?${util.passthrough($self, 'userID', 'tagID', 'order', 'inherited', 'state')[1:]}">all</a>
|
||||
<a href="builds?${util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'inherited', 'state')[1:]}">all</a>
|
||||
#else
|
||||
<strong>all</strong>
|
||||
#end if
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
#if $len($buildPages) > 1
|
||||
<form class="pageJump">
|
||||
Page:
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
#for $pageNum in $buildPages
|
||||
<option value="$pageNum"#if $pageNum == $buildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>
|
||||
#end for
|
||||
|
|
@ -88,25 +88,25 @@
|
|||
</form>
|
||||
#end if
|
||||
#if $buildStart > 0
|
||||
<a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')"><<<</a>
|
||||
<a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')"><<<</a>
|
||||
#end if
|
||||
#if $totalBuilds != 0
|
||||
<strong>Builds #echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>
|
||||
#end if
|
||||
#if $buildStart + $buildCount < $totalBuilds
|
||||
<a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')">>>></a>
|
||||
<a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')">>>></a>
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="list-header">
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'build_id')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">ID</a> $util.sortImage($self, 'build_id')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'nvr')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">NVR</a> $util.sortImage($self, 'nvr')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'build_id')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">ID</a> $util.sortImage($self, 'build_id')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'nvr')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">NVR</a> $util.sortImage($self, 'nvr')</th>
|
||||
#if $tag
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'tag_name')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">Tag</a> $util.sortImage($self, 'tag_name')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'tag_name')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">Tag</a> $util.sortImage($self, 'tag_name')</th>
|
||||
#end if
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'owner_name')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">Built by</a> $util.sortImage($self, 'owner_name')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'completion_time')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">Finished</a> $util.sortImage($self, 'completion_time')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'state')$util.passthrough($self, 'userID', 'tagID', 'prefix', 'inherited', 'state')">State</a> $util.sortImage($self, 'state')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'owner_name')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">Built by</a> $util.sortImage($self, 'owner_name')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'completion_time')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">Finished</a> $util.sortImage($self, 'completion_time')</th>
|
||||
<th><a href="builds?order=$util.toggleOrder($self, 'state')$util.passthrough($self, 'userID', 'tagID', 'packageID', 'prefix', 'inherited', 'state')">State</a> $util.sortImage($self, 'state')</th>
|
||||
</tr>
|
||||
#if $len($builds) > 0
|
||||
#for $build in $builds
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
#if $len($buildPages) > 1
|
||||
<form class="pageJump">
|
||||
Page:
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
<select onchange="javascript: window.location = 'builds?start=' + this.value * $buildRange + '$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')';">
|
||||
#for $pageNum in $buildPages
|
||||
<option value="$pageNum"#if $pageNum == $buildCurrentPage then ' selected' else ''#>#echo $pageNum + 1#</option>
|
||||
#end for
|
||||
|
|
@ -140,13 +140,13 @@
|
|||
</form>
|
||||
#end if
|
||||
#if $buildStart > 0
|
||||
<a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')"><<<</a>
|
||||
<a href="builds?start=#echo $buildStart - $buildRange #$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')"><<<</a>
|
||||
#end if
|
||||
#if $totalBuilds != 0
|
||||
<strong>Builds #echo $buildStart + 1 # through #echo $buildStart + $buildCount # of $totalBuilds</strong>
|
||||
#end if
|
||||
#if $buildStart + $buildCount < $totalBuilds
|
||||
<a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough($self, 'userID', 'tagID', 'order', 'prefix', 'inherited', 'state')">>>></a>
|
||||
<a href="builds?start=#echo $buildStart + $buildRange#$util.passthrough($self, 'userID', 'tagID', 'packageID', 'order', 'prefix', 'inherited', 'state')">>>></a>
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ def _setUserCookie(req, user):
|
|||
options = req.get_options()
|
||||
cookie = mod_python.Cookie.SignedCookie('user', user,
|
||||
secret=options['Secret'],
|
||||
secure=True,
|
||||
path=os.path.dirname(req.uri),
|
||||
expires=(time.time() + (int(options['LoginTimeout']) * 60 * 60)))
|
||||
mod_python.Cookie.add_cookie(req, cookie)
|
||||
|
|
@ -110,13 +111,34 @@ def _getServer(req):
|
|||
req._session = session
|
||||
return session
|
||||
|
||||
def _redirectBack(req, page):
|
||||
def _getBaseURL(req):
|
||||
pieces = req.uri.split('/')
|
||||
base = '/'.join(pieces[:-1])
|
||||
return req.construct_url(base)
|
||||
|
||||
def _redirectBack(req, page, forceSSL):
|
||||
if page:
|
||||
mod_python.util.redirect(req, page)
|
||||
# We'll work with the page we were given
|
||||
pass
|
||||
elif req.headers_in.get('Referer'):
|
||||
mod_python.util.redirect(req, req.headers_in.get('Referer'))
|
||||
page = req.headers_in.get('Referer')
|
||||
else:
|
||||
mod_python.util.redirect(req, 'index')
|
||||
page = 'index'
|
||||
|
||||
# Modify the scheme if necessary
|
||||
if page.startswith('http'):
|
||||
pass
|
||||
elif page.startswith('/'):
|
||||
page = req.construct_url(page)
|
||||
else:
|
||||
page = _getBaseURL(req) + '/' + page
|
||||
if forceSSL:
|
||||
page = page.replace('http:', 'https:')
|
||||
else:
|
||||
page = page.replace('https:', 'http:')
|
||||
|
||||
# and redirect to the page
|
||||
mod_python.util.redirect(req, page)
|
||||
|
||||
def login(req, page=None):
|
||||
session = _getServer(req)
|
||||
|
|
@ -127,10 +149,10 @@ def login(req, page=None):
|
|||
req.add_common_vars()
|
||||
env = req.subprocess_env
|
||||
if not env.get('HTTPS') == 'on':
|
||||
https_url = options['KojiWebURL'].replace('http://', 'https://') + '/login'
|
||||
if req.args:
|
||||
https_url += '?' + req.args
|
||||
mod_python.util.redirect(req, https_url)
|
||||
dest = 'login'
|
||||
if page:
|
||||
dest = dest + '?page=' + page
|
||||
_redirectBack(req, dest, forceSSL=True)
|
||||
return
|
||||
|
||||
if env.get('SSL_CLIENT_VERIFY') != 'SUCCESS':
|
||||
|
|
@ -157,13 +179,13 @@ def login(req, page=None):
|
|||
raise koji.AuthError, 'KojiWeb is incorrectly configured for authentication, contact the system administrator'
|
||||
|
||||
_setUserCookie(req, username)
|
||||
|
||||
_redirectBack(req, page)
|
||||
# To protect the session cookie, we must forceSSL
|
||||
_redirectBack(req, page, forceSSL=True)
|
||||
|
||||
def logout(req, page=None):
|
||||
_clearUserCookie(req)
|
||||
|
||||
_redirectBack(req, page)
|
||||
_redirectBack(req, page, forceSSL=False)
|
||||
|
||||
def index(req, packageOrder='package_name', packageStart=None, buildOrder='-completion_time', buildStart=None, taskOrder='-completion_time', taskStart=None):
|
||||
values = _initValues(req)
|
||||
|
|
@ -810,6 +832,15 @@ def buildinfo(req, buildID):
|
|||
rpms = server.listBuildRPMs(build['id'])
|
||||
rpms.sort(_sortbyname)
|
||||
|
||||
rpmsByArch = {}
|
||||
debuginfoByArch = {}
|
||||
for rpm in rpms:
|
||||
canon_arch = koji.canonArch(rpm['arch'])
|
||||
if rpm['name'].endswith('-debuginfo') or rpm['name'].endswith('-debuginfo-common'):
|
||||
debuginfoByArch.setdefault(canon_arch, []).append(rpm)
|
||||
else:
|
||||
rpmsByArch.setdefault(canon_arch, []).append(rpm)
|
||||
|
||||
if build['task_id']:
|
||||
task = server.getTaskInfo(build['task_id'], request=True)
|
||||
else:
|
||||
|
|
@ -817,7 +848,8 @@ def buildinfo(req, buildID):
|
|||
|
||||
values['build'] = build
|
||||
values['tags'] = tags
|
||||
values['rpms'] = rpms
|
||||
values['rpmsByArch'] = rpmsByArch
|
||||
values['debuginfoByArch'] = debuginfoByArch
|
||||
values['task'] = task
|
||||
if req.currentUser:
|
||||
values['perms'] = server.getUserPerms(req.currentUser['id'])
|
||||
|
|
@ -839,7 +871,7 @@ def buildinfo(req, buildID):
|
|||
|
||||
return _genHTML(req, 'buildinfo.chtml')
|
||||
|
||||
def builds(req, userID=None, tagID=None, state=None, order='-completion_time', start=None, prefix=None, inherited='1'):
|
||||
def builds(req, userID=None, tagID=None, packageID=None, state=None, order='-completion_time', start=None, prefix=None, inherited='1'):
|
||||
values = _initValues(req, 'Builds', 'builds')
|
||||
server = _getServer(req)
|
||||
|
||||
|
|
@ -864,6 +896,14 @@ def builds(req, userID=None, tagID=None, state=None, order='-completion_time', s
|
|||
values['tagID'] = tagID
|
||||
values['tag'] = tag
|
||||
|
||||
package = None
|
||||
if packageID != None:
|
||||
if packageID.isdigit():
|
||||
packageID = int(packageID)
|
||||
package = server.getPackage(packageID, strict=True)
|
||||
values['packageID'] = packageID
|
||||
values['package'] = package
|
||||
|
||||
if state == 'all':
|
||||
state = None
|
||||
elif state != None:
|
||||
|
|
@ -880,10 +920,13 @@ def builds(req, userID=None, tagID=None, state=None, order='-completion_time', s
|
|||
|
||||
if tag:
|
||||
# don't need to consider 'state' here, since only completed builds would be tagged
|
||||
builds = kojiweb.util.paginateResults(server, values, 'listTagged', kw={'tag': tag['id'], 'inherit': bool(inherited), 'prefix': prefix},
|
||||
builds = kojiweb.util.paginateResults(server, values, 'listTagged', kw={'tag': tag['id'], 'package': (package and package['name'] or None),
|
||||
'owner': (user and user['name'] or None),
|
||||
'inherit': bool(inherited), 'prefix': prefix},
|
||||
start=start, dataName='builds', prefix='build', order=order)
|
||||
else:
|
||||
builds = kojiweb.util.paginateMethod(server, values, 'listBuilds', kw={'userID': (user and user['id'] or None), 'state': state, 'prefix': prefix},
|
||||
builds = kojiweb.util.paginateMethod(server, values, 'listBuilds', kw={'userID': (user and user['id'] or None), 'packageID': (package and package['id'] or None),
|
||||
'state': state, 'prefix': prefix},
|
||||
start=start, dataName='builds', prefix='build', order=order)
|
||||
|
||||
values['chars'] = [chr(char) for char in range(48, 58) + range(97, 123)]
|
||||
|
|
@ -1259,6 +1302,7 @@ def buildtargetdelete(req, targetID):
|
|||
mod_python.util.redirect(req, 'buildtargets')
|
||||
|
||||
def reports(req):
|
||||
server = _getServer(req)
|
||||
values = _initValues(req, 'Reports', 'reports')
|
||||
return _genHTML(req, 'reports.chtml')
|
||||
|
||||
|
|
@ -1499,33 +1543,40 @@ def buildsbytarget(req, days='7', start=None, order='-builds'):
|
|||
|
||||
return _genHTML(req, 'buildsbytarget.chtml')
|
||||
|
||||
def recentbuilds(req, user=None, tag=None, userID=None, tagID=None):
|
||||
def recentbuilds(req, user=None, tag=None, package=None):
|
||||
values = _initValues(req, 'Recent Build RSS')
|
||||
server = _getServer(req)
|
||||
|
||||
|
||||
tagObj = None
|
||||
if tag != None:
|
||||
if tag.isdigit():
|
||||
tag = int(tag)
|
||||
tagObj = server.getTag(tag)
|
||||
elif tagID != None:
|
||||
tagID = int(tagID)
|
||||
tagObj = server.getTag(tagID)
|
||||
|
||||
userObj = None
|
||||
if user != None:
|
||||
if user.isdigit():
|
||||
user = int(user)
|
||||
userObj = server.getUser(user)
|
||||
elif userID != None:
|
||||
userID = int(userID)
|
||||
userObj = server.getUser(userID)
|
||||
|
||||
packageObj = None
|
||||
if package:
|
||||
if package.isdigit():
|
||||
package = int(package)
|
||||
packageObj = server.getPackage(package)
|
||||
|
||||
if tagObj != None:
|
||||
builds = server.listTagged(tagObj['id'], inherit=True)
|
||||
builds = server.listTagged(tagObj['id'], inherit=True, package=(packageObj and packageObj['name'] or None),
|
||||
owner=(userObj and userObj['name'] or None))
|
||||
builds.sort(kojiweb.util.sortByKeyFunc('-completion_time', noneGreatest=True))
|
||||
builds = builds[:20]
|
||||
elif userObj != None:
|
||||
builds = server.listBuilds(userID=userObj['id'], queryOpts={'order': '-completion_time',
|
||||
'limit': 20})
|
||||
else:
|
||||
builds = server.listBuilds(queryOpts={'order': '-completion_time', 'limit': 20})
|
||||
kwargs = {}
|
||||
if userObj:
|
||||
kwargs['userID'] = userObj['id']
|
||||
if packageObj:
|
||||
kwargs['packageID'] = packageObj['id']
|
||||
builds = server.listBuilds(queryOpts={'order': '-completion_time', 'limit': 20}, **kwargs)
|
||||
|
||||
server.multicall = True
|
||||
for build in builds:
|
||||
|
|
@ -1554,8 +1605,9 @@ def recentbuilds(req, user=None, tag=None, userID=None, tagID=None):
|
|||
|
||||
values['tag'] = tagObj
|
||||
values['user'] = userObj
|
||||
values['package'] = packageObj
|
||||
values['builds'] = builds
|
||||
values['weburl'] = req.get_options().get('KojiWebURL', 'http://localhost/koji')
|
||||
values['weburl'] = _getBaseURL(req)
|
||||
|
||||
req.content_type = 'text/xml'
|
||||
return _genHTML(req, 'recentbuilds.chtml')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
#if $user
|
||||
#silent $query.append('userID=%i' % $user.id)
|
||||
#end if
|
||||
#if $package
|
||||
#silent $query.append('packageID=%i' % $package.id)
|
||||
#end if
|
||||
#if $query
|
||||
#echo '%s/%s?%s' % ($weburl, 'builds', '&'.join($query))
|
||||
#else
|
||||
|
|
@ -19,10 +22,13 @@
|
|||
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>koji: most recent builds#if $tag then ' into tag ' + $tag.name else ''##if $user then ' by user ' + $user.name else ''#</title>
|
||||
<title>Koji: recent builds#if $package then ' of package ' + $package.name else ''##if $tag then ' into tag ' + $tag.name else ''##if $user then ' by user ' + $user.name else ''#</title>
|
||||
<link>$linkURL()</link>
|
||||
<description>
|
||||
A list of the most recent builds
|
||||
#if $package
|
||||
of package $package.name
|
||||
#end if
|
||||
#if $tag
|
||||
into tag $tag.name
|
||||
#end if
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue