def build_packages(self): """ Function calls build class for building packages """ try: builder = Builder(self.conf.buildtool) except NotImplementedError as ni_e: raise RebaseHelperError('%s. Supported build tools are %s', ni_e.message, Builder.get_supported_tools()) for version in ['old', 'new']: spec_object = self.spec_file if version == 'old' else self.rebase_spec_file build_dict = {} build_dict['name'] = spec_object.get_package_name() build_dict['version'] = spec_object.get_version() logger.debug(build_dict) patches = [x.get_path() for x in spec_object.get_patches()] results_dir = os.path.join(self.results_dir, version) spec = spec_object.get_path() sources = spec_object.get_sources() failed_before = False while True: try: build_dict.update(builder.build(spec, sources, patches, results_dir, **build_dict)) OutputLogger.set_build_data(version, build_dict) break except SourcePackageBuildError: # always fail for original version if version == 'old': raise RebaseHelperError('Creating old SRPM package failed.') logger.error('Building source package failed.') # TODO: implement log analyzer for SRPMs and add the checks here!!! raise except BinaryPackageBuildError: # always fail for original version rpm_dir = os.path.join(results_dir, 'RPM') build_log = 'build.log' build_log_path = os.path.join(rpm_dir, build_log) if version == 'old': raise RebaseHelperError('Building old RPM package failed. Check log %s', build_log_path) logger.error('Building binary packages failed.') try: files = BuildLogAnalyzer.parse_log(rpm_dir, build_log) except BuildLogAnalyzerMissingError: raise RebaseHelperError('Build log %s does not exist', build_log_path) except BuildLogAnalyzerMakeError: raise RebaseHelperError('Building package failed during build. Check log %s', build_log_path) except BuildLogAnalyzerPatchError: raise RebaseHelperError('Building package failed during patching. Check log %s' % build_log_path) if files['missing']: missing_files = '\n'.join(files['added']) logger.info('Files not packaged in the SPEC file:\n%s', missing_files) elif files['deleted']: deleted_files = '\n'.join(files['deleted']) logger.warning('Removed files packaged in SPEC file:\n%s', deleted_files) else: raise RebaseHelperError("Build failed, but no issues were found in the build log %s", build_log) self.rebase_spec_file.modify_spec_files_section(files) if not self.conf.non_interactive: if failed_before: if not ConsoleHelper.get_message('Do you want rebase-helper to try build the packages one more time'): raise KeyboardInterrupt else: logger.warning('Some patches were not successfully applied') shutil.rmtree(os.path.join(results_dir, 'RPM')) shutil.rmtree(os.path.join(results_dir, 'SRPM')) return False # build just failed, otherwise we would break out of the while loop failed_before = True shutil.rmtree(os.path.join(results_dir, 'RPM')) shutil.rmtree(os.path.join(results_dir, 'SRPM')) return True
def build_parser(): parser = CustomArgumentParser(description=PROGRAM_DESCRIPTION, formatter_class=CustomHelpFormatter) parser.add_argument("-v", "--verbose", default=False, action="store_true", help="be more verbose (recommended)") parser.add_argument("-p", "--patch-only", default=False, action="store_true", help="only apply patches") parser.add_argument("-b", "--build-only", default=False, action="store_true", help="only build SRPM and RPMs") parser.add_argument("--buildtool", choices=Builder.get_supported_tools(), default=Builder.get_default_tool(), help="build tool to use, defaults to %(default)s") parser.add_argument( "--pkgcomparetool", choices=checkers_runner.get_supported_tools(), default=checkers_runner.get_default_tools(), type=lambda s: s.split(','), help= "set of tools to use for package comparison, defaults to %(default)s" ) parser.add_argument( "--outputtool", choices=OutputTool.get_supported_tools(), default=OutputTool.get_default_tool(), help= "tool to use for formatting rebase output, defaults to %(default)s" ) parser.add_argument( "-w", "--keep-workspace", default=False, action="store_true", help="do not remove workspace directory after finishing") parser.add_argument("--not-download-sources", default=False, action="store_true", help="do not download sources") parser.add_argument("-c", "--continue", default=False, action="store_true", dest='cont', help="continue previously interrupted rebase") parser.add_argument("sources", metavar='SOURCES', help="new upstream sources") parser.add_argument("--non-interactive", default=False, action="store_true", dest='non_interactive', help="do not interact with user") parser.add_argument( "--comparepkgs-only", default=False, dest="comparepkgs", metavar="COMPAREPKGS_DIR", help= "compare already built packages, %(metavar)s must be a directory " "with the following structure: <dir_name>/{old,new}/RPM") parser.add_argument( "--builds-nowait", default=False, action="store_true", help="do not wait for koji or copr builds to finish") # deprecated argument, kept for backward compatibility parser.add_argument("--fedpkg-build-tasks", dest="fedpkg_build_tasks", type=lambda s: s.split(','), help=argparse.SUPPRESS) parser.add_argument("--build-tasks", dest="build_tasks", metavar="OLD_TASK,NEW_TASK", type=lambda s: s.split(','), help="comma-separated koji or copr task ids") parser.add_argument( "--results-dir", help="directory where rebase-helper output will be stored") parser.add_argument( "--build-retries", default=2, help="number of retries of a failed build, defaults to %(default)d", type=int) parser.add_argument( "--builder-options", default=None, metavar="BUILDER_OPTIONS", help= "enable arbitrary local builder option(s), enclose %(metavar)s in quotes " "and note that = before it is mandatory") return parser
def build_binary_packages(self): """Function calls build class for building packages""" try: builder = Builder(self.conf.buildtool) except NotImplementedError as e: raise RebaseHelperError('{}. Supported build tools are {}'.format( six.text_type(e), Builder.get_supported_tools())) for version in ['old', 'new']: successful_builds = 0 try_build_again = False while successful_builds < 1: results_dir = '{}-build'.format(os.path.join(self.results_dir, version)) spec = None task_id = None koji_build_id = None build_dict = {} if self.conf.build_tasks is None: spec = self.spec_file if version == 'old' else self.rebase_spec_file package_name = spec.get_package_name() package_version = spec.get_version() package_full_version = spec.get_full_version() if version == 'old' and self.conf.get_old_build_from_koji: if KojiHelper.functional: session = KojiHelper.create_session() koji_version, koji_build_id = KojiHelper.get_latest_build(session, package_name) if koji_version: if koji_version != package_version: logger.warning('Version of the latest Koji build (%s) with id (%s) ' 'differs from version in SPEC file (%s)!', koji_version, koji_build_id, package_version) package_version = package_full_version = koji_version else: logger.warning('Unable to find the latest Koji build!') else: logger.warning('Unable to get the latest Koji build!') build_dict = dict( name=package_name, version=package_version, builds_nowait=self.conf.builds_nowait, build_tasks=self.conf.build_tasks, builder_options=self.conf.builder_options, srpm=results_store.get_build(version).get('srpm'), srpm_logs=results_store.get_build(version).get('logs')) # prepare for building builder.prepare(spec, self.conf) logger.info('Building binary packages for %s version %s', package_name, package_full_version) else: task_id = self.conf.build_tasks[0] if version == 'old' else self.conf.build_tasks[1] try: if self.conf.build_tasks is None: if koji_build_id: session = KojiHelper.create_session() build_dict['rpm'], build_dict['logs'] = KojiHelper.download_build(session, koji_build_id, results_dir) else: build_dict.update(builder.build(spec, results_dir, **build_dict)) if builder.creates_tasks() and task_id and not koji_build_id: if not self.conf.builds_nowait: build_dict['rpm'], build_dict['logs'] = builder.wait_for_task(build_dict, task_id, results_dir) elif self.conf.build_tasks: build_dict['rpm'], build_dict['logs'] = builder.get_detached_task(task_id, results_dir) build_dict = self._sanitize_build_dict(build_dict) results_store.set_build_data(version, build_dict) successful_builds += 1 except RebaseHelperError: # Proper RebaseHelperError instance was created already. Re-raise it. raise except BinaryPackageBuildError as e: build_dict.update(builder.get_logs()) build_dict['binary_package_build_error'] = six.text_type(e) build_dict = self._sanitize_build_dict(build_dict) results_store.set_build_data(version, build_dict) if e.logfile is None: msg = 'Building {} RPM packages failed; see logs in {} for more information'.format( version, os.path.join(results_dir, 'RPM') ) else: msg = 'Building {} RPM packages failed; see {} for more information'.format(version, e.logfile) logger.info(msg) if self.rebase_spec_file: # Save current rebase spec file content self.rebase_spec_file.save() if not self.conf.non_interactive and \ ConsoleHelper.get_message('Do you want to try it one more time'): try_build_again = True else: raise RebaseHelperError(msg, logfiles=builder.get_logs().get('logs')) except Exception: raise RebaseHelperError('Building package failed with unknown reason. ' 'Check all available log files.') if try_build_again: successful_builds = 0 try_build_again = False logger.info('Now it is time to make changes to %s if necessary.', self.rebase_spec_file.path) if not ConsoleHelper.get_message('Do you want to continue with the rebuild now'): raise KeyboardInterrupt # Update rebase spec file content after potential manual modifications self.rebase_spec_file._read_spec_content() # pylint: disable=protected-access self.rebase_spec_file._update_data() # pylint: disable=protected-access # clear current version output directories if os.path.exists(os.path.join(results_dir, 'RPM')): shutil.rmtree(os.path.join(results_dir, 'RPM')) if self.conf.builds_nowait and not self.conf.build_tasks: if builder.creates_tasks(): self.print_task_info(builder)
def build_parser(): parser = CustomArgumentParser(description=PROGRAM_DESCRIPTION, formatter_class=CustomHelpFormatter) parser.add_argument("-v", "--verbose", default=False, action="store_true", help="be more verbose (recommended)") parser.add_argument("-p", "--patch-only", default=False, action="store_true", help="only apply patches") parser.add_argument("-b", "--build-only", default=False, action="store_true", help="only build SRPM and RPMs") parser.add_argument( "--buildtool", choices=Builder.get_supported_tools(), default=Builder.get_default_tool(), help="build tool to use, defaults to %(default)s", ) parser.add_argument( "--pkgcomparetool", choices=checkers_runner.get_supported_tools(), default=checkers_runner.get_default_tools(), type=lambda s: s.split(","), help="set of tools to use for package comparison, defaults to %(default)s", ) parser.add_argument( "--outputtool", choices=OutputTool.get_supported_tools(), default=OutputTool.get_default_tool(), help="tool to use for formatting rebase output, defaults to %(default)s", ) parser.add_argument( "-w", "--keep-workspace", default=False, action="store_true", help="do not remove workspace directory after finishing", ) parser.add_argument( "--not-download-sources", default=False, action="store_true", help="do not download sources" ) parser.add_argument( "-c", "--continue", default=False, action="store_true", dest="cont", help="continue previously interrupted rebase", ) parser.add_argument("sources", metavar="SOURCES", help="new upstream sources") parser.add_argument( "--non-interactive", default=False, action="store_true", dest="non_interactive", help="do not interact with user", ) parser.add_argument( "--comparepkgs-only", default=False, dest="comparepkgs", metavar="COMPAREPKGS_DIR", help="compare already built packages, %(metavar)s must be a directory " "with the following structure: <dir_name>/{old,new}/RPM", ) parser.add_argument( "--builds-nowait", default=False, action="store_true", help="do not wait for koji or copr builds to finish" ) # deprecated argument, kept for backward compatibility parser.add_argument( "--fedpkg-build-tasks", dest="fedpkg_build_tasks", type=lambda s: s.split(","), help=argparse.SUPPRESS ) parser.add_argument( "--build-tasks", dest="build_tasks", metavar="OLD_TASK,NEW_TASK", type=lambda s: s.split(","), help="comma-separated koji or copr task ids", ) parser.add_argument("--results-dir", help="directory where rebase-helper output will be stored") parser.add_argument( "--build-retries", default=2, help="number of retries of a failed build, defaults to %(default)d", type=int ) parser.add_argument( "--builder-options", default=None, metavar="BUILDER_OPTIONS", help="enable arbitrary local builder option(s), enclose %(metavar)s in quotes " "and note that = before it is mandatory", ) return parser
def build_packages(self): """Function calls build class for building packages""" try: builder = Builder(self.conf.buildtool) except NotImplementedError as ni_e: raise RebaseHelperError( '%s. Supported build tools are %s' % six.text_type(ni_e), Builder.get_supported_tools()) for version in ['old', 'new']: spec_object = self.spec_file if version == 'old' else self.rebase_spec_file build_dict = {} task_id = None koji_build_id = None if self.conf.build_tasks is None: pkg_name = spec_object.get_package_name() pkg_version = spec_object.get_version() pkg_full_version = spec_object.get_full_version() if version == 'old' and self.conf.get_old_build_from_koji: if KojiHelper.functional: koji_version, koji_build_id = KojiHelper.get_latest_build( pkg_name) if koji_version: if koji_version != pkg_version: logger.warning( 'Version of the latest Koji build (%s) with id (%s) ' 'differs from version in SPEC file (%s)!', koji_version, koji_build_id, pkg_version) pkg_version = pkg_full_version = koji_version else: logger.warning( 'Unable to find the latest Koji build!') else: logger.warning('Unable to get the latest Koji build!') # prepare for building builder.prepare(spec_object, self.conf) build_dict['name'] = pkg_name build_dict['version'] = pkg_version patches = [x.get_path() for x in spec_object.get_patches()] spec = spec_object.get_path() sources = spec_object.get_sources() logger.info('Building packages for %s version %s', pkg_name, pkg_full_version) else: if version == 'old': task_id = self.conf.build_tasks[0] else: task_id = self.conf.build_tasks[1] results_dir = os.path.join(self.results_dir, version) + '-build' files = {} number_retries = 0 while self.conf.build_retries != number_retries: try: if self.conf.build_tasks is None: if koji_build_id: build_dict['rpm'], build_dict[ 'logs'] = KojiHelper.download_build( koji_build_id, results_dir) else: build_dict.update( builder.build(spec, sources, patches, results_dir, **build_dict)) if builder.creates_tasks() and not koji_build_id: if not self.conf.builds_nowait: build_dict['rpm'], build_dict[ 'logs'] = builder.wait_for_task( build_dict, results_dir) if build_dict['rpm'] is None: return False elif self.conf.build_tasks: build_dict['rpm'], build_dict[ 'logs'] = builder.get_detached_task( task_id, results_dir) if build_dict['rpm'] is None: return False # Build finishes properly. Go out from while cycle results_store.set_build_data(version, build_dict) break except SourcePackageBuildError as e: build_dict.update(builder.get_logs()) build_dict['source_package_build_error'] = six.text_type(e) results_store.set_build_data(version, build_dict) # always fail for original version if version == 'old': raise RebaseHelperError( 'Creating old SRPM package failed.') logger.error('Building source package failed.') # TODO: implement log analyzer for SRPMs and add the checks here!!! raise except BinaryPackageBuildError as e: # always fail for original version rpm_dir = os.path.join(results_dir, 'RPM') build_dict.update(builder.get_logs()) build_dict['binary_package_build_error'] = six.text_type(e) results_store.set_build_data(version, build_dict) build_log = 'build.log' build_log_path = os.path.join(rpm_dir, build_log) if version == 'old': error_message = 'Building old RPM package failed. Check logs: {} '.format( builder.get_logs().get('logs', 'N/A')) raise RebaseHelperError( error_message, logfiles=builder.get_logs().get('logs')) logger.error('Building binary packages failed.') msg = 'Building package failed' try: files = BuildLogAnalyzer.parse_log(rpm_dir, build_log) except BuildLogAnalyzerMissingError: raise RebaseHelperError('Build log %s does not exist', build_log_path) except BuildLogAnalyzerMakeError: raise RebaseHelperError( '%s during build. Check log %s', msg, build_log_path, logfiles=[build_log_path]) except BuildLogAnalyzerPatchError: raise RebaseHelperError( '%s during patching. Check log %s', msg, build_log_path, logfiles=[build_log_path]) except RuntimeError: if self.conf.build_retries == number_retries: raise RebaseHelperError( '%s with unknown reason. Check log %s', msg, build_log_path, logfiles=[build_log_path]) if 'missing' in files: missing_files = '\n'.join(files['missing']) logger.info('Files not packaged in the SPEC file:\n%s', missing_files) elif 'deleted' in files: deleted_files = '\n'.join(files['deleted']) logger.warning( 'Removed files packaged in SPEC file:\n%s', deleted_files) else: if self.conf.build_retries == number_retries: raise RebaseHelperError( "Build failed, but no issues were found in the build log %s", build_log, logfiles=[build_log]) self.rebase_spec_file.modify_spec_files_section(files) if not self.conf.non_interactive: msg = 'Do you want rebase-helper to try to build the packages one more time' if not ConsoleHelper.get_message(msg): raise KeyboardInterrupt else: logger.warning( 'Some patches were not successfully applied') # build just failed, otherwise we would break out of the while loop logger.debug('Number of retries is %s', self.conf.build_retries) number_retries += 1 if self.conf.build_retries > number_retries: # only remove builds if this retry is not the last one if os.path.exists(os.path.join(results_dir, 'RPM')): shutil.rmtree(os.path.join(results_dir, 'RPM')) if os.path.exists(os.path.join(results_dir, 'SRPM')): shutil.rmtree(os.path.join(results_dir, 'SRPM')) if self.conf.build_retries == number_retries: raise RebaseHelperError( 'Building package failed with unknown reason. Check all available log files.' ) if self.conf.builds_nowait and not self.conf.build_tasks: if builder.creates_tasks(): self.print_task_info(builder) return True
def build_packages(self): """Function calls build class for building packages""" if self.conf.buildtool == 'fedpkg' and not koji_builder: print ('Importing module koji failed. Switching to mockbuild.') self.conf.buildtool = 'mock' try: builder = Builder(self.conf.buildtool) except NotImplementedError as ni_e: raise RebaseHelperError('%s. Supported build tools are %s' % six.text_type(ni_e), Builder.get_supported_tools()) for version in ['old', 'new']: spec_object = self.spec_file if version == 'old' else self.rebase_spec_file build_dict = {} task_id = None if self.conf.build_tasks is None: build_dict['name'] = spec_object.get_package_name() build_dict['version'] = spec_object.get_version() patches = [x.get_path() for x in spec_object.get_patches()] spec = spec_object.get_path() sources = spec_object.get_sources() logger.info('Building packages for %s version %s', spec_object.get_package_name(), spec_object.get_version()) else: if version == 'old': task_id = self.conf.build_tasks.split(',')[0] else: task_id = self.conf.build_tasks.split(',')[1] results_dir = os.path.join(self.results_dir, version) build_dict['builds_nowait'] = self.conf.builds_nowait build_dict['build_tasks'] = self.conf.build_tasks files = {} number_retries = 0 while self.conf.build_retries != number_retries: try: if self.conf.build_tasks is None: build_dict.update(builder.build(spec, sources, patches, results_dir, **build_dict)) if not self.conf.builds_nowait: if self.conf.buildtool == 'fedpkg': while True: kh = KojiHelper() build_dict['rpm'], build_dict['logs'] = kh.get_koji_tasks(build_dict['koji_task_id'], results_dir) if build_dict['rpm']: break else: if self.conf.build_tasks: if self.conf.buildtool == 'fedpkg': kh = KojiHelper() try: build_dict['rpm'], build_dict['logs'] = kh.get_koji_tasks(task_id, results_dir) OutputLogger.set_build_data(version, build_dict) if not build_dict['rpm']: return False except TypeError: logger.info('Koji tasks are not finished yet. Try again later') return False elif self.conf.buildtool == 'copr': copr_helper = CoprHelper() client = copr_helper.get_client() build_id = int(task_id) status = copr_helper.get_build_status(client, build_id) if status in ['importing', 'pending', 'starting', 'running']: logger.info('Copr build is not finished yet. Try again later') return False else: build_dict['rpm'], build_dict['logs'] = copr_helper.download_build(client, build_id, results_dir) if status not in ['succeeded', 'skipped']: logger.info('Copr build {} did not complete successfully'.format(build_id)) return False # Build finishes properly. Go out from while cycle OutputLogger.set_build_data(version, build_dict) break except SourcePackageBuildError: # always fail for original version if version == 'old': raise RebaseHelperError('Creating old SRPM package failed.') logger.error('Building source package failed.') # TODO: implement log analyzer for SRPMs and add the checks here!!! raise except BinaryPackageBuildError: # always fail for original version rpm_dir = os.path.join(results_dir, 'RPM') build_dict.update(builder.get_logs()) OutputLogger.set_build_data(version, build_dict) build_log = 'build.log' build_log_path = os.path.join(rpm_dir, build_log) if version == 'old': raise RebaseHelperError('Building old RPM package failed. Check log %s', build_log_path) logger.error('Building binary packages failed.') msg = 'Building package failed' try: files = BuildLogAnalyzer.parse_log(rpm_dir, build_log) except BuildLogAnalyzerMissingError: raise RebaseHelperError('Build log %s does not exist', build_log_path) except BuildLogAnalyzerMakeError: raise RebaseHelperError('%s during build. Check log %s', msg, build_log_path) except BuildLogAnalyzerPatchError: raise RebaseHelperError('%s during patching. Check log %s', msg, build_log_path) except RuntimeError: if self.conf.build_retries == number_retries: raise RebaseHelperError('%s with unknown reason. Check log %s', msg, build_log_path) if 'missing' in files: missing_files = '\n'.join(files['missing']) logger.info('Files not packaged in the SPEC file:\n%s', missing_files) elif 'deleted' in files: deleted_files = '\n'.join(files['deleted']) logger.warning('Removed files packaged in SPEC file:\n%s', deleted_files) else: if self.conf.build_retries == number_retries: raise RebaseHelperError("Build failed, but no issues were found in the build log %s", build_log) self.rebase_spec_file.modify_spec_files_section(files) if not self.conf.non_interactive: msg = 'Do you want rebase-helper to try build the packages one more time' if not ConsoleHelper.get_message(msg): raise KeyboardInterrupt else: logger.warning('Some patches were not successfully applied') # build just failed, otherwise we would break out of the while loop logger.debug('Number of retries is %s', self.conf.build_retries) if os.path.exists(os.path.join(results_dir, 'RPM')): shutil.rmtree(os.path.join(results_dir, 'RPM')) if os.path.exists(os.path.join(results_dir, 'SRPM')): shutil.rmtree(os.path.join(results_dir, 'SRPM')) number_retries += 1 if self.conf.build_retries == number_retries: raise RebaseHelperError('Building package failed with unknow reason. Check all available log files.') return True
"help": "compare already built packages, %(metavar)s must be a directory " "with the following structure: <dir_name>/{old,new}/RPM", }, ], { "name": ["-c", "--continue"], "default": False, "switch": True, "dest": "cont", "help": "continue previously interrupted rebase", }, # tool selection { "name": ["--buildtool"], "choices": Builder.get_supported_tools(), "default": Builder.get_default_tool(), "help": "build tool to use, defaults to %(default)s", }, { "name": ["--srpm-buildtool"], "choices": SRPMBuilder.get_supported_tools(), "default": SRPMBuilder.get_default_tool(), "help": "SRPM build tool to use, defaults to %(default)s", }, { "name": ["--pkgcomparetool"], "choices": checkers_runner.get_supported_tools(), "default": checkers_runner.get_default_tools(),
def build_parser(): parser = CustomArgumentParser(description=PROGRAM_DESCRIPTION, formatter_class=CustomHelpFormatter) parser.add_argument("--version", default=False, action="store_true", help="show rebase-helper version and exit") parser.add_argument("-v", "--verbose", default=False, action="store_true", help="be more verbose (recommended)") group = parser.add_mutually_exclusive_group() group.add_argument("-b", "--build-only", default=False, action="store_true", help="only build SRPM and RPMs") group.add_argument( "--comparepkgs-only", default=False, dest="comparepkgs", metavar="COMPAREPKGS_DIR", help= "compare already built packages, %(metavar)s must be a directory " "with the following structure: <dir_name>/{old,new}/RPM") group.add_argument("-p", "--patch-only", default=False, action="store_true", help="only apply patches") parser.add_argument("--buildtool", choices=Builder.get_supported_tools(), default=Builder.get_default_tool(), help="build tool to use, defaults to %(default)s") parser.add_argument( "--pkgcomparetool", choices=checkers_runner.get_supported_tools(), default=checkers_runner.get_default_tools(), type=lambda s: s.split(','), help= "set of tools to use for package comparison, defaults to %(default)s" ) parser.add_argument( "--outputtool", choices=BaseOutputTool.get_supported_tools(), default=BaseOutputTool.get_default_tool(), help= "tool to use for formatting rebase output, defaults to %(default)s" ) parser.add_argument( "--versioneer", choices=versioneers_runner.get_available_versioneers(), default=None, help="tool to use for determining latest upstream version") parser.add_argument("--not-download-sources", default=False, action="store_true", help="do not download sources") parser.add_argument( "-w", "--keep-workspace", default=False, action="store_true", help="do not remove workspace directory after finishing") parser.add_argument("-c", "--continue", default=False, action="store_true", dest='cont', help="continue previously interrupted rebase") parser.add_argument( "--color", default='auto', dest='color', choices=['always', 'never', 'auto'], help="colorize the output, defaults to %(default)s") parser.add_argument( "--disable-inapplicable-patches", default=False, action="store_true", dest='disable_inapplicable_patches', help="disable inapplicable patches in rebased SPEC file") parser.add_argument("--non-interactive", default=False, action="store_true", dest='non_interactive', help="do not interact with user") parser.add_argument("--build-tasks", dest="build_tasks", metavar="OLD_TASK,NEW_TASK", type=lambda s: s.split(','), help="comma-separated remote build task ids") parser.add_argument("--builds-nowait", default=False, action="store_true", help="do not wait for remote builds to finish") parser.add_argument( "--builder-options", default=None, metavar="BUILDER_OPTIONS", help= "enable arbitrary local builder option(s), enclose %(metavar)s in quotes " "and note that = before it is mandatory") parser.add_argument( "--build-retries", default=2, help="number of retries of a failed build, defaults to %(default)d", type=int) parser.add_argument( "--results-dir", help="directory where rebase-helper output will be stored") parser.add_argument( "--get-old-build-from-koji", default=False, action="store_true", help= "do not build old sources, download latest build from Koji instead" ) parser.add_argument("sources", metavar='SOURCES', nargs='?', default=None, help="new upstream sources") return parser
def build_packages(self): """Function calls build class for building packages""" if self.conf.buildtool == KojiBuildTool.CMD and not koji_builder: logger.info( 'Importing module koji failed. Switching to mock builder.') self.conf.buildtool = MockBuildTool.CMD try: builder = Builder(self.conf.buildtool) except NotImplementedError as ni_e: raise RebaseHelperError( '%s. Supported build tools are %s' % six.text_type(ni_e), Builder.get_supported_tools()) for version in ['old', 'new']: spec_object = self.spec_file if version == 'old' else self.rebase_spec_file build_dict = {} task_id = None if self.conf.build_tasks is None: build_dict['name'] = spec_object.get_package_name() build_dict['version'] = spec_object.get_version() patches = [x.get_path() for x in spec_object.get_patches()] spec = spec_object.get_path() sources = spec_object.get_sources() logger.info('Building packages for %s version %s', spec_object.get_package_name(), spec_object.get_full_version()) else: if version == 'old': task_id = self.conf.build_tasks[0] else: task_id = self.conf.build_tasks[1] results_dir = os.path.join(self.results_dir, version) build_dict['builds_nowait'] = self.conf.builds_nowait build_dict['build_tasks'] = self.conf.build_tasks build_dict['builder_options'] = self.conf.builder_options files = {} number_retries = 0 while self.conf.build_retries != number_retries: try: if self.conf.build_tasks is None: build_dict.update( builder.build(spec, sources, patches, results_dir, **build_dict)) if not self.conf.builds_nowait: if self.conf.buildtool == KojiBuildTool.CMD: while not build_dict['rpm']: kh = KojiHelper() build_dict['rpm'], build_dict[ 'logs'] = kh.get_koji_tasks( build_dict['koji_task_id'], results_dir) else: if self.conf.build_tasks: if self.conf.buildtool == KojiBuildTool.CMD: kh = KojiHelper() try: build_dict['rpm'], build_dict[ 'logs'] = kh.get_koji_tasks( task_id, results_dir) results_store.set_build_data( version, build_dict) if not build_dict['rpm']: return False except TypeError: logger.info( 'Koji tasks are not finished yet. Try again later' ) return False elif self.conf.buildtool == CoprBuildTool.CMD: copr_helper = CoprHelper() client = copr_helper.get_client() build_id = int(task_id) status = copr_helper.get_build_status( client, build_id) if status in [ 'importing', 'pending', 'starting', 'running' ]: logger.info( 'Copr build is not finished yet. Try again later' ) return False else: build_dict['rpm'], build_dict[ 'logs'] = copr_helper.download_build( client, build_id, results_dir) if status not in ['succeeded', 'skipped']: logger.info( 'Copr build {} did not complete successfully' .format(build_id)) return False # Build finishes properly. Go out from while cycle results_store.set_build_data(version, build_dict) break except SourcePackageBuildError: build_dict.update(builder.get_logs()) results_store.set_build_data(version, build_dict) # always fail for original version if version == 'old': raise RebaseHelperError( 'Creating old SRPM package failed.') logger.error('Building source package failed.') # TODO: implement log analyzer for SRPMs and add the checks here!!! raise except BinaryPackageBuildError: # always fail for original version rpm_dir = os.path.join(results_dir, 'RPM') build_dict.update(builder.get_logs()) results_store.set_build_data(version, build_dict) build_log = 'build.log' build_log_path = os.path.join(rpm_dir, build_log) if version == 'old': error_message = 'Building old RPM package failed. Check logs: {} '.format( builder.get_logs().get('logs', 'N/A')) raise RebaseHelperError(error_message) logger.error('Building binary packages failed.') msg = 'Building package failed' try: files = BuildLogAnalyzer.parse_log(rpm_dir, build_log) except BuildLogAnalyzerMissingError: raise RebaseHelperError('Build log %s does not exist', build_log_path) except BuildLogAnalyzerMakeError: raise RebaseHelperError( '%s during build. Check log %s', msg, build_log_path) except BuildLogAnalyzerPatchError: raise RebaseHelperError( '%s during patching. Check log %s', msg, build_log_path) except RuntimeError: if self.conf.build_retries == number_retries: raise RebaseHelperError( '%s with unknown reason. Check log %s', msg, build_log_path) if 'missing' in files: missing_files = '\n'.join(files['missing']) logger.info('Files not packaged in the SPEC file:\n%s', missing_files) elif 'deleted' in files: deleted_files = '\n'.join(files['deleted']) logger.warning( 'Removed files packaged in SPEC file:\n%s', deleted_files) else: if self.conf.build_retries == number_retries: raise RebaseHelperError( "Build failed, but no issues were found in the build log %s", build_log) self.rebase_spec_file.modify_spec_files_section(files) if not self.conf.non_interactive: msg = 'Do you want rebase-helper to try build the packages one more time' if not ConsoleHelper.get_message(msg): raise KeyboardInterrupt else: logger.warning( 'Some patches were not successfully applied') # build just failed, otherwise we would break out of the while loop logger.debug('Number of retries is %s', self.conf.build_retries) if os.path.exists(os.path.join(results_dir, 'RPM')): shutil.rmtree(os.path.join(results_dir, 'RPM')) if os.path.exists(os.path.join(results_dir, 'SRPM')): shutil.rmtree(os.path.join(results_dir, 'SRPM')) number_retries += 1 if self.conf.build_retries == number_retries: raise RebaseHelperError( 'Building package failed with unknown reason. Check all available log files.' ) return True