Skip to content

Ci set matrix improvements #7057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/shared_bindings_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import re
import subprocess
import sys
import functools

from concurrent.futures import ThreadPoolExecutor

Expand Down Expand Up @@ -80,12 +81,11 @@
repository_urls = {}
"""Cache of repository URLs for frozen modules."""

root_dir = pathlib.Path(__file__).resolve().parent.parent

def get_circuitpython_root_dir():
""" The path to the root './circuitpython' directory.
"""
file_path = pathlib.Path(__file__).resolve()
root_dir = file_path.parent.parent

return root_dir

def get_shared_bindings():
Expand All @@ -102,7 +102,7 @@ def get_board_mapping():
"""
boards = {}
for port in SUPPORTED_PORTS:
board_path = os.path.join("../ports", port, "boards")
board_path = root_dir / "ports" / port / "boards"
for board_path in os.scandir(board_path):
if board_path.is_dir():
board_files = os.listdir(board_path.path)
Expand Down Expand Up @@ -276,6 +276,7 @@ def lookup_setting(settings, key, default=''):
key = value[2:-1]
return value

@functools.cache
def all_ports_all_boards(ports=SUPPORTED_PORTS):
for port in ports:

Expand Down
71 changes: 56 additions & 15 deletions tools/ci_set_matrix.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,35 @@
base branch while pushes will compare to the current ref. We override this
for the adafruit/circuitpython repo so we build all docs/boards for pushes.

When making changes to the script it is useful to manually test it.
You can for instance run
```shell
tools/ci_set_matrix ports/raspberrypi/common-hal/socket/SSLSocket.c
```
and (at the time this comment was written) get a series of messages indicating
that only the single board raspberry_pi_pico_w would be built.
"""

import re
import os
import sys
import json
import yaml
import pathlib
from concurrent.futures import ThreadPoolExecutor

tools_dir = pathlib.Path(__file__).resolve().parent
top_dir = tools_dir.parent

sys.path.insert(0, str(tools_dir / "adabot"))
sys.path.insert(0, str(top_dir / "docs"))

import build_board_info
from shared_bindings_matrix import get_settings_from_makefile
from shared_bindings_matrix import (
get_settings_from_makefile,
SUPPORTED_PORTS,
all_ports_all_boards,
)

PORT_TO_ARCH = {
"atmel-samd": "arm",
Expand All @@ -40,12 +59,17 @@
"tools/ci_check_duplicate_usb_vid_pid.py",
]

changed_files = {}
try:
changed_files = json.loads(os.environ["CHANGED_FILES"])
except json.decoder.JSONDecodeError as exc:
if exc.msg != "Expecting value":
raise
if len(sys.argv) > 1:
print("Using files list on commandline")
changed_files = sys.argv[1:]
else:
c = os.environ["CHANGED_FILES"]
if c == "":
print("CHANGED_FILES is in environment, but value is empty")
changed_files = []
else:
print("Using files list in CHANGED_FILES")
changed_files = json.loads(os.environ["CHANGED_FILES"])


def set_output(name, value):
Expand Down Expand Up @@ -74,13 +98,29 @@ def set_boards_to_build(build_all):
port_to_boards[port].add(board_id)
board_to_port[board_id] = port

def compute_board_settings(boards):
need = set(boards) - set(board_settings.keys())
if not need:
return

def get_settings(board):
return (
board,
get_settings_from_makefile(str(top_dir / "ports" / board_to_port[board]), board),
)

with ThreadPoolExecutor(max_workers=os.cpu_count()) as ex:
board_settings.update(ex.map(get_settings, need))

boards_to_build = all_board_ids

if not build_all:
boards_to_build = set()
board_pattern = re.compile(r"^ports/[^/]+/boards/([^/]+)/")
port_pattern = re.compile(r"^ports/([^/]+)/")
module_pattern = re.compile(r"^(ports/[^/]+/shared-bindings|shared-module)/([^/]+)/")
module_pattern = re.compile(
r"^(ports/[^/]+/(?:common-hal|bindings)|shared-bindings|shared-module)/([^/]+)/"
)
for p in changed_files:
# See if it is board specific
board_matches = board_pattern.search(p)
Expand All @@ -91,9 +131,9 @@ def set_boards_to_build(build_all):

# See if it is port specific
port_matches = port_pattern.search(p)
port = port_matches.group(1) if port_matches else None
module_matches = module_pattern.search(p)
if port_matches and not module_matches:
port = port_matches.group(1)
if port and not module_matches:
if port != "unix":
boards_to_build.update(port_to_boards[port])
continue
Expand All @@ -109,11 +149,12 @@ def set_boards_to_build(build_all):
# As a (nearly) last resort, for some certain files, we compute the settings from the
# makefile for each board and determine whether to build them that way.
if p.startswith("frozen") or p.startswith("supervisor") or module_matches:
for board in all_board_ids:
if board not in board_settings:
board_settings[board] = get_settings_from_makefile(
"../ports/" + board_to_port[board], board
)
if port:
board_ids = port_to_boards[port]
else:
board_ids = all_board_ids
compute_board_settings(board_ids)
for board in board_ids:
settings = board_settings[board]

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