-
Notifications
You must be signed in to change notification settings - Fork 704
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'easybuilders:develop' into easybuild-easyconfigs-Archiv…
…e-Zip
- Loading branch information
Showing
419 changed files
with
21,331 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
# NOTE: In order to write comment and edit labels, this script requires workflows with write permissions. | ||
# It should not use any untrusted third party code, or any code checked into the repository itself | ||
# as that could indirectly grant PRs the ability to edit labels and comments on PRs. | ||
|
||
import os | ||
import git | ||
import requests | ||
import json | ||
from pathlib import Path | ||
|
||
|
||
def get_first_commit_date(repo, file_path): | ||
commits = list(repo.iter_commits(paths=file_path)) | ||
if commits: | ||
return commits[-1].committed_date | ||
else: | ||
raise ValueError(f'{file_path} has no commit info, this should not happen') | ||
|
||
|
||
def sort_by_added_date(repo, file_paths): | ||
files_with_dates = [(get_first_commit_date(repo, file_path), file_path) for file_path in file_paths] | ||
sorted_files = sorted(files_with_dates, reverse=True) | ||
return [file for date, file in sorted_files] | ||
|
||
|
||
def similar_easyconfigs(repo, new_file): | ||
possible_neighbours = [x for x in new_file.parent.glob('*.eb') if x != new_file] | ||
return sort_by_added_date(repo, possible_neighbours) | ||
|
||
|
||
def pr_ecs(pr_diff): | ||
new_ecs = [] | ||
changed_ecs = [] | ||
for item in pr_diff: | ||
if item.a_path.endswith('.eb'): | ||
if item.change_type == 'A': | ||
new_ecs.append(Path(item.a_path)) | ||
else: | ||
changed_ecs.append(Path(item.a_path)) | ||
return new_ecs, changed_ecs | ||
|
||
|
||
GITHUB_API_URL = 'https://api.github.com' | ||
event_path = os.getenv('GITHUB_EVENT_PATH') | ||
token = os.getenv('GH_TOKEN') | ||
repo = os.getenv('GITHUB_REPOSITORY') | ||
base_branch_name = os.getenv('GITHUB_BASE_REF') | ||
|
||
with open(event_path) as f: | ||
data = json.load(f) | ||
|
||
pr_number = data['pull_request']['number'] | ||
# Can't rely on merge_commit_sha for pull_request_target as it might be outdated | ||
# merge_commit_sha = data['pull_request']['merge_commit_sha'] | ||
|
||
print("PR number:", pr_number) | ||
print("Base branch name:", base_branch_name) | ||
|
||
# Change into "pr" checkout directory to allow diffs and glob to work on the same content | ||
os.chdir('pr') | ||
gitrepo = git.Repo('.') | ||
|
||
target_commit = gitrepo.commit('origin/' + base_branch_name) | ||
print("Target commit ref:", target_commit) | ||
merge_commit = gitrepo.head.commit | ||
print("Merge commit:", merge_commit) | ||
pr_diff = target_commit.diff(merge_commit) | ||
|
||
new_ecs, changed_ecs = pr_ecs(pr_diff) | ||
modified_workflow = any(item.a_path.startswith('.github/workflows/') for item in pr_diff) | ||
|
||
|
||
print("Changed ECs:", ', '.join(str(p) for p in changed_ecs)) | ||
print("Newly added ECs:", ', '.join(str(p) for p in new_ecs)) | ||
print("Modified workflow:", modified_workflow) | ||
|
||
new_software = 0 | ||
updated_software = 0 | ||
to_diff = dict() | ||
for new_file in new_ecs: | ||
neighbours = similar_easyconfigs(gitrepo, new_file) | ||
print(f"Found {len(neighbours)} neighbours for {new_file}") | ||
if neighbours: | ||
updated_software += 1 | ||
to_diff[new_file] = neighbours | ||
else: | ||
new_software += 1 | ||
|
||
print(f"Generating comment for {len(to_diff)} updates softwares") | ||
# Limit comment size for large PRs: | ||
if len(to_diff) > 20: # Too much, either bad PR or some broad change. Not diffing. | ||
max_diffs_per_software = 0 | ||
elif len(to_diff) > 10: | ||
max_diffs_per_software = 1 | ||
elif len(to_diff) > 5: | ||
max_diffs_per_software = 2 | ||
else: | ||
max_diffs_per_software = 3 | ||
|
||
comment = '' | ||
if max_diffs_per_software > 0: | ||
for new_file, neighbours in to_diff.items(): | ||
compare_neighbours = neighbours[:max_diffs_per_software] | ||
if compare_neighbours: | ||
print(f"Diffs for {new_file}") | ||
comment += f'#### Updated software `{new_file.name}`\n\n' | ||
|
||
for neighbour in compare_neighbours: | ||
print(f"against {neighbour}") | ||
comment += '<details>\n' | ||
comment += f'<summary>Diff against <code>{neighbour.name}</code></summary>\n\n' | ||
comment += f'[{neighbour}](https://github.com/{repo}/blob/{base_branch_name}/{neighbour})\n\n' | ||
comment += '```diff\n' | ||
comment += gitrepo.git.diff(f'HEAD:{neighbour}', f'HEAD:{new_file}') | ||
comment += '\n```\n</details>\n\n' | ||
|
||
print("Adjusting labels") | ||
current_labels = [label['name'] for label in data['pull_request']['labels']] | ||
|
||
label_checks = [(changed_ecs, 'change'), | ||
(new_software, 'new'), | ||
(updated_software, 'update'), | ||
(modified_workflow, 'workflow')] | ||
|
||
labels_add = [] | ||
labels_del = [] | ||
for condition, label in label_checks: | ||
if condition and label not in current_labels: | ||
labels_add.append(label) | ||
elif not condition and label in current_labels: | ||
labels_del.append(label) | ||
|
||
url = f"{GITHUB_API_URL}/repos/{repo}/issues/{pr_number}/labels" | ||
|
||
headers = { | ||
"Accept": "application/vnd.github+json", | ||
"Authorization": f"Bearer {token}", | ||
"X-GitHub-Api-Version": "2022-11-28", | ||
} | ||
|
||
if labels_add: | ||
print(f"Setting labels: {labels_add} at {url}") | ||
response = requests.post(url, headers=headers, json={"labels": labels_add}) | ||
if response.status_code == 200: | ||
print(f"Labels {labels_add} added successfully.") | ||
else: | ||
print(f"Failed to add labels: {response.status_code}, {response.text}") | ||
|
||
for label in labels_del: | ||
print(f"Removing label: {label} at {url}") | ||
response = requests.delete(f'{url}/{label}', headers=headers) | ||
if response.status_code == 200: | ||
print(f"Label {label} removed successfully.") | ||
else: | ||
print(f"Failed to delete label: {response.status_code}, {response.text}") | ||
|
||
# Write comment with diff | ||
if updated_software: | ||
# Search for comment by bot to potentially replace | ||
url = f"{GITHUB_API_URL}/repos/{repo}/issues/{pr_number}/comments" | ||
response = requests.get(url, headers=headers) | ||
comment_id = None | ||
for existing_comment in response.json(): | ||
if existing_comment["user"]["login"] == "github-actions[bot]": # Bot username in GitHub Actions | ||
comment_id = existing_comment["id"] | ||
|
||
if comment_id: | ||
# Update existing comment | ||
url = f"{GITHUB_API_URL}/repos/{repo}/issues/comments/{comment_id}" | ||
response = requests.patch(url, headers=headers, json={"body": comment}) | ||
if response.status_code == 200: | ||
print("Comment updated successfully.") | ||
else: | ||
print(f"Failed to update comment: {response.status_code}, {response.text}") | ||
else: | ||
# Post a new comment | ||
url = f"{GITHUB_API_URL}/repos/{repo}/issues/{pr_number}/comments" | ||
response = requests.post(url, headers=headers, json={"body": comment}) | ||
if response.status_code == 201: | ||
print("Comment posted successfully.") | ||
else: | ||
print(f"Failed to post comment: {response.status_code}, {response.text}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
name: Tagbot | ||
on: [pull_request_target] | ||
|
||
concurrency: | ||
group: "${{ github.workflow }}-${{ github.event.pull_request.number }}" | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
tagbot: | ||
# Note: can't rely on github.event.pull_request.merge_commit_sha because pull_request_target | ||
# does not wait for github mergability check, and the value is outdated. | ||
# Instead we merge manually in a temporary subdir "pr" | ||
runs-on: ubuntu-24.04 | ||
permissions: | ||
pull-requests: write | ||
steps: | ||
- name: Checkout base branch for workflow scripts | ||
uses: actions/checkout@v4 | ||
|
||
- name: Checkout PR for computing diff into "pr" subdirectory | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: "${{ github.event.pull_request.head.sha }}" | ||
path: 'pr' | ||
fetch-depth: 0 | ||
|
||
- name: Attempt test merge | ||
id: merge | ||
run: | | ||
git config user.name "github-workflow" | ||
git config user.email "[email protected]" | ||
git merge --no-edit --no-ff origin/${{ github.event.pull_request.base.ref }} | ||
continue-on-error: true | ||
working-directory: pr | ||
|
||
- name: Abort if merge failed | ||
if: steps.merge.outcome == 'failure' | ||
run: | | ||
echo "Merge conflict detected, failing job." | ||
exit 1 | ||
- name: set up Python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3.12 | ||
|
||
- name: Get packages | ||
run: pip install gitpython requests | ||
|
||
- name: Tag and comment | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: python .github/workflows/tagbot.py | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name = 'AOCC' | ||
version = '4.2.0' | ||
|
||
homepage = 'https://developer.amd.com/amd-aocc/' | ||
description = """AOCC is a high-performance x86 CPU compiler for C, C++, and Fortran programming languages. | ||
It supports target-dependent and target-independent optimizations. It is highly optimized for x86 targets, | ||
especially for AMD “Zen”-based processors giving a performance edge for time critical HPC and other | ||
applications over other compilers.""" | ||
|
||
# Clang also depends on libstdc++ during runtime, but this dependency is | ||
# already specified as the toolchain. | ||
toolchain = {'name': 'GCCcore', 'version': '13.3.0'} | ||
|
||
source_urls = [ | ||
'https://download.amd.com/developer/eula/%(namelower)s/%(namelower)s-%(version_major)s-%(version_minor)s' | ||
] | ||
sources = ['%(namelower)s-compiler-%(version)s.tar'] | ||
checksums = ['ed5a560ec745b24dc0685ccdcbde914843fb2f2dfbfce1ba592de4ffbce1ccab'] | ||
|
||
dependencies = [ | ||
('binutils', '2.42'), | ||
('ncurses', '6.5'), | ||
('zlib', '1.3.1'), | ||
('libxml2', '2.12.7'), | ||
] | ||
|
||
clangversion = '16.0.3' | ||
|
||
moduleclass = 'compiler' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name = 'AOCC' | ||
version = '5.0.0' | ||
|
||
homepage = 'https://developer.amd.com/amd-aocc/' | ||
description = "AMD Optimized C/C++ & Fortran compilers (AOCC) based on LLVM 13.0" | ||
|
||
# Clang also depends on libstdc++ during runtime, but this dependency is | ||
# already specified as the toolchain. | ||
toolchain = {'name': 'GCCcore', 'version': '14.2.0'} | ||
|
||
source_urls = ['https://download.amd.com/developer/eula/aocc/aocc-5-0/'] | ||
sources = ['aocc-compiler-%(version)s.tar'] | ||
checksums = ['966fac2d2c759e9de6e969c10ada7a7b306c113f7f1e07ea376829ec86380daa'] | ||
|
||
clangversion = '17.0.6' | ||
|
||
dependencies = [ | ||
('binutils', '2.42'), | ||
('ncurses', '6.5'), | ||
('zlib', '1.3.1'), | ||
('libxml2', '2.13.4'), | ||
] | ||
|
||
moduleclass = 'compiler' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
easyblock = 'PythonBundle' | ||
|
||
name = 'ASE' | ||
version = '3.23.0' | ||
|
||
homepage = 'https://wiki.fysik.dtu.dk/ase' | ||
description = """ASE is a python package providing an open source Atomic Simulation Environment | ||
in the Python scripting language. | ||
From version 3.20.1 we also include the ase-ext package, it contains optional reimplementations | ||
in C of functions in ASE. ASE uses it automatically when installed.""" | ||
|
||
toolchain = {'name': 'gfbf', 'version': '2023b'} | ||
|
||
dependencies = [ | ||
('Python', '3.11.5'), | ||
('Python-bundle-PyPI', '2023.10'), | ||
('SciPy-bundle', '2023.11'), | ||
('Flask', '3.0.0'), | ||
('matplotlib', '3.8.2'), | ||
('Tkinter', '%(pyver)s'), # Needed by GUI of ASE | ||
('spglib-python', '2.5.0'), # optional | ||
] | ||
|
||
use_pip = True | ||
sanity_pip_check = True | ||
|
||
exts_list = [ | ||
('pytest-mock', '3.14.0', { | ||
'checksums': ['2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0'], | ||
}), | ||
('ase', version, { | ||
'checksums': ['91a2aa31d89bd90b0efdfe4a7e84264f32828b2abfc9f38e65e041ad76fec8ae'], | ||
}), | ||
('ase-ext', '20.9.0', { | ||
'checksums': ['a348b0e42cf9fdd11f04b3df002b0bf150002c8df2698ff08d3c8fc7a1223aed'], | ||
}), | ||
] | ||
|
||
sanity_check_paths = { | ||
'files': ['bin/ase'], | ||
'dirs': ['lib/python%(pyshortver)s/site-packages'], | ||
} | ||
|
||
# make sure Tkinter is available, otherwise 'ase gui' will not work | ||
sanity_check_commands = ["python -c 'import tkinter' "] | ||
|
||
moduleclass = 'chem' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
easyblock = 'PythonBundle' | ||
|
||
name = 'ASE' | ||
version = '3.23.0' | ||
|
||
homepage = 'https://wiki.fysik.dtu.dk/ase' | ||
description = """ASE is a python package providing an open source Atomic Simulation Environment | ||
in the Python scripting language. | ||
From version 3.20.1 we also include the ase-ext package, it contains optional reimplementations | ||
in C of functions in ASE. ASE uses it automatically when installed.""" | ||
|
||
toolchain = {'name': 'gfbf', 'version': '2024a'} | ||
|
||
dependencies = [ | ||
('Python', '3.12.3'), | ||
('Python-bundle-PyPI', '2024.06'), | ||
('SciPy-bundle', '2024.05'), | ||
('Flask', '3.0.3'), | ||
('matplotlib', '3.9.2'), | ||
('Tkinter', '%(pyver)s'), # Needed by GUI of ASE | ||
('spglib-python', '2.5.0'), # optional | ||
] | ||
|
||
use_pip = True | ||
sanity_pip_check = True | ||
|
||
exts_list = [ | ||
('pytest-mock', '3.14.0', { | ||
'checksums': ['2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0'], | ||
}), | ||
('ase', version, { | ||
'checksums': ['91a2aa31d89bd90b0efdfe4a7e84264f32828b2abfc9f38e65e041ad76fec8ae'], | ||
}), | ||
('ase-ext', '20.9.0', { | ||
'checksums': ['a348b0e42cf9fdd11f04b3df002b0bf150002c8df2698ff08d3c8fc7a1223aed'], | ||
}), | ||
] | ||
|
||
sanity_check_paths = { | ||
'files': ['bin/ase'], | ||
'dirs': ['lib/python%(pyshortver)s/site-packages'], | ||
} | ||
|
||
# make sure Tkinter is available, otherwise 'ase gui' will not work | ||
sanity_check_commands = ["python -c 'import tkinter' "] | ||
|
||
moduleclass = 'chem' |
Oops, something went wrong.