Skip to content

Commit 481e492

Browse files
committed
always build with all warnings, but not fatal error
1 parent 8c2dd0b commit 481e492

File tree

2 files changed

+49
-80
lines changed

2 files changed

+49
-80
lines changed

.github/workflows/githubci.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
strategy:
88
fail-fast: false
99
matrix:
10-
arduino-platform:
10+
board:
1111
# Alphabetical order
1212
- 'metro_m0'
1313
- 'hallowing'
@@ -66,8 +66,4 @@ jobs:
6666
arduino-cli lib install $LIB_DEPS
6767
6868
- name: Build examples
69-
run: python3 extras/build_all.py ${{ matrix.arduino-platform }}
70-
71-
# How to mark this as allowed-to-fail?
72-
- name: Build examples (-Wall)
73-
run: python3 extras/build_all.py --all_warnings --warnings_do_not_cause_job_failure
69+
run: python3 extras/build_all.py ${{ matrix.board }}

extras/build_all.py

Lines changed: 47 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,49 @@
22
import glob
33
import sys
44
import subprocess
5+
from subprocess import Popen, PIPE
56
import time
6-
import argparse
7-
8-
FQBN_PREFIX='adafruit:samd:adafruit_'
97

10-
11-
parser = argparse.ArgumentParser(
12-
description='python wrapper for adafruit arduino CI workflows',
13-
allow_abbrev=False
14-
)
15-
parser.add_argument(
16-
'--all_warnings', '--Wall',
17-
action='store_true',
18-
help='build with all warnings enabled (`--warnings all`)',
19-
)
20-
parser.add_argument(
21-
'--warnings_do_not_cause_job_failure',
22-
action='store_true',
23-
help='failed builds will be listed as failed, but not cause job to exit with an error status',
24-
)
25-
parser.add_argument(
26-
'build_boards',
27-
metavar='board',
28-
nargs='*',
29-
help='list of boards to be built -- Note that the fqbn is created by prepending "{}"'.format(FQBN_PREFIX),
30-
default= [ 'metro_m0', 'metro_m4', 'circuitplayground_m0', 'feather_m4_can' ]
31-
)
32-
args = parser.parse_args()
8+
SUCCEEDED = "\033[32msucceeded\033[0m"
9+
FAILED = "\033[31mfailed\033[0m"
10+
SKIPPED = "\033[35mskipped\033[0m"
11+
WARNING = "\033[33mwarnings\033[0m "
3312

3413
exit_status = 0
3514
success_count = 0
3615
fail_count = 0
3716
skip_count = 0
38-
build_format = '| {:22} | {:30} | {:9} '
39-
build_separator = '-' * 80
4017

41-
def errorOutputFilter(line: str):
42-
if len(line) == 0:
43-
return False
44-
if line.isspace(): # Note: empty string does not match here!
45-
return False
46-
# TODO: additional items to remove?
47-
return True
18+
build_format = '| {:20} | {:35} | {:18} | {:6} |'
19+
build_separator = '-' * 83
20+
21+
FQBN_PREFIX='adafruit:samd:adafruit_'
22+
23+
default_boards = [ 'metro_m0', 'metro_m4', 'circuitplayground_m0', 'feather_m4_can' ]
24+
build_boards = []
25+
26+
# build all variants if input not existed
27+
if len(sys.argv) > 1:
28+
build_boards.append(sys.argv[1])
29+
else:
30+
build_boards = default_boards
31+
32+
all_examples = list(glob.iglob('libraries/**/*.ino', recursive=True))
33+
all_examples.sort()
4834

49-
def build_examples(variant: str):
50-
global args, exit_status, success_count, fail_count, skip_count, build_format, build_separator
35+
def build_examples(variant):
36+
global exit_status, success_count, fail_count, skip_count, build_format, build_separator
5137

5238
print('\n')
5339
print(build_separator)
54-
print('| {:^76} |'.format('Board ' + variant))
40+
print('| {:^79} |'.format('Board ' + variant))
5541
print(build_separator)
56-
print((build_format + '| {:6} |').format('Library', 'Example', 'Result', 'Time'))
42+
print(build_format.format('Library', 'Example', '\033[39mResult\033[0m', 'Time'))
5743
print(build_separator)
5844

5945
fqbn = "{}{}".format(FQBN_PREFIX, variant)
6046

61-
for sketch in glob.iglob('libraries/**/*.ino', recursive=True):
47+
for sketch in all_examples:
6248
# TODO skip TinyUSB library examples for now
6349
if "libraries/Adafruit_TinyUSB_Arduino" in sketch:
6450
continue
@@ -69,60 +55,47 @@ def build_examples(variant: str):
6955
# Skip if not contains: ".board.test.only" for a specific board
7056
sketchdir = os.path.dirname(sketch)
7157
if os.path.exists(sketchdir + '/.all.test.skip') or os.path.exists(sketchdir + '/.' + variant + '.test.skip'):
72-
success = "\033[33mskipped\033[0m "
73-
elif glob.glob(sketchdir+"/.*.test.only") and not os.path.exists(sketchdir + '/.build.' + variant):
74-
success = "\033[33mskipped\033[0m "
58+
success = SKIPPED
59+
skip_count += 1
60+
elif glob.glob(sketchdir+"/.*.test.only") and not os.path.exists(sketchdir + '/.' + variant + '.test.only'):
61+
success = SKIPPED
62+
skip_count += 1
7563
else:
76-
# TODO - preferably, would have STDERR show up in **both** STDOUT and STDERR.
77-
# preferably, would use Python logging handler to get both distinct outputs and one merged output
78-
# for now, split STDERR when building with all warnings enabled, so can detect warning/error output.
79-
if args.all_warnings:
80-
build_result = subprocess.run("arduino-cli compile --warnings all --fqbn {} {}".format(fqbn, sketch), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
81-
else:
82-
build_result = subprocess.run("arduino-cli compile --warnings default --fqbn {} {}".format(fqbn, sketch), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
83-
84-
# get stderr into a form where len(warningLines) indicates a true warning was output to stderr
85-
warningLines = [];
86-
if args.all_warnings and build_result.stderr:
87-
tmpWarningLines = build_result.stderr.decode("utf-8").splitlines()
88-
warningLines = list(filter(errorOutputFilter, (tmpWarningLines)))
64+
build_result = subprocess.run("arduino-cli compile --warnings all --fqbn {} {}".format(fqbn, sketch), shell=True, stdout=PIPE, stderr=PIPE)
8965

66+
# get stderr into a form where warning/error was output to stderr
9067
if build_result.returncode != 0:
9168
exit_status = build_result.returncode
92-
success = "\033[31mfailed\033[0m "
93-
fail_count += 1
94-
elif len(warningLines) != 0:
95-
if not args.warnings_do_not_cause_job_failure:
96-
exit_status = -1
97-
success = "\033[31mwarnings\033[0m "
69+
success = FAILED
9870
fail_count += 1
9971
else:
100-
success = "\033[32msucceeded\033[0m"
10172
success_count += 1
73+
if build_result.stderr:
74+
success = WARNING
75+
else:
76+
success = SUCCEEDED
10277

10378
build_duration = time.monotonic() - start_time
10479

105-
print((build_format + '| {:5.2f}s |').format(sketch.split(os.path.sep)[1], os.path.basename(sketch), success, build_duration))
80+
print(build_format.format(sketch.split(os.path.sep)[1], os.path.basename(sketch), success, '{:5.2f}s'.format(build_duration)))
10681

107-
if success != "\033[33mskipped\033[0m ":
82+
if success != SKIPPED:
83+
# Build failed
10884
if build_result.returncode != 0:
10985
print(build_result.stdout.decode("utf-8"))
110-
if (build_result.stderr):
111-
print(build_result.stderr.decode("utf-8"))
112-
if len(warningLines) != 0:
113-
for line in warningLines:
114-
print(line)
115-
else:
116-
skip_count += 1
86+
87+
# Build with warnings
88+
if build_result.stderr:
89+
print(build_result.stderr.decode("utf-8"))
11790

11891
build_time = time.monotonic()
11992

120-
for board in args.build_boards:
93+
for board in build_boards:
12194
build_examples(board)
12295

12396
print(build_separator)
12497
build_time = time.monotonic() - build_time
125-
print("Build Summary: {} \033[32msucceeded\033[0m, {} \033[31mfailed\033[0m, {} \033[33mskipped\033[0m and took {:.2f}s".format(success_count, fail_count, skip_count, build_time))
98+
print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, build_time))
12699
print(build_separator)
127100

128101
sys.exit(exit_status)

0 commit comments

Comments
 (0)