in sync/notify/bugs.py [0:0]
def for_sync(sync: DownstreamSync,
results: Results,
) -> Mapping[int, list[ResultsEntryStatus]]:
"""Create the bugs for followup work for test problems found in a sync.
This creates bugs that will be owned by the triage owner of the component
for any followup work that's revealed by the changes in a sync. Currently
this is for crashes and certain kinds of failures e.g. Firefox-only failures
that are not already known in the wpt metadata.
:returns: A dict {bug_id: bug_info} where bug_info is a list of test results
that are included in the bug, each represented as a tuple
(test_id, subtest, results, status)"""
rv: MutableMapping[int, list[ResultsEntryStatus]] = {}
newrelic.agent.record_custom_event("sync_bug", params={
"sync_bug": sync.bug,
})
new_crashes = list(results.iter_filter(lambda _test, _subtest, result:
(result.has_crash("firefox") and
not result.has_link(status="CRASH"))))
new_failures = list(results.iter_filter(filter_test_failures))
if not new_failures and not new_crashes:
newrelic.agent.record_custom_event("sync_bug_nothing_relevant", params={
"sync_bug": sync.bug,
})
return rv
existing = sync.notify_bugs
git_work = sync.gecko_worktree.get()
path_prefix = env.config["gecko"]["path"]["wpt"]
seen = set()
for key, test_results, bug_data, link_status, require_opt_in in [
("crash", new_crashes, bug_data_crash, "CRASH", False),
("failure", new_failures, bug_data_failure, None, True)]:
# Tests excluding those for which we already generated a bug
test_results = [item for item in test_results
if (item[0], item[1]) not in seen]
if not test_results:
continue
seen |= {(item[0], item[1]) for item in test_results}
test_ids = list({test_id for test_id, _subtest, _result in test_results})
test_id_by_path = test_ids_to_paths(git_work, test_ids)
test_path_by_id = {}
for path, ids in test_id_by_path.items():
for test_id in ids:
test_path_by_id[test_id] = os.path.relpath(path, path_prefix)
paths = set(test_path_by_id.values())
logger.info(f"Got paths {paths}")
components = components_for_wpt_paths(git_work, paths)
components_by_path = {}
for component, component_paths in components.items():
for path in component_paths:
components_by_path[path] = component
test_results_by_component = defaultdict(list)
for test_id, subtest, test_result in test_results:
test_path = test_path_by_id.get(test_id)
if not test_path:
# This can be missing if the test landed in a commit that's upstream but not here
# so it's in wpt.fyi data but not here
continue
component = components_by_path[test_path]
test_results_by_component[component].append((test_id, subtest, test_result))
opt_in_components = {item.strip()
for item in
env.config["notify"].get("components", "").split(";")}
for component, test_results in test_results_by_component.items():
if component == "UNKNOWN":
# For things with no component don't file a bug
continue
component_key = f"{key} :: {component}"
if require_opt_in and component not in opt_in_components:
logger.info("Not filing bugs for component %s" % component)
newrelic.agent.record_custom_event("sync_bug_not_enabled", params={
"sync_bug": sync.bug,
"component": component
})
continue
if component_key not in existing:
product, component = component.split(" :: ")
summary, comment = bug_data(sync,
test_results,
results.treeherder_url,
results.wpt_sha)
depends = []
if sync.bug:
depends = [sync.bug]
bug_id = make_bug(summary, comment, product, component, depends)
sync.notify_bugs = sync.notify_bugs.copy(**{component_key: bug_id}) # type: ignore
newrelic.agent.record_custom_event("sync_bug_filing", params={
"sync_bug": sync.bug,
"component": component
})
else:
newrelic.agent.record_custom_event("sync_bug_existing", params={
"sync_bug": sync.bug,
"component": component
})
bug_id = existing[component_key]
rv[bug_id] = [item + (link_status,) for item in test_results]
return rv