Skip to content

Commit 496057e

Browse files
authored
Merge pull request #7057 from jepler/ci-set-matrix-improvements
Ci set matrix improvements
2 parents b4c2ef1 + d08b43f commit 496057e

File tree

2 files changed

+61
-19
lines changed

2 files changed

+61
-19
lines changed

docs/shared_bindings_matrix.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import re
2828
import subprocess
2929
import sys
30+
import functools
3031

3132
from concurrent.futures import ThreadPoolExecutor
3233

@@ -80,12 +81,11 @@
8081
repository_urls = {}
8182
"""Cache of repository URLs for frozen modules."""
8283

84+
root_dir = pathlib.Path(__file__).resolve().parent.parent
85+
8386
def get_circuitpython_root_dir():
8487
""" The path to the root './circuitpython' directory.
8588
"""
86-
file_path = pathlib.Path(__file__).resolve()
87-
root_dir = file_path.parent.parent
88-
8989
return root_dir
9090

9191
def get_shared_bindings():
@@ -102,7 +102,7 @@ def get_board_mapping():
102102
"""
103103
boards = {}
104104
for port in SUPPORTED_PORTS:
105-
board_path = os.path.join("../ports", port, "boards")
105+
board_path = root_dir / "ports" / port / "boards"
106106
for board_path in os.scandir(board_path):
107107
if board_path.is_dir():
108108
board_files = os.listdir(board_path.path)
@@ -276,6 +276,7 @@ def lookup_setting(settings, key, default=''):
276276
key = value[2:-1]
277277
return value
278278

279+
@functools.cache
279280
def all_ports_all_boards(ports=SUPPORTED_PORTS):
280281
for port in ports:
281282

tools/ci_set_matrix.py

100644100755
Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,35 @@
1212
base branch while pushes will compare to the current ref. We override this
1313
for the adafruit/circuitpython repo so we build all docs/boards for pushes.
1414
15+
When making changes to the script it is useful to manually test it.
16+
You can for instance run
17+
```shell
18+
tools/ci_set_matrix ports/raspberrypi/common-hal/socket/SSLSocket.c
19+
```
20+
and (at the time this comment was written) get a series of messages indicating
21+
that only the single board raspberry_pi_pico_w would be built.
1522
"""
1623

1724
import re
1825
import os
1926
import sys
2027
import json
2128
import yaml
29+
import pathlib
30+
from concurrent.futures import ThreadPoolExecutor
31+
32+
tools_dir = pathlib.Path(__file__).resolve().parent
33+
top_dir = tools_dir.parent
34+
35+
sys.path.insert(0, str(tools_dir / "adabot"))
36+
sys.path.insert(0, str(top_dir / "docs"))
2237

2338
import build_board_info
24-
from shared_bindings_matrix import get_settings_from_makefile
39+
from shared_bindings_matrix import (
40+
get_settings_from_makefile,
41+
SUPPORTED_PORTS,
42+
all_ports_all_boards,
43+
)
2544

2645
PORT_TO_ARCH = {
2746
"atmel-samd": "arm",
@@ -40,12 +59,17 @@
4059
"tools/ci_check_duplicate_usb_vid_pid.py",
4160
]
4261

43-
changed_files = {}
44-
try:
45-
changed_files = json.loads(os.environ["CHANGED_FILES"])
46-
except json.decoder.JSONDecodeError as exc:
47-
if exc.msg != "Expecting value":
48-
raise
62+
if len(sys.argv) > 1:
63+
print("Using files list on commandline")
64+
changed_files = sys.argv[1:]
65+
else:
66+
c = os.environ["CHANGED_FILES"]
67+
if c == "":
68+
print("CHANGED_FILES is in environment, but value is empty")
69+
changed_files = []
70+
else:
71+
print("Using files list in CHANGED_FILES")
72+
changed_files = json.loads(os.environ["CHANGED_FILES"])
4973

5074

5175
def set_output(name, value):
@@ -74,13 +98,29 @@ def set_boards_to_build(build_all):
7498
port_to_boards[port].add(board_id)
7599
board_to_port[board_id] = port
76100

101+
def compute_board_settings(boards):
102+
need = set(boards) - set(board_settings.keys())
103+
if not need:
104+
return
105+
106+
def get_settings(board):
107+
return (
108+
board,
109+
get_settings_from_makefile(str(top_dir / "ports" / board_to_port[board]), board),
110+
)
111+
112+
with ThreadPoolExecutor(max_workers=os.cpu_count()) as ex:
113+
board_settings.update(ex.map(get_settings, need))
114+
77115
boards_to_build = all_board_ids
78116

79117
if not build_all:
80118
boards_to_build = set()
81119
board_pattern = re.compile(r"^ports/[^/]+/boards/([^/]+)/")
82120
port_pattern = re.compile(r"^ports/([^/]+)/")
83-
module_pattern = re.compile(r"^(ports/[^/]+/shared-bindings|shared-module)/([^/]+)/")
121+
module_pattern = re.compile(
122+
r"^(ports/[^/]+/(?:common-hal|bindings)|shared-bindings|shared-module)/([^/]+)/"
123+
)
84124
for p in changed_files:
85125
# See if it is board specific
86126
board_matches = board_pattern.search(p)
@@ -91,9 +131,9 @@ def set_boards_to_build(build_all):
91131

92132
# See if it is port specific
93133
port_matches = port_pattern.search(p)
134+
port = port_matches.group(1) if port_matches else None
94135
module_matches = module_pattern.search(p)
95-
if port_matches and not module_matches:
96-
port = port_matches.group(1)
136+
if port and not module_matches:
97137
if port != "unix":
98138
boards_to_build.update(port_to_boards[port])
99139
continue
@@ -109,11 +149,12 @@ def set_boards_to_build(build_all):
109149
# As a (nearly) last resort, for some certain files, we compute the settings from the
110150
# makefile for each board and determine whether to build them that way.
111151
if p.startswith("frozen") or p.startswith("supervisor") or module_matches:
112-
for board in all_board_ids:
113-
if board not in board_settings:
114-
board_settings[board] = get_settings_from_makefile(
115-
"../ports/" + board_to_port[board], board
116-
)
152+
if port:
153+
board_ids = port_to_boards[port]
154+
else:
155+
board_ids = all_board_ids
156+
compute_board_settings(board_ids)
157+
for board in board_ids:
117158
settings = board_settings[board]
118159

119160
# Check frozen files to see if they are in each board.

0 commit comments

Comments
 (0)