Skip to content

Commit 6b7abc0

Browse files
committed
Record compiler warning count in sketches report
This data can be useful for detecting an increase in compiler warnings. When deltas reports are enabled, compiler warning count for the base ref compilation as well as the delta will be recorded in the report and the delta printed to the workflow run log.
1 parent 11a78a5 commit 6b7abc0

File tree

6 files changed

+712
-11
lines changed

6 files changed

+712
-11
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ GitHub access token used to get information from the GitHub API. Only needed for
118118

119119
### `enable-deltas-report`
120120

121-
Set to `true` to cause the action to determine the change in memory usage of the compiled sketches. If the workflow is triggered by a `pull_request` event, the comparison is between the pull request branch and the tip of the pull request's base branch. If the workflow is triggered by a `push` event, the comparison is between the pushed commit and its immediate parent. This may be used with the [`arduino/actions/libraries/report-size-deltas` action](https://github.com/arduino/actions/tree/master/libraries/report-size-deltas). Default `false`.
121+
Set to `true` to cause the action to determine the change in memory usage and compiler warnings of the compiled sketches. If the workflow is triggered by a `pull_request` event, the comparison is between the pull request branch and the tip of the pull request's base branch. If the workflow is triggered by a `push` event, the comparison is between the pushed commit and its immediate parent. This may be used with the [`arduino/actions/libraries/report-size-deltas` action](https://github.com/arduino/actions/tree/master/libraries/report-size-deltas). Default `false`.
122122

123123
## Example usage
124124

@@ -133,7 +133,7 @@ Only compiling examples:
133133
version: 1.1.3
134134
```
135135

136-
Storing the memory usage change report as a [workflow artifact](https://help.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts):
136+
Storing the sketches compilation report report as a [workflow artifact](https://help.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts):
137137
```yaml
138138
- uses: arduino/actions/libraries/compile-examples@master
139139
with:

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ inputs:
2626
description: 'GitHub access token used to get information from the GitHub API. Only needed if you are using the size deltas report feature with a private repository.'
2727
default: ''
2828
enable-deltas-report:
29-
description: 'Set to true to cause the action to determine the change in memory usage of the compiled sketches between the head and base refs of a PR and the immediate parent commit of a push'
29+
description: 'Set to true to cause the action to determine the change in memory usage and compiler warnings of the compiled sketches between the head and base refs of a PR and the immediate parent commit of a push'
3030
default: false
3131
runs:
3232
using: 'docker'

compilesketches/compilesketches.py

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class ReportKeys:
9292
commit_url = "commit_url"
9393
compilation_success = "compilation_success"
9494
sizes = "sizes"
95+
warnings = "warnings"
9596
name = "name"
9697
absolute = "absolute"
9798
relative = "relative"
@@ -886,8 +887,13 @@ def get_sketch_report(self, compilation_result):
886887
compilation_result -- object returned by compile_sketch()
887888
"""
888889
current_sizes = self.get_sizes_from_output(compilation_result=compilation_result)
890+
current_warning_count = self.get_warning_count_from_output(compilation_result=compilation_result)
891+
889892
previous_sizes = None
890-
if self.do_deltas_report(compilation_result=compilation_result, current_sizes=current_sizes):
893+
previous_warning_count = None
894+
if self.do_deltas_report(compilation_result=compilation_result,
895+
current_sizes=current_sizes,
896+
current_warnings=current_warning_count):
891897
# Get data for the sketch at the base ref
892898
# Get the head ref
893899
repository = git.Repo(path=os.environ["GITHUB_WORKSPACE"])
@@ -904,13 +910,16 @@ def get_sketch_report(self, compilation_result):
904910
repository.git.checkout(original_git_ref, recurse_submodules=True)
905911

906912
previous_sizes = self.get_sizes_from_output(compilation_result=previous_compilation_result)
913+
previous_warning_count = self.get_warning_count_from_output(compilation_result=previous_compilation_result)
907914

908915
# Add global data for sketch to report
909916
sketch_report = {
910917
self.ReportKeys.name: str(path_relative_to_workspace(path=compilation_result.sketch)),
911918
self.ReportKeys.compilation_success: compilation_result.success,
912919
self.ReportKeys.sizes: self.get_sizes_report(current_sizes=current_sizes,
913-
previous_sizes=previous_sizes)
920+
previous_sizes=previous_sizes),
921+
self.ReportKeys.warnings: self.get_warnings_report(current_warnings=current_warning_count,
922+
previous_warnings=previous_warning_count)
914923
}
915924

916925
return sketch_report
@@ -1008,18 +1017,37 @@ def get_size_data_from_output(self, compilation_output, memory_type, size_data_t
10081017

10091018
return size_data
10101019

1011-
def do_deltas_report(self, compilation_result, current_sizes):
1020+
def get_warning_count_from_output(self, compilation_result):
1021+
"""Parse the stdout from the compilation process and return the number of compiler warnings. Since the
1022+
information is likely not relevant in that case, "N/A" is returned if compilation failed.
1023+
1024+
Keyword arguments:
1025+
compilation_result -- object returned by compile_sketch()
1026+
"""
1027+
if compilation_result.success is True:
1028+
compiler_warning_regex = ":[0-9]+:[0-9]+: warning:"
1029+
warning_count = len(re.findall(pattern=compiler_warning_regex, string=compilation_result.output))
1030+
else:
1031+
warning_count = self.not_applicable_indicator
1032+
1033+
return warning_count
1034+
1035+
def do_deltas_report(self, compilation_result, current_sizes, current_warnings):
10121036
"""Return whether size deltas reporting is enabled.
10131037
10141038
Keyword arguments:
10151039
compilation_result -- object returned by compile_sketch()
10161040
current_sizes -- memory usage data from the compilation
1041+
current_warnings -- compiler warning count
10171042
"""
10181043
return (
10191044
self.enable_deltas_report
10201045
and compilation_result.success
1021-
and any(size.get(self.ReportKeys.absolute) != self.not_applicable_indicator for
1046+
and (
1047+
any(size.get(self.ReportKeys.absolute) != self.not_applicable_indicator for
10221048
size in current_sizes)
1049+
or current_warnings != self.not_applicable_indicator
1050+
)
10231051
)
10241052

10251053
def checkout_deltas_base_ref(self):
@@ -1112,6 +1140,42 @@ def get_size_report(self, current_size, previous_size):
11121140

11131141
return size_report
11141142

1143+
def get_warnings_report(self, current_warnings, previous_warnings):
1144+
"""Return a dictionary containing the compiler warning counts.
1145+
1146+
Keyword arguments:
1147+
current_warnings -- compiler warning count at the head ref
1148+
previous_warnings -- compiler warning count at the base ref, or None if the size deltas feature is not enabled
1149+
"""
1150+
warnings_report = {
1151+
self.ReportKeys.current: {
1152+
self.ReportKeys.absolute: current_warnings,
1153+
}
1154+
}
1155+
1156+
if previous_warnings is not None:
1157+
# Deltas reports are enabled
1158+
# Calculate the change in the warnings count
1159+
if (
1160+
current_warnings == self.not_applicable_indicator
1161+
or previous_warnings == self.not_applicable_indicator
1162+
):
1163+
warnings_delta = self.not_applicable_indicator
1164+
else:
1165+
warnings_delta = current_warnings - previous_warnings
1166+
1167+
# Print the warning count change to the log
1168+
print("Change in compiler warning count:", warnings_delta)
1169+
1170+
warnings_report[self.ReportKeys.previous] = {
1171+
self.ReportKeys.absolute: previous_warnings
1172+
}
1173+
warnings_report[self.ReportKeys.delta] = {
1174+
self.ReportKeys.absolute: warnings_delta
1175+
}
1176+
1177+
return warnings_report
1178+
11151179
def get_sketches_report(self, sketch_report_list):
11161180
"""Return the dictionary containing data on all sketch compilations for each board
11171181
@@ -1141,6 +1205,10 @@ def get_sketches_report(self, sketch_report_list):
11411205
if sizes_summary_report:
11421206
sketches_report[self.ReportKeys.boards][0][self.ReportKeys.sizes] = sizes_summary_report
11431207

1208+
warnings_summary_report = self.get_warnings_summary_report(sketch_report_list=sketch_report_list)
1209+
if warnings_summary_report:
1210+
sketches_report[self.ReportKeys.boards][0][self.ReportKeys.warnings] = warnings_summary_report
1211+
11441212
return sketches_report
11451213

11461214
def get_sizes_summary_report(self, sketch_report_list):
@@ -1241,6 +1309,48 @@ def get_sizes_summary_report(self, sketch_report_list):
12411309

12421310
return sizes_summary_report
12431311

1312+
def get_warnings_summary_report(self, sketch_report_list):
1313+
"""Return a dictionary containing a summary of the compilation warnings count for all sketch compilations.
1314+
1315+
Keyword arguments:
1316+
sketch_report_list -- list of reports from each sketch compilation
1317+
"""
1318+
summary_report_minimum = None
1319+
summary_report_maximum = None
1320+
for sketch_report in sketch_report_list:
1321+
if self.ReportKeys.delta in sketch_report[self.ReportKeys.warnings]:
1322+
sketch_report_delta = (
1323+
sketch_report[self.ReportKeys.warnings][self.ReportKeys.delta][self.ReportKeys.absolute]
1324+
)
1325+
1326+
if (
1327+
summary_report_minimum is None
1328+
or summary_report_minimum == self.not_applicable_indicator
1329+
or summary_report_minimum > sketch_report_delta
1330+
):
1331+
summary_report_minimum = sketch_report_delta
1332+
1333+
if (
1334+
summary_report_maximum is None
1335+
or summary_report_maximum == self.not_applicable_indicator
1336+
or summary_report_maximum < sketch_report_delta
1337+
):
1338+
summary_report_maximum = sketch_report_delta
1339+
1340+
if summary_report_minimum is not None:
1341+
warnings_summary_report = {
1342+
self.ReportKeys.delta: {
1343+
self.ReportKeys.absolute: {
1344+
self.ReportKeys.minimum: summary_report_minimum,
1345+
self.ReportKeys.maximum: summary_report_maximum
1346+
}
1347+
}
1348+
}
1349+
else:
1350+
warnings_summary_report = {}
1351+
1352+
return warnings_summary_report
1353+
12441354
def create_sketches_report_file(self, sketches_report):
12451355
"""Write the report for the report sketch to a file.
12461356

0 commit comments

Comments
 (0)