-
Notifications
You must be signed in to change notification settings - Fork 2
ci(cache): add a ci.toml declaring fbuild's cache ceiling (8.73 GiB = 87% of the 10 GiB cap) #1652
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| # ci.toml — FastLED/fbuild's CI contract. Checked and planned by ci-lint | ||
| # (zackees/ci.yml). Nothing here generates YAML: it bounds what the YAML may | ||
| # do and decides what each run selects. | ||
| # | ||
| # This file is CACHE-ONLY policy. fbuild already runs 90+ workflows of its | ||
| # own shape (one per board, plus acceptance/bench/qemu lanes); those are not | ||
| # rewritten here. What this declares is the ceiling on the repository's | ||
| # Actions cache, which as of 2026-10-05 sat at 8.73 GiB of GitHub's 10 GiB | ||
| # cap across 43 entries -- 87% -- with no declared bound at all, so nothing | ||
| # could tell the janitor what to keep and what to trim. | ||
| # | ||
| # Sizing rule used throughout: every `max` is at or above the largest entry | ||
| # MEASURED live in this repository, and every `max x cardinality` product is | ||
| # at or above the family's measured live total. Over-stating costs headroom; | ||
| # under-stating makes `ci-lint cache janitor` delete live caches. | ||
| schema = 3 | ||
| profile = "fbuild-cache-policy" | ||
| linter = "zackees/ci.yml@92106df315bd28de24ef1808c893c91a5859122d" | ||
|
|
||
| # ── Platforms ──────────────────────────────────────────────────────────────── | ||
| # The runner labels and target triples fbuild's own release/build workflows | ||
| # actually use. `ubuntu-latest` / `windows-latest` are the pinned aliases for | ||
| # the fleet-pinned `ubuntu-24.04` / `windows-2025` labels; see the PR body. | ||
| [platforms] | ||
| linux-x64 = { target = "x86_64-unknown-linux-musl", runs-on = "ubuntu-24.04", group = "linux" } | ||
| linux-arm64 = { target = "aarch64-unknown-linux-musl", runs-on = "ubuntu-24.04-arm", group = "linux" } | ||
| # CT-006 requires [platforms].*.target to equal Cargo.toml's | ||
| # [workspace.metadata.soldr].targets exactly. Soldr builds BOTH a musl and a | ||
| # gnu target per Linux arch, so declaring only musl understated the compile | ||
| # family's cardinality by two. See the note on `compile` below: the extra | ||
| # platforms are what push it over the cap. | ||
| linux-x64-gnu = { target = "x86_64-unknown-linux-gnu", runs-on = "ubuntu-24.04", group = "linux" } | ||
| linux-arm64-gnu = { target = "aarch64-unknown-linux-gnu", runs-on = "ubuntu-24.04-arm", group = "linux" } | ||
| windows-x64 = { target = "x86_64-pc-windows-msvc", runs-on = "windows-2025", group = "windows" } | ||
| windows-arm64 = { target = "aarch64-pc-windows-msvc", runs-on = "windows-11-arm", group = "windows" } | ||
| macos-arm64 = { target = "aarch64-apple-darwin", runs-on = "macos-15", group = "macos" } | ||
| macos-x64 = { target = "x86_64-apple-darwin", runs-on = "macos-15-intel", group = "macos" } | ||
|
|
||
| # ── Suites ─────────────────────────────────────────────────────────────────── | ||
| # fbuild's real entry points under ci/. Each id generates [ci-test-<id>] and | ||
| # [no-test-<id>]. | ||
| [suites] | ||
| unit = { run = "uv run ci/test.py", required = true } | ||
| lint = { run = "uv run ci/lint.py", required = true } | ||
| dylint = { run = "uv run ci/run_dylint.py" } | ||
| board-build = { run = "uv run ci/trampoline.py" } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '30,63p' ci.tomlRepository: FastLED/fbuild Length of output: 1463 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '--- checkout ---'
git rev-parse --show-toplevel
git rev-parse --verify 7f3081d99484fad5cda73e263508c65ee8441e6f^{commit}
git rev-parse --verify a03aaa5ffaf82b5cdc9f951595a5f8fe2d7f5606^{commit}
printf '%s\n' '--- focused diff ---'
git diff --find-renames a03aaa5ffaf82b5cdc9f951595a5f8fe2d7f5606 7f3081d99484fad5cda73e263508c65ee8441e6f -- ci.toml ci/trampoline.py
printf '%s\n' '--- target path and CI files ---'
if test -f ci/trampoline.py; then
nl -ba ci/trampoline.py
else
echo 'ci/trampoline.py is absent in the working tree'
fi
rg --files ci | sort
printf '%s\n' '--- trampoline references and script configuration ---'
rg -n -F -- 'trampoline.py' .
rg -n -- '(\[project\.scripts\]|\[tool\.uv\.scripts\]|ci/test\.py|ci/lint\.py|ci/run_dylint\.py)' pyproject.toml uv.toml ci.toml ci 2>/dev/null || test "$?" -eq 1Repository: FastLED/fbuild Length of output: 14353 Make
🤖 Prompt for AI Agents |
||
|
|
||
| # ── Flows ──────────────────────────────────────────────────────────────────── | ||
| [flow.pr] # every PR push; tags compose on top | ||
| platforms = ["linux-x64"] | ||
| suites = ["unit", "lint"] | ||
| dylint = "all-platforms" | ||
| budget = { critical-path = "30m" } | ||
|
|
||
| [flow.main] | ||
| extends = "pr" | ||
| cache = "write" | ||
| # CACHE-004: without pre-prune the worst case carries the lockfile-change peak | ||
| # on top of steady state. See the arithmetic in the PR body. | ||
| pre-prune = true | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| [flow.release] | ||
| platforms = "all" | ||
| suites = "all" | ||
| publish = "pypi" | ||
|
|
||
| # ── Tags that are not derived ──────────────────────────────────────────────── | ||
| [tags] | ||
| ci-full = { add = { platforms = "all", suites = ["board-build"] } } | ||
| ci-native = { add = { platforms = ["linux-x64", "linux-arm64"] } } | ||
|
|
||
| # ── Caches ─────────────────────────────────────────────────────────────────── | ||
| # Measured 2026-10-05 (read-only GET, 43 entries, 8.73 GiB = 87% of the 10 GiB | ||
| # cap). Per-family live totals and maxima are in the PR body; every number | ||
| # below is at or above its measurement. | ||
| [cache] | ||
| budget = "9.5GB" # 9728 MB. Measured steady state 8941 MB. | ||
| write-on = ["main", "release"] # base layers: default branch only | ||
| never = ["linked-tests", "nextest-archives", "wheels", "incremental", "target-dir", "perf-results"] | ||
| retired = ["cook-delta-v2"] | ||
| # fbuild's PR pushes add no cache entries of their own: the composite action's | ||
| # `save` input is the switch for that, and PR runs restore only. | ||
| pr = { mode = "none", families = [], max-per-pr = "0MB", budget = "0MB", trim = "on-close" } | ||
|
|
||
| [cache.family] | ||
| # setup-soldr's build cache. THE dominant family: 19 live entries, 7883 MB | ||
| # (7.34 GiB) -- 16 linux-x64 job shapes (largest 808 MB), 2 macos (614 MB), | ||
| # 1 windows (986 MB). 7518 MB of that is on refs/heads/main. | ||
| # | ||
| # `max` x cardinality(per) is the janitor's LRU budget, and it must be at or | ||
| # above the family's measured live bytes or `ci-lint cache janitor` deletes a | ||
| # live cache: 1300 MB x 6 platforms = 7800 MB >= 7518 MB measured. | ||
| # | ||
| # The 19 live entries are 19 distinct WRITER SHAPES (acceptance-205-*, | ||
| # bench-205-*, python-facades, qemu-linux-runtime, native-*, dylint-unified, | ||
| # fbuild-rust-debug, check-ubuntu-py312), only 6 of which are platforms. So the | ||
| # entry-COUNT model (6 x 2 = 12) is narrower than reality and the live audit | ||
| # reports CACHE-004 `needs_review` for this family. That is left in place | ||
| # deliberately: the byte proof holds (7518 MB live <= 7800 MB declared) and | ||
| # the shortfall is a real modelling gap, not something to paper over. Widening | ||
| # it needs a `per` axis for job shape -- which schema 3 DOES have, as | ||
| # `shapes` (zackees/ci.yml#334, added for running-process's ~1.25 GiB shapes). | ||
| # | ||
| # `per = "platform"` was the wrong model and CT-006 exposed it. Soldr declares | ||
| # FOUR Linux targets (musl + gnu, per Cargo.toml's | ||
| # [workspace.metadata.soldr].targets), so the real cardinality is 8, and | ||
| # 1300 MB x 8 = 10.4 GB -- over the cap. But no live entry corresponds to a | ||
| # gnu target at all: the 19 entries are 19 distinct WRITER SHAPES, and only | ||
| # one names a target triple (`native-aarch64-unknown-linux-musl`, 453 MB). | ||
| # Multiplying one ceiling by the platform count modelled writer shapes as | ||
| # platforms and papered over the gap. | ||
| # | ||
| # `shapes` is the measured truth -- one ceiling per writer shape, sized from | ||
| # the live listing so the janitor's LRU budget stays at or above real bytes. | ||
| compile = { via = "setup-soldr:build-cache", max = "1300MB", lockfile = true, per = "platform", min = "1MB", evict = "lru", shapes = { "check-windows-check" = { max = "1000MB" }, "check-ubuntu-py312" = { max = "820MB" }, "fbuild-rust-debug" = { max = "650MB" }, "check-macos-test" = { max = "620MB" }, "native-aarch64-unknown-linux-musl" = { max = "460MB" }, "native-aarch64-apple-darwin" = { max = "400MB" }, "benchmark-build-comparison" = { max = "350MB" }, "dylint-unified" = { max = "340MB" }, "acceptance-205" = { max = "340MB" }, "esp32s3-size-parity" = { max = "245MB" }, "bench-205-resolve" = { max = "230MB" }, "qemu-linux-runtime" = { max = "220MB" }, "python-facades" = { max = "200MB" }, "bench-205-scan-throughput" = { max = "180MB" } } } | ||
| # Cargo registry: 2 live entries, 480 MB total, largest 294 MB. Lockfile-keyed. | ||
| registry = { via = "setup-soldr:cargo-registry", max = "500MB", lockfile = true, per = "none", min = "1MB", evict = "lru" } | ||
| # Dylint tool/driver/foundation: 1 live entry, 589 MB. | ||
| dylint = { via = "setup-soldr:dylint", max = "600MB", lockfile = true, per = "none", min = "1MB", evict = "lru" } | ||
| # Solo toolchain: 2 live entries (v0.9.27, v0.9.29), 343 MB total. Retired in | ||
| # the reference template, but LIVE here -- declared, not retired. | ||
| solo = { via = "setup-soldr:solo-toolchain", max = "350MB", lockfile = true, per = "none", min = "1MB", evict = "lru" } | ||
| mini = { via = "setup-soldr:soldr-mini", max = "50MB", lockfile = true, per = "none", min = "1MB" } | ||
|
|
||
| # setup-soldr's thin target cache (setup-soldr-targetcache-thin-v2-*) is NOT | ||
| # declared here: ci-lint has no `via` value for that prefix. It is 18 live | ||
| # entries totalling 3.7 KB -- four orders of magnitude below the noise floor, | ||
| # so it costs no budget and would misrepresent the family table if faked. | ||
|
|
||
| # Nearest-ancestor promotion is NOT available. `[cache.promote] mode = "off"`. | ||
| [cache.promote] | ||
| mode = "off" | ||
|
|
||
| # ── Local (bosn -> act) ────────────────────────────────────────────────────── | ||
| # No `[local.gate.*]` keys: fbuild ships no local-gate.toml and no declared | ||
| # local gate, and an incomplete `[local.gate]` would make `ci-lint local-gate` | ||
| # demand one. `ci_lint.gate_isolation` still applies -- fbuild's own suite is | ||
| # self-hosted tooling and must not run on a developer host. | ||
| [local] | ||
| runner = "bosn" | ||
| lanes = ["unit", "lint"] | ||
| cache = "off" | ||
|
|
||
| # ── Allow ──────────────────────────────────────────────────────────────────── | ||
| [allow.workflows] | ||
| "ci-minimal.yml" = ["unit", "lint"] | ||
| "ci-full.yml" = ["unit", "lint", "dylint", "board-build"] | ||
| "ci-test.yml" = ["unit", "lint", "dylint", "board-build"] | ||
|
|
||
| [allow] | ||
| actions = [] | ||
| tools = [] | ||
| secrets = [] | ||
| platform-selector = "python3 ci/select_boards.py" | ||
| platform-code = ["ci/select_boards.py"] | ||
|
|
||
| [allow.setup-soldr] | ||
| only-in = ".github/actions/setup" | ||
|
|
||
| [allow.cache-actions] | ||
| # The composite action .github/actions/setup/action.yml is fbuild's one | ||
| # sanctioned raw actions/cache* location (it owns the fbuild install, | ||
| # packages, and build-payload caches). | ||
| only-in = ".github/actions/setup" | ||
|
|
||
| [allow.permissions] | ||
| "release-auto.yml" = ["contents", "id-token"] | ||
|
|
||
| # ── Publish ────────────────────────────────────────────────────────────────── | ||
| [publish.pypi] | ||
| auth = "oidc" | ||
| environment = "pypi" | ||
| mode = "rehearsal" | ||
Uh oh!
There was an error while loading. Please reload this page.