Skip to content

Commit 14c273a

Browse files
Merge pull request #4342 from easybuilders/4.8.x
release EasyBuild v4.8.1
2 parents e082752 + a338514 commit 14c273a

File tree

32 files changed

+779
-140
lines changed

32 files changed

+779
-140
lines changed

.github/workflows/end2end.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: End-to-end test of EasyBuild in different distros
2+
on: [push, pull_request]
3+
jobs:
4+
build_publish:
5+
name: End-to-end test
6+
runs-on: ubuntu-latest
7+
strategy:
8+
matrix:
9+
container:
10+
- centos-7.9
11+
- centos-8.5
12+
- fedora-36
13+
- opensuse-15.4
14+
- rockylinux-8.8
15+
- rockylinux-9.2
16+
- ubuntu-20.04
17+
- ubuntu-22.04
18+
fail-fast: false
19+
container:
20+
image: ghcr.io/easybuilders/${{ matrix.container }}-amd64
21+
steps:
22+
- name: Check out the repo
23+
uses: actions/checkout@v3
24+
25+
- name: download and unpack easyblocks and easyconfigs repositories
26+
run: |
27+
cd $HOME
28+
for pkg in easyblocks easyconfigs; do
29+
curl -OL https://github.com/easybuilders/easybuild-${pkg}/archive/develop.tar.gz
30+
tar xfz develop.tar.gz
31+
rm -f develop.tar.gz
32+
done
33+
34+
- name: Set up environment
35+
shell: bash
36+
run: |
37+
# collect environment variables to be set in subsequent steps in script that can be sourced
38+
echo "export PATH=$PWD:$PATH" > /tmp/eb_env
39+
echo "export PYTHONPATH=$PWD:$HOME/easybuild-easyblocks-develop:$HOME/easybuild-easyconfigs-develop" >> /tmp/eb_env
40+
41+
- name: Run commands to check test environment
42+
shell: bash
43+
run: |
44+
cmds=(
45+
"whoami"
46+
"pwd"
47+
"env | sort"
48+
"eb --version"
49+
"eb --show-system-info"
50+
"eb --check-eb-deps"
51+
"eb --show-config"
52+
)
53+
for cmd in "${cmds[@]}"; do
54+
echo ">>> $cmd"
55+
sudo -u easybuild bash -l -c "source /tmp/eb_env; $cmd"
56+
done
57+
58+
- name: End-to-end test of installing bzip2 with EasyBuild
59+
shell: bash
60+
run: |
61+
sudo -u easybuild bash -l -c "source /tmp/eb_env; eb bzip2-1.0.8.eb --trace --robot"

RELEASE_NOTES

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@ For more detailed information, please see the git log.
44
These release notes can also be consulted at https://easybuild.readthedocs.io/en/latest/Release_notes.html.
55

66

7+
v4.8.1 (11 September 2023)
8+
--------------------------
9+
10+
update/bugfix release
11+
12+
- various enhancements, including:
13+
- add end-to-end test for running EasyBuild in different Linux distros using containers (#3968)
14+
- suggest default title in `--review-pr` (#4287)
15+
- add `build_and_install_loop` hooks to run before and after the install loop for individual easyconfigs (#4304)
16+
- implement support for `cancel_hook` and `fail_hook` (#4315, #4325)
17+
- add postiter hook to the list of steps so the corresponding hook can be used (#4316)
18+
- add `run_shell_cmd` hook (#4323)
19+
- add `build_info_msg` easyconfig parameter to print message during installation of an easyconfig (#4324)
20+
- add `--silence-hook-trigger` configuration option to supress printing of debug message every time a hook is triggered (#4329)
21+
- add support for using fine grained Github tokens (#4332)
22+
- add definitions for ifbf and iofbf toolchain (#4337)
23+
- add support for submodule filtering and specifying extra Git configuration in `git_config` (#4338, #4339)
24+
- various bug fixes, including:
25+
- improve error when checksum dict has no entry for a file (#4150)
26+
- avoid error being logged when `checksums.json` is not found (#4261)
27+
- don't fail in `mkdir` if path gets created while processing it (#4300, #4328)
28+
- ignore request for external module (meta)data when no modules tool is active (#4308)
29+
- use sys.executable to obtain path to `python` command in tests, rather than assuming that `python` command is available in `$PATH` (#4309)
30+
- fix `test_add_and_remove_module_path` by replacing string comparison of paths by checking whether they point to the same path (since symlinks may cause trouble) (#4312)
31+
- enhance `Toolchain.get_flag` to handle lists (#4319)
32+
- only add extensions in module file if there are extensions (#4331)
33+
34+
735
v4.8.0 (7 July 2023)
836
--------------------
937

easybuild/framework/easyblock.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,13 @@ def get_checksums_from_json(self, always_read=False):
395395
:param always_read: always read the checksums.json file, even if it has been read before
396396
"""
397397
if always_read or self.json_checksums is None:
398-
try:
399-
path = self.obtain_file("checksums.json", no_download=True)
398+
path = self.obtain_file("checksums.json", no_download=True, warning_only=True)
399+
if path is not None:
400400
self.log.info("Loading checksums from file %s", path)
401401
json_txt = read_file(path)
402402
self.json_checksums = json.loads(json_txt)
403-
# if the file can't be found, return an empty dict
404-
except EasyBuildError:
403+
else:
404+
# if the file can't be found, return an empty dict
405405
self.json_checksums = {}
406406

407407
return self.json_checksums
@@ -736,7 +736,8 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True):
736736
return exts_sources
737737

738738
def obtain_file(self, filename, extension=False, urls=None, download_filename=None, force_download=False,
739-
git_config=None, no_download=False, download_instructions=None, alt_location=None):
739+
git_config=None, no_download=False, download_instructions=None, alt_location=None,
740+
warning_only=False):
740741
"""
741742
Locate the file with the given name
742743
- searches in different subdirectories of source path
@@ -789,7 +790,13 @@ def obtain_file(self, filename, extension=False, urls=None, download_filename=No
789790
return fullpath
790791

791792
except IOError as err:
792-
raise EasyBuildError("Downloading file %s from url %s to %s failed: %s", filename, url, fullpath, err)
793+
if not warning_only:
794+
raise EasyBuildError("Downloading file %s "
795+
"from url %s to %s failed: %s", filename, url, fullpath, err)
796+
else:
797+
self.log.warning("Downloading file %s "
798+
"from url %s to %s failed: %s", filename, url, fullpath, err)
799+
return None
793800

794801
else:
795802
# try and find file in various locations
@@ -866,8 +873,13 @@ def obtain_file(self, filename, extension=False, urls=None, download_filename=No
866873
self.dry_run_msg(" * %s (MISSING)", filename)
867874
return filename
868875
else:
869-
raise EasyBuildError("Couldn't find file %s anywhere, and downloading it is disabled... "
876+
if not warning_only:
877+
raise EasyBuildError("Couldn't find file %s anywhere, and downloading it is disabled... "
878+
"Paths attempted (in order): %s ", filename, ', '.join(failedpaths))
879+
else:
880+
self.log.warning("Couldn't find file %s anywhere, and downloading it is disabled... "
870881
"Paths attempted (in order): %s ", filename, ', '.join(failedpaths))
882+
return None
871883
elif git_config:
872884
return get_source_tarball_from_git(filename, targetdir, git_config)
873885
else:
@@ -959,7 +971,11 @@ def obtain_file(self, filename, extension=False, urls=None, download_filename=No
959971
error_msg += "and downloading it didn't work either... "
960972
error_msg += "Paths attempted (in order): %s " % failedpaths_msg
961973

962-
raise EasyBuildError(error_msg, filename)
974+
if not warning_only:
975+
raise EasyBuildError(error_msg, filename)
976+
else:
977+
self.log.warning(error_msg, filename)
978+
return None
963979

964980
#
965981
# GETTER/SETTER UTILITY FUNCTIONS
@@ -4174,6 +4190,10 @@ def build_and_install_one(ecdict, init_env):
41744190
dry_run_msg('', silent=silent)
41754191
print_msg("processing EasyBuild easyconfig %s" % spec, log=_log, silent=silent)
41764192

4193+
if ecdict['ec']['build_info_msg']:
4194+
msg = "This easyconfig provides the following build information:\n\n%s\n"
4195+
print_msg(msg % ecdict['ec']['build_info_msg'], log=_log, silent=silent)
4196+
41774197
if dry_run:
41784198
# print note on interpreting dry run output (argument is reference to location of dry run messages)
41794199
print_dry_run_note('below', silent=silent)

easybuild/framework/easyconfig/default.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@
228228
'buildstats': [None, "A list of dicts with build statistics", OTHER],
229229
'deprecated': [False, "String specifying reason why this easyconfig file is deprecated "
230230
"and will be archived in the next major release of EasyBuild", OTHER],
231+
'build_info_msg': [None, "String with information to be printed to stdout and logged during the building "
232+
"of the easyconfig", OTHER],
231233
}
232234

233235

easybuild/framework/easyconfig/easyconfig.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
from easybuild.tools.module_naming_scheme.mns import DEVEL_MODULE_SUFFIX
7474
from easybuild.tools.module_naming_scheme.utilities import avail_module_naming_schemes, det_full_ec_version
7575
from easybuild.tools.module_naming_scheme.utilities import det_hidden_modname, is_valid_module_name
76-
from easybuild.tools.modules import modules_tool
76+
from easybuild.tools.modules import modules_tool, NoModulesTool
7777
from easybuild.tools.py2vs3 import OrderedDict, create_base_metaclass, string_type
7878
from easybuild.tools.systemtools import check_os_dependency, pick_dep_version
7979
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME, is_system_toolchain
@@ -1306,6 +1306,9 @@ def probe_external_module_metadata(self, mod_name, existing_metadata=None):
13061306
:param existing_metadata: already available metadata for this external module (if any)
13071307
"""
13081308
res = {}
1309+
if isinstance(self.modules_tool, NoModulesTool):
1310+
self.log.debug('Ignoring request for external module data for %s as no modules tool is active', mod_name)
1311+
return res
13091312

13101313
if existing_metadata is None:
13111314
existing_metadata = {}

easybuild/framework/easyconfig/tools.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
from easybuild.tools.filetools import find_easyconfigs, is_patch_file, locate_files
6161
from easybuild.tools.filetools import read_file, resolve_path, which, write_file
6262
from easybuild.tools.github import GITHUB_EASYCONFIGS_REPO
63-
from easybuild.tools.github import det_pr_labels, download_repo, fetch_easyconfigs_from_pr, fetch_pr_data
63+
from easybuild.tools.github import det_pr_labels, det_pr_title, download_repo, fetch_easyconfigs_from_pr, fetch_pr_data
6464
from easybuild.tools.github import fetch_files_from_pr
6565
from easybuild.tools.multidiff import multidiff
6666
from easybuild.tools.py2vs3 import OrderedDict
@@ -561,6 +561,11 @@ def review_pr(paths=None, pr=None, colored=True, branch='develop', testing=False
561561
lines.extend(['', "This PR is associated with a generic '.x' milestone, "
562562
"it should be associated to the next release milestone once merged"])
563563

564+
default_new_title = det_pr_title([ec['ec'] for ec in ecs])
565+
if default_new_title != pr_data['title']:
566+
lines.extend(['', "If this PR contains only new easyconfigs and has not been edited from the default, "
567+
"then the title should be: %s" % default_new_title])
568+
564569
return '\n'.join(lines)
565570

566571

easybuild/main.py

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
from easybuild.tools.github import add_pr_labels, install_github_token, list_prs, merge_pr, new_branch_github, new_pr
7070
from easybuild.tools.github import new_pr_from_branch
7171
from easybuild.tools.github import sync_branch_with_develop, sync_pr_with_develop, update_branch, update_pr
72-
from easybuild.tools.hooks import START, END, load_hooks, run_hook
72+
from easybuild.tools.hooks import BUILD_AND_INSTALL_LOOP, PRE_PREF, POST_PREF, START, END, CANCEL, FAIL
73+
from easybuild.tools.hooks import load_hooks, run_hook
7374
from easybuild.tools.modules import modules_tool
7475
from easybuild.tools.options import opts_dict_to_eb_opts, set_up_configuration, use_color
7576
from easybuild.tools.output import COLOR_GREEN, COLOR_RED, STATUS_BAR, colorize, print_checks, rich_live_cm
@@ -545,8 +546,10 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session
545546
exit_on_failure = not (options.dump_test_report or options.upload_test_report)
546547

547548
with rich_live_cm():
549+
run_hook(PRE_PREF + BUILD_AND_INSTALL_LOOP, hooks, args=[ordered_ecs])
548550
ecs_with_res = build_and_install_software(ordered_ecs, init_session_state,
549551
exit_on_failure=exit_on_failure)
552+
run_hook(POST_PREF + BUILD_AND_INSTALL_LOOP, hooks, args=[ecs_with_res])
550553
else:
551554
ecs_with_res = [(ec, {}) for ec in ordered_ecs]
552555

@@ -577,30 +580,20 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session
577580
return overall_success
578581

579582

580-
def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
583+
def main(args=None, logfile=None, do_build=None, testing=False, modtool=None, prepared_cfg_data=None):
581584
"""
582585
Main function: parse command line options, and act accordingly.
583586
:param args: command line arguments to use
584587
:param logfile: log file to use
585588
:param do_build: whether or not to actually perform the build
586589
:param testing: enable testing mode
590+
:param prepared_cfg_data: prepared configuration data for main function, as returned by prepare_main (or None)
587591
"""
592+
if prepared_cfg_data is None or any([args, logfile, testing]):
593+
init_session_state, eb_go, cfg_settings = prepare_main(args=args, logfile=logfile, testing=testing)
594+
else:
595+
init_session_state, eb_go, cfg_settings = prepared_cfg_data
588596

589-
register_lock_cleanup_signal_handlers()
590-
591-
# if $CDPATH is set, unset it, it'll only cause trouble...
592-
# see https://github.com/easybuilders/easybuild-framework/issues/2944
593-
if 'CDPATH' in os.environ:
594-
del os.environ['CDPATH']
595-
596-
# When EB is run via `exec` the special bash variable $_ is not set
597-
# So emulate this here to allow (module) scripts depending on that to work
598-
if '_' not in os.environ:
599-
os.environ['_'] = sys.executable
600-
601-
# purposely session state very early, to avoid modules loaded by EasyBuild meddling in
602-
init_session_state = session_state()
603-
eb_go, cfg_settings = set_up_configuration(args=args, logfile=logfile, testing=testing)
604597
options, orig_paths = eb_go.options, eb_go.args
605598

606599
if 'python2' not in build_option('silence_deprecation_warnings'):
@@ -729,10 +722,41 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
729722
cleanup(logfile, eb_tmpdir, testing, silent=False)
730723

731724

725+
def prepare_main(args=None, logfile=None, testing=None):
726+
"""
727+
Prepare for calling main function by setting up the EasyBuild configuration
728+
:param args: command line arguments to take into account when parsing the EasyBuild configuration settings
729+
:param logfile: log file to use
730+
:param testing: enable testing mode
731+
:return: 3-tuple with initial session state data, EasyBuildOptions instance, and tuple with configuration settings
732+
"""
733+
register_lock_cleanup_signal_handlers()
734+
735+
# if $CDPATH is set, unset it, it'll only cause trouble...
736+
# see https://github.com/easybuilders/easybuild-framework/issues/2944
737+
if 'CDPATH' in os.environ:
738+
del os.environ['CDPATH']
739+
740+
# When EB is run via `exec` the special bash variable $_ is not set
741+
# So emulate this here to allow (module) scripts depending on that to work
742+
if '_' not in os.environ:
743+
os.environ['_'] = sys.executable
744+
745+
# purposely session state very early, to avoid modules loaded by EasyBuild meddling in
746+
init_session_state = session_state()
747+
eb_go, cfg_settings = set_up_configuration(args=args, logfile=logfile, testing=testing)
748+
749+
return init_session_state, eb_go, cfg_settings
750+
751+
732752
if __name__ == "__main__":
753+
init_session_state, eb_go, cfg_settings = prepare_main()
754+
hooks = load_hooks(eb_go.options.hooks)
733755
try:
734-
main()
756+
main(prepared_cfg_data=(init_session_state, eb_go, cfg_settings))
735757
except EasyBuildError as err:
758+
run_hook(FAIL, hooks, args=[err])
736759
print_error(err.msg)
737760
except KeyboardInterrupt as err:
761+
run_hook(CANCEL, hooks, args=[err])
738762
print_error("Cancelled by user: %s" % err)

easybuild/toolchains/ifbf.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
##
2+
# Copyright 2012-2023 Ghent University
3+
#
4+
# This file is part of EasyBuild,
5+
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
6+
# with support of Ghent University (http://ugent.be/hpc),
7+
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
8+
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
9+
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
10+
#
11+
# https://github.com/easybuilders/easybuild
12+
#
13+
# EasyBuild is free software: you can redistribute it and/or modify
14+
# it under the terms of the GNU General Public License as published by
15+
# the Free Software Foundation v2.
16+
#
17+
# EasyBuild is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
24+
##
25+
"""
26+
EasyBuild support for ifbf toolchain (includes Intel compilers, FlexiBLAS, and FFTW).
27+
28+
Authors:
29+
30+
* Sebastian Achilles (Juelich Supercomputing Centre)
31+
"""
32+
33+
from easybuild.toolchains.intel_compilers import IntelCompilersToolchain
34+
from easybuild.toolchains.fft.fftw import Fftw
35+
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS
36+
37+
38+
class Ifbf(IntelCompilersToolchain, FlexiBLAS, Fftw):
39+
"""
40+
Compiler toolchain with Intel compilers, FlexiBLAS, and FFTW
41+
"""
42+
NAME = 'ifbf'
43+
SUBTOOLCHAIN = IntelCompilersToolchain.NAME
44+
OPTIONAL = True

0 commit comments

Comments
 (0)