summaryrefslogtreecommitdiff
path: root/.github
diff options
context:
space:
mode:
Diffstat (limited to '.github')
-rwxr-xr-x.github/scripts/ci_set_matrix.py8
-rw-r--r--.github/scripts/hil_ci_set_matrix.py11
-rw-r--r--.github/workflows/build.yml36
-rw-r--r--.github/workflows/build_util.yml13
4 files changed, 43 insertions, 25 deletions
diff --git a/.github/scripts/ci_set_matrix.py b/.github/scripts/ci_set_matrix.py
index 79f466893..409e6dbc1 100755
--- a/.github/scripts/ci_set_matrix.py
+++ b/.github/scripts/ci_set_matrix.py
@@ -131,7 +131,13 @@ def set_matrix_json(select=None):
# a family this file does not list builds on no toolchain, so it contributes no
# leg. hw/bsp holds several CI has never built (efm32, py32f0, same7x, ...) plus
# espressif, whose boards hil-build-esp builds by name.
- unbuilt = sorted(f for f in sel_fams if f not in family_list)
+ # espressif is not a gap: its examples need the ESP-IDF environment
+ # (CLAUDE.md: `. "$IDF_PATH/export.sh"` before any build), which the cmake legs
+ # do not have - that is why it is commented out of family_list above. Its
+ # coverage comes from hil-build-esp, which builds those boards BY NAME in an IDF
+ # container, so an espressif-only PR is already validated and falling open to the
+ # full matrix would add 74 legs, none of which can compile espressif.
+ unbuilt = sorted(f for f in sel_fams if f not in family_list and f != 'espressif')
if unbuilt and not any(matrix.values()):
# NONE of the selected families is buildable here, so every leg would skip
# and the PR would go green from a build job that ran no compiler. That is
diff --git a/.github/scripts/hil_ci_set_matrix.py b/.github/scripts/hil_ci_set_matrix.py
index bf50061dd..b567f347c 100644
--- a/.github/scripts/hil_ci_set_matrix.py
+++ b/.github/scripts/hil_ci_set_matrix.py
@@ -1,5 +1,6 @@
import argparse
import json
+import shlex
import os
import sys
@@ -112,14 +113,20 @@ def main():
# Each variant builds into cmake-build-<variant.name> with its own cmake
# -D defines and raw CFLAGS. No 'variant' -> a single build named after
- # the board.
+ # the board; an always-on define (MAX3421_HOST=1, LOGGER=rtt) is a single
+ # self-named variant carrying it.
variants = board.get('variant') or [{'name': name, 'flags': ''}]
for v in variants:
arg = build_board
if v['name'] != name:
arg += f' --build-name {v["name"]}'
+ # build_util.yml's Build step splices this string into bash source,
+ # so the quoting round-trips a spaced value into one argv item like
+ # build_board's argv path. The SAME string also reaches the get_deps
+ # env expansion and the artifact-name charset, where spaced/quoted
+ # values still fail (loudly) -- keep defines space-free
for d in v.get('defines', []):
- arg += f' -D{d}'
+ arg += f' -D{shlex.quote(d)}'
for tok in v.get('flags', '').split():
arg += f' --cflag={tok}'
append_build_arg(toolchain, arg)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 39a4e7afd..70555b111 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -41,6 +41,7 @@ jobs:
- 'tools/ci_select.py'
- 'tools/get_deps.py'
- 'tools/metrics.py'
+ - 'tools/rtt.py'
- '.github/actions/**'
- '.github/workflows/build.yml'
- '.github/workflows/build_util.yml'
@@ -68,14 +69,9 @@ jobs:
with:
fetch-depth: 0
- # The `ci-full` PR label turns the scoping off for one PR: no selection file is
- # written, so both matrices and every rig job fall back to the unscoped behaviour.
- # An escape hatch is the point - a selector bug under-selects SILENTLY, and without
- # a label the only routes back to a full matrix are accidental (touch an
- # unclassified path, or break the selector badly enough that it falls open).
- name: CI selection (PR only)
id: hil-select
- if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'ci-full')
+ if: github.event_name == 'pull_request'
env:
BASE_REF: ${{ github.base_ref }}
run: |
@@ -179,29 +175,43 @@ jobs:
# treats false like null, so .build.full is compared explicitly.
EXAMPLE_MAP='{}'
BUILD_FILTERED='false'
- FAM_REGEX=''
+ FAMILY_REGEX=''
if [ -n "$BUILD_SELECT_FILE" ]; then
EXAMPLE_MAP=$(jq -c '.build.family_examples // {}' "$BUILD_SELECT_FILE") || EXAMPLE_MAP='{}'
BUILD_FILTERED=$(jq -r 'if (.build? | type) == "object" and .build.full == false then "true" else "false" end' "$BUILD_SELECT_FILE") || BUILD_FILTERED='false'
if [ "$BUILD_FILTERED" = "true" ]; then
- FAM_REGEX=$(jq -r '.build.families | join("|")' "$BUILD_SELECT_FILE") || FAM_REGEX=''
+ FAMILY_COUNT=$(jq -r '.build.families | length' "$BUILD_SELECT_FILE") || FAMILY_COUNT=0
+ FAMILY_REGEX=$(jq -r '.build.families | join("|")' "$BUILD_SELECT_FILE") || FAMILY_REGEX=''
# family names come from hw/bsp dir names, which rule 6 reads straight out
# of the PR's diff path - and this is interpolated raw into a
# `name_is_regexp` artifact pattern, so a regex metacharacter there would
# silently match another family's baseline
- case "$FAM_REGEX" in
+ FAMILY_REJECTED=0
+ case "$FAMILY_REGEX" in
*[!-A-Za-z0-9_\|]*)
echo "::warning::unexpected characters in the family list - dropping the scoping"
- FAM_REGEX='' ;;
+ FAMILY_REGEX=''; FAMILY_REJECTED=1 ;;
esac
- if [ -z "$FAM_REGEX" ]; then
- # all three drop together, as CircleCI's fall-open does. Resetting only
+ # An EMPTY families list and a REJECTED one both leave FAMILY_REGEX empty and
+ # mean opposite things, so branch on which happened. Testing `-z` alone sent
+ # every nothing-selected PR down the fall-open path: a docs/.gitignore diff
+ # (#3842) and a test/hil-only diff (#3840) each rebuilt all 74 cmake legs
+ # after the selector had correctly chosen none.
+ if [ "$FAMILY_REJECTED" = "1" ]; then
+ # unusable: fall open, and all three drop together. Resetting only
# build_filtered leaves the build scoped while code-metrics takes the
# UNSCOPED branch, diffing a 1-family run against the full averaged
# baseline and publishing that as the PR's code-size impact.
BUILD_FILTERED='false'
EXAMPLE_MAP='{}'
MATRIX_JSON=$(python .github/scripts/ci_set_matrix.py)
+ elif [ "$FAMILY_COUNT" = "0" ]; then
+ # legitimate nothing-selected. MATRIX_JSON already holds the all-empty
+ # matrix ci_set_matrix produced from this selection - keep it, so every
+ # leg skips. Nothing is built, so there is nothing to compare a baseline
+ # against: build_filtered goes false to keep code-metrics off the scoped
+ # path, and EXAMPLE_MAP stays '{}' (family_examples is empty anyway).
+ BUILD_FILTERED='false'
fi
fi
fi
@@ -210,7 +220,7 @@ jobs:
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
echo "example_map=$EXAMPLE_MAP" >> $GITHUB_OUTPUT
echo "build_filtered=$BUILD_FILTERED" >> $GITHUB_OUTPUT
- echo "build_families_regex=$FAM_REGEX" >> $GITHUB_OUTPUT
+ echo "build_families_regex=$FAMILY_REGEX" >> $GITHUB_OUTPUT
# HIL matrix (merged from tinyusb + hifiphile configs), scoped on PRs.
# Scoping is best-effort too: fall back to the unscoped (full) matrix.
diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml
index 52999616d..407ed1e71 100644
--- a/.github/workflows/build_util.yml
+++ b/.github/workflows/build_util.yml
@@ -126,16 +126,11 @@ jobs:
MEMBROWSE_API_KEY: ${{ secrets.MEMBROWSE_API_KEY }}
run: |
# if code-changed is false --> there is no elf -> membrowse target upload with --identical flag
- # $EX_ARGS is passed for the BOARD it picks, not to scope the targets:
- # --one-first now chooses a board that can build the -e set (tools/build.py),
- # so omitting it here would configure a DIFFERENT, empty build dir and upload
- # --identical for a board that was never compiled. The target list is not
- # scoped by it - `examples-membrowse-upload` is not `all`, so it passes
- # through as the aggregate, which has no DEPENDS (hw/bsp/family_support.cmake):
- # it rebuilds nothing and still records every example, --identical for the
- # ones without an elf.
+ # deliberately unscoped by $EX_ARGS: keeps the size history on a stable board
+ # per family, at the cost of an --identical-only upload where that board is not
+ # the one the Build step picked (test_ci_metrics pins which families those are)
BUILD_PY_ARGS="-s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }}"
- python tools/build.py $BUILD_PY_ARGS --target examples-membrowse-upload -j 1 ${{ matrix.arg }} $EX_ARGS
+ python tools/build.py $BUILD_PY_ARGS --target examples-membrowse-upload -j 1 ${{ matrix.arg }}
shell: bash
- name: Upload Artifacts for Metrics