class ParticipantHandler(object): """Participant class as defined by the SkyNET API""" def __init__(self): self.obs = None self.oscrc = None self.validator = Validator() def handle_wi_control(self, ctrl): """Job control thread""" pass def handle_lifecycle_control(self, ctrl): """Handle messages for the participant itself, like start and stop.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """Setup the Buildservice instance :param namespace: Alias to the OBS apiurl. """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def _get_spec_file(self, prj, pkg, rev): file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) specs = [ fil for fil in file_list if fil.endswith(".spec")] if len(specs) > 1: specs = [ fil for fil in specs if (fil == "%s.spec" % pkg or fil.endswith(":%s.spec" % pkg))] if not specs: return "No specfile in %s" % pkg, None elif len(specs) > 1: return "Couldn't determine which spec file to use for %s " % pkg, None print specs fil = specs[0] spec = self.obs.getFile(prj, pkg, fil, revision=rev) specob = None with NamedTemporaryFile() as specf: specf.write(spec) specf.flush() try: specob = parse_spec(specf.name) except ValueError, exobj: return "Could not parse spec in %s: %s" % (pkg, exobj), None return None, specob
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def get_changes_file(self, prj, pkg, rev=None): """ Get a package's changes file """ changelog = "" file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".changes"): changelog = self.obs.getFile(prj, pkg, fil) return changelog def handle_wi(self, wid): """ actual job thread """ wid.result = False missing = [name for name in ["project", "package"] if not getattr(wid.fields, name, None)] if missing: raise RuntimeError("Missing mandatory field(s): %s" % ", ".join(missing)) self.setup_obs(wid.fields.ev.namespace) wid.fields.changelog = self.get_changes_file( wid.fields.project, wid.fields.package) wid.result = True
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def get_changes_file(self, prj, pkg, rev=None): """ Get a package's changes file """ changelog = "" file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".changes"): changelog = self.obs.getFile(prj, pkg, fil) return changelog def handle_wi(self, wid): """ actual job thread """ wid.result = False missing = [ name for name in ["project", "package"] if not getattr(wid.fields, name, None) ] if missing: raise RuntimeError("Missing mandatory field(s): %s" % ", ".join(missing)) self.setup_obs(wid.fields.ev.namespace) wid.fields.changelog = self.get_changes_file(wid.fields.project, wid.fields.package) wid.result = True
class ParticipantHandler(object): """Participant class as defined by the SkyNET API""" def __init__(self): self.obs = None self.oscrc = None self.validator = Validator() def handle_wi_control(self, ctrl): """Job control thread""" pass def handle_lifecycle_control(self, ctrl): """Handle messages for the participant itself, like start and stop.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """Setup the Buildservice instance :param namespace: Alias to the OBS apiurl. """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def check_spec_version_match(self, version, prj, pkg, rev=None): """Check that spec version matches given version""" spec = "" file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".spec"): spec = self.obs.getFile(prj, pkg, fil, revision=rev) break if not spec: return False, "No specfile in %s" % pkg with NamedTemporaryFile() as specf: specf.write(spec) specf.flush() try: specob = parse_spec(specf.name) except ValueError, exobj: return False, "Could not parse spec in %s: %s" % (pkg, exobj) src_hdrs = [pkg for pkg in specob.packages if pkg.header.isSource()][0] spec_version = src_hdrs.header[rpm.RPMTAG_VERSION] if spec_version != version.split('-')[0]: return False, "Last changelog version %s does not match" \ " version %s in spec file." % (version, spec_version) return True, None
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def get_changes_file(self, prj, pkg, rev=None): """ Get a package's changes file """ changelog = "" try: file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".changes"): changelog = self.obs.getFile(prj, pkg, fil, revision=rev) except HTTPError, e: if e.code == 404: pass return changelog
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) @CheckActionProcessor("check_package_is_complete") def is_complete(self, action, wid): """ Package file completeness check """ filelist = self.obs.getPackageFileList(action['sourceproject'], action['sourcepackage'], action['sourcerevision']) if "_service" in filelist: filelist.remove("_service") if "_ccache" in filelist: filelist.remove("_ccache") if "_src" in filelist: filelist.remove("_src") spec = self.has_spec_file(action, wid, filelist)[0] changes = self.has_changes_file(action, wid, filelist)[0] sources = spec and self.check_source_files(action, wid, filelist)[0] return (spec and changes and sources), "" def get_rpm_sources(self, action, filelist): """Extract source file list from package spec. :parma action: OBS request action dictionary :param filelist: List of package files :returns: List of source file names :raises SourceError: If something goes wrong """ try: specs = [name for name in filelist if name.endswith(".spec")] if len(specs) > 1: specs = [ name for name in filelist if name.endswith("%s.spec" % action['sourcepackage']) ] if len(specs) > 1: specs = [ name for name in filelist if name.endswith(":%s.spec" % action['sourcepackage']) ] spec_name = specs[0] except IndexError: # raise SourceError("No spec file found") return [] print spec_name try: spec = self.obs.getFile(action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"]) except Exception, exobj: raise SourceError( "Failed to fetch spec file %s/%s/%s rev %s: %s" % (action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"], exobj)) import hashlib print "Spec file retrieved from", action["sourceproject"], action[ "sourcepackage"], action["sourcerevision"], ": ", hashlib.md5( spec).hexdigest() try: tmp_spec = NamedTemporaryFile(mode="w", delete=False) tmp_spec.file.write(spec) tmp_spec.file.flush() print "Parsing spec file from", tmp_spec.name spec_obj = parse_spec(tmp_spec.name) sources = [ os.path.basename(name) for name, _, _ in spec_obj.sources ] tmp_spec.close() except ValueError, exobj: raise SourceError("Failed to parse spec file: %s" % exobj)
class ParticipantHandler(object): """ Class implementation as required by the API""" def __init__(self): self.oscrc = None self.obs = None def handle_lifecycle_control(self, ctrl): """Participant lifecycle control.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def handle_wi(self, wid): """Participant workitem handler.""" wid.result = False if not wid.fields.msg: wid.fields.msg = [] if not wid.fields.ev: raise RuntimeError("Mandatory field 'ev' missing") if not wid.fields.ev.actions: raise RuntimeError("Mandatory field 'ev.actions' missing") if not wid.fields.ev.namespace: raise RuntimeError("Mandatory field 'ev.namespace' missing") wid.fields.package_conf = {} # We need direct access to the dictionary as DictAttrProxy does not # have __getitem__ package_conf = wid.fields.package_conf.as_dict() self._setup_obs(wid.fields.ev.namespace) for action in wid.fields.ev.actions: self._process_action(action, package_conf) wid.result = True def _setup_obs(self, namespace): """Initialize buildservice instance.""" self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def _get_boss_conf(self, project, package, revision=None): """Fetch boss.conf contents for package. :returns: boss.conf contents as string or None if package does not have boss.conf """ try: self.log.info("getting %s %s" % (project, package)) contents = self.obs.getFile( project, package, "boss.conf", revision) except HTTPError, exobj: if exobj.getcode() == 404: # Package does not have boss.conf contents = None else: # something else failed on OBS self.log.info("WTF!\n%s" % exobj) contents = None except Exception: # buildservice raises all kinds of weird exceptions self.log.info("Failed to get boss.conf for %s %s revision %s" % \ (project, package, revision)) raise
class ParticipantHandler(object): """ Class implementation as required by the API""" def __init__(self): self.oscrc = None self.obs = None def handle_lifecycle_control(self, ctrl): """Participant lifecycle control.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def handle_wi(self, wid): """Participant workitem handler.""" wid.result = False if not wid.fields.msg: wid.fields.msg = [] if not wid.fields.ev: raise RuntimeError("Mandatory field 'ev' missing") if not wid.fields.ev.actions: raise RuntimeError("Mandatory field 'ev.actions' missing") if not wid.fields.ev.namespace: raise RuntimeError("Mandatory field 'ev.namespace' missing") wid.fields.package_conf = {} # We need direct access to the dictionary as DictAttrProxy does not # have __getitem__ package_conf = wid.fields.package_conf.as_dict() self._setup_obs(wid.fields.ev.namespace) for action in wid.fields.ev.actions: self._process_action(action, package_conf) wid.result = True def _setup_obs(self, namespace): """Initialize buildservice instance.""" self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def _get_boss_conf(self, project, package, revision=None): """Fetch boss.conf contents for package. :returns: boss.conf contents as string or None if package does not have boss.conf """ try: self.log.info("getting %s %s" % (project, package)) contents = self.obs.getFile(project, package, "boss.conf", revision) except HTTPError, exobj: if exobj.getcode() == 404: # Package does not have boss.conf contents = None else: # something else failed on OBS self.log.info("WTF!\n%s" % exobj) contents = None except Exception: # buildservice raises all kinds of weird exceptions self.log.info("Failed to get boss.conf for %s %s revision %s" % \ (project, package, revision)) raise
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) @CheckActionProcessor("check_package_is_complete") def is_complete(self, action, wid): """ Package file completeness check """ filelist = self.obs.getPackageFileList( action['sourceproject'], action['sourcepackage'], action['sourcerevision']) # Remove all files starting with _ which don't have a : in # them (_constraints, _service but not _service:filename) filelist = [f for f in filelist if not re.match(r"_[^:]*$", f)] spec = self.has_spec_file(action, wid, filelist)[0] changes = self.has_changes_file(action, wid, filelist)[0] sources = spec and self.check_source_files(action, wid, filelist)[0] return (spec and changes and sources), "" def get_rpm_sources(self, action, filelist): """Extract source file list from package spec. :parma action: OBS request action dictionary :param filelist: List of package files :returns: List of source file names :raises SourceError: If something goes wrong """ try: specs = [name for name in filelist if name.endswith(".spec")] if len(specs) > 1: specs = [name for name in filelist if name.endswith("%s.spec" % action['sourcepackage'])] if len(specs) > 1: specs = [name for name in filelist if name.endswith(":%s.spec" % action['sourcepackage'])] spec_name = specs[0] except IndexError: # raise SourceError("No spec file found") return [] print spec_name try: spec = self.obs.getFile(action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"]) except Exception, exobj: raise SourceError("Failed to fetch spec file %s/%s/%s rev %s: %s" % (action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"], exobj)) import hashlib print "Spec file retrieved from", action["sourceproject"], action["sourcepackage"], action["sourcerevision"], ": ", hashlib.md5(spec).hexdigest() try: tmp_spec = NamedTemporaryFile(mode="w", delete=False) tmp_spec.file.write(spec) tmp_spec.file.flush() print "Parsing spec file from", tmp_spec.name spec_obj = parse_spec(tmp_spec.name) sources = [os.path.basename(name) for name, _, _ in spec_obj.sources] tmp_spec.close() except ValueError, exobj: raise SourceError("Failed to parse spec file: %s" % exobj)
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def get_spec_file(self, prj, pkg, rev=None): """ Get a package's spec file """ spec = "" file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".spec"): spec = self.obs.getFile(prj, pkg, fil, revision=rev) return spec @CheckActionProcessor("check_spec") def spec_valid(self, action, _wid): """ Get spec file and check for various indications of spec file validity """ spec = self.get_spec_file(action['sourceproject'], action['sourcepackage'], action['sourcerevision']) if has_section_or_tag(spec, "%changelog"): return False, "Spec file should not contain the %%changelog tag, "\ "otherwise the changes file is ignored." return True, None def handle_wi(self, wid): """ actual job thread """ wid.result = False if not wid.fields.msg: wid.fields.msg = [] actions = wid.fields.ev.actions if not actions: raise RuntimeError("Mandatory field: actions does not exist.") self.setup_obs(wid.fields.ev.namespace) result = True for action in actions: # Assert validity of spec file valid, _ = self.spec_valid(action, wid) result = result and valid wid.result = result
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) @CheckActionProcessor("check_package_is_complete") def is_complete(self, action, wid): """ Package file completeness check """ filelist = self.obs.getPackageFileList( action['sourceproject'], action['sourcepackage'], action['sourcerevision']) if "_service" in filelist: filelist.remove("_service") if "_ccache" in filelist: filelist.remove("_ccache") if "_src" in filelist: filelist.remove("_src") spec = self.has_spec_file(action, wid, filelist)[0] changes = self.has_changes_file(action, wid, filelist)[0] sources = spec and self.check_source_files(action, wid, filelist)[0] return (spec and changes and sources), "" def get_rpm_sources(self, action, filelist): """Extract source file list from package spec. :parma action: OBS request action dictionary :param filelist: List of package files :returns: List of source file names :raises SourceError: If something goes wrong """ try: spec_name = [name for name in filelist if name.endswith(".spec")][0] except IndexError: # raise SourceError("No spec file found") return [] try: spec = self.obs.getFile(action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"]) except Exception, exobj: raise SourceError("Failed to fetch spec file %s/%s/%s rev %s: %s" % (action["sourceproject"], action["sourcepackage"], spec_name, action["sourcerevision"], exobj)) try: tmp_spec = NamedTemporaryFile(mode="w") tmp_spec.file.write(spec) tmp_spec.file.flush() spec_obj = parse_spec(tmp_spec.name) sources = [os.path.basename(name) for name, _, _ in spec_obj.sources] tmp_spec.close() except ValueError, exobj: raise SourceError("Failed to parse spec file: %s" % exobj)
class ParticipantHandler(object): """Participant class as defined by the SkyNET API.""" def __init__(self): self.oscrc = None self.namespace = None self.obs = None self.spec_re = None def handle_lifecycle_control(self, ctrl): """Participant life cycle control.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") else: raise RuntimeError("Participant config missing " "[obs] oscrc option") if ctrl.config.has_option("check_yaml", "spec_pattern"): pat = ctrl.config.get("check_yaml", "spec_pattern") else: pat = DEFAULT_SPEC_PATTERN self.spec_re = re.compile(pat) self.log.info("oscrc: %s" % self.oscrc) self.log.info("spec_pattern: %s" % pat) def handle_wi_control(self, ctrl): """Job control.""" pass def setup_obs(self, namespace): """Set up OBS instance.""" if not self.obs or self.namespace != namespace: self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) self.namespace = namespace def handle_wi(self, wid): """Job thread.""" wid.result = False if not isinstance(wid.fields.msg, list): wid.fields.msg = [] if not wid.fields.ev: raise RuntimeError("Missing mandatory field 'ev'") if not isinstance(wid.fields.ev.actions, list): raise RuntimeError("Mandatory field ev.actions not a list") if not isinstance(wid.fields.ev.namespace, basestring): raise RuntimeError("Mandatory field ev.namespace not a string") self.setup_obs(wid.fields.ev.namespace) result = True for action in wid.fields.ev.actions: pkg_result, _ = self.__handle_action(action, wid) result = result and pkg_result wid.result = result @CheckActionProcessor("check_yaml_matches_spec") def __handle_action(self, action, _wid): """Process single action from OBS event info. :param action: Single dictionary from OBS event actions list :returns: True if all good, False otherwise """ project = action["sourceproject"] package = action["sourcepackage"] revision = action["sourcerevision"] files = self.obs.getPackageFileList(project, package, revision) with Lab(prefix="check_yaml_spec_") as lab: spec = None yaml = None for name in files: if name.endswith(".spec"): lab.store(name, self.obs.getFile(project, package, name, revision)) spec = name elif name.endswith(".yaml"): lab.store(name, self.obs.getFile(project, package, name, revision)) yaml = name if not (spec and self.spec_re.search(lab.open(spec).read())): # No spec file or spec not from spectacle, skip return True, None if not yaml: return False, "SPEC file generated with spectacle, " \ "but yaml not present" snapshot = lab.take_snapshot() # Download rest of the files files.remove(spec) files.remove(yaml) for name in files: lab.store(name, self.obs.getFile(project, package, name, revision)) # Run specify specify = subprocess.Popen(["specify", "-n", "-N", lab.real_path(yaml)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env={"ANSI_COLORS_DISABLED":"1"}) rcode = specify.wait() if rcode != 0: return False, "Running specify failed:\n%s" \ % specify.stdout.read() # Get the diff diff = lab.get_diff(spec, snapshot) clean_diff = [] for line in diff: # ignore the ? seperator lines if line[0] == "?": continue # Remove diff markers and white space stripped = line[2:].strip() # skip empty lines if not stripped: continue # skip comments if stripped[0] == "#": continue # effective change clean_diff.append(line) if clean_diff: return False, "Spec file changed by specify:\n%s" \ % "".join(clean_diff) return True, None
class ParticipantHandler(object): """Participant class as defined by the SkyNET API""" def __init__(self): self.obs = None self.oscrc = None self.validator = Validator() def handle_wi_control(self, ctrl): """Job control thread""" pass def handle_lifecycle_control(self, ctrl): """Handle messages for the participant itself, like start and stop.""" if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """Setup the Buildservice instance :param namespace: Alias to the OBS apiurl. """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def _get_spec_file(self, prj, pkg, rev): file_list = [] try: file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) except: pass specs = [ fil for fil in file_list if fil.endswith(".spec")] if len(specs) > 1: specs = [ fil for fil in specs if (fil == "%s.spec" % pkg or fil.endswith(":%s.spec" % pkg))] if not specs: return "No specfile in %s" % pkg, None elif len(specs) > 1: return "Couldn't determine which spec file to use for %s " % pkg, None print specs fil = specs[0] spec = self.obs.getFile(prj, pkg, fil, revision=rev) specob = None print fil print spec with NamedTemporaryFile() as specf: specf.write(spec) specf.flush() try: specob = parse_spec(specf.name) except ValueError, exobj: return "Could not parse spec in %s: %s" % (pkg, exobj), None return None, specob
class ParticipantHandler(object): """ Participant class as defined by the SkyNET API """ def __init__(self): self.obs = None self.oscrc = None def handle_wi_control(self, ctrl): """ job control thread """ pass def handle_lifecycle_control(self, ctrl): """ participant control thread """ if ctrl.message == "start": if ctrl.config.has_option("obs", "oscrc"): self.oscrc = ctrl.config.get("obs", "oscrc") def setup_obs(self, namespace): """ setup the Buildservice instance using the namespace as an alias to the apiurl """ self.obs = BuildService(oscrc=self.oscrc, apiurl=namespace) def get_spec_file(self, prj, pkg, rev=None): """ Get a package's spec file """ spec = "" file_list = self.obs.getPackageFileList(prj, pkg, revision=rev) for fil in file_list: if fil.endswith(".spec"): spec = self.obs.getFile(prj, pkg, fil, revision=rev) return spec @CheckActionProcessor("check_spec") def spec_valid(self, action, _wid): """ Get spec file and check for various indications of spec file validity """ spec = self.get_spec_file(action["sourceproject"], action["sourcepackage"], action["sourcerevision"]) if has_section_or_tag(spec, "%changelog"): return False, "Spec file should not contain the %%changelog tag, " "otherwise the changes file is ignored." return True, None def handle_wi(self, wid): """ actual job thread """ wid.result = False if not wid.fields.msg: wid.fields.msg = [] actions = wid.fields.ev.actions if not actions: raise RuntimeError("Mandatory field: actions does not exist.") self.setup_obs(wid.fields.ev.namespace) result = True for action in actions: # Assert validity of spec file valid, _ = self.spec_valid(action, wid) result = result and valid wid.result = result