|
| 1 | +================================================== |
| 2 | +New Features (2026-06-19) — SBOM & Suite Sharding |
| 3 | +================================================== |
| 4 | + |
| 5 | +Two pure-standard-library ops tools from the security and scale research |
| 6 | +angles, wired through the full stack (facade, ``AC_*`` executor commands, |
| 7 | +MCP tools, Script Builder): a **CycloneDX SBOM generator** and a |
| 8 | +**duration-aware suite sharder** (with shard-result merge). |
| 9 | + |
| 10 | +.. contents:: |
| 11 | + :local: |
| 12 | + :depth: 2 |
| 13 | + |
| 14 | + |
| 15 | +CycloneDX SBOM |
| 16 | +============= |
| 17 | + |
| 18 | +Supply-chain regulation (EU Cyber Resilience Act, US EO 14028) increasingly |
| 19 | +requires a machine-readable Software Bill of Materials. ``build_sbom`` walks |
| 20 | +the installed Python distributions and emits a **CycloneDX 1.6** JSON |
| 21 | +document — no third-party dependency:: |
| 22 | + |
| 23 | + from je_auto_control import build_sbom, write_sbom |
| 24 | + |
| 25 | + sbom = build_sbom("je_auto_control") # dependency closure of the pkg |
| 26 | + sbom = build_sbom(None) # every installed distribution |
| 27 | + write_sbom("sbom.cdx.json", "je_auto_control", |
| 28 | + extra_components=[{"type": "file", "name": "login.json", |
| 29 | + "version": "1"}]) |
| 30 | + |
| 31 | +Each component carries ``name`` / ``version`` / ``purl`` (``pkg:pypi/...``) |
| 32 | +and, when available, its license. ``extra_components`` lets you inventory |
| 33 | +action files alongside code. Exposed as ``AC_generate_sbom`` / |
| 34 | +``ac_generate_sbom``. |
| 35 | + |
| 36 | + |
| 37 | +Duration-aware suite sharding |
| 38 | +============================ |
| 39 | + |
| 40 | +Splitting a suite across N workers by *count* wastes time when tests differ |
| 41 | +in duration — the slowest worker defines wall-clock. ``shard_flows`` balances |
| 42 | +shards by **historical per-flow duration** from the run-history store using |
| 43 | +greedy bin-packing:: |
| 44 | + |
| 45 | + from je_auto_control import shard_flows, merge_results |
| 46 | + |
| 47 | + shards = shard_flows(all_flows, shards=4) # ~equal time per shard |
| 48 | + # ... each worker runs its shard, produces a report ... |
| 49 | + report = merge_results([shard_report_1, shard_report_2, ...]) |
| 50 | + |
| 51 | +Flows with no history fall back to the mean of known flows (so new tests |
| 52 | +spread evenly). ``merge_results`` recombines per-shard report dicts — summing |
| 53 | +``total`` / ``passed`` / ``failed`` / ``skipped`` / ``errors`` and |
| 54 | +concatenating ``results``. Exposed as ``AC_shard_suite`` / ``AC_merge_results`` |
| 55 | +(and ``ac_shard_suite`` / ``ac_merge_results``). |
0 commit comments