Skip to content

Commit 239ce6d

Browse files
authored
Merge pull request #31 from per1234/handle-missing-deltas
Handle sketches reports with missing size data
2 parents 9595935 + d7b275e commit 239ce6d

File tree

4 files changed

+562
-125
lines changed

4 files changed

+562
-125
lines changed

reportsizedeltas/reportsizedeltas.py

Lines changed: 159 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def set_verbosity(enable_verbosity):
3636
"""Turn debug output on or off.
3737
3838
Keyword arguments:
39-
enable_verbosity -- this will generally be controlled via the script's --verbose command line argument
39+
enable_verbosity -- enable/disable verbose output
4040
(True, False)
4141
"""
4242
# DEBUG: automatically generated output and all higher log level output
@@ -60,6 +60,7 @@ class ReportSizeDeltas:
6060
token -- GitHub access token
6161
"""
6262
report_key_beginning = "**Memory usage change @ "
63+
not_applicable_indicator = "N/A"
6364

6465
class ReportKeys:
6566
"""Key names used in the sketches report dictionary"""
@@ -122,9 +123,9 @@ def report_size_deltas_from_workflow_artifacts(self):
122123
pr_number = pr_data["number"]
123124
pr_head_sha = pr_data["head"]["sha"]
124125
print("::debug::Processing pull request number:", pr_number)
125-
# When a PR is locked, only collaborators may comment. The automatically generated GITHUB_TOKEN will
126-
# likely be used, which is owned by the github-actions bot, who doesn't have collaborator status. So
127-
# locking the thread would cause the job to fail.
126+
# When a PR is locked, only collaborators may comment. The automatically generated GITHUB_TOKEN owned by
127+
# the github-actions bot will likely be used. The bot doesn't have collaborator status so it will
128+
# generally be impossible to make reports on locked PRs.
128129
if pr_data["locked"]:
129130
print("::debug::PR locked, skipping")
130131
continue
@@ -279,7 +280,7 @@ def get_sketches_reports(self, artifact_folder_object):
279280
"""Parse the artifact files and return a list containing the data.
280281
281282
Keyword arguments:
282-
artifact_folder_object -- object containing the data about the temporary folder that stores the markdown files
283+
artifact_folder_object -- object containing the data about the temporary folder that stores the Markdown files
283284
"""
284285
with artifact_folder_object as artifact_folder:
285286
# artifact_folder will be a string when running in non-local report mode
@@ -291,6 +292,8 @@ def get_sketches_reports(self, artifact_folder_object):
291292
report_data = json.load(report_file)
292293
if (
293294
(self.ReportKeys.boards not in report_data)
295+
or (self.ReportKeys.sizes
296+
not in report_data[self.ReportKeys.boards][0])
294297
or (self.ReportKeys.maximum
295298
not in report_data[self.ReportKeys.boards][0][self.ReportKeys.sizes][0])
296299
):
@@ -314,7 +317,7 @@ def generate_report(self, sketches_reports):
314317
"""Return the Markdown for the deltas report comment.
315318
316319
Keyword arguments:
317-
sketches_reports -- list of sketches_reports containing the data to generate the deltas report from
320+
sketches_reports -- list of sketches reports containing the data to generate the deltas report from
318321
"""
319322
# From https://github.community/t/maximum-length-for-the-comment-body-in-issues-and-pr/148867/2
320323
# > PR body/Issue comments are still stored in MySQL as a mediumblob with a maximum value length of 262,144.
@@ -325,73 +328,15 @@ def generate_report(self, sketches_reports):
325328

326329
# Generate summary report data
327330
summary_report_data = [[fqbn_column_heading]]
328-
row_number = 0
329331
for fqbns_data in sketches_reports:
330332
for fqbn_data in fqbns_data[self.ReportKeys.boards]:
331-
row_number += 1
332-
# Add a row to the report
333-
row = ["" for _ in range(len(summary_report_data[0]))]
334-
row[0] = fqbn_data[self.ReportKeys.board]
335-
summary_report_data.append(row)
336-
337-
# Populate the row with data
338-
for size_data in fqbn_data[self.ReportKeys.sizes]:
339-
# Determine column number for this memory type
340-
column_number = get_report_column_number(
341-
report=summary_report_data,
342-
column_heading=size_data[self.ReportKeys.name]
343-
)
344-
345-
# Add the absolute memory data to the cell
346-
summary_report_data[row_number][column_number] = (
347-
get_summary_value(
348-
show_emoji=True,
349-
minimum=size_data[self.ReportKeys.delta][self.ReportKeys.absolute][self.ReportKeys.minimum],
350-
maximum=size_data[self.ReportKeys.delta][self.ReportKeys.absolute][self.ReportKeys.maximum]
351-
)
352-
)
353-
354-
# Add the relative memory data to the cell
355-
summary_report_data[row_number][column_number + 1] = (
356-
get_summary_value(
357-
show_emoji=False,
358-
minimum=size_data[self.ReportKeys.delta][self.ReportKeys.relative][self.ReportKeys.minimum],
359-
maximum=size_data[self.ReportKeys.delta][self.ReportKeys.relative][self.ReportKeys.maximum]
360-
)
361-
)
333+
self.add_summary_report_row(summary_report_data, fqbn_data)
362334

363335
# Generate detailed report data
364336
full_report_data = [[fqbn_column_heading]]
365-
row_number = 0
366337
for fqbns_data in sketches_reports:
367338
for fqbn_data in fqbns_data[self.ReportKeys.boards]:
368-
row_number += 1
369-
# Add a row to the report
370-
row = ["" for _ in range(len(full_report_data[0]))]
371-
row[0] = fqbn_data[self.ReportKeys.board]
372-
full_report_data.append(row)
373-
374-
# Populate the row with data
375-
for sketch in fqbn_data[self.ReportKeys.sketches]:
376-
for size_data in sketch[self.ReportKeys.sizes]:
377-
# Determine column number for this memory type
378-
column_number = get_report_column_number(
379-
report=full_report_data,
380-
column_heading=(
381-
sketch[self.ReportKeys.name] + "<br>"
382-
+ size_data[self.ReportKeys.name]
383-
)
384-
)
385-
386-
# Add the absolute memory data to the cell
387-
full_report_data[row_number][column_number] = (
388-
size_data[self.ReportKeys.delta][self.ReportKeys.absolute]
389-
)
390-
391-
# Add the relative memory data to the cell
392-
full_report_data[row_number][column_number + 1] = (
393-
size_data[self.ReportKeys.delta][self.ReportKeys.relative]
394-
)
339+
self.add_detailed_report_row(full_report_data, fqbn_data)
395340

396341
# Add comment heading
397342
report_markdown = self.report_key_beginning + sketches_reports[0][self.ReportKeys.commit_hash] + "**\n\n"
@@ -425,6 +370,151 @@ def generate_report(self, sketches_reports):
425370
logger.debug("Report:\n" + report_markdown)
426371
return report_markdown
427372

373+
def add_summary_report_row(self, report_data, fqbn_data):
374+
"""Add a row to the summary report.
375+
376+
Keyword arguments:
377+
report_data -- the report to add the row to
378+
right_directory -- the data used to populate the row
379+
"""
380+
row_number = len(report_data)
381+
# Add a row to the report
382+
row = ["" for _ in range(len(report_data[0]))]
383+
row[0] = fqbn_data[self.ReportKeys.board]
384+
report_data.append(row)
385+
386+
# Populate the row with data
387+
for size_data in fqbn_data[self.ReportKeys.sizes]:
388+
# Determine column number for this memory type
389+
column_number = get_report_column_number(
390+
report=report_data,
391+
column_heading=size_data[self.ReportKeys.name]
392+
)
393+
394+
# Add the memory data to the cell
395+
if self.ReportKeys.delta in size_data:
396+
# Absolute data
397+
report_data[row_number][column_number] = (
398+
self.get_summary_value(
399+
show_emoji=True,
400+
minimum=size_data[self.ReportKeys.delta][self.ReportKeys.absolute][
401+
self.ReportKeys.minimum],
402+
maximum=size_data[self.ReportKeys.delta][self.ReportKeys.absolute][
403+
self.ReportKeys.maximum]
404+
)
405+
)
406+
407+
# Relative data
408+
report_data[row_number][column_number + 1] = (
409+
self.get_summary_value(
410+
show_emoji=False,
411+
minimum=size_data[self.ReportKeys.delta][self.ReportKeys.relative][
412+
self.ReportKeys.minimum],
413+
maximum=size_data[self.ReportKeys.delta][self.ReportKeys.relative][
414+
self.ReportKeys.maximum]
415+
)
416+
)
417+
else:
418+
# Absolute data
419+
report_data[row_number][column_number] = (
420+
self.get_summary_value(
421+
show_emoji=True,
422+
minimum=self.not_applicable_indicator,
423+
maximum=self.not_applicable_indicator
424+
)
425+
)
426+
427+
# Relative data
428+
report_data[row_number][column_number + 1] = (
429+
self.get_summary_value(
430+
show_emoji=False,
431+
minimum=self.not_applicable_indicator,
432+
maximum=self.not_applicable_indicator
433+
)
434+
)
435+
436+
def add_detailed_report_row(self, report_data, fqbn_data):
437+
"""Add a row to the detailed report.
438+
439+
Keyword arguments:
440+
report_data -- the report to add the row to
441+
right_directory -- the data used to populate the row
442+
"""
443+
row_number = len(report_data)
444+
# Add a row to the report
445+
row = ["" for _ in range(len(report_data[0]))]
446+
row[0] = fqbn_data[self.ReportKeys.board]
447+
report_data.append(row)
448+
449+
# Populate the row with data
450+
for sketch in fqbn_data[self.ReportKeys.sketches]:
451+
for size_data in sketch[self.ReportKeys.sizes]:
452+
# Determine column number for this memory type
453+
column_number = get_report_column_number(
454+
report=report_data,
455+
column_heading=(
456+
sketch[self.ReportKeys.name] + "<br>"
457+
+ size_data[self.ReportKeys.name]
458+
)
459+
)
460+
461+
# Add the memory data to the cell
462+
if self.ReportKeys.delta in size_data:
463+
# Absolute
464+
report_data[row_number][column_number] = (
465+
size_data[self.ReportKeys.delta][self.ReportKeys.absolute]
466+
)
467+
468+
# Relative
469+
report_data[row_number][column_number + 1] = (
470+
size_data[self.ReportKeys.delta][self.ReportKeys.relative]
471+
)
472+
else:
473+
# Absolute
474+
report_data[row_number][column_number] = self.not_applicable_indicator
475+
476+
# Relative
477+
report_data[row_number][column_number + 1] = self.not_applicable_indicator
478+
479+
def get_summary_value(self, show_emoji, minimum, maximum):
480+
"""Return the Markdown formatted text for a memory change data cell in the report table.
481+
482+
Keyword arguments:
483+
show_emoji -- whether to add the emoji change indicator
484+
minimum -- minimum amount of change for this memory type
485+
maximum -- maximum amount of change for this memory type
486+
"""
487+
size_decrease_emoji = ":green_heart:"
488+
size_ambiguous_emoji = ":grey_question:"
489+
size_increase_emoji = ":small_red_triangle:"
490+
491+
value = None
492+
if minimum == self.not_applicable_indicator:
493+
value = self.not_applicable_indicator
494+
emoji = None
495+
elif minimum < 0 and maximum <= 0:
496+
emoji = size_decrease_emoji
497+
elif minimum == 0 and maximum == 0:
498+
emoji = None
499+
elif minimum >= 0 and maximum > 0:
500+
emoji = size_increase_emoji
501+
else:
502+
emoji = size_ambiguous_emoji
503+
504+
if value is None:
505+
# Prepend + to positive values to improve readability
506+
if minimum > 0:
507+
minimum = "+" + str(minimum)
508+
if maximum > 0:
509+
maximum = "+" + str(maximum)
510+
511+
value = str(minimum) + " - " + str(maximum)
512+
513+
if show_emoji and (emoji is not None):
514+
value = emoji + " " + value
515+
516+
return value
517+
428518
def comment_report(self, pr_number, report_markdown):
429519
"""Submit the report as a comment on the PR thread
430520
@@ -476,7 +566,7 @@ def get_json_response(self, url):
476566
except json.decoder.JSONDecodeError as exception:
477567
# Output some information on the exception
478568
logger.warning(str(exception.__class__.__name__) + ": " + str(exception))
479-
# pass on the exception to the caller
569+
# Pass the exception on to the caller
480570
raise exception
481571

482572
if not json_data:
@@ -648,59 +738,18 @@ def get_report_column_number(report, column_heading):
648738
# Absolute column
649739
# Add the heading
650740
report[0].append(column_heading)
651-
# Expand the size of the last (current) row to match the new number of columns
741+
# Expand the size of the final row (the current row) to match the new number of columns
652742
report[len(report) - 1].append("")
653743

654744
# Relative column
655745
# Add the heading
656746
report[0].append(relative_column_heading)
657-
# Expand the size of the last (current) row to match the new number of columns
747+
# Expand the size of the final row (the current row) to match the new number of columns
658748
report[len(report) - 1].append("")
659749

660750
return column_number
661751

662752

663-
def get_summary_value(show_emoji, minimum, maximum):
664-
"""Return the Markdown formatted text for a memory change data cell in the report table.
665-
666-
Keyword arguments:
667-
show_emoji -- whether to add the emoji change indicator
668-
minimum -- minimum amount of change for this memory type
669-
minimum -- maximum amount of change for this memory type
670-
"""
671-
size_decrease_emoji = ":green_heart:"
672-
size_ambiguous_emoji = ":grey_question:"
673-
size_increase_emoji = ":small_red_triangle:"
674-
not_applicable_indicator = "N/A"
675-
676-
value = None
677-
if minimum == not_applicable_indicator:
678-
value = not_applicable_indicator
679-
emoji = None
680-
elif minimum < 0 and maximum <= 0:
681-
emoji = size_decrease_emoji
682-
elif minimum == 0 and maximum == 0:
683-
emoji = None
684-
elif minimum >= 0 and maximum > 0:
685-
emoji = size_increase_emoji
686-
else:
687-
emoji = size_ambiguous_emoji
688-
689-
if value is None:
690-
# Prepend + to positive values to improve readability
691-
if minimum > 0:
692-
minimum = "+" + str(minimum)
693-
if maximum > 0:
694-
maximum = "+" + str(maximum)
695-
696-
value = str(minimum) + " - " + str(maximum)
697-
698-
if show_emoji and (emoji is not None):
699-
value = emoji + " " + value
700-
701-
return value
702-
703-
704753
def generate_markdown_table(row_list):
705754
"""Return the data formatted as a Markdown table
706755

0 commit comments

Comments
 (0)