65 """So now we have a URL to a failing test.
66 We need to check that the test is failing for the correct reason - namely a reference file which needs updating
67 The information we need to collect is:
68 - the AMI tag of the failing tests
69 - the merge request number
70 - the location of the reference file
71 - the location of the copied file
72 - the name of the test
73 - the new version number
74 - the new version directory
76 page = requests.get(url)
81 test_match = re.search(
r'All (?P<ami_tag>\w+) athena steps completed successfully', text)
82 ami_tag = test_match.group(
'ami_tag')
if test_match
else None
87 match_attempt_2 = re.search(
r'AMIConfig (?P<ami_tag>\w+)', text)
89 ami_tag = match_attempt_2.group(
'ami_tag')
92 print(
'WARNING: Did not find an AMI tag in the test "{}". Ignoring.'.format(test_name))
95 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)
97 print(
'FATAL: Could not process the URL as expected. Aborting.')
101 mr_number = mr_match.group(
'mr_number')
102 date = mr_match.group(
'date')
103 human_readable_date =
':'.join(date.split(
'-')[0:3]) +
" at " +
':'.join(date.split(
'-')[3:])
105 if "Your change breaks the digest in test" in text
or 'ERROR Your change modifies the output in test' in text:
107 failing_tests[branch].append(
process_digest_change(text, ami_tag, mr_number, human_readable_date, test_name))
109 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:
111 failing_tests[branch].append(
process_diffpool_change(text, ami_tag, mr_number, human_readable_date, test_name))
116 eos_path_root =
'/eos/atlas/atlascerngroupdisk/data-art/grid-input/WorkflowReferences/'
120 copied_file_match = re.search(
r'^ERROR Copied.*', text, flags=re.MULTILINE)
121 if not copied_file_match:
122 print(
"FATAL: Could not find matching copied file")
124 copied_file_path = copied_file_match.group().
split(
'to')[1].
strip().
strip(
"'").
strip(
"'")+
'/'
127 ref_file_match = re.search(
r'INFO Reading the reference file from location.*', text)
128 if not ref_file_match:
129 print(
"FATAL: Could not find matching reference file")
132 ref_file_path = ref_file_match.group().
split(
'location')[1].
strip()
133 existing_version_number= ref_file_path.split(
'/')[-2]
134 branch = ref_file_path.split(
'/')[-4]
135 new_version_number =
'v'+
str(int(existing_version_number[1:])+1)
136 new_version_directory = eos_path_root+branch+
'/'+ami_tag+
'/'+new_version_number
137 old_version_directory = eos_path_root+branch+
'/'+ami_tag+
'/'+existing_version_number
140 copied_file_match = re.search(
r'^ERROR Copied.*', text, flags=re.MULTILINE)
141 if not copied_file_match:
142 print(
"FATAL: Could not find matching copied file")
146 ami_tag_check = ref_file_path.split(
'/')[-3].
strip()
147 if ami_tag_check!=ami_tag:
148 print(
'FATAL: Sanity check: "{}" from reference file path "{}" does not match ami tag "{}" extracted previously.'.format(ami_tag_check, ref_file_path, ami_tag))
152 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')
157 existing_version_number =
None
158 new_version_directory =
None
159 copied_file_path =
None
160 new_version_number=
None
163 ref_file_match = re.search(
164 r"differs from the reference (?:'|')([^'&]+?)(?:'|')",
167 if not ref_file_match:
168 print(
"FATAL: Could not find matching reference file")
170 ref_file_path = ref_file_match.group(1)
178 for line
in text.split(
'\n'):
179 if 'differs from the reference' in line:
187 diff_lines.append(html.unescape(line))
189 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')
194 print(
'Updating reference files')
195 print(
'========================')
197 for branch, tests
in failing_tests.items():
199 print(
'Processing test: {} on branch {}'.format(test.name, branch))
200 if test.type ==
'DiffPool':
202 print(
' * This is a DiffPool test but uses a shared reference. No update needed.')
205 print(
' * This is a DiffPool test, and currently has version {} of {}. Will update References.py with new version.'.format(test.existing_version, test.tag))
207 print(
' -> The new version is: {}. Creating directory and copying files on EOS now.'.format(test.new_version))
213 commands = list(dict.fromkeys(commands))
216 if update_local_files:
219 print (
'Updating local References.py file with new version {} for tag {}'.format(test.new_version, test.tag))
221 with open(
'Tools/WorkflowTestRunner/python/References.py',
'r')
as f:
222 lines = f.readlines()
225 if test.existing_version
in line:
226 line = line.replace(test.existing_version, test.new_version)
229 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=
'')
230 print(
'** Are you sure your branch is up-to-date with main? We cannot update an older version of References.py!')
235 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))
237 with open(
'Tools/WorkflowTestRunner/python/References.py',
'w')
as f:
239 elif test.type ==
'Digest' and update_local_files:
240 print(
' * This is a Digest test. Need to update reference file {}.'.format(test.existing_ref))
244 digest_old = [line
for line
in test.diff
if line.startswith(
'<')]
245 digest_new = [line
for line
in test.diff
if line.startswith(
'>')]
247 with open(
'Tools/PROCTools/data/'+test.existing_ref,
'r')
as f:
248 lines = f.readlines()
249 for current_line, line
in enumerate(lines):
250 split_curr_line = line.split()
251 if (split_curr_line[0] ==
'run'):
256 if (
not split_curr_line[0].isnumeric())
or (
not split_curr_line[1].isnumeric()):
257 print(
'FATAL: Found a line in current digest which does not start with run/event numbers: {}'.format(line))
260 split_old_diff_line = digest_old[diff_line].
split()
261 split_old_diff_line.pop(0)
262 split_new_diff_line = digest_new[diff_line].
split()
263 split_new_diff_line.pop(0)
266 if split_curr_line[0] == split_old_diff_line[0]
and split_curr_line[1] == split_old_diff_line[1]:
268 if split_curr_line!=split_old_diff_line:
269 print(
'FATAL: It seems like this line was already changed.')
270 print(
'Line we expected: {}'.format(test.old_diff_lines[diff_line]))
271 print(
'Line we got : {}'.format(line))
275 if split_curr_line[0] == split_new_diff_line[0]
and split_curr_line[1] == split_new_diff_line[1]:
277 data.append(
"".join([
"{:>12}".format(x)
for x
in split_new_diff_line])+
'\n')
278 if ((diff_line+1)<len(digest_old)):
285 print(
' -> Updating PROCTools digest file {}'.format(test.existing_ref))
286 with open(
'Tools/PROCTools/data/'+test.existing_ref,
'w')
as f:
288 elif test.type ==
'Content' and update_local_files:
289 print(
' * This is a Content test. Need to update reference file {}.'.format(test.existing_ref))
290 subprocess.run(f
'patch --quiet Tools/PROCTools/data/{test.existing_ref}',
291 input=
'\n'.join(test.diff)+
'\n',
292 text=
True, shell=
True, check=
True)
299 If called with actually_update=False, this function will return a list of commands which would have been executed.
304 if test.shared_ref
is True:
307 if test.new_version_directory
not in dirs_created:
308 commands.append(
"mkdir -p " + test.new_version_directory)
309 dirs_created.append(test.new_version_directory)
313 commands.append(
"cp " + test.copied_file_path +
"* "+ test.new_version_directory+
"/")
314 commands.append(
"cp -n " + test.existing_ref +
"/* "+ test.new_version_directory+
"/")
316 print(
' -> Copying files from {} to {}'.format(test.copied_file_path, test.new_version_directory))
318 for command
in commands:
320 subprocess.call( command, shell=
True)
321 except Exception
as e:
322 print(
'Command failed due to:', e)
323 print(
'Do you have EOS available on this machine?')
324 except Exception
as e:
325 print(
'FATAL: Unable to copy files due to:', e)
328 f = open(test.new_version_directory+
'/info.txt',
'w')
329 f.write(
'Merge URL: https://gitlab.cern.ch/atlas/athena/-/merge_requests/{}\n'.format(test.mr))
330 f.write(
'Date: {}\n'.format(test.date))
331 f.write(
'AMI: {}\n'.format(test.tag))
332 f.write(
'Test name: {}\n'.format(test.name))
333 f.write(
'Files copied from: {}\n'.format(test.copied_file_path))
409 print(
'Summary of tests which need work:')
411 if not failing_tests:
412 print(
" -> None found. Aborting.")
416 reference_folders = []
417 for branch,tests
in failing_tests.items():
418 print (
' * Branch: {}'.format(branch))
421 if test.type ==
'DiffPool':
422 if not test.new_version_directory:
423 print(
'FATAL: No path to "new version" for test {} of type DiffPool.'.format(test.name))
426 if os.path.exists(test.new_version_directory):
427 msg = f
'WARNING: The directory {test.new_version_directory} already exists. Are you sure you want to overwrite the existing references?'
428 if input(
"%s (y/N) " % msg).lower() !=
'y':
431 if (test.existing_ref
not in reference_folders):
432 reference_folders.append(test.existing_ref)
433 elif check_for_duplicates
and not test.shared_ref:
434 print(
'FATAL: Found two tests which both change the same reference file: {}, which is not supported.'.format(test.existing_ref))
435 print(
'Consider running again in --test-run mode, to get a copy of the copy commands that could be run.')
436 print(
'The general advice is to take the largest file (since it will have the most events).')
439 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)