def test_create_test_report(self): """Test create_test_report function.""" logfile = os.path.join(self.test_prefix, 'log.txt') write_file(logfile, "Bazel failed with: error") ecs_with_res = [ ({'spec': 'test.eb'}, {'success': True}), ({'spec': 'fail.eb'}, { 'success': False, 'err': EasyBuildError("error: bazel"), 'traceback': "in bazel", 'log_file': logfile, }), ] init_session_state = { 'easybuild_configuration': ['EASYBUILD_DEBUG=1'], 'environment': {'USER': '******'}, 'module_list': [{'mod_name': 'test'}], 'system_info': {'name': 'test'}, 'time': gmtime(0), } res = create_test_report("just a test", ecs_with_res, init_session_state) patterns = [ "**SUCCESS** _test.eb_", "**FAIL (build issue)** _fail.eb_", "01 Jan 1970 00:00:00", "EASYBUILD_DEBUG=1", ] for pattern in patterns: self.assertTrue(pattern in res['full'], "Pattern '%s' found in: %s" % (pattern, res['full'])) for pattern in patterns[:2]: self.assertTrue(pattern in res['full'], "Pattern '%s' found in: %s" % (pattern, res['overview'])) # mock create_gist function, we don't want to actually create a gist every time we run this test... def fake_create_gist(*args, **kwargs): return 'https://gist.github.com/test' easybuild.tools.testing.create_gist = fake_create_gist res = create_test_report("just a test", ecs_with_res, init_session_state, pr_nrs=[123], gist_log=True) patterns.insert(2, "https://gist.github.com/test") patterns.extend([ "https://github.com/easybuilders/easybuild-easyconfigs/pull/123", ]) for pattern in patterns: self.assertTrue(pattern in res['full'], "Pattern '%s' found in: %s" % (pattern, res['full'])) for pattern in patterns[:3]: self.assertTrue(pattern in res['full'], "Pattern '%s' found in: %s" % (pattern, res['overview'])) self.assertTrue("**SUCCESS** _test.eb_" in res['overview'])
def build_and_install_software(ecs, init_session_state, exit_on_failure=True): """Build and install software for all provided parsed easyconfig files.""" # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps init_env = copy.deepcopy(os.environ) res = [] for ec in ecs: ec_res = {} try: (ec_res['success'], app_log, err) = build_and_install_one(ec, init_env) ec_res['log_file'] = app_log if not ec_res['success']: ec_res['err'] = EasyBuildError(err) except Exception, err: # purposely catch all exceptions ec_res['success'] = False ec_res['err'] = err ec_res['traceback'] = traceback.format_exc() # keep track of success/total count if ec_res['success']: test_msg = "Successfully built %s" % ec['spec'] else: test_msg = "Build of %s failed" % ec['spec'] if 'err' in ec_res: test_msg += " (err: %s)" % ec_res['err'] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if 'log_file' in ec_res and ec_res['log_file']: test_report_fp = "%s_test_report.md" % '.'.join( ec_res['log_file'].split('.')[:-1]) parent_dir = os.path.dirname(test_report_fp) # parent dir for test report may not be writable at this time, e.g. when --read-only-installdir is used if os.stat(parent_dir).st_mode & 0200: write_file(test_report_fp, test_report_txt) else: adjust_permissions(parent_dir, stat.S_IWUSR, add=True, recursive=False) write_file(test_report_fp, test_report_txt) adjust_permissions(parent_dir, stat.S_IWUSR, add=False, recursive=False) if not ec_res['success'] and exit_on_failure: if 'traceback' in ec_res: raise EasyBuildError(ec_res['traceback']) else: raise EasyBuildError(test_msg) res.append((ec, ec_res))
def build_and_install_software(ecs, init_session_state, exit_on_failure=True, hooks=None): """ Build and install software for all provided parsed easyconfig files. :param ecs: easyconfig files to install software with :param init_session_state: initial session state, to use in test reports :param exit_on_failure: whether or not to exit on installation failure :param hooks: list of defined pre- and post-step hooks """ # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps init_env = copy.deepcopy(os.environ) run_hook(START, hooks) res = [] for ec in ecs: ec_res = {} try: (ec_res['success'], app_log, err) = build_and_install_one(ec, init_env, hooks=hooks) ec_res['log_file'] = app_log if not ec_res['success']: ec_res['err'] = EasyBuildError(err) except Exception, err: # purposely catch all exceptions ec_res['success'] = False ec_res['err'] = err ec_res['traceback'] = traceback.format_exc() # keep track of success/total count if ec_res['success']: test_msg = "Successfully built %s" % ec['spec'] else: test_msg = "Build of %s failed" % ec['spec'] if 'err' in ec_res: test_msg += " (err: %s)" % ec_res['err'] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if 'log_file' in ec_res and ec_res['log_file']: test_report_fp = "%s_test_report.md" % '.'.join(ec_res['log_file'].split('.')[:-1]) parent_dir = os.path.dirname(test_report_fp) # parent dir for test report may not be writable at this time, e.g. when --read-only-installdir is used if os.stat(parent_dir).st_mode & 0200: write_file(test_report_fp, test_report_txt) else: adjust_permissions(parent_dir, stat.S_IWUSR, add=True, recursive=False) write_file(test_report_fp, test_report_txt) adjust_permissions(parent_dir, stat.S_IWUSR, add=False, recursive=False) if not ec_res['success'] and exit_on_failure: if 'traceback' in ec_res: raise EasyBuildError(ec_res['traceback']) else: raise EasyBuildError(test_msg) res.append((ec, ec_res))
def build_and_install_software(ecs, init_session_state, exit_on_failure=True): """Build and install software for all provided parsed easyconfig files.""" # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps init_env = copy.deepcopy(os.environ) res = [] for ec in ecs: ec_res = {} try: (ec_res["success"], app_log, err) = build_and_install_one(ec, init_env) ec_res["log_file"] = app_log if not ec_res["success"]: ec_res["err"] = EasyBuildError(err) except Exception, err: # purposely catch all exceptions ec_res["success"] = False ec_res["err"] = err ec_res["traceback"] = traceback.format_exc() # keep track of success/total count if ec_res["success"]: test_msg = "Successfully built %s" % ec["spec"] else: test_msg = "Build of %s failed" % ec["spec"] if "err" in ec_res: test_msg += " (err: %s)" % ec_res["err"] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if "log_file" in ec_res and ec_res["log_file"]: test_report_fp = "%s_test_report.md" % ".".join(ec_res["log_file"].split(".")[:-1]) parent_dir = os.path.dirname(test_report_fp) # parent dir for test report may not be writable at this time, e.g. when --read-only-installdir is used if os.stat(parent_dir).st_mode & 0200: write_file(test_report_fp, test_report_txt) else: adjust_permissions(parent_dir, stat.S_IWUSR, add=True, recursive=False) write_file(test_report_fp, test_report_txt) adjust_permissions(parent_dir, stat.S_IWUSR, add=False, recursive=False) if not ec_res["success"] and exit_on_failure: if "traceback" in ec_res: raise EasyBuildError(ec_res["traceback"]) else: raise EasyBuildError(test_msg) res.append((ec, ec_res))
def build_and_install_software(ecs, init_session_state, exit_on_failure=True): """Build and install software for all provided parsed easyconfig files.""" # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps orig_environ = copy.deepcopy(os.environ) res = [] for ec in ecs: ec_res = {} try: (ec_res['success'], app_log, err) = build_and_install_one(ec, orig_environ) ec_res['log_file'] = app_log if not ec_res['success']: ec_res['err'] = EasyBuildError(err) except Exception, err: # purposely catch all exceptions ec_res['success'] = False ec_res['err'] = err ec_res['traceback'] = traceback.format_exc() # keep track of success/total count if ec_res['success']: test_msg = "Successfully built %s" % ec['spec'] else: test_msg = "Build of %s failed" % ec['spec'] if 'err' in ec_res: test_msg += " (err: %s)" % ec_res['err'] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if 'log_file' in ec_res: test_report_fp = "%s_test_report.md" % '.'.join( ec_res['log_file'].split('.')[:-1]) write_file(test_report_fp, test_report_txt) if not ec_res['success'] and exit_on_failure: if 'traceback' in ec_res: _log.error(ec_res['traceback']) else: _log.error(test_msg) res.append((ec, ec_res))
def build_and_install_software(ecs, init_session_state, exit_on_failure=True): """Build and install software for all provided parsed easyconfig files.""" # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps orig_environ = copy.deepcopy(os.environ) res = [] for ec in ecs: ec_res = {} try: (ec_res['success'], app_log, err) = build_and_install_one(ec, orig_environ) ec_res['log_file'] = app_log if not ec_res['success']: ec_res['err'] = EasyBuildError(err) except Exception, err: # purposely catch all exceptions ec_res['success'] = False ec_res['err'] = err ec_res['traceback'] = traceback.format_exc() # keep track of success/total count if ec_res['success']: test_msg = "Successfully built %s" % ec['spec'] else: test_msg = "Build of %s failed" % ec['spec'] if 'err' in ec_res: test_msg += " (err: %s)" % ec_res['err'] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if 'log_file' in ec_res: test_report_fp = "%s_test_report.md" % '.'.join(ec_res['log_file'].split('.')[:-1]) write_file(test_report_fp, test_report_txt) if not ec_res['success'] and exit_on_failure: if 'traceback' in ec_res: _log.error(ec_res['traceback']) else: _log.error(test_msg) res.append((ec, ec_res))
correct_builds_cnt = len([ ec_res for (_, ec_res) in ecs_with_res if ec_res.get('success', False) ]) overall_success = correct_builds_cnt == len(ordered_ecs) success_msg = "Build succeeded for %s out of %s" % (correct_builds_cnt, len(ordered_ecs)) repo = init_repository(get_repository(), get_repositorypath()) repo.cleanup() # report back in PR in case of testing if options.upload_test_report: msg = success_msg + " (%d easyconfigs in this PR)" % len(paths) test_report = create_test_report(msg, ecs_with_res, init_session_state, pr_nr=options.from_pr, gist_log=True) if options.from_pr: # upload test report to gist and issue a comment in the PR to notify msg = post_easyconfigs_pr_test_report(options.from_pr, test_report, success_msg, init_session_state, overall_success) print_msg(msg) else: # only upload test report as a gist gist_url = upload_test_report_as_gist(test_report) print_msg("Test report uploaded to %s" % gist_url) else: test_report = create_test_report(success_msg, ecs_with_res,
def build_and_install_software(ecs, init_session_state, exit_on_failure=True): """ Build and install software for all provided parsed easyconfig files. :param ecs: easyconfig files to install software with :param init_session_state: initial session state, to use in test reports :param exit_on_failure: whether or not to exit on installation failure """ # obtain a copy of the starting environment so each build can start afresh # we shouldn't use the environment from init_session_state, since relevant env vars might have been set since # e.g. via easyconfig.handle_allowed_system_deps init_env = copy.deepcopy(os.environ) start_progress_bar(STATUS_BAR, size=len(ecs)) res = [] ec_results = [] failed_cnt = 0 for ec in ecs: ec_res = {} try: (ec_res['success'], app_log, err) = build_and_install_one(ec, init_env) ec_res['log_file'] = app_log if not ec_res['success']: ec_res['err'] = EasyBuildError(err) except Exception as err: # purposely catch all exceptions ec_res['success'] = False ec_res['err'] = err ec_res['traceback'] = traceback.format_exc() if ec_res['success']: ec_results.append(ec['full_mod_name'] + ' (' + colorize('OK', COLOR_GREEN) + ')') else: ec_results.append(ec['full_mod_name'] + ' (' + colorize('FAILED', COLOR_RED) + ')') failed_cnt += 1 # keep track of success/total count if ec_res['success']: test_msg = "Successfully built %s" % ec['spec'] else: test_msg = "Build of %s failed" % ec['spec'] if 'err' in ec_res: test_msg += " (err: %s)" % ec_res['err'] # dump test report next to log file test_report_txt = create_test_report(test_msg, [(ec, ec_res)], init_session_state) if 'log_file' in ec_res and ec_res['log_file']: test_report_fp = "%s_test_report.md" % '.'.join( ec_res['log_file'].split('.')[:-1]) parent_dir = os.path.dirname(test_report_fp) # parent dir for test report may not be writable at this time, e.g. when --read-only-installdir is used if os.stat(parent_dir).st_mode & 0o200: write_file(test_report_fp, test_report_txt['full']) else: adjust_permissions(parent_dir, stat.S_IWUSR, add=True, recursive=False) write_file(test_report_fp, test_report_txt['full']) adjust_permissions(parent_dir, stat.S_IWUSR, add=False, recursive=False) if not ec_res['success'] and exit_on_failure: if 'traceback' in ec_res: raise EasyBuildError(ec_res['traceback']) else: raise EasyBuildError(test_msg) res.append((ec, ec_res)) if failed_cnt: # if installations failed: indicate th status_label = ' (%s): ' % colorize('%s failed!' % failed_cnt, COLOR_RED) failed_ecs = [x for x in ec_results[::-1] if 'FAILED' in x] ok_ecs = [x for x in ec_results[::-1] if x not in failed_ecs] status_label += ', '.join(failed_ecs + ok_ecs) else: status_label = ': ' + ', '.join(ec_results[::-1]) update_progress_bar(STATUS_BAR, label=status_label) stop_progress_bar(STATUS_BAR) return res
if not testing or (testing and do_build): ecs_with_res = build_and_install_software(ordered_ecs, init_session_state, exit_on_failure=exit_on_failure) else: ecs_with_res = [(ec, {}) for ec in ordered_ecs] correct_builds_cnt = len([ec_res for (_, ec_res) in ecs_with_res if ec_res.get('success', False)]) overall_success = correct_builds_cnt == len(ordered_ecs) success_msg = "Build succeeded for %s out of %s" % (correct_builds_cnt, len(ordered_ecs)) repo = init_repository(get_repository(), get_repositorypath()) repo.cleanup() # report back in PR in case of testing if options.upload_test_report: msg = success_msg + " (%d easyconfigs in this PR)" % len(paths) test_report = create_test_report(msg, ecs_with_res, init_session_state, pr_nr=options.from_pr, gist_log=True) if options.from_pr: # upload test report to gist and issue a comment in the PR to notify msg = post_easyconfigs_pr_test_report(options.from_pr, test_report, success_msg, init_session_state, overall_success) print_msg(msg) else: # only upload test report as a gist gist_url = upload_test_report_as_gist(test_report) print_msg("Test report uploaded to %s" % gist_url) else: test_report = create_test_report(success_msg, ecs_with_res, init_session_state) _log.debug("Test report: %s" % test_report) if options.dump_test_report is not None: write_file(options.dump_test_report, test_report) _log.info("Test report dumped to %s" % options.dump_test_report)