def review_pr(pr, colored=True, branch='develop'): """ Print multi-diff overview between easyconfigs in specified PR and specified branch. :param pr: pull request number in easybuild-easyconfigs repo to review :param colored: boolean indicating whether a colored multi-diff should be generated :param branch: easybuild-easyconfigs branch to compare with """ tmpdir = tempfile.mkdtemp() download_repo_path = download_repo(branch=branch, path=tmpdir) repo_path = os.path.join(download_repo_path, 'easybuild', 'easyconfigs') pr_files = [ path for path in fetch_easyconfigs_from_pr(pr) if path.endswith('.eb') ] lines = [] ecs, _ = parse_easyconfigs([(fp, False) for fp in pr_files], validate=False) for ec in ecs: files = find_related_easyconfigs(repo_path, ec['ec']) _log.debug("File in PR#%s %s has these related easyconfigs: %s" % (pr, ec['spec'], files)) if files: lines.append(multidiff(ec['spec'], files, colored=colored)) else: lines.extend([ '', "(no related easyconfigs found for %s)\n" % os.path.basename(ec['spec']) ]) return '\n'.join(lines)
def review_pr(paths=None, pr=None, colored=True, branch='develop'): """ Print multi-diff overview between specified easyconfigs or PR and specified branch. :param pr: pull request number in easybuild-easyconfigs repo to review :param paths: path tuples (path, generated) of easyconfigs to review :param colored: boolean indicating whether a colored multi-diff should be generated :param branch: easybuild-easyconfigs branch to compare with """ tmpdir = tempfile.mkdtemp() download_repo_path = download_repo(branch=branch, path=tmpdir) repo_path = os.path.join(download_repo_path, 'easybuild', 'easyconfigs') if pr: pr_files = [path for path in fetch_easyconfigs_from_pr(pr) if path.endswith('.eb')] elif paths: pr_files = paths else: raise EasyBuildError("No PR # or easyconfig path specified") lines = [] ecs, _ = parse_easyconfigs([(fp, False) for fp in pr_files], validate=False) for ec in ecs: files = find_related_easyconfigs(repo_path, ec['ec']) if pr: pr_msg = "PR#%s" % pr else: pr_msg = "new PR" _log.debug("File in %s %s has these related easyconfigs: %s" % (pr_msg, ec['spec'], files)) if files: lines.append(multidiff(ec['spec'], files, colored=colored)) else: lines.extend(['', "(no related easyconfigs found for %s)\n" % os.path.basename(ec['spec'])]) return '\n'.join(lines)
def review_pr(pr, colored=True, branch="develop"): """ Print multi-diff overview between easyconfigs in specified PR and specified branch. @param pr: pull request number in easybuild-easyconfigs repo to review @param colored: boolean indicating whether a colored multi-diff should be generated @param branch: easybuild-easyconfigs branch to compare with """ tmpdir = tempfile.mkdtemp() download_repo_path = download_repo(branch=branch, path=tmpdir) repo_path = os.path.join(download_repo_path, "easybuild", "easyconfigs") pr_files = [path for path in fetch_easyconfigs_from_pr(pr) if path.endswith(".eb")] lines = [] ecs, _ = parse_easyconfigs([(fp, False) for fp in pr_files], validate=False) for ec in ecs: files = find_related_easyconfigs(repo_path, ec["ec"]) _log.debug("File in PR#%s %s has these related easyconfigs: %s" % (pr, ec["spec"], files)) if files: lines.append(multidiff(ec["spec"], files, colored=colored)) else: lines.extend(["", "(no related easyconfigs found for %s)\n" % os.path.basename(ec["spec"])]) return "\n".join(lines)
def test_multidiff(self): """Test multidiff function.""" test_easyconfigs = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs') other_toy_ecs = [ os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-deps.eb'), os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-1.3.12-test.eb'), ] # default (colored) toy_ec = os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0.eb') lines = multidiff(toy_ec, other_toy_ecs).split('\n') expected = "Comparing \x1b[0;35mtoy-0.0.eb\x1b[0m with toy-0.0-deps.eb, toy-0.0-gompi-1.3.12-test.eb" red = "\x1b[0;41m" green = "\x1b[0;42m" endcol = "\x1b[0m" self.assertEqual(lines[0], expected) self.assertEqual(lines[1], "=====") # different versionsuffix self.assertTrue(lines[2].startswith( "3 %s- versionsuffix = '-test'%s (1/2) toy-0.0-" % (red, endcol))) self.assertTrue(lines[3].startswith( "3 %s- versionsuffix = '-deps'%s (1/2) toy-0.0-" % (red, endcol))) # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line (removed chars in toolchain name/version, in red) expected = "7 %(endcol)s-%(endcol)s toolchain = {" expected += "'name': '%(endcol)s%(red)sgo%(endcol)sm\x1b[0m%(red)spi%(endcol)s', " expected = expected % {'endcol': endcol, 'green': green, 'red': red} self.assertTrue(lines[7].startswith(expected)) # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line (added chars in toolchain name/version, in green) expected = "7 %(endcol)s+%(endcol)s toolchain = {" expected += "'name': '%(endcol)s%(green)sdu%(endcol)sm\x1b[0m%(green)smy%(endcol)s', " expected = expected % {'endcol': endcol, 'green': green, 'red': red} self.assertTrue(lines[8].startswith(expected)) # no postinstallcmds in toy-0.0-deps.eb expected = "28 %s+ postinstallcmds = " % green self.assertTrue(any([line.startswith(expected) for line in lines])) expected = "29 %s+%s (1/2) toy-0.0" % (green, endcol) self.assertTrue(any(l.startswith(expected) for l in lines), "Found '%s' in: %s" % (expected, lines)) self.assertEqual(lines[-1], "=====") lines = multidiff(toy_ec, other_toy_ecs, colored=False).split('\n') self.assertEqual( lines[0], "Comparing toy-0.0.eb with toy-0.0-deps.eb, toy-0.0-gompi-1.3.12-test.eb" ) self.assertEqual(lines[1], "=====") # different versionsuffix self.assertTrue( lines[2].startswith("3 - versionsuffix = '-test' (1/2) toy-0.0-")) self.assertTrue( lines[3].startswith("3 - versionsuffix = '-deps' (1/2) toy-0.0-")) # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line with squigly line underneath to mark removed chars expected = "7 - toolchain = {'name': 'gompi', 'version': '1.3.12'} (1/2) toy" self.assertTrue(lines[7].startswith(expected)) expected = " ? ^^ ^^ " self.assertTrue(lines[8].startswith(expected)) # different toolchain in toy-0.0-gompi-1.3.12-test: '-' line with squigly line underneath to mark added chars expected = "7 + toolchain = {'name': 'dummy', 'version': 'dummy'} (1/2) toy" self.assertTrue(lines[9].startswith(expected)) expected = " ? ^^ ^^ " self.assertTrue(lines[10].startswith(expected)) # no postinstallcmds in toy-0.0-deps.eb expected = "28 + postinstallcmds = " self.assertTrue(any(l.startswith(expected) for l in lines), "Found '%s' in: %s" % (expected, lines)) expected = "29 + (1/2) toy-0.0-" self.assertTrue(any(l.startswith(expected) for l in lines), "Found '%s' in: %s" % (expected, lines)) self.assertEqual(lines[-1], "=====")
def review_pr(paths=None, pr=None, colored=True, branch='develop', testing=False): """ Print multi-diff overview between specified easyconfigs or PR and specified branch. :param pr: pull request number in easybuild-easyconfigs repo to review :param paths: path tuples (path, generated) of easyconfigs to review :param colored: boolean indicating whether a colored multi-diff should be generated :param branch: easybuild-easyconfigs branch to compare with :param testing: whether to ignore PR labels (used in test_review_pr) """ pr_target_repo = build_option('pr_target_repo') or GITHUB_EASYCONFIGS_REPO if pr_target_repo != GITHUB_EASYCONFIGS_REPO: raise EasyBuildError( "Reviewing PRs for repositories other than easyconfigs hasn't been implemented yet" ) tmpdir = tempfile.mkdtemp() download_repo_path = download_repo(branch=branch, path=tmpdir) repo_path = os.path.join(download_repo_path, 'easybuild', 'easyconfigs') if pr: pr_files = [ path for path in fetch_easyconfigs_from_pr(pr) if path.endswith('.eb') ] elif paths: pr_files = paths else: raise EasyBuildError("No PR # or easyconfig path specified") lines = [] ecs, _ = parse_easyconfigs([(fp, False) for fp in pr_files], validate=False) for ec in ecs: files = find_related_easyconfigs(repo_path, ec['ec']) if pr: pr_msg = "PR#%s" % pr else: pr_msg = "new PR" _log.debug("File in %s %s has these related easyconfigs: %s" % (pr_msg, ec['spec'], files)) if files: lines.append(multidiff(ec['spec'], files, colored=colored)) else: lines.extend([ '', "(no related easyconfigs found for %s)\n" % os.path.basename(ec['spec']) ]) if pr: file_info = det_file_info(pr_files, download_repo_path) pr_target_account = build_option('pr_target_account') github_user = build_option('github_user') pr_data, _ = fetch_pr_data(pr, pr_target_account, pr_target_repo, github_user) pr_labels = [label['name'] for label in pr_data['labels']] if not testing else [] expected_labels = det_pr_labels(file_info, pr_target_repo) missing_labels = [ label for label in expected_labels if label not in pr_labels ] if missing_labels: lines.extend([ '', "This PR should be labelled with %s" % ', '.join(["'%s'" % ml for ml in missing_labels]) ]) if not pr_data['milestone']: lines.extend(['', "This PR should be associated with a milestone"]) elif '.x' in pr_data['milestone']['title']: lines.extend([ '', "This PR is associated with a generic '.x' milestone, " "it should be associated to the next release milestone once merged" ]) return '\n'.join(lines)
def test_multidiff(self): """Test multidiff function.""" test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs') other_toy_ecs = [ os.path.join(test_easyconfigs, 'toy-0.0-deps.eb'), os.path.join(test_easyconfigs, 'toy-0.0-gompi-1.3.12-test.eb'), ] # default (colored) lines = multidiff(os.path.join(test_easyconfigs, 'toy-0.0.eb'), other_toy_ecs).split('\n') expected = "Comparing \x1b[0;35mtoy-0.0.eb\x1b[0m with toy-0.0-deps.eb, toy-0.0-gompi-1.3.12-test.eb" red = "\x1b[0;41m" green = "\x1b[0;42m" endcol = "\x1b[0m" self.assertEqual(lines[0], expected) self.assertEqual(lines[1], "=====") # different versionsuffix self.assertEqual(lines[2], "3 %s- versionsuffix = '-test'%s (1/2) toy-0.0-gompi-1.3.12-test.eb" % (red, endcol)) self.assertEqual(lines[3], "3 %s- versionsuffix = '-deps'%s (1/2) toy-0.0-deps.eb" % (red, endcol)) # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line (removed chars in toolchain name/version, in red) expected = "7 %(endcol)s-%(endcol)s toolchain = {" expected += "'name': '%(endcol)s%(red)sgo%(endcol)sm\x1b[0m%(red)spi%(endcol)s', " expected = expected % {'endcol': endcol, 'green': green, 'red': red} self.assertTrue(lines[7].startswith(expected)) # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line (added chars in toolchain name/version, in green) expected = "7 %(endcol)s+%(endcol)s toolchain = {" expected += "'name': '%(endcol)s%(green)sdu%(endcol)sm\x1b[0m%(green)smy%(endcol)s', " expected = expected % {'endcol': endcol, 'green': green, 'red': red} self.assertTrue(lines[8].startswith(expected)) # no postinstallcmds in toy-0.0-deps.eb expected = "28 %s+ postinstallcmds = " % green self.assertTrue(any([line.startswith(expected) for line in lines])) self.assertTrue("29 %s+%s (1/2) toy-0.0-deps.eb" % (green, endcol) in lines) self.assertEqual(lines[-1], "=====") lines = multidiff(os.path.join(test_easyconfigs, 'toy-0.0.eb'), other_toy_ecs, colored=False).split('\n') self.assertEqual(lines[0], "Comparing toy-0.0.eb with toy-0.0-deps.eb, toy-0.0-gompi-1.3.12-test.eb") self.assertEqual(lines[1], "=====") # different versionsuffix self.assertEqual(lines[2], "3 - versionsuffix = '-test' (1/2) toy-0.0-gompi-1.3.12-test.eb") self.assertEqual(lines[3], "3 - versionsuffix = '-deps' (1/2) toy-0.0-deps.eb") # different toolchain in toy-0.0-gompi-1.3.12-test: '+' line with squigly line underneath to mark removed chars expected = "7 - toolchain = {'name': 'gompi', 'version': '1.3.12'} (1/2) toy" self.assertTrue(lines[7].startswith(expected)) expected = " ? ^^ ^^ ^^^^^^" self.assertEqual(lines[8], expected) # different toolchain in toy-0.0-gompi-1.3.12-test: '-' line with squigly line underneath to mark added chars expected = "7 + toolchain = {'name': 'dummy', 'version': 'dummy'} (1/2) toy" self.assertTrue(lines[9].startswith(expected)) expected = " ? ^^ ^^ ^^^^^" self.assertEqual(lines[10], expected) # no postinstallcmds in toy-0.0-deps.eb expected = "28 + postinstallcmds = " self.assertTrue(any([line.startswith(expected) for line in lines])) self.assertTrue("29 + (1/2) toy-0.0-deps.eb" in lines) self.assertEqual(lines[-1], "=====")