Example #1
0
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)
Example #2
0
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)
Example #3
0
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], "=====")
Example #5
0
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], "=====")