diff options
Diffstat (limited to 'fedpkg-autobuilder')
-rwxr-xr-x | fedpkg-autobuilder | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/fedpkg-autobuilder b/fedpkg-autobuilder new file mode 100755 index 0000000..00e0670 --- /dev/null +++ b/fedpkg-autobuilder @@ -0,0 +1,191 @@ +#!/usr/bin/python + +# fedpkg-autobuilder: +# Daemon which runs fedpkg-pull-build-chain continually. +# +# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) +# Copyright (C) 2010 Red Hat, Inc. +# Written by Colin Walters <walters@verbum.org> + +import getopt +import os +import sys +import subprocess +import shutil +import logging +import xml.dom.minidom +import ConfigParser + +import dbus, dbus.service +import glib +import gobject +from dbus.mainloop.glib import DBusGMainLoop +DBusGMainLoop(set_as_default=True) + +PULLBUILD_SERVICE = 'org.fedoraproject.FedpkgPullBuildChain' +PULLBUILD_OBJPATH = '/org/fedoraproject/FedpkgPullBuildChain' + +# First ensure we have a bus +if not 'DBUS_SESSION_BUS_ADDRESS' in os.environ: + args = ['dbus-launch'] + args.extend(sys.argv) + sys.execvp('dbus-launch', args) + +def check_call_verbose(*args, **kwargs): + print "Running: %r" % (args[0], ) + subprocess.check_call(*args, **kwargs) + +STATE_BURNING = 'burning' +STATE_SUCCESS = 'success' + +STATUS_ACTIVE = 'active' +STATUS_IDLE = 'idle' + +class Autobuilder(dbus.service.Object): + def __init__(self, config): + dbus.service.Object.__init__(self, dbus.SessionBus(), '/org/fedoraproject/FedpkgAutoBuilder') + self._config = config + + self._resultdir = config.get('build', 'resultdir') + self._release = config.get('build', 'release') + + try: + self._architectures = config.get('build', 'architectures').split() + except ConfigParser.NoOptionError, e: + self._architectures = None + + modules = config.get('build', 'modules') + self._modules = modules.split() + + self._pullbuild_pid = None + + bus = dbus.SessionBus() + self._bus_proxy = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), + 'org.freedesktop.DBus') + self._bus_proxy.connect_to_signal('NameOwnerChanged', self.__on_name_owner_changed) + self._pullbuild_proxy = None + + self._status = STATUS_IDLE + + self._state = STATE_BURNING + self._statedata = {} + self._reread_state() + + @dbus.service.signal(dbus_interface='org.fedoraproject.FedpkgAutoBuilder', + signature='sa{sv}') + def StateChanged(self, state, statedata): + pass + + @dbus.service.signal(dbus_interface='org.fedoraproject.FedpkgAutoBuilder', + signature='s') + def StatusChanged(self, status): + pass + + @dbus.service.method(dbus_interface='org.fedoraproject.FedpkgAutoBuilder', + in_signature='', out_signature='sa{sv}') + def GetState(self): + return (self._state, self._statedata) + + @dbus.service.method(dbus_interface='org.fedoraproject.FedpkgAutoBuilder', + in_signature='', out_signature='s') + def GetStatus(self): + return self._status + + def _reread_state(self): + self._state = STATE_SUCCESS + self._statedata = {} + for module in self._modules: + lastbuild_path = os.path.join('_build', module, 'lastbuild-status') + if not os.path.exists(lastbuild_path): + self._state = STATE_BURNING + self._statedata['failed'] = module + break + f = open(lastbuild_path) + status = f.read() + f.close() + if status != 'success': + self._state = STATE_BURNING + self._statedata['failed'] = odule + break + self.StateChanged(self._state, self._statedata) + + def initiate_build(self): + if self._pullbuild_pid is not None: + logging.info("Can't initiate build, one is in progress") + return + args = ['fedpkg-pull-build-chain', '--resultdir=' + self._resultdir, '--release=' + self._release] + if self._architectures is not None: + for arch in self._architectures: + args.append('--arch=' + arch) + + args.extend(self._modules) + + (self._pullbuild_pid, _, _, _) = glib.spawn_async(args, flags=glib.SPAWN_DO_NOT_REAP_CHILD|glib.SPAWN_SEARCH_PATH) + logging.info("started builder, pid=%d" % (self._pullbuild_pid, )) + self._status = STATUS_ACTIVE + self.StatusChanged(self._status) + glib.child_watch_add(self._pullbuild_pid, self.__on_builder_exited) + + def __on_name_owner_changed(self, name, prev_owner, new_owner): + if name != PULLBUILD_SERVICE: + return + if new_owner == '': + del self._pullbuild_proxy + self._pullbuild_proxy = None + return + logging.debug("NameOwnerChanged %r %r %r" % (name, prev_owner, new_owner)) + bus = dbus.SessionBus() + proxy = bus.get_object(PULLBUILD_SERVICE, PULLBUILD_OBJPATH) + self._pullbuild_proxy = dbus.Interface(proxy, PULLBUILD_SERVICE) + self._pullbuild_proxy.connect_to_signal('StateChanged', self.__on_builder_state_changed) + + def __on_builder_state_changed(self, state, statedata): + logging.info("builder state=%s statedata=%r" % (state, statedata)) + + def __on_builder_exited(self, pid, condition): + logging.info("builder pid=%d exited, condition=%r", pid, condition) + self._pullbuild_pid = None + self._status = STATUS_IDLE + self.StatusChanged(self._status) + + def start(self): + self.initiate_build() + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], '', ['conf=']) + except Getopt.GetoptError, e: + print unicode(e) + print "Usage: fedpkg-autobuilder --conf=file.conf" + + conf = None + for o, a in opts: + if o in ('-c', '--conf'): + conf = a + + if not conf: + print "Must specify --conf=file.conf" + sys.exit(1) + + logging.basicConfig(level=logging.INFO) + + parser = ConfigParser.SafeConfigParser() + parser.read(conf) + build_time = int(parser.get('autobuild', 'time')) + + f = open('session-address', 'w') + f.write(os.environ['DBUS_SESSION_BUS_ADDRESS']) + f.close() + bus = dbus.SessionBus() + bus_name = dbus.service.BusName('org.fedoraproject.FedpkgAutobuilder', bus=bus) + + loop = gobject.MainLoop() + + builder = Autobuilder(parser) + builder.initiate_build() + glib.timeout_add(build_time * 1000, lambda: builder.initiate_build() or True) + + loop.run() + +if __name__ == '__main__': + main() |