Skip to content

Commit 90735a8

Browse files
committed
Merge branch 'develop' into install-test
2 parents fd77d35 + 00eb94f commit 90735a8

348 files changed

Lines changed: 1419 additions & 531 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/unit_tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ jobs:
248248
# try and make sure output of running tests is clean (no printed messages/warnings)
249249
IGNORE_PATTERNS="no GitHub token available"
250250
IGNORE_PATTERNS+="|skipping SvnRepository test"
251+
IGNORE_PATTERNS+="|Skipping test_dep_graph"
251252
IGNORE_PATTERNS+="|requires Lmod as modules tool"
252253
IGNORE_PATTERNS+="|stty: 'standard input': Inappropriate ioctl for device"
253254
IGNORE_PATTERNS+="|CryptographyDeprecationWarning: Python 3.7"
@@ -256,6 +257,8 @@ jobs:
256257
IGNORE_PATTERNS+="|GC3Pie not available, skipping test"
257258
IGNORE_PATTERNS+="|CryptographyDeprecationWarning: TripleDES has been moved"
258259
IGNORE_PATTERNS+="|algorithms.TripleDES"
260+
# ignore lines with only successful ('.') and skipped ('s') tests
261+
IGNORE_PATTERNS+="|^[\.s]+$"
259262
# '|| true' is needed to avoid that GitHub Actions stops the job on non-zero exit of grep (i.e. when there are no matches)
260263
PRINTED_MSG=$(egrep -v "${IGNORE_PATTERNS}" test_framework_suite.log | grep '\.\n*[A-Za-z]' || true)
261264
test "x$PRINTED_MSG" = "x" || (echo "ERROR: Found printed messages in output of test suite" && echo "${PRINTED_MSG}" && exit 1)

RELEASE_NOTES

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,87 @@ For more detailed information, please see the git log.
33

44
These release notes can also be consulted at https://docs.easybuild.io/release-notes .
55

6+
v5.2.1 (20 Feb 2026)
7+
--------------------
8+
9+
update/bugfix release
10+
11+
- bug fixes:
12+
- ignore stderr for `rocm-smi` during test report creation (#5087)
13+
- use initially stored environment to determine GPU info for test reports (#5088)
14+
- add back `easybuild.toolchains.compiler.nvhpc` as deprecated toolchain compiler (#5089, #5096, #5105)
15+
- properly handle toolchains defining `openmp` toolchain opt as `dict` (relevant for NVHPC toolchain) (#5093)
16+
- enhance `get_source_tarball_from_git` to ensure that Git repo URL does not contain double slashes due to trailing slash in source URL (#5097)
17+
- fix crash with `MarkupError` in Rich when showing failed shell command containing special characters (#5098)
18+
- fix sub-toolchains of NVHPC and NVHPCToolchain and load each one where appropriate (#5103)
19+
- don't require installation prefix for toolchain dependencies that are an external module (#5108)
20+
- enhancements:
21+
- add support for injecting checksums for Rust crates (#4661)
22+
- include full shell command that failed in raised error (#5074)
23+
- improve error reporting for failures in `eb --merge-pr` and similar (#5076)
24+
- add LLVM toolchains using ParaStationMPI (#5094)
25+
- enhancements and fixes for test suite:
26+
- ignore output lines with skipped tests in check for unexpected output of test suite (#5082)
27+
- import specific submodule `pygraph.classes.digraph` in `test_dep_graph*` so we can skip the test if import fails with setuptools >= 82.0.0 (#5111, #5116)
28+
- other changes:
29+
- extend list of easyconfig parameters that extensions should not inherit: `sources`, `patches`, `checksums`, `skipsteps` (#5075)
30+
- deprecate `print_error` function and replace it with new `print_error_and_exit` function (#5092)
31+
- replace use of `datetime.utcfromtimestamp` which is deprecated since Python 3.12 (#5091)
32+
33+
34+
v5.2.0 (23 Dec 2025)
35+
--------------------
36+
37+
feature release
38+
39+
- new features:
40+
- add support for NVHPC toolchain with nvidia-compilers, NVHPCX, NVBLAS, and NVScaLAPACK (#4927, #5073)
41+
- add support for LLVM-based toolchains `lfoss` and `lmpflf` (+ subtoolchains `llvm-compilers`, `lfbf`, `lompi`, `lmpich`) (#4914)
42+
- various other enhancements, including:
43+
- add support for `--disable-robot` (#4781)
44+
- make specifying `exts_defaultclass` optional (#4800)
45+
- retry fetching source file for extensions from PyPI with alternative filename (with `-` replaced with `_` in extension name) (#4943)
46+
- handle `post_install_patches` in GitHub uploads (#5016)
47+
- take into account alternative name `post_install_patches` when checking checksums (#5017)
48+
- improve test report formatting (#5018)
49+
- add `--keep-going` option to fail at the end not at first failing installation + use proper exit code as determined by `main` function (#5022)
50+
- add templates for source with just version numbers (like `VERSION_TAR_GZ` and `V_VERSION_TAR_GZ`) (#5025)
51+
- add templates for patch versions (#5028)
52+
- add `search_path_vars_headers` and `search_path_vars_linker` properties to `Toolchain` (#5031)
53+
- print total runtime of all builds (#5032)
54+
- unset `$PROMPT_COMMAND` in `cmd.sh` shell (#5034)
55+
- add `runtime_only` options to `EasyConfig.dependency_names` method (#5044)
56+
- remove superflous `module list` call in `ModulesTool.load` (#5046)
57+
- add backtrace to logged exception (#5047)
58+
- add support for both `$VAR` and `${VAR}` variable formats in `modextravars` (#5049)
59+
- show more readable error message when uploading gist or posting comment failed (#5056)
60+
- set `$___EASYBUILD___` environment variable to '`EasyBuild`' to indicate that you're in an EasyBuild session (#5058)
61+
- vendor a copy of `tomli` in `easybuild.tools.tomllib` (#5063)
62+
- allow `f` suffix in CUDA compute capabilities (#5067)
63+
- vendor copy of tomli-w 1.2.0, use it to implement `dump_toml` function in `easybuild.tools.filetools` (#5071)
64+
- various bug fixes, including:
65+
- pass correct `-march` option on RISC-V systems when `optarch` toolchain option is enabled (#5029)
66+
- pass dependencies to `toolchain.prepare` when setting up build environment for extensions (#5023, #5041)
67+
- also pick up on toolchain components in `Toolchain._add_dependency_variables` (#5042, #5048)
68+
- don't append empty component to `start_dir` in `EasyBlock.guess_start_dir` (#5057)
69+
- enhancements and fixes for test suite:
70+
- also with test Python 3.14 (#4992)
71+
- fix `test_gitrepo` in case global Git configuration is not in place (#5013)
72+
- introduce `saved_env` context manager for restoring environment in tests (#5015)
73+
- add decorator to ignore PR test failures due to rate limit (#5019)
74+
- also run tests with Lmod 9.0 (#5026)
75+
- enable flake8-comprehension code style check and fix issues (#5043)
76+
- disable trace output by default in tests (#5053)
77+
- add back CI for Python 3.6 by using `pyenv` (#5064)
78+
- fix `test_github_det_commit_status` by using more recent commits (#5066)
79+
- fix ignoring of URLError in `test_copy_ec_from_commit` (#5077)
80+
- other changes:
81+
- deprecate support for running EasyBuild with Python < 3.9 (#4966)
82+
- make command environment of shell commands more discoverable in the log (#4999, #5078)
83+
- don't show command string again when showing in which folder it runs (#5003)
84+
- remove escaping when converting `EasyBuildError` to a string (#5009)
85+
- add example hook for updating OpenSSL 1.x dependency to 3.x (#5035)
86+
687

788
v5.1.2 (26 Sept 2025)
889
---------------------

easybuild/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
##
2-
# Copyright 2011-2025 Ghent University
2+
# Copyright 2011-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

easybuild/base/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright 2015-2025 Ghent University
2+
# Copyright 2015-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

easybuild/base/fancylogger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright 2011-2025 Ghent University
2+
# Copyright 2011-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

easybuild/base/generaloption.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright 2011-2025 Ghent University
2+
# Copyright 2011-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

easybuild/base/testing.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright 2014-2025 Ghent University
2+
# Copyright 2014-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
@@ -210,6 +210,15 @@ def mocked_stdout(self):
210210
finally:
211211
self.mock_stdout(False)
212212

213+
@contextmanager
214+
def mocked_stderr(self):
215+
"""Context manager to mock stdout"""
216+
self.mock_stderr(True)
217+
try:
218+
yield sys.stderr
219+
finally:
220+
self.mock_stderr(False)
221+
213222
@contextmanager
214223
def mocked_stdout_stderr(self, mock_stdout=True, mock_stderr=True):
215224
"""Context manager to mock stdout and stderr"""

easybuild/framework/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
##
2-
# Copyright 2009-2025 Ghent University
2+
# Copyright 2009-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

easybuild/framework/easyblock.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# #
2-
# Copyright 2009-2025 Ghent University
2+
# Copyright 2009-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
@@ -81,7 +81,7 @@
8181
from easybuild.tools import LooseVersion, config
8282
from easybuild.tools.build_details import get_build_stats
8383
from easybuild.tools.build_log import EasyBuildError, EasyBuildExit, dry_run_msg, dry_run_warning, dry_run_set_dirs
84-
from easybuild.tools.build_log import print_error, print_msg, print_warning
84+
from easybuild.tools.build_log import print_error_and_exit, print_msg, print_warning
8585
from easybuild.tools.config import CHECKSUM_PRIORITY_JSON, DEFAULT_ENVVAR_USERS_MODULES
8686
from easybuild.tools.config import EASYBUILD_SOURCES_URL, EBPYTHONPREFIXES # noqa
8787
from easybuild.tools.config import FORCE_DOWNLOAD_ALL, FORCE_DOWNLOAD_PATCHES, FORCE_DOWNLOAD_SOURCES
@@ -173,6 +173,14 @@ def extra_options(extra=None):
173173

174174
return extra
175175

176+
@staticmethod
177+
def src_parameter_names():
178+
"""
179+
Return list of EasyConfig parameter that contribute to the sources in the `src` member
180+
(or equivalently to the `sources` parameter of a parsed EasyConfig)
181+
"""
182+
return ['sources']
183+
176184
#
177185
# INIT
178186
#
@@ -1919,7 +1927,7 @@ def clean_up_fake_module(self, fake_mod_data):
19191927
# self.short_mod_name might not be set (e.g. during unit tests)
19201928
if fake_mod_path and self.short_mod_name is not None:
19211929
try:
1922-
self.modules_tool.unload([self.short_mod_name], log_changes=False)
1930+
self.modules_tool.unload([self.short_mod_name], hide_output=True)
19231931
self.modules_tool.remove_module_path(os.path.join(fake_mod_path, self.mod_subdir))
19241932
remove_dir(os.path.dirname(fake_mod_path))
19251933
except OSError as err:
@@ -2982,7 +2990,8 @@ def prepare_step(self, start_dir=True, load_tc_deps_modules=True):
29822990
if os.path.isabs(self.rpath_wrappers_dir):
29832991
_log.info(f"Using {self.rpath_wrappers_dir} to store/use RPATH wrappers")
29842992
else:
2985-
raise EasyBuildError(f"Path used for rpath_wrappers_dir is not an absolute path: {path}")
2993+
raise EasyBuildError("Path used for rpath_wrappers_dir is not an absolute path: %s",
2994+
self.rpath_wrappers_dir)
29862995

29872996
if self.iter_idx > 0:
29882997
# reset toolchain for iterative runs before preparing it again
@@ -3071,8 +3080,9 @@ def _test_step(self):
30713080
except RunShellCmdError as err:
30723081
err.print()
30733082
ec_path = os.path.basename(self.cfg.path)
3074-
error_msg = f"shell command '{err.cmd_name} ...' failed in test step for {ec_path}"
3075-
self.report_test_failure(error_msg)
3083+
error_msg = "shell command '{cmd}' failed in test step for " + ec_path
3084+
self.log.warning(error_msg.format(cmd=err.cmd))
3085+
self.report_test_failure(error_msg.format(cmd=f"{err.cmd_name} ..."))
30763086

30773087
def stage_install_step(self):
30783088
"""Install in a stage directory before actual installation."""
@@ -4357,7 +4367,7 @@ def xs2str(xs):
43574367

43584368
# allow oversubscription of P processes on C cores (P>C) for software installed on top of Open MPI;
43594369
# this is useful to avoid failing of sanity check commands that involve MPI
4360-
if self.toolchain.mpi_family() and self.toolchain.mpi_family() in toolchain.OPENMPI:
4370+
if self.toolchain.mpi_family() and self.toolchain.mpi_family() == toolchain.OPENMPI:
43614371
env.setvar('OMPI_MCA_rmaps_base_oversubscribe', '1')
43624372

43634373
# run sanity checks from an empty temp directory
@@ -4922,15 +4932,16 @@ def run_all_steps(self, run_test_cases):
49224932
self.run_step(step_name, step_methods)
49234933
except RunShellCmdError as err:
49244934
err.print()
4925-
error_msg = (
4926-
f"shell command '{err.cmd_name} ...' failed with exit code {err.exit_code} "
4927-
f"in {step_name} step for {os.path.basename(self.cfg.path)}"
4935+
msg = (
4936+
"shell command '{cmd}' failed with exit code "
4937+
f"{err.exit_code} in {step_name} step for {os.path.basename(self.cfg.path)}"
49284938
)
4939+
self.log.warning(msg.format(cmd=err.cmd)) # pylint: disable=logging-format-interpolation
49294940
try:
49304941
step_exit_code = EasyBuildExit[f"FAIL_{step_name.upper()}_STEP"]
49314942
except KeyError:
49324943
step_exit_code = EasyBuildExit.ERROR
4933-
raise EasyBuildError(error_msg, exit_code=step_exit_code) from err
4944+
raise EasyBuildError(msg.format(cmd=f"{err.cmd_name} ..."), exit_code=step_exit_code) from err
49344945
finally:
49354946
if not self.dry_run:
49364947
step_duration = datetime.now() - start_time
@@ -5064,8 +5075,8 @@ def build_and_install_one(ecdict, init_env):
50645075
app = app_class(ecdict['ec'])
50655076
_log.info("Obtained application instance for %s (easyblock: %s)" % (name, easyblock))
50665077
except EasyBuildError as err:
5067-
print_error("Failed to get application instance for %s (easyblock: %s): %s" % (name, easyblock, err.msg),
5068-
silent=silent)
5078+
print_error_and_exit("Failed to get application instance for %s (easyblock: %s): %s", name, easyblock, err.msg,
5079+
silent=silent, exit_code=err.exit_code)
50695080

50705081
# application settings
50715082
stop = build_option('stop')
@@ -5601,8 +5612,8 @@ def make_checksum_lines(checksums, indent_level):
56015612
if app.src:
56025613
placeholder = '# PLACEHOLDER FOR SOURCES/PATCHES WITH CHECKSUMS'
56035614

5604-
# grab raw lines for source_urls, sources, data_sources, patches
5605-
keys = ['data_sources', 'patches', 'source_urls', 'sources']
5615+
# grab raw lines for the following params
5616+
keys = ['data_sources', 'source_urls'] + app.src_parameter_names() + ['patches']
56065617
raw = {}
56075618
for key in keys:
56085619
regex = re.compile(r'^(%s(?:.|\n)*?\])\s*$' % key, re.M)
@@ -5613,15 +5624,11 @@ def make_checksum_lines(checksums, indent_level):
56135624

56145625
_log.debug("Raw lines for %s easyconfig parameters: %s", '/'.join(keys), raw)
56155626

5616-
# inject combination of source_urls/sources/patches/checksums into easyconfig
5617-
# by replacing first occurence of placeholder that was put in place
5618-
sources_raw = raw.get('sources', '')
5619-
data_sources_raw = raw.get('data_sources', '')
5620-
source_urls_raw = raw.get('source_urls', '')
5621-
patches_raw = raw.get('patches', '')
5627+
# inject combination of the grabbed lines and the checksums into the easyconfig
5628+
# by replacing first the occurence of the placeholder that was put in place
5629+
raw_text = ''.join(raw.get(key, '') for key in keys)
56225630
regex = re.compile(placeholder + '\n', re.M)
5623-
ectxt = regex.sub(source_urls_raw + sources_raw + data_sources_raw + patches_raw + checksums_txt + '\n',
5624-
ectxt, count=1)
5631+
ectxt = regex.sub(raw_text + checksums_txt + '\n', ectxt, count=1)
56255632

56265633
# get rid of potential remaining placeholders
56275634
ectxt = regex.sub('', ectxt)

easybuild/framework/easyconfig/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# #
2-
# Copyright 2009-2025 Ghent University
2+
# Copyright 2009-2026 Ghent University
33
#
44
# This file is part of EasyBuild,
55
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),

0 commit comments

Comments
 (0)