summaryrefslogtreecommitdiff
path: root/.github
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-08-21 12:41:47 +0700
committerhathach <[email protected]>2026-08-21 12:41:47 +0700
commite13eff8d4e757ebe7709a58fce44017b8be5a84d (patch)
tree32073e11437e057d92ff843290d3a5594c86d528 /.github
parentf96ddbaa1e11a98f8076df48ba73026191c28399 (diff)
ci: fix nine ways the selection under-selected or mismatched
Every one of these dropped coverage silently - the worst failure mode here, because the PR still goes green. Found by review, each reproduced first. Selection rules: * class_macros derived the config macro from the class DIRECTORY, so a change to src/class/midi/midi2_device.c selected the midi_test examples (which do not compile it) and never examples/device/midi2_device (the only one that enables CFG_TUD_MIDI2, and the only one that does). The file's own macro is unioned in where it differs - union, never replace: over-selecting costs a build, under-selecting merges a break. * the ${FAMILY_MCUS} fallback added for espressif fired on any family whose _family_mcus came back empty, and _cmake_sets is if()-blind and keeps the FIRST definition - so mcx/frdm_mcxn947 answered MCXA15, a token six examples' skip.txt names, dropping 12 firmware images CMake builds. Limited now to families that never spell set(FAMILY_MCUS ...) at all. * lib_examples read only an example's top-level CMakeLists.txt/Makefile; host/msc_file_explorer_freertos names lib/embedded-cli in src/CMakeLists.txt and survived by luck. The whole example tree is scanned. (SEGGER_RTT and rt-thread still resolve to nothing: all three references sit inside a LOGGER=rtt guard no CI build sets - the documented ruling, not a miss.) * get_family_boards applied ci_skip_boards/ci_preferred_boards only under GITHUB_ACTIONS/CIRCLECI, so the selector answered differently on a laptop than on a runner; _prune_buildable forces CI semantics. Its one-board pick also abandoned the whole preferred list when entry one could not build the -e set, and asked skip_example without the build's -D tokens. * _config_enables and lib_examples still read with the locale encoding - under LC_ALL=C the selector tracebacked on three tracked tusb_config.h files. The whole selector and its suite run clean there now. Workflows: * the Membrowse Upload step omitted $EX_ARGS, but --one-first now picks the board from the -e set, so it configured a different, empty build dir and uploaded --identical for a board never compiled. It takes $EX_ARGS for the BOARD; the target stays the aggregate, which has no DEPENDS and still records every example. * blanking FAM_REGEX reset only build_filtered, leaving the build scoped while code-metrics took the UNSCOPED branch and diffed a 1-family run against the full averaged baseline. All three drop together now, as CircleCI's fall-open does. * CircleCI's EX_ARGS had no character screen and is used unquoted, and its code-metrics job still exit 1'd on an empty metrics set - which a scoped build makes a legitimate outcome. * a `ci-full` PR label now turns the scoping off for one PR. A selector bug under-selects silently, and without a label the only ways back to a full matrix are accidental. Performance, since the selector gates every other job: family.cmake texts are read once rather than per changed directory (a 6,000-file dep bump re-read 84 files 99,892 times) and _scrape_mcu is cached: 2.2s -> 0.29s there, 0.8s -> 0.33s on a class diff. Tests: a drift guard for hw/bsp families absent from ci_set_matrix.family_list (they select zero legs now, where they used to ride the full matrix); the rule-4 port test asserted a SUBSET, which set() satisfies, so it could not fail on the empty selection it exists to catch; the GITHUB_ENV guard test counted a SUM of two guards. Drops metrics.py's --only-examples, which nothing called, and applies the TOTAL scrub to the by-example branch that skipped it.
Diffstat (limited to '.github')
-rw-r--r--.github/workflows/build.yml24
-rw-r--r--.github/workflows/build_util.yml16
2 files changed, 28 insertions, 12 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2ee124cb3..39a4e7afd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -68,9 +68,14 @@ 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'
+ if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'ci-full')
env:
BASE_REF: ${{ github.base_ref }}
run: |
@@ -166,8 +171,6 @@ jobs:
fi
fi
[ -z "$MATRIX_JSON" ] && MATRIX_JSON=$(python .github/scripts/ci_set_matrix.py)
- echo "matrix=$MATRIX_JSON"
- echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
# Build-axis extras: the per-family example map rides as a side channel
# (a value inside matrix entries would break CircleCI's family parameter
@@ -188,12 +191,23 @@ jobs:
# silently match another family's baseline
case "$FAM_REGEX" in
*[!-A-Za-z0-9_\|]*)
- echo "::warning::unexpected characters in the family list - unscoped metrics"
+ echo "::warning::unexpected characters in the family list - dropping the scoping"
FAM_REGEX='' ;;
esac
- [ -z "$FAM_REGEX" ] && BUILD_FILTERED='false'
+ if [ -z "$FAM_REGEX" ]; then
+ # all three drop together, as CircleCI's fall-open does. 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)
+ fi
fi
fi
+ # emitted once, after every path that can still change it
+ echo "matrix=$MATRIX_JSON"
+ 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
diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml
index dfbd83ee2..52999616d 100644
--- a/.github/workflows/build_util.yml
+++ b/.github/workflows/build_util.yml
@@ -126,14 +126,16 @@ jobs:
MEMBROWSE_API_KEY: ${{ secrets.MEMBROWSE_API_KEY }}
run: |
# if code-changed is false --> there is no elf -> membrowse target upload with --identical flag
- # Deliberately NOT scoped by $EX_ARGS: <TARGET>-membrowse-upload has no
- # DEPENDS (hw/bsp/family_support.cmake), so the aggregate rebuilds nothing -
- # it just records every example, reporting the ones with an elf and
- # --identical for the rest. Filtering it here would drop the excluded
- # examples from the dataset membrowse-comment.yml reports against, instead
- # of recording them as unchanged.
+ # $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.
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 }}
+ python tools/build.py $BUILD_PY_ARGS --target examples-membrowse-upload -j 1 ${{ matrix.arg }} $EX_ARGS
shell: bash
- name: Upload Artifacts for Metrics