Skip to content

perf(ci): run shared-code changes against a core board set, not all 80 - #1397

Merged
zackees merged 2 commits into
mainfrom
perf/1396-reduce-ci-builders
Aug 24, 2026
Merged

perf(ci): run shared-code changes against a core board set, not all 80#1397
zackees merged 2 commits into
mainfrom
perf/1396-reduce-ci-builders

Conversation

@zackees

@zackees zackees commented Aug 24, 2026

Copy link
Copy Markdown
Member

Problem

ci/ci_common_paths.txt force-runs every per-board workflow. Its own guidance says so deliberately:

Bias: be BROAD here. A safety-net force-run on every common-code edit is the right trade vs. missing a regression that only a board build catches.

That trade has stopped paying. The list includes crates/fbuild-core/**, crates/fbuild-cli/**, crates/fbuild-paths/**, the workspace manifest and lockfile, and more — so a one-line edit almost anywhere schedules all 80 board builds, ~94 checks per PR.

Combined with strict: true branch protection this compounds: every merge makes every other open PR out-of-date, each then needs a fresh ~20-minute full sweep, and the queue serializes. Observed directly across a 14-PR session — wall-clock was dominated by re-running board builds for changes that could not affect them.

Shape of the fix

The machinery already exists (#835): ci/render_workflows.py renders each board's on: paths: from ci/board_families.json + ci/ci_common_paths.txt, and nightly-platforms.yml already sweeps everything daily.

What is missing is a core set. Proposal:

  • Core boards — one representative per family, two where a family spans distinct toolchains (ESP32 Xtensa vs RISC-V, STM32 F1/M3 vs H7/M7, SAM M3 vs M4, Teensy M4 vs M7). Shared-code paths run these.
  • Every other board — triggers only on its own test dir, its family's crate paths, and its own workflow file. Family-specific work keeps full family coverage.
  • Nightly covers all 80 as the safety net, moved to 3am local.

Also: hw-ci.yml is pull_request-triggered but has no concurrency block, so pushing to a PR branch queues another hardware run behind the old one instead of superseding it. It is the only PR-triggered workflow missing that guard — and it matters more there than anywhere else, because those jobs occupy a physical board.

Measured effect

change before after
fbuild-core one-liner 80 17
fbuild-cli change 80 17
workspace lockfile bump 80 17
ESP32 orchestrator change 9 9
Teensy linker change 8 8
docs only 0 0

Platform-specific coverage is unchanged; only the shared-code blast radius shrinks.

Summary by CodeRabbit

  • CI Improvements

    • Build workflows now run only when their board-specific tests, platform code, or workflow configuration changes.
    • Pull-request hardware runs can be canceled when superseded, reducing redundant execution.
    • Common-code changes now rely on core-board checks and nightly platform coverage.
  • Scheduling

    • Nightly platform checks now run at 11:00 UTC.
  • Configuration

    • Board metadata and CI path guidance were reformatted and clarified.
    • Core-board classifications were updated for selected platforms.

Closes #1396.

`ci/ci_common_paths.txt` force-ran every per-board workflow, by design — its
guidance said "be BROAD here". With `crates/fbuild-core/**`,
`crates/fbuild-cli/**`, the workspace manifest and lockfile all on that list,
a one-line edit almost anywhere scheduled all 80 board builds, ~94 checks per
PR.

Under `strict: true` branch protection that compounds: every merge makes every
other open PR out-of-date, each needs a fresh full sweep, and the queue
serializes behind board builds for changes that cannot affect them.

## What changed

The render pipeline from #835 already had the right shape; it was missing a
core set. `ci/board_families.json` entries can now carry `"core": true`, and
`render_paths_for_board` applies the common paths only to those.

17 core boards, covering all 13 families. Two where a family spans genuinely
different toolchains rather than different board JSON:

  esp32   esp32dev (Xtensa) + esp32c3 (RISC-V)
  stm32   stm32f103c8 (F1/M3) + stm32h747xi (H7/M7)
  sam     due (SAM3X/M3) + samd51p (M4)
  teensy  teensy30 (M4) + teensy41 (M7)

Every other board still triggers on its own test dir, its family's crate
paths, and its own workflow file — so family-specific work keeps full family
coverage. The nightly sweep still runs all 80, moved from 09:00 to 11:00 UTC
(3am PST) as the safety net.

Measured, by replaying path filters against realistic diffs:

  fbuild-core one-liner       80 -> 17
  fbuild-cli change           80 -> 17
  workspace lockfile bump     80 -> 17
  ESP32 orchestrator change    9 ->  9
  Teensy linker change         8 ->  8
  docs only                    0 ->  0

## Also

`hw-ci.yml` was the one `pull_request`-triggered workflow with no
`concurrency` block, so pushing to a PR branch queued a second hardware run
behind the first instead of superseding it. That is worse there than
elsewhere: the job holds a physical board, so a superseded run occupies
hardware nobody is waiting on. Non-PR events key on `run_id` so scheduled
sweeps never cancel each other, matching the rendered per-board blocks.

Both source-of-truth comments are updated: being broad in `ci_common_paths`
is still correct, it now costs 17 workflows rather than 80.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e2033075-f785-4f46-9237-882faee24931

📥 Commits

Reviewing files that changed from the base of the PR and between 0d2ed4c and 6fbf26d.

📒 Files selected for processing (82)
  • .github/workflows/build-apollo3_red.yml
  • .github/workflows/build-apollo3_thing_explorable.yml
  • .github/workflows/build-atmega8.yml
  • .github/workflows/build-atmega8a.yml
  • .github/workflows/build-attiny1604.yml
  • .github/workflows/build-attiny1616.yml
  • .github/workflows/build-attiny4313.yml
  • .github/workflows/build-attiny85.yml
  • .github/workflows/build-attiny88.yml
  • .github/workflows/build-blackpill.yml
  • .github/workflows/build-bluepill.yml
  • .github/workflows/build-ch32l103.yml
  • .github/workflows/build-ch32v003.yml
  • .github/workflows/build-ch32v006.yml
  • .github/workflows/build-ch32v103.yml
  • .github/workflows/build-ch32v203.yml
  • .github/workflows/build-ch32v208.yml
  • .github/workflows/build-ch32v303.yml
  • .github/workflows/build-ch32v307.yml
  • .github/workflows/build-ch32x035.yml
  • .github/workflows/build-clearcore.yml
  • .github/workflows/build-due.yml
  • .github/workflows/build-esp32c2.yml
  • .github/workflows/build-esp32c3.yml
  • .github/workflows/build-esp32c5.yml
  • .github/workflows/build-esp32c6.yml
  • .github/workflows/build-esp32h2.yml
  • .github/workflows/build-esp32p4.yml
  • .github/workflows/build-esp32s2.yml
  • .github/workflows/build-esp32s3.yml
  • .github/workflows/build-esp8266.yml
  • .github/workflows/build-giga-r1.yml
  • .github/workflows/build-leonardo.yml
  • .github/workflows/build-lpc804.yml
  • .github/workflows/build-lpc845.yml
  • .github/workflows/build-lpc845brk.yml
  • .github/workflows/build-lpcxpresso804.yml
  • .github/workflows/build-lpcxpresso845max.yml
  • .github/workflows/build-matrix_portal_m4.yml
  • .github/workflows/build-mgm240.yml
  • .github/workflows/build-nano-every.yml
  • .github/workflows/build-nano_every.yml
  • .github/workflows/build-nice_nano_nrf52840.yml
  • .github/workflows/build-nrf52840-sense.yml
  • .github/workflows/build-nrf52840_dk.yml
  • .github/workflows/build-nrfmicro_nrf52840.yml
  • .github/workflows/build-nucleo-f429zi.yml
  • .github/workflows/build-nucleo-f439zi.yml
  • .github/workflows/build-nucleo_f429zi.yml
  • .github/workflows/build-nucleo_f439zi.yml
  • .github/workflows/build-qtpy_m0.yml
  • .github/workflows/build-rp2040.yml
  • .github/workflows/build-rp2350.yml
  • .github/workflows/build-rpipico.yml
  • .github/workflows/build-rpipico2.yml
  • .github/workflows/build-sam3x8e_due.yml
  • .github/workflows/build-samd21.yml
  • .github/workflows/build-samd21_zero.yml
  • .github/workflows/build-samd51j.yml
  • .github/workflows/build-samd51p.yml
  • .github/workflows/build-stm32f103c8.yml
  • .github/workflows/build-stm32f103cb.yml
  • .github/workflows/build-stm32f103tb.yml
  • .github/workflows/build-stm32f411ce.yml
  • .github/workflows/build-stm32h747xi.yml
  • .github/workflows/build-supermini_nrf52840.yml
  • .github/workflows/build-teensy30.yml
  • .github/workflows/build-teensy31.yml
  • .github/workflows/build-teensy32.yml
  • .github/workflows/build-teensy35.yml
  • .github/workflows/build-teensy36.yml
  • .github/workflows/build-teensy40.yml
  • .github/workflows/build-teensylc.yml
  • .github/workflows/build-thingplusmatter.yml
  • .github/workflows/build-tinystm.yml
  • .github/workflows/build-uno-r4-wifi.yml
  • .github/workflows/build-uno_r4_wifi.yml
  • .github/workflows/hw-ci.yml
  • .github/workflows/nightly-platforms.yml
  • ci/board_families.json
  • ci/ci_common_paths.txt
  • ci/render_workflows.py

📝 Walkthrough

Walkthrough

The change narrows board workflow triggers to board-specific paths, marks three boards as core for shared-path changes, updates workflow rendering, adds pull-request run cancellation, and moves the nightly platform schedule to 11:00 UTC.

Changes

Workflow trigger scoping

Layer / File(s) Summary
Core board metadata and workflow rendering
ci/board_families.json, ci/ci_common_paths.txt, ci/render_workflows.py
Three boards are marked as core. Common paths now trigger only core board workflows.
Board-specific workflow path filters
.github/workflows/build-*.yml
Board workflows now monitor platform tests, build sources, and their own workflow files. Broad repository path filters were removed.
Hardware run concurrency and nightly scheduling
.github/workflows/hw-ci.yml, .github/workflows/nightly-platforms.yml, ci/render_workflows.py
Superseded pull-request hardware runs are canceled. The nightly schedule moves from 09:00 UTC to 11:00 UTC.

Estimated code review effort: 3 (Moderate) | ~20 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/1396-reduce-ci-builders

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Follow-up on #1396. The first pass picked 17 core boards — one
per family, two where a family spans distinct toolchains. That is more
coverage than shared code needs.

Shared-code changes now run three boards:

  uno       AVR      (avr-gcc)
  esp32dev  ESP32    (Xtensa)
  teensy41  Teensy   (ARM)

One per toolchain family a shared-code change can plausibly break. All three
already run on ubuntu-latest and already share one soldr build cache — the
`cache-key-suffix: fbuild-rust-debug` in template_build.yml is
board-independent by design, so the Rust rebuild happens once and the other
two hit it rather than rebuilding.

Measured against realistic diffs:

  fbuild-core one-liner    80 -> 3
  fbuild-cli change        80 -> 3
  workspace lockfile bump  80 -> 3
  ESP32 orchestrator        9 -> 9
  teensy linker             8 -> 8
  AVR mcu change           11 -> 11

Family-specific coverage is untouched: an ESP32 change still runs all nine
ESP32 boards. Everything else is covered by the nightly sweep at 3am.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@zackees
zackees merged commit ea2a8ff into main Aug 24, 2026
8 of 97 checks passed
@zackees
zackees deleted the perf/1396-reduce-ci-builders branch August 24, 2026 01:55
@fastled-project-sync fastled-project-sync Bot moved this to Triage in FastLED Tracker Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

1 participant