Skip to content

Commit ab75116

Browse files
committed
Merge branch 'develop' into tests_python2
2 parents 6428354 + 0546463 commit ab75116

File tree

17 files changed

+380
-59
lines changed

17 files changed

+380
-59
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: 24 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

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

easybuild/toolchains/iofbf.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 iofbf toolchain (includes Intel compilers, OpenMPI,
27+
FlexiBLAS, LAPACK, ScaLAPACK and FFTW).
28+
29+
Authors:
30+
31+
* Sebastian Achilles (Juelich Supercomputing Centre)
32+
"""
33+
34+
from easybuild.toolchains.iompi import Iompi
35+
from easybuild.toolchains.ifbf import Ifbf
36+
from easybuild.toolchains.fft.fftw import Fftw
37+
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS
38+
from easybuild.toolchains.linalg.scalapack import ScaLAPACK
39+
40+
41+
class Iofbf(Iompi, FlexiBLAS, ScaLAPACK, Fftw):
42+
"""
43+
Compiler toolchain with Intel compilers (icc/ifort), OpenMPI,
44+
FlexiBLAS, LAPACK, ScaLAPACK and FFTW.
45+
"""
46+
NAME = 'iofbf'
47+
SUBTOOLCHAIN = [Iompi.NAME, Ifbf.NAME]

easybuild/tools/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX):
301301
'sequential',
302302
'set_default_module',
303303
'set_gid_bit',
304+
'silence_hook_trigger',
304305
'skip_extensions',
305306
'skip_test_cases',
306307
'skip_test_step',

easybuild/tools/filetools.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,14 +1264,11 @@ def verify_checksum(path, checksums):
12641264

12651265
for checksum in checksums:
12661266
if isinstance(checksum, dict):
1267-
if filename in checksum:
1267+
try:
12681268
# Set this to a string-type checksum
12691269
checksum = checksum[filename]
1270-
elif build_option('enforce_checksums'):
1271-
raise EasyBuildError("Missing checksum for %s", filename)
1272-
else:
1273-
# Set to None and allow to fail elsewhere
1274-
checksum = None
1270+
except KeyError:
1271+
raise EasyBuildError("Missing checksum for %s in %s", filename, checksum)
12751272

12761273
if isinstance(checksum, string_type):
12771274
# if no checksum type is specified, it is assumed to be MD5 (32 characters) or SHA256 (64 characters)
@@ -1301,7 +1298,8 @@ def verify_checksum(path, checksums):
13011298
# no matching checksums
13021299
return False
13031300
else:
1304-
raise EasyBuildError("Invalid checksum spec '%s', should be a string (MD5) or 2-tuple (type, value).",
1301+
raise EasyBuildError("Invalid checksum spec '%s': should be a string (MD5 or SHA256), "
1302+
"2-tuple (type, value), or tuple of alternative checksum specs.",
13051303
checksum)
13061304

13071305
actual_checksum = compute_checksum(path, typ)
@@ -2619,6 +2617,8 @@ def get_source_tarball_from_git(filename, targetdir, git_config):
26192617
recursive = git_config.pop('recursive', False)
26202618
clone_into = git_config.pop('clone_into', False)
26212619
keep_git_dir = git_config.pop('keep_git_dir', False)
2620+
extra_config_params = git_config.pop('extra_config_params', None)
2621+
recurse_submodules = git_config.pop('recurse_submodules', None)
26222622

26232623
# input validation of git_config dict
26242624
if git_config:
@@ -2644,7 +2644,11 @@ def get_source_tarball_from_git(filename, targetdir, git_config):
26442644
targetpath = os.path.join(targetdir, filename)
26452645

26462646
# compose 'git clone' command, and run it
2647-
clone_cmd = ['git', 'clone']
2647+
if extra_config_params:
2648+
git_cmd = 'git ' + ' '.join(['-c %s' % param for param in extra_config_params])
2649+
else:
2650+
git_cmd = 'git'
2651+
clone_cmd = [git_cmd, 'clone']
26482652

26492653
if not keep_git_dir and not commit:
26502654
# Speed up cloning by only fetching the most recent commit, not the whole history
@@ -2655,6 +2659,8 @@ def get_source_tarball_from_git(filename, targetdir, git_config):
26552659
clone_cmd.extend(['--branch', tag])
26562660
if recursive:
26572661
clone_cmd.append('--recursive')
2662+
if recurse_submodules:
2663+
clone_cmd.extend(["--recurse-submodules='%s'" % pat for pat in recurse_submodules])
26582664
else:
26592665
# checkout is done separately below for specific commits
26602666
clone_cmd.append('--no-checkout')
@@ -2674,16 +2680,21 @@ def get_source_tarball_from_git(filename, targetdir, git_config):
26742680

26752681
# if a specific commit is asked for, check it out
26762682
if commit:
2677-
checkout_cmd = ['git', 'checkout', commit]
2678-
if recursive:
2679-
checkout_cmd.extend(['&&', 'git', 'submodule', 'update', '--init', '--recursive'])
2683+
checkout_cmd = [git_cmd, 'checkout', commit]
2684+
2685+
if recursive or recurse_submodules:
2686+
checkout_cmd.extend(['&&', git_cmd, 'submodule', 'update', '--init'])
2687+
if recursive:
2688+
checkout_cmd.append('--recursive')
2689+
if recurse_submodules:
2690+
checkout_cmd.extend(["--recurse-submodules='%s'" % pat for pat in recurse_submodules])
26802691

26812692
run.run_cmd(' '.join(checkout_cmd), log_all=True, simple=True, regexp=False, path=repo_name)
26822693

26832694
elif not build_option('extended_dry_run'):
26842695
# If we wanted to get a tag make sure we actually got a tag and not a branch with the same name
26852696
# This doesn't make sense in dry-run mode as we don't have anything to check
2686-
cmd = 'git describe --exact-match --tags HEAD'
2697+
cmd = '%s describe --exact-match --tags HEAD' % git_cmd
26872698
# Note: Disable logging to also disable the error handling in run_cmd
26882699
(out, ec) = run.run_cmd(cmd, log_ok=False, log_all=False, regexp=False, path=repo_name)
26892700
if ec != 0 or tag not in out.splitlines():
@@ -2696,13 +2707,16 @@ def get_source_tarball_from_git(filename, targetdir, git_config):
26962707
# make the repo unshallow first;
26972708
# this is equivalent with 'git fetch -unshallow' in Git 1.8.3+
26982709
# (first fetch seems to do nothing, unclear why)
2699-
cmds.append('git fetch --depth=2147483647 && git fetch --depth=2147483647')
2710+
cmds.append('%s fetch --depth=2147483647 && git fetch --depth=2147483647' % git_cmd)
27002711

2701-
cmds.append('git checkout refs/tags/' + tag)
2712+
cmds.append('%s checkout refs/tags/' % git_cmd + tag)
27022713
# Clean all untracked files, e.g. from left-over submodules
2703-
cmds.append('git clean --force -d -x')
2714+
cmds.append('%s clean --force -d -x' % git_cmd)
27042715
if recursive:
2705-
cmds.append('git submodule update --init --recursive')
2716+
cmds.append('%s submodule update --init --recursive' % git_cmd)
2717+
elif recurse_submodules:
2718+
cmds.append('%s submodule update --init ' % git_cmd)
2719+
cmds[-1] += ' '.join(["--recurse-submodules='%s'" % pat for pat in recurse_submodules])
27062720
for cmd in cmds:
27072721
run.run_cmd(cmd, log_all=True, simple=True, regexp=False, path=repo_name)
27082722

easybuild/tools/github.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,15 +2250,18 @@ def install_github_token(github_user, silent=False):
22502250
def validate_github_token(token, github_user):
22512251
"""
22522252
Check GitHub token:
2253-
* see if it conforms expectations (only [a-f]+[0-9] characters, length of 40)
2254-
* see if it can be used for authenticated access
2253+
* see if it conforms expectations (classic GitHub token with only [0-9a-f] characters
2254+
and length of 40 starting with 'ghp_', or fine-grained GitHub token with only
2255+
alphanumeric ([a-zA-Z0-9]) characters + '_' and length of 93 starting with 'github_pat_'),
2256+
* see if it can be used for authenticated access.
22552257
"""
22562258
# cfr. https://github.blog/2021-04-05-behind-githubs-new-authentication-token-formats/
22572259
token_regex = re.compile('^ghp_[a-zA-Z0-9]{36}$')
22582260
token_regex_old_format = re.compile('^[0-9a-f]{40}$')
2261+
# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#githubs-token-formats
2262+
token_regex_fine_grained = re.compile('github_pat_[a-zA-Z0-9_]{82}')
22592263

2260-
# token should be 40 characters long, and only contain characters in [0-9a-f]
2261-
sanity_check = bool(token_regex.match(token))
2264+
sanity_check = bool(token_regex.match(token)) or bool(token_regex_fine_grained.match(token))
22622265
if sanity_check:
22632266
_log.info("Sanity check on token passed")
22642267
else:

0 commit comments

Comments
 (0)