63 """So now we have a URL to a failing test.
64 We need to check that the test is failing for the correct reason - namely a reference file which needs updating
65 The information we need to collect is:
66 - the AMI tag of the failing tests
67 - the merge request number
68 - the location of the reference file
69 - the location of the copied file
70 - the name of the test
71 - the new version number
72 - the new version directory
74 page = requests.get(url)
79 test_match = re.search(
r'All (?P<ami_tag>\w+) athena steps completed successfully', text)
80 ami_tag = test_match.group(
'ami_tag')
if test_match
else None
85 match_attempt_2 = re.search(
r'AMIConfig (?P<ami_tag>\w+)', text)
87 ami_tag = match_attempt_2.group(
'ami_tag')
90 print(
'WARNING: Did not find an AMI tag in the test "{}". Ignoring.'.format(test_name))
93 mr_match = re.search(
r'ARDOC_TestLog_MR-(?P<mr_number>\d+)-(?P<date>\d{4}-\d{2}-\d{2}-\d{2}-\d{2})', url)
95 print(
'FATAL: Could not process the URL as expected. Aborting.')
99 mr_number = mr_match.group(
'mr_number')
100 date = mr_match.group(
'date')
101 human_readable_date =
':'.join(date.split(
'-')[0:3]) +
" at " +
':'.join(date.split(
'-')[3:])
103 if "Your change breaks the digest in test" in text
or 'ERROR Your change modifies the output in test' in text:
105 failing_tests[branch].append(
process_digest_change(text, ami_tag, mr_number, human_readable_date, test_name))
107 if 'ERROR Your change breaks the frozen tier0 policy in test' in text
or 'ERROR Your change breaks the frozen derivation policy in test' in text:
109 failing_tests[branch].append(
process_diffpool_change(text, ami_tag, mr_number, human_readable_date, test_name))
114 eos_path_root =
'/eos/atlas/atlascerngroupdisk/data-art/grid-input/WorkflowReferences/'
118 copied_file_match = re.search(
r'^ERROR Copied.*', text, flags=re.MULTILINE)
119 if not copied_file_match:
120 print(
"FATAL: Could not find matching copied file")
122 copied_file_path = copied_file_match.group().
split(
'to')[1].
strip().
strip(
"'").
strip(
"'")+
'/'
125 ref_file_match = re.search(
r'INFO Reading the reference file from location.*', text)
126 if not ref_file_match:
127 print(
"FATAL: Could not find matching reference file")
130 ref_file_path = ref_file_match.group().
split(
'location')[1].
strip()
131 existing_version_number= ref_file_path.split(
'/')[-2]
132 branch = ref_file_path.split(
'/')[-4]
133 new_version_number =
'v'+str(int(existing_version_number[1:])+1)
134 new_version_directory = eos_path_root+branch+
'/'+ami_tag+
'/'+new_version_number
135 old_version_directory = eos_path_root+branch+
'/'+ami_tag+
'/'+existing_version_number
138 copied_file_match = re.search(
r'^ERROR Copied.*', text, flags=re.MULTILINE)
139 if not copied_file_match:
140 print(
"FATAL: Could not find matching copied file")
144 ami_tag_check = ref_file_path.split(
'/')[-3].
strip()
145 if ami_tag_check!=ami_tag:
146 print(
'FATAL: Sanity check: "{}" from reference file path "{}" does not match ami tag "{}" extracted previously.'.format(ami_tag_check, ref_file_path, ami_tag))
150 test =
CITest(name=test_name, tag=ami_tag, mr=mr_number, date=human_readable_date, existing_ref = old_version_directory, existing_version = existing_version_number, new_version = new_version_number, new_version_directory = new_version_directory, copied_file_path = copied_file_path, diff=
None, type=
'DiffPool')
155 existing_version_number =
None
156 new_version_directory =
None
157 copied_file_path =
None
158 new_version_number=
None
161 ref_file_match = re.search(
162 r"differs from the reference (?:'|')([^'&]+?)(?:'|')",
165 if not ref_file_match:
166 print(
"FATAL: Could not find matching reference file")
168 ref_file_path = ref_file_match.group(1)
176 for line
in text.split(
'\n'):
177 if 'differs from the reference' in line:
185 diff_lines.append(html.unescape(line))
187 test =
CITest(name=test_name, tag=ami_tag, mr=mr_number, date=human_readable_date, existing_ref = ref_file_path, existing_version = existing_version_number, new_version = new_version_number, new_version_directory = new_version_directory, copied_file_path = copied_file_path, diff=diff_lines, type=
'Content' if 'content.ref' in ref_file_path
else 'Digest')
192 print(
'Updating reference files')
193 print(
'========================')
195 for branch, tests
in failing_tests.items():
197 print(
'Processing test: {} on branch {}'.format(test.name, branch))
198 if test.type ==
'DiffPool':
199 print(
' * This is a DiffPool test, and currently has version {} of {}. Will update References.py with new version.'.format(test.existing_version, test.tag))
201 print(
' -> The new version is: {}. Creating directory and copying files on EOS now.'.format(test.new_version))
207 commands = list(dict.fromkeys(commands))
210 if update_local_files:
213 print (
'Updating local References.py file with new version {} for tag {}'.format(test.new_version, test.tag))
215 with open(
'Tools/WorkflowTestRunner/python/References.py',
'r')
as f:
216 lines = f.readlines()
219 if test.existing_version
in line:
220 line = line.replace(test.existing_version, test.new_version)
223 print(
'** WARNING: For tag {} we were looking for existing version {}, but the line in the file is: {}'.format(test.tag, test.existing_version, line), end=
'')
224 print(
'** Are you sure your branch is up-to-date with main? We cannot update an older version of References.py!')
229 print(
'** WARNING - no matching line was found for the AMI tag {} in References.py. Are you sure your branch is up-to-date with main? We cannot update an older version of References.py!'.format(test.tag))
231 with open(
'Tools/WorkflowTestRunner/python/References.py',
'w')
as f:
233 elif test.type ==
'Digest' and update_local_files:
234 print(
' * This is a Digest test. Need to update reference file {}.'.format(test.existing_ref))
238 digest_old = [line
for line
in test.diff
if line.startswith(
'<')]
239 digest_new = [line
for line
in test.diff
if line.startswith(
'>')]
241 with open(
'Tools/PROCTools/data/'+test.existing_ref,
'r')
as f:
242 lines = f.readlines()
243 for current_line, line
in enumerate(lines):
244 split_curr_line = line.split()
245 if (split_curr_line[0] ==
'run'):
250 if (
not split_curr_line[0].isnumeric())
or (
not split_curr_line[1].isnumeric()):
251 print(
'FATAL: Found a line in current digest which does not start with run/event numbers: {}'.format(line))
254 split_old_diff_line = digest_old[diff_line].
split()
255 split_old_diff_line.pop(0)
256 split_new_diff_line = digest_new[diff_line].
split()
257 split_new_diff_line.pop(0)
260 if split_curr_line[0] == split_old_diff_line[0]
and split_curr_line[1] == split_old_diff_line[1]:
262 if split_curr_line!=split_old_diff_line:
263 print(
'FATAL: It seems like this line was already changed.')
264 print(
'Line we expected: {}'.format(test.old_diff_lines[diff_line]))
265 print(
'Line we got : {}'.format(line))
269 if split_curr_line[0] == split_new_diff_line[0]
and split_curr_line[1] == split_new_diff_line[1]:
271 data.append(
"".join([
"{:>12}".format(x)
for x
in split_new_diff_line])+
'\n')
272 if ((diff_line+1)<len(digest_old)):
279 print(
' -> Updating PROCTools digest file {}'.format(test.existing_ref))
280 with open(
'Tools/PROCTools/data/'+test.existing_ref,
'w')
as f:
282 elif test.type ==
'Content' and update_local_files:
283 print(
' * This is a Content test. Need to update reference file {}.'.format(test.existing_ref))
284 subprocess.run(f
'patch --quiet Tools/PROCTools/data/{test.existing_ref}',
285 input=
'\n'.join(test.diff)+
'\n',
286 text=
True, shell=
True, check=
True)
293 If called with actually_update=False, this function will return a list of commands which would have been executed.
296 if test.new_version_directory
not in dirs_created:
297 commands.append(
"mkdir -p " + test.new_version_directory)
298 dirs_created.append(test.new_version_directory)
302 commands.append(
"cp " + test.copied_file_path +
"* "+ test.new_version_directory+
"/")
303 commands.append(
"cp -n " + test.existing_ref +
"/* "+ test.new_version_directory+
"/")
305 print(
' -> Copying files from {} to {}'.format(test.copied_file_path, test.new_version_directory))
307 for command
in commands:
309 subprocess.call( command, shell=
True)
310 except Exception
as e:
311 print(
'Command failed due to:', e)
312 print(
'Do you have EOS available on this machine?')
313 except Exception
as e:
314 print(
'FATAL: Unable to copy files due to:', e)
317 f = open(test.new_version_directory+
'/info.txt',
'w')
318 f.write(
'Merge URL: https://gitlab.cern.ch/atlas/athena/-/merge_requests/{}\n'.format(test.mr))
319 f.write(
'Date: {}\n'.format(test.date))
320 f.write(
'AMI: {}\n'.format(test.tag))
321 f.write(
'Test name: {}\n'.format(test.name))
322 f.write(
'Files copied from: {}\n'.format(test.copied_file_path))
368 print(
'Summary of tests which need work:')
370 if not failing_tests:
371 print(
" -> None found. Aborting.")
375 reference_folders = []
376 for branch,tests
in failing_tests.items():
377 print (
' * Branch: {}'.format(branch))
380 if test.type ==
'DiffPool':
381 if not test.new_version_directory:
382 print(
'FATAL: No path to "new version" for test {} of type DiffPool.'.format(test.name))
385 if os.path.exists(test.new_version_directory):
386 msg = f
'WARNING: The directory {test.new_version_directory} already exists. Are you sure you want to overwrite the existing references?'
387 if input(
"%s (y/N) " % msg).lower() !=
'y':
390 if (test.existing_ref
not in reference_folders):
391 reference_folders.append(test.existing_ref)
392 elif check_for_duplicates:
393 print(
'FATAL: Found two tests which both change the same reference file: {}, which is not supported.'.format(test.existing_ref))
394 print(
'Consider running again in --test-run mode, to get a copy of the copy commands that could be run.')
395 print(
'The general advice is to take the largest file (since it will have the most events), and/or take the non-legacy one.')
398 return 'https://gitlab.cern.ch/atlas/athena/-/merge_requests/'+mr
__init__(self, name, tag, mr, date, existing_ref, existing_version, new_version, new_version_directory, copied_file_path, diff, type)