def test_default_profile_list(self): tmp_dir = tempfile.mkdtemp() try: # Generate a couple of random profiles profiles_dir = os.path.join(tmp_dir, '.conan', 'profiles') os.makedirs(profiles_dir) with profile_for(CompilerClangApple(arch='x86', build_type='Release', version='7.3', libcxx='libc++'), basepath=profiles_dir) as _1: with profile_for(CompilerClangLinux(arch='x86', build_type='Release', version='4.0', libcxx='libstdc++'), basepath=profiles_dir) as _2: with context_env(CONAN_USER_HOME=tmp_dir): generator = JobGeneratorProfiles(conanfile_wrapper=self.conanfile_wrapper, settings=self.settings, osys=platform_system()) self.assertEqual(len(list(generator.enumerate_jobs())), 2) finally: shutil.rmtree(tmp_dir, ignore_errors=True)
def test_profile_file(self): compiler = ATestCompiler() with profile_for(compiler) as ff: profile = parse_profile(ff) self.assertEqual(profile['settings']['build_type'], compiler.build_type) self.assertEqual(profile['settings']['arch'], compiler.arch) self.assertEqual(profile['settings']['compiler'], compiler.id) self.assertEqual(profile['settings']['compiler.version'], compiler.version) self.assertEqual(profile['settings']['os'], compiler.osys)
def test_dry_run(self): runner = AppveyorRunner(conanfile=self.conanfile, settings=self.settings, osys="Windows", dry_run=True) with context_env(CONAN_GCC_VERSIONS="6", CONAN_ARCHS='x86', CONAN_BUILD_PACKAGES='pckg1'): compiler, options = list(runner.enumerate_jobs())[0] with profile_for(compiler=compiler) as profile_file: runner.set_compiler(compiler) runner.set_profile(profile_file) r = runner.run(options={'shared': True}, username='******', channel='testing') self.assertEqual(r, DRY_RUN)
def test_profile_file(self): kwargs = self.get_compiler_init_arguments() compiler = self.compiler_class(**kwargs) with profile_for(compiler) as ff: parser = parse_profile(ff) profile_true = self.get_profile_file() self.assertListEqual(parser.sections(), profile_true.sections()) for section in parser.sections(): self.assertDictEqual(dict(parser.items(section)), dict(profile_true.items(section)))
def test_run_fail(self): runner = AppveyorRunner(conanfile=self.conanfile, settings=self.settings, osys="Windows") with context_env(CONAN_GCC_VERSIONS="6", CONAN_ARCHS='x86', CONAN_BUILD_PACKAGES='pckg1'): compiler, options = list(runner.enumerate_jobs())[0] with profile_for(compiler=compiler) as profile_file: runner.set_compiler(compiler) runner.set_profile(profile_file) with mock.patch('conan_sword_and_sorcery.ci.runners.base_runner.cmd', return_value=1) as mocked_cmd: r = runner.run(options={'shared': True}, username='******', channel='testing') self.assertEqual(r, FAIL)
def test_run_fail(self, DockerHelperMocked): runner = TravisRunner(conanfile=self.conanfile, settings=self.settings, osys="Linux") with context_env(CONAN_GCC_VERSIONS="6", CONAN_ARCHS='x86', CONAN_BUILD_PACKAGES='pckg1'): compiler, options = list(runner.enumerate_jobs())[0] with profile_for(compiler=compiler) as profile_file: runner.set_compiler(compiler) runner.set_profile(profile_file) r = runner.run(options={'shared': True}, username='******', channel='testing') self.assertEqual(r, FAIL)
def test_compiler_clang(self): version = '3.9' libcxx = 'libstdc++11' arch = 'x86' build_type = 'Release' compiler = CompilerClangLinux(arch=arch, build_type=build_type, version=version, libcxx=libcxx) with profile_for(compiler) as ff: parser = parse_profile(ff) options = {} for section in parser.sections(): options.update(parser.items(section)) self.assertDictEqual(options, {'os': compiler.osys, 'arch': arch, 'build_type': build_type, 'compiler': compiler.id, 'compiler.version': version, 'compiler.libcxx': libcxx, 'CC': '/usr/bin/clang-{}'.format(version), 'CXX': '/usr/bin/clang++-{}'.format(version),})
def test_run_success(self): runner = AppveyorRunner(conanfile=self.conanfile, settings=self.settings, osys="Windows") with context_env(CONAN_GCC_VERSIONS="6", CONAN_ARCHS='x86', CONAN_BUILD_PACKAGES='pckg1'): compiler, options = list(runner.enumerate_jobs())[0] with profile_for(compiler=compiler) as profile_file: runner.set_compiler(compiler) runner.set_profile(profile_file) with mock.patch('conan_sword_and_sorcery.ci.runners.base_runner.cmd', return_value=0) as mocked_cmd: r = runner.run(options={'shared': True}, username='******', channel='testing') self.assertEqual(r, SUCCESS) args, kwargs = mocked_cmd.call_args self.assertEqual(len(args), 0) # All arguments are passed with name self.assertEqual(kwargs['exception'], None) command = kwargs.get('command') self.assertIn('--build=pckg1', command) self.assertIn('--build=outdated', command) self.assertIn('--build={}'.format(runner.recipe.name), command) self.assertIn('--profile {}'.format(profile_file), command) self.assertIn('-o {}:shared=True'.format(runner.recipe.name), command)
def test_upload(self, DockerHelperMocked): runner = TravisRunner(conanfile=self.conanfile, settings=self.settings, osys="Linux") with context_env(CONAN_GCC_VERSIONS="6", CONAN_ARCHS='x86', CONAN_BUILD_PACKAGES='pckg1'): compiler, options = list(runner.enumerate_jobs())[0] with profile_for(compiler=compiler) as profile_file: runner.set_compiler(compiler) with mock.patch( 'conan_sword_and_sorcery.ci.runners.base_runner.upload', return_value=0) as mocked_upload: with context_env(CONAN_UPLOAD_ONLY_WHEN_STABLE="True", TRAVIS_BRANCH='non-stable-branch'): runner.upload(username='******', channel='testing') with context_env(CONAN_UPLOAD_ONLY_WHEN_STABLE="False", TRAVIS_BRANCH='non-stable-branch'): runner.upload(username='******', channel='testing') args, kwargs = mocked_upload.call_args self.assertEqual(kwargs['username'], 'test')
def run(conanfile, filter_func=None, dry_run=False): # Do the work osys = platform_system() # Look for runner runner = RunnerRegistry.get_runner(conanfile=conanfile, settings=get_settings(), osys=osys, dry_run=dry_run) all_jobs = runner.enumerate_jobs() all_jobs = list(JobGeneratorBase.filter_jobs(all_jobs, filter=filter_func)) sys.stdout.write("All combinations sum up to {} jobs\n".format(len(all_jobs))) # - may paginate total_pages = os.environ.get("CONAN_TOTAL_PAGES", None) current_page = os.environ.get("CONAN_CURRENT_PAGE", None) msg = '' if total_pages or current_page: assert total_pages and current_page, "Both environment variables must be set: CONAN_TOTAL_PAGES and CONAN_CURRENT_PAGE" init, end = slice(len(all_jobs), int(current_page), int(total_pages)) all_jobs = all_jobs[init:end] msg = "(page {}/{})".format(current_page, total_pages) # Print jobs to run sys.stdout.write("Jobs to run... {}\n".format(msg)) print_jobs(all_jobs) results = [] # Get username and channel USERNAME = os.getenv("CONAN_USERNAME", 'conan') CHANNEL = os.getenv("CONAN_CHANNEL", 'stable' if runner.is_stable_branch() else 'testing') # Aggregate jobs by compiler and iterate grouped_jobs = groupby(all_jobs, itemgetter(0)) i = 0 total = len(all_jobs) with ExitStack() as stack: # Add remotes in order of precedence ADDITIONAL_REMOTES = get_env("CONAN_REMOTES", []) for remote in reversed(ADDITIONAL_REMOTES): _ = stack.enter_context(conan.remote(url=remote)) REMOTE = os.getenv("CONAN_UPLOAD", None) if REMOTE and REMOTE not in ADDITIONAL_REMOTES: _ = stack.enter_context(conan.remote(url=REMOTE)) # Run jobs for compiler, options in grouped_jobs: # Get a runner for each compiler (will modify profile) runner.set_compiler(compiler) with profile_for(compiler) as profile_file: runner.set_profile(profile_file) for _, opt in options: i += 1 options_str = ["{}={}".format(key, value) for key, value in opt.items()] sys.stdout.write("\n==> [{:>2}/{}] {}: {}\n".format(i, total, str(compiler), ', '.join(options_str))) ret = runner.run(opt, username=USERNAME, channel=CHANNEL) sys.stdout.write(ret + '\n\n') results.append(ret) # Summary of jobs status sys.stdout.write("Summing up... {}\n".format(msg)) print_jobs(all_jobs, job_status=results) succeed = len(results) == results.count(SUCCESS) if not succeed: sys.stdout.write("Only {} out of {} jobs succeeded (status={}) :/ \n\n".format(results.count(SUCCESS), len(results), SUCCESS)) if not dry_run: return -1 else: sys.stdout.write("All jobs succeeded!\n\n") # Upload (will raise if errors) runner.upload(USERNAME, CHANNEL) return 0 if succeed else -1