def update_consider(self, origins, origin_project, package): if origin_project not in origins: self.logger.info('skipped irrelevant origin: {}'.format(origin_project)) return for project in origins[origin_project]: if self.project and project != self.project: self.logger.info('skipping filtered target project: {}'.format(project)) continue # Check if package is of kind source in target or does not exists in # target and is source in origin project -- this allows for deletes # and new submissions. Execute the check lazily due to expense. kind_target = package_kind(self.apiurl, project, package) kind_target_source = kind_target == 'source' kind_new_source = (kind_target is None and package_kind(self.apiurl, origin_project, package) == 'source') if kind_target_source or kind_new_source: self.logger.info('checking for updates to {}/{}...'.format(project, package)) request_future = origin_update(self.apiurl, project, package) if request_future: request_future.print_and_create(self.dry) elif not kind_target_source: self.logger.info(f'skipped updating non-source package {project}/{package}') else: self.logger.info(f'skipped submitting new non-source package {project}/{package}')
def osrt_origin_update_packages(apiurl, project): packages = set(package_list_kind_filtered(apiurl, project)) # Include packages from origins with initial update enabled to allow for # potential new package submissions. for origin in origin_updatable_initial(apiurl, project): for package in package_list(apiurl, origin): # Only add missing package if it does not exist in target # project. If it exists in target then it is not a source # package (since origin list is filtered to source) and should # not be updated. This also properly avoids submitting a package # that is a subpackage in target, but is a source package in an # origin project. if package in packages or entity_exists(apiurl, project, package): continue # No sense submitting a non-source package (most expensive). if package_kind(apiurl, origin, package) == 'source': packages.add(package) return packages
def check_source_submission(self, src_project, src_package, src_rev, tgt_project, tgt_package): kind = package_kind(self.apiurl, tgt_project, tgt_package) if not (kind is None or kind == 'source'): self.review_messages['accepted'] = 'skipping {} package since not source'.format(kind) return True advance, result = self.config_validate(tgt_project) if not advance: return result if self.request_age_wait(): # Allow for parallel submission to be created. return None source_hash_new = package_source_hash(self.apiurl, src_project, src_package, src_rev) origin_info_new = origin_find(self.apiurl, tgt_project, tgt_package, source_hash_new) source_hash_old = package_source_hash(self.apiurl, tgt_project, tgt_package) origin_info_old = origin_find(self.apiurl, tgt_project, tgt_package, source_hash_old, True) # Check if simulating the devel project is appropriate. devel_project, reason = self.devel_project_simulate_check(src_project, tgt_project) if devel_project and (reason.startswith('change_devel command') or origin_info_new is None): self.logger.debug(f'reevaluate considering {devel_project} as devel since {reason}') try: with devel_project_simulate(self.apiurl, tgt_project, tgt_package, src_project, src_package): # Recurse with simulated devel project. ret = self.check_source_submission( src_project, src_package, src_rev, tgt_project, tgt_package) self.review_messages['accepted']['comment'] = reason return ret except devel_project_simulate_exception: # Invalid infinite recursion so fallback to normal behavior. pass result = policy_evaluate(self.apiurl, tgt_project, tgt_package, origin_info_new, origin_info_old, source_hash_new, source_hash_old) return self.policy_result_handle(tgt_project, tgt_package, origin_info_new, origin_info_old, result)
def check_source_submission(self, source_project, source_package, source_revision, target_project, target_package): super(CheckSource, self).check_source_submission(source_project, source_package, source_revision, target_project, target_package) self.target_project_config(target_project) if self.single_action_require and len(self.request.actions) != 1: self.review_messages[ 'declined'] = 'Only one action per request allowed' return False kind = package_kind(self.apiurl, target_project, target_package) if kind == 'meta': self.review_messages[ 'accepted'] = 'Skipping all checks for meta packages' return True elif (kind is not None and kind != 'source'): self.review_messages[ 'declined'] = 'May not modify a non-source package of type {}'.format( kind) return False inair_renamed = target_package != source_package if not self.ignore_devel: self.logger.info( 'checking if target package exists and has devel project') devel_project, devel_package = devel_project_get( self.apiurl, target_project, target_package) if devel_project: if (source_project != devel_project or source_package != devel_package) and \ not(source_project == target_project and source_package == target_package): # Not from proper devel project/package and not self-submission. self.review_messages[ 'declined'] = 'Expected submission from devel package %s/%s' % ( devel_project, devel_package) return False else: # Check to see if other packages exist with the same source project # which indicates that the project has already been used as devel. if not self.is_devel_project(source_project, target_project): self.review_messages['declined'] = ( '%s is not a devel project of %s, submit the package to a devel project first. ' 'See https://en.opensuse.org/openSUSE:How_to_contribute_to_Factory#How_to_request_a_new_devel_project for details.' ) % (source_project, target_project) return False else: if source_project.endswith(':Update'): # Allow for submission like: # - source: openSUSE:Leap:15.0:Update/google-compute-engine.8258 # - target: openSUSE:Leap:15.1/google-compute-engine # Note: home:jberry:Update would also be allowed via this condition, # but that should be handled by leaper and human review. # Ignore a dot in package name (ex. tpm2.0-abrmd) and instead # only look for ending in dot number. match = re.match(r'(.*)\.\d+$', source_package) if match: inair_renamed = target_package != match.group(1) if not self.in_air_rename_allow and inair_renamed: self.review_messages[ 'declined'] = 'Source and target package names must match' return False # Checkout and see if renaming package screws up version parsing. dir = os.path.expanduser('~/co/%s' % self.request.reqid) if os.path.exists(dir): self.logger.warning('directory %s already exists' % dir) shutil.rmtree(dir) os.makedirs(dir) os.chdir(dir) old_info = {'version': None} try: CheckSource.checkout_package(self.apiurl, target_project, target_package, pathname=dir, server_service_files=True, expand_link=True) shutil.rmtree(os.path.join(target_package, '.osc')) os.rename(target_package, '_old') old_info = self.package_source_parse(target_project, target_package) except HTTPError as e: if e.code == 404: self.logger.info('target package does not exist %s/%s' % (target_project, target_package)) else: raise e CheckSource.checkout_package(self.apiurl, source_project, source_package, revision=source_revision, pathname=dir, server_service_files=True, expand_link=True) os.rename(source_package, target_package) shutil.rmtree(os.path.join(target_package, '.osc')) new_info = self.package_source_parse(source_project, source_package, source_revision, target_package) filename = new_info.get('filename', '') if not (filename.endswith('.kiwi') or filename == 'Dockerfile') and new_info['name'] != target_package: shutil.rmtree(dir) self.review_messages[ 'declined'] = "A package submitted as %s has to build as 'Name: %s' - found Name '%s'" % ( target_package, target_package, new_info['name']) return False # Run check_source.pl script and interpret output. source_checker = os.path.join(CheckSource.SCRIPT_PATH, 'check_source.pl') civs = '' new_version = None if old_info['version'] and old_info['version'] != new_info['version']: new_version = new_info['version'] civs += "NEW_VERSION='{}' ".format(new_version) civs += 'LC_ALL=C perl %s _old %s 2>&1' % (source_checker, target_package) p = subprocess.Popen(civs, shell=True, stdout=subprocess.PIPE, close_fds=True) ret = os.waitpid(p.pid, 0)[1] checked = decode_list(p.stdout.readlines()) output = ' '.join(checked).replace('\033', '') os.chdir('/tmp') # ret = 0 : Good # ret = 1 : Bad # ret = 2 : Bad but can be non-fatal in some cases if ret > 1 and target_project.startswith('openSUSE:Leap:') and ( source_project.startswith('SUSE:SLE-15:') or source_project.startswith('openSUSE:Factory')): pass elif ret != 0: shutil.rmtree(dir) self.review_messages[ 'declined'] = "Output of check script:\n" + output return False shutil.rmtree(dir) self.review_messages['accepted'] = 'Check script succeeded' if len(checked): self.review_messages[ 'accepted'] += "\n\nOutput of check script (non-fatal):\n" + output if not self.skip_add_reviews: if self.add_review_team and self.review_team is not None: self.add_review(self.request, by_group=self.review_team, msg='Please review sources') if self.only_changes(): self.logger.debug('only .changes modifications') if self.staging_group and self.review_user in group_members( self.apiurl, self.staging_group): if not self.dryrun: osc.core.change_review_state( self.apiurl, str(self.request.reqid), 'accepted', by_group=self.staging_group, message= 'skipping the staging process since only .changes modifications' ) else: self.logger.debug( 'unable to skip staging review since not a member of staging group' ) elif self.repo_checker is not None: self.add_review(self.request, by_user=self.repo_checker, msg='Please review build success') if self.bad_rpmlint_entries: if self.has_whitelist_warnings(source_project, source_package, target_project, target_package): # if there are any add a review for the security team # maybe add the found warnings to the message for the review self.add_review(self.request, by_group=self.security_review_team, msg=CheckSource.AUDIT_BUG_MESSAGE) if self.suppresses_whitelist_warnings(source_project, source_package): self.add_review(self.request, by_group=self.security_review_team, msg=CheckSource.AUDIT_BUG_MESSAGE) return True