v0.27.35 - A Couple New Knobs
Pre-release
Pre-release
Changes in v0.27.35 — collection.skip_largest_percent: the temporary large-repo skip switch
- Knob:
collection.skip_largest_percent(float, default 0 =
off;0.5= skip the top 0.5%). "Largest" = forge-reported
repo_info.commit_countORpr_countat/above the fleet's
(1−N/100) percentile — EITHER measure qualifies. Repos never
measured (no repo_info snapshot) are NEVER skipped: an unknown
repo must collect so it can be measured. Misconfiguration
(negative, ≥100) collapses to disabled, never to a surprise clamp. - Mechanism:
db.LargestRepoIDs(fraction)(percentile_cont over
the latest-snapshot-only repo_info, ~94K rows, one cheap query)
→ scheduler caches the id set 6 hours (largeRepoExclusions;
refresh horizon derived from the multi-day re-measure cadence;
failed refresh keeps the previous set) →DequeueNextgains an
excludeRepoIDs []int64param (NOT (repo_id = ANY($2)), nil
coerced to empty — the= ANY(NULL)-yields-NULL trap from
v0.27.4). Effective-value log on every refresh: repos_excluded +
the actual commit/pr thresholds in force. - Semantics: skipped repos stay 'queued', overdue, untouched —
remove the knob + restart serve and they collect immediately.
In-flight jobs are never affected. The gate is ABSOLUTE while
enabled (monitor Boost cannot override — documented; disable the
knob to force-collect a monster). Knob off = zero overhead (helper
returns before any store access, pinned by test). - Tests: SQL-shape + nil-coercion pins, fraction guard rails,
cascade integration (fleet-max repo always in the set at any
fraction; NULL-count repo never in it; DequeueNext exclusion
honored deterministically on the shared scratch via sub-fleet
priorities), config knob suite (percent→fraction + JSON surface +
frozen key), scheduler wiring pins + zero-cost-off behavioral.
No schema change. Unit + cascade + staticcheck green. - TRACKED FOLLOW-UP (operator-requested, not yet built):
investigate the pytorch/pytorch-class anomaly — a handful of very
large repos seem to NEVER complete without an error. Diagnose from
collection_queue.last_error history + the long-jobs watchdog dumps
before proposing fixes.
Changes in v0.27.34 — fleet-level GitHub API-outage circuit breaker (claims pause during hard 5xx storms)
- Breaker lives on the KeyPool (platform/ratelimit.go) — every
REST + GraphQL client for a platform shares the pool, so it is the
one place that sees the platform's 5xx behavior fleet-wide, and
gh/gl get independent breakers with zero new plumbing. Both 5xx
retry branches (httpclient.go + graphql.go — the storm was
GraphQL-dominated, a REST-only hook would have missed it) call
NoteServerError();UpdateFromResponse's 2xx branch closes the
breaker. - Consecutive-without-success is the trip signal
(APIOutageThreshold = 25attempts, ~2–3 requests' full retry
cycles): the measured storm had 58% per-retry success, and a
brownout like that must keep grinding through per-request backoff —
only a HARD outage (nothing succeeding anywhere) pauses the fleet.
ANY 2xx closes the breaker instantly and zeroes the counter. - The pause gates CLAIMS, never in-flight work:
fillWorkerSlotscheckss.ghKeys.APIHealthy()(after dbHealthy,
before the claim loop) and skips the tick while open, with
transition-only logging (apiClaimsPausedCAS — a 2-hour outage
logs two lines, not one per poll tick). In-flight jobs keep their
own retry/backoff and act as the PROBES: their first success
reopens everything.APIOutagePause = 10 minis a probe window,
not a sentence — while errors keep arriving at/above threshold the
pause keeps extending (a long outage stays paused with no timer
management); if traffic stops entirely, claims resume after the
window and 1–2 probe jobs re-trip it in seconds if the outage
persists. Nil pool (keyless deployment) = always healthy.
Deliberate simplification (documented in-code): queue claims are
not platform-filtered, so a GitHub outage also pauses the tiny
GitLab share. - Recovery of storm casualties needs nothing new: the 160 exhausted
jobs already carried force_full_collect=TRUE (54 rows still
pending at analysis time) via the v0.18.24/v0.20.5 plumbing. - Tests: threshold boundary, brownout-never-trips (the 58%-success
shape), success-closes-instantly + counter reset, pause-extension
under continued errors, probe-window expiry, nil-pool safety,
-race concurrency, dual-branch wiring pins, scheduler gate pin
(dbHealthy → APIHealthy → claim ordering + CAS transition logging).
No schema change. Unit + cascade + staticcheck green.
Changes in v0.27.33 — SPDX 2.3 conformance: the filesAnalyzed trap + suggested filename conventions
- filesAnalyzed (REAL non-conformance, fixed): SPDX 2.3 §7.8
defaults an OMITTED filesAnalyzed to TRUE, and §7.9 then makes
packageVerificationCode MANDATORY. generateSPDX emitted neither —
every package implicitly claimed its files were analyzed and then
failed to provide the mandatory verification code. spdxPackage now
carriesfilesAnalyzedwith NO omitempty (always emitted, always
false — we never analyze package files). The schema ground-truth
test gains the §7.8/§7.9 conditional-cardinality check the JSON
schema itself cannot express (prose rule): every package must
declare filesAnalyzed=false OR carry a verification code. - Filename conventions (SHOULD, adopted): SBOM downloads now use
the recognized extensions —sbom-repo-N.spdx.json(spec §4.4
suggested convention) andsbom-repo-N.cdx.json/
sbom-repo-N-with-vulns.cdx.json(CycloneDX's convention). - Everything else audited CONFORMANT: JSON serialization + UTF-8
(§4.4; the pgx tracer guarantees stored strings), all mandatory
document fields (SPDX-2.3 / CC0-1.0 / SPDXRef-DOCUMENT / name /
unique documentNamespace via per-doc uuid / created in the spec's
UTC format / "Tool: aveloxis-" creator form), package
mandatories (name, SPDXID, downloadLocation — NOASSERTION where
permitted), DESCRIBES relationship present, license fields valid
expressions or NOASSERTION (v0.27.29; optional in 2.3 anyway). - Also confirmed same-day for the operator: file-level license
tracking + presentation are intact — /scancode-licenses
(license → file_count aggregation) + /scancode-files (per-file
path/license/copyright) endpoints and the web GUI repo-detail
tables are untouched; the SPA has never rendered the per-file
tables (pre-existing gap, candidate parity work, not a
regression). Gap CLOSED same-day, GUI-side only (aveloxis-gui,
no backend change): home.html/home.js gain a "Source file
licenses (ScanCode)" section at the bottom of every repository
page — sortable path/license/copyright table (300-row initial
slice + Show-all for monorepos), freshness line from
/scancode-licenses (last_run + scancode version), JSON export,
jump-dropdown entry, and the two HONEST empty states: "ScanCode
has not run for this repository yet — it runs on its own worker
cadence" (last_run empty) vs "ScanCode ran on and found no
per-file detections" (ran, zero rows).
What's Changed
Full Changelog: v0.27.32...v0.27.35