Skip to content

Use version suffixes in PR title instead of Python versions when using --new-pr #4253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 40 additions & 33 deletions easybuild/tools/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,45 @@ def new_branch_github(paths, ecs, commit_msg=None):
return res


def det_pr_title(ecs):
"""
Create title for PR based on first easyconfigs
:param ecs: list of parsed easyconfigs
"""

# only use most common toolchain(s) in toolchain label of PR title
toolchains = ['%(name)s/%(version)s' % ec['toolchain'] for ec in ecs]
toolchains_counted = sorted([(toolchains.count(tc), tc) for tc in nub(toolchains)])
toolchain_label = ','.join([tc for (cnt, tc) in toolchains_counted if cnt == toolchains_counted[-1][0]])

# only use most common module class(es) in moduleclass label of PR title
classes = [ec['moduleclass'] for ec in ecs]
classes_counted = sorted([(classes.count(c), c) for c in nub(classes)])
class_label = ','.join([tc for (cnt, tc) in classes_counted if cnt == classes_counted[-1][0]])

names_and_versions = nub(["%s v%s" % (ec.name, ec.version) for ec in ecs])
if len(names_and_versions) <= 3:
main_title = ', '.join(names_and_versions)
else:
main_title = ', '.join(names_and_versions[:3] + ['...'])

title = "{%s}[%s] %s" % (class_label, toolchain_label, main_title)

# Find all suffixes
suffixes = []
for ec in ecs:
if 'versionsuffix' in ec and ec['versionsuffix']:
suffixes.append(ec['versionsuffix'].strip('-').replace('-', ' '))
if suffixes:
suffixes = sorted(nub(suffixes))
if len(suffixes) <= 2:
title += ' w/ ' + ', '.join(suffixes)
else:
title += ' w/ ' + ', '.join(suffixes[:2] + ['...'])

return title


@only_if_module_is_available('git', pkgname='GitPython')
def new_pr_from_branch(branch_name, title=None, descr=None, pr_target_repo=None, pr_metadata=None, commit_msg=None):
"""
Expand Down Expand Up @@ -1691,42 +1730,10 @@ def new_pr_from_branch(branch_name, title=None, descr=None, pr_target_repo=None,

labels = det_pr_labels(file_info, pr_target_repo)

if pr_target_repo == GITHUB_EASYCONFIGS_REPO:
# only use most common toolchain(s) in toolchain label of PR title
toolchains = ['%(name)s/%(version)s' % ec['toolchain'] for ec in file_info['ecs']]
toolchains_counted = sorted([(toolchains.count(tc), tc) for tc in nub(toolchains)])
toolchain_label = ','.join([tc for (cnt, tc) in toolchains_counted if cnt == toolchains_counted[-1][0]])

# only use most common module class(es) in moduleclass label of PR title
classes = [ec['moduleclass'] for ec in file_info['ecs']]
classes_counted = sorted([(classes.count(c), c) for c in nub(classes)])
class_label = ','.join([tc for (cnt, tc) in classes_counted if cnt == classes_counted[-1][0]])

if title is None:
if pr_target_repo == GITHUB_EASYCONFIGS_REPO:
if file_info['ecs'] and all(file_info['new']) and not deleted_paths:
# mention software name/version in PR title (only first 3)
names_and_versions = nub(["%s v%s" % (ec.name, ec.version) for ec in file_info['ecs']])
if len(names_and_versions) <= 3:
main_title = ', '.join(names_and_versions)
else:
main_title = ', '.join(names_and_versions[:3] + ['...'])

title = "{%s}[%s] %s" % (class_label, toolchain_label, main_title)

# if Python is listed as a dependency, then mention Python version(s) in PR title
pyver = []
for ec in file_info['ecs']:
# iterate over all dependencies (incl. build dependencies & multi-deps)
for dep in ec.dependencies():
if dep['name'] == 'Python':
# check whether Python is listed as a multi-dep if it's marked as a build dependency
if dep['build_only'] and 'Python' not in ec['multi_deps']:
continue
else:
pyver.append(dep['version'])
if pyver:
title += " w/ Python %s" % ' + '.join(sorted(nub(pyver)))
title = det_pr_title(file_info['ecs'])
elif pr_target_repo == GITHUB_EASYBLOCKS_REPO:
if file_info['eb_names'] and all(file_info['new']) and not deleted_paths:
plural = 's' if len(file_info['eb_names']) > 1 else ''
Expand Down
67 changes: 66 additions & 1 deletion test/framework/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
from easybuild.tools.filetools import read_file, write_file
from easybuild.tools.github import GITHUB_EASYCONFIGS_REPO, GITHUB_EASYBLOCKS_REPO, GITHUB_MERGEABLE_STATE_CLEAN
from easybuild.tools.github import VALID_CLOSE_PR_REASONS
from easybuild.tools.github import is_patch_for, pick_default_branch
from easybuild.tools.github import det_pr_title, is_patch_for, pick_default_branch
from easybuild.tools.testing import create_test_report, post_pr_test_report, session_state
from easybuild.tools.py2vs3 import HTTPError, URLError, ascii_letters
import easybuild.tools.github as gh
Expand Down Expand Up @@ -116,6 +116,71 @@ def tearDown(self):

super(GithubTest, self).tearDown()

def test_det_pr_title(self):
"""Test det_pr_title function"""
# check if patches for extensions are found
rawtxt = textwrap.dedent("""
easyblock = 'ConfigureMake'
name = '%s'
version = '%s'
homepage = 'http://foo.com/'
description = ''
toolchain = {'name': '%s', 'version': '%s'}
moduleclass = '%s'
%s
""")

# 1 easyconfig, with no versionsuffix
ecs = []
ecs.append(EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools', '')))
self.assertEqual(det_pr_title(ecs), '{tools}[GCC/11.2.0] prog v1')

# 2 easyconfigs, with no versionsuffixes
ecs.append(EasyConfig(None, rawtxt=rawtxt % ('otherprog', '2', 'GCCcore', '11.2.0', 'lib', '')))
self.assertEqual(det_pr_title(ecs), '{lib,tools}[GCC/11.2.0,GCCcore/11.2.0] prog v1, otherprog v2')

# 3 easyconfigs, with no versionsuffixes
ecs.append(EasyConfig(None, rawtxt=rawtxt % ('extraprog', '3', 'foss', '2022a', 'astro', '')))
self.assertEqual(det_pr_title(ecs),
'{astro,lib,tools}[GCC/11.2.0,GCCcore/11.2.0,foss/2022a] prog v1, otherprog v2, extraprog v3')

# 2 easyconfigs for the same prog, with no versionsuffixes
ecs[1] = EasyConfig(None, rawtxt=rawtxt % ('prog', '2', 'GCC', '11.3.0', 'tools', ''))
ecs.pop(2)
self.assertEqual(det_pr_title(ecs), '{tools}[GCC/11.2.0,GCC/11.3.0] prog v1, prog v2')

# 1 easyconfig, with versionsuffix
ecs = []
ecs.append(EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-Python-3.10.4"')))
self.assertEqual(det_pr_title(ecs), '{tools}[GCC/11.2.0] prog v1 w/ Python 3.10.4')

# 1 easyconfig, with versionsuffix
ecs[0] = EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-Python-3.10.4-CUDA-11.3.1"'))
self.assertEqual(det_pr_title(ecs), '{tools}[GCC/11.2.0] prog v1 w/ Python 3.10.4 CUDA 11.3.1')

# 2 easyconfigs, with same versionsuffix
ecs[0] = EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-Python-3.10.4"'))
ecs.append(EasyConfig(None, rawtxt=rawtxt % ('prog', '2', 'GCC', '11.3.0', 'tools',
'versionsuffix = "-Python-3.10.4"')))
self.assertEqual(det_pr_title(ecs), '{tools}[GCC/11.2.0,GCC/11.3.0] prog v1, prog v2 w/ Python 3.10.4')

# 2 easyconfigs, with different versionsuffix
ecs[0] = EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-CUDA-11.3.1"'))
self.assertEqual(det_pr_title(ecs),
'{tools}[GCC/11.2.0,GCC/11.3.0] prog v1, prog v2 w/ CUDA 11.3.1, Python 3.10.4')

# 2 easyconfigs, with unusual versionsuffixes
ecs[0] = EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-contrib"'))
ecs[1] = EasyConfig(None, rawtxt=rawtxt % ('prog', '1', 'GCC', '11.2.0', 'tools',
'versionsuffix = "-Python-3.10.4-CUDA-11.3.1-contrib"'))
self.assertEqual(det_pr_title(ecs),
'{tools}[GCC/11.2.0] prog v1 w/ Python 3.10.4 CUDA 11.3.1 contrib, contrib')

def test_github_pick_default_branch(self):
"""Test pick_default_branch function."""

Expand Down