in mozci/console/commands/push.py [0:0]
def handle(self) -> None:
self.branch = self.argument("branch")
pushes = classify_commands_pushes(
self.branch,
self.option("from-date"),
self.option("to-date"),
self.option("rev"),
)
classify_parameters = retrieve_classify_parameters(self.option)
output = self.option("output")
if output and not os.path.isdir(output):
os.makedirs(output)
self.line(
"<comment>Provided --output pointed to a inexistent directory that is now created.</comment>"
)
retriggerable_backfillable_patterns = config.get(
"retriggerable-backfillable-task-names", []
)
try:
retrigger_limit = int(self.option("retrigger-limit"))
except ValueError:
raise Exception("Provided --retrigger-limit should be an int.")
try:
backfill_limit = int(self.option("backfill-limit"))
except ValueError:
raise Exception("Provided --backfill-limit should be an int.")
for push in pushes:
try:
classification, regressions, to_retrigger_or_backfill = push.classify(
**classify_parameters
)
self.backfill_and_retrigger_failures(
push,
retriggerable_backfillable_patterns,
classify_parameters,
retrigger_limit,
backfill_limit,
to_retrigger_or_backfill,
)
self.line(
f"Push associated with the head revision {push.rev} on "
f"the branch {self.branch} is classified as {classification.name}"
)
except Exception as e:
self.line(
f"<error>Couldn't classify push {push.push_uuid}: {e}.</error>"
)
# Print the error stacktrace in red
self.line(f"<error>{traceback.format_exc()}</error>")
continue
if self.option("show-intermittents"):
self.line("-" * 50)
self.line(
"Printing tasks that should be marked as intermittent failures:"
)
for task in regressions.intermittent:
self.line(task)
self.line("-" * 50)
if output:
def _serialize_regressions(regressions):
return {
group: [
{
"task_id": task.id,
"label": task.label,
"autoclassify": is_autoclassifiable(task),
"tests": [
test_name
for group_failures in task.failure_types.values()
for test_name, _ in group_failures
],
}
for task in failing_tasks
]
for group, failing_tasks in regressions.items()
}
to_save = {
"push": {
"id": push.push_uuid,
"classification": classification.name,
},
"failures": {
"real": _serialize_regressions(regressions.real),
"intermittent": _serialize_regressions(
regressions.intermittent
),
"unknown": _serialize_regressions(regressions.unknown),
},
}
filename = f"{output}/classify_output_{self.branch}_{push.rev}.json"
with open(filename, "w") as file:
json.dump(to_save, file, indent=2)
self.line(
f"Classification and regressions details for push {push.push_uuid} were saved in {filename} JSON file"
)
# Send a notification when some emails are declared in the config
emails = config.get("emails", {}).get("classifications")
matrix_room = config.get("matrix-room-id")
if emails or matrix_room:
# Load previous classification from taskcluster
try:
previous = push.get_existing_classification(
self.option("environment")
)
except SourcesNotFound:
# We still want to send a notification if the current one is bad
previous = None
self.send_notifications(
emails, matrix_room, push, previous, classification, regressions
)