22# It should not use any untrusted third party code, or any code checked into the repository itself
33# as that could indirectly grant PRs the ability to edit labels and comments on PRs.
44
5+ import json
56import os
7+ from pathlib import Path
8+
69import git
710import requests
8- import json
9- from pathlib import Path
1011
1112
1213def get_first_commit_date (repo , file_path ):
@@ -23,8 +24,8 @@ def sort_by_added_date(repo, file_paths):
2324 return [file for date , file in sorted_files ]
2425
2526
26- def similar_easyconfigs (repo , new_file ):
27- possible_neighbours = [x for x in new_file .parent .glob ('*.eb' ) if x != new_file ]
27+ def similar_easyconfigs (repo , new_file , new_ecs ):
28+ possible_neighbours = [x for x in new_file .parent .glob ('*.eb' ) if x not in new_ecs ]
2829 return sort_by_added_date (repo , possible_neighbours )
2930
3031
@@ -74,11 +75,16 @@ def pr_ecs(pr_diff):
7475print ("Newly added ECs:" , ', ' .join (str (p ) for p in new_ecs ))
7576print ("Modified workflow:" , modified_workflow )
7677
78+
79+ # Check for new and updated software.
80+ # First, try to determine if the software exists. If so,
81+ # we'll generate a comment diffing against existing EasyConfigs
82+ # to make review easier.
7783new_software = 0
7884updated_software = 0
79- to_diff = dict ()
85+ to_diff = {}
8086for new_file in new_ecs :
81- neighbours = similar_easyconfigs (gitrepo , new_file )
87+ neighbours = similar_easyconfigs (gitrepo , new_file , new_ecs )
8288 print (f"Found { len (neighbours )} neighbours for { new_file } " )
8389 if neighbours :
8490 updated_software += 1
@@ -114,13 +120,88 @@ def pr_ecs(pr_diff):
114120 comment += gitrepo .git .diff (f'HEAD:{ neighbour } ' , f'HEAD:{ new_file } ' )
115121 comment += '\n ```\n </details>\n \n '
116122
123+ # After that, try to add additional labels based on the PR contents.
124+ # Add manual_label if download_instructions is present. This reads the file.
125+ manual_download = False
126+ for file in new_ecs + changed_ecs :
127+ if file .is_file ():
128+ with file .open () as f :
129+ content = f .read ()
130+ if 'download_instructions' in content :
131+ manual_download = True
132+ break
133+
134+ # Add toolchain labels based on matching new added / changed filenames againt our toolchain policy
135+ # This doesn't include LLVM or NVHPC yet, and needs to be adapted together with the test suite
136+ # when adding new toolchains and their respective labels.
137+ # We are only checking the file names here and will not read the actual file.
138+ gcc_tc_gen_map = {
139+ '10.2' : '2020b' ,
140+ '10.3' : '2021a' ,
141+ '11.2' : '2021b' ,
142+ '11.3' : '2022a' ,
143+ '12.2' : '2022b' ,
144+ '12.3' : '2023a' ,
145+ '13.2' : '2023b' ,
146+ '13.3' : '2024a' ,
147+ '14.2' : '2025a' ,
148+ '14.3' : '2025b' ,
149+ }
150+
151+ ic_tc_gen_map = {
152+ '2021.2.0' : '2021a' ,
153+ '2021.4.0' : '2021b' ,
154+ '2022.1.0' : '2022a' ,
155+ '2023.1.0' : '2023a' ,
156+ '2023.2.1' : '2023b' ,
157+ '2024.2.0' : '2024a' ,
158+ '2025.1.1' : '2025a' ,
159+ '2025.2.0' : '2025b' ,
160+ }
161+
162+ llvm_tc_gen_map = {
163+ '20.1.5' : '2023b' ,
164+ '20.1.8' : '2025b' ,
165+ }
166+
167+ toolchain_names = ['foss' , 'gompi' , 'gfbf' , 'iimpi' , 'iimkl' , 'intel' , 'llvm-compilers' , 'lfbf' ,
168+ 'lompi' , 'lmpich' , 'lfoss' , 'lmpflf' ]
169+ toolchain_present = {}
170+ for toolchain_ver in gcc_tc_gen_map .values ():
171+ toolchain_present [toolchain_ver ] = False
172+
173+ for file in new_ecs + changed_ecs :
174+ file_path = str (file )
175+ # Check for GCCcore / GCC
176+ for gcc_version , toolchain_version in gcc_tc_gen_map .items ():
177+ if f"-GCCcore-{ gcc_version } " in file_path or f"-GCC-{ gcc_version } " in file_path :
178+ toolchain_present [toolchain_version ] = True
179+ continue
180+ # Check for intel-compilers
181+ for intel_version , toolchain_version in ic_tc_gen_map .items ():
182+ if f"-intel-compilers-{ intel_version } " in file_path :
183+ toolchain_present [toolchain_version ] = True
184+ continue
185+ for llvm_version , toolchain_version in llvm_tc_gen_map .items ():
186+ if f"-llvm-compilers-{ llvm_version } " in file_path :
187+ toolchain_present [toolchain_version ] = True
188+ continue
189+ # Check for common toolchains with our toolchain naming
190+ for toolchain_version in gcc_tc_gen_map .values ():
191+ if any (f"-{ toolchain_name } -{ toolchain_version } " in file_path for toolchain_name in toolchain_names ):
192+ toolchain_present [toolchain_version ] = True
193+ continue
194+
117195print ("Adjusting labels" )
118196current_labels = [label ['name' ] for label in data ['pull_request' ]['labels' ]]
119197
120198label_checks = [(changed_ecs , 'change' ),
121199 (new_software , 'new' ),
122200 (updated_software , 'update' ),
123- (modified_workflow , 'workflow' )]
201+ (modified_workflow , 'workflow' ),
202+ (manual_download , 'manual_download' )]
203+ # This covers all the toolchain labels we may be able to add
204+ label_checks += [(val , key ) for key , val in toolchain_present .items ()]
124205
125206labels_add = []
126207labels_del = []
@@ -164,6 +245,11 @@ def pr_ecs(pr_diff):
164245 if existing_comment ["user" ]["login" ] == "github-actions[bot]" : # Bot username in GitHub Actions
165246 comment_id = existing_comment ["id" ]
166247
248+ if len (comment ) >= 65536 :
249+ # Comment is too long to post, so post a message saying that
250+ comment = "Diff of new easyconfig(s) against existing ones is too long for a GitHub comment. "
251+ comment += "Use `--review-pr` (and `--review-pr-filter` / `--review-pr-max`) locally."
252+
167253 if comment_id :
168254 # Update existing comment
169255 url = f"{ GITHUB_API_URL } /repos/{ repo } /issues/comments/{ comment_id } "
0 commit comments