Skip to content

release-train: develop -> staging - #1035

Merged
tracebloc-release-train[bot] merged 3 commits into
stagingfrom
release-train/to-staging
Sep 10, 2026
Merged

release-train: develop -> staging#1035
tracebloc-release-train[bot] merged 3 commits into
stagingfrom
release-train/to-staging

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed release-train/to-staging branch (a mirror of develop), so it never collides with a human PR. Merged only when the fr-gate is green.


Note

Medium Risk
Touches registry selection, image-refresh reconcile guards, and default resource requests that affect scheduling and training fit; changes are heavily tested but alter production pull/update behavior on edges using ghcr.io or custom registries.

Overview
Chart 1.9.112 adds images.traceblocRegistry so tracebloc control-plane images (jobs-manager, pods-monitor, resource-monitor, requests-proxy) can be pulled from docker.io or ghcr.io without re-homing every image via global.imageRegistry. A shared tracebloc.tbRegistry helper drives pod image refs, post-install NOTES, and the image-refresh CronJob. Refresh now resolves digests on that registry (not a hard-coded docker.io), gates on chart-rendered IMAGE_REGISTRY_RESOLVABLE (docker.io/ghcr.io only), and keeps imagePullPolicy aligned via tracebloc.imageRefreshResolvable. mysql-client and third-party images are unchanged.

An interim control-plane resource trim (backend#2461) lowers default requests (and some limits) so the rendered footprint fits under the installer’s 3 GiB reserve—fixing training pods stuck Pending on small nodes. Embedded installer footprint constants, envelope/schedulability guards, and Helm unit tests are updated accordingly; jobs-manager/pods-monitor now use lower memory requests while keeping prior limits for OOM headroom.

CI: the unit-test job drops pre-baked Google Chrome apt sources before apt-get update to avoid unrelated mirror hash failures. INSTALL.md documents traceblocRegistry and GHCR egress.

Reviewed by Cursor Bugbot for commit b3c66bd. Bugbot is set up for automated code reviews on this repo. Configure here.

LukasWodka and others added 3 commits September 10, 2026 13:30
…es (images.traceblocRegistry) (#1028)

* feat(chart): one registry helper for the tracebloc control-plane images (images.traceblocRegistry)

The four tracebloc-published control-plane image sites (jobs-manager init+api,
pods-monitor, requests-proxy, resource-monitor), the image-refresh CronJob and
NOTES.txt each derived "which registry" on their own, all as a docker.io
literal behind the global.imageRegistry dig. Route them through ONE helper,
tracebloc.tbRegistry: global.imageRegistry (mirror) wins, then the new
tracebloc-only knob images.traceblocRegistry, then the chart default.

The default is unchanged (docker.io): default installs render byte-identically
(696 existing tests untouched). The knob is the per-edge opt-in to the ghcr.io
copies -- the images are published to both registries at the same digests --
and the per-edge rollback once the default moves in a follow-up.

image-refresh now resolves digests on the registry the pods pull from instead
of a docker.io literal, and its "can I reconcile here" guard reads a
chart-rendered verdict (IMAGE_REGISTRY_RESOLVABLE) derived from the same
declaration (tracebloc.imageRefreshResolvableRegistries: docker.io ghcr.io)
that flips the pods to IfNotPresent -- so the pull policy and the script's
inert path cannot disagree. Not routed on purpose: tracebloc/mysql-client
(frozen, digest-pinned, Docker Hub only), busybox and the other third-party
images, and JOB_IMAGE_HOST (the training images move in their own step).

32 new helm unit tests (tests/tracebloc_registry_test.yaml), mutation-proved
against seven breakages; schema entry; docs.

* test(image-refresh): the stale-pin bats harness supplies IMAGE_REGISTRY, which the branch now resolves on

The branch reads $IMAGE_REGISTRY instead of a docker.io literal, and the
harness runs under set -eu with the pod's env hand-supplied -- so the whole
suite (14 tests) went red in CI while the two refresh-script suites run
locally stayed green. Run every file that exercises the script, derived by
grep, not the two that came to mind.
… before installing bats (#1029)

* ci(standard-checks): drop the runner image's Google Chrome apt source before installing bats

dl.google.com served a Hash Sum mismatch for ~10 minutes on 2026-09-09 and all three bounded bats-install attempts lost on main; nothing in this job reads that repository.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* ci: drop every Google Chrome apt source file, deb822 .sources included, not only .list

Bugbot (Medium): current ubuntu-latest images write google-chrome.sources, which the .list glob left in place, so apt-get update could still reach dl.google.com.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ope fits a 2-core / 8 GiB node again (1.9.112) (#1032)

* fix(chart): interim control-plane trim so the smallest training envelope fits a 2-core / 8 GiB node again (1.9.112)

Since chart 1.9.109 the kubelet reservation is honest (#1017) and since
client-runtime#544 the jobs-manager's admission subtracts the chart's real
requests. On the smallest supported node that made the arithmetic visible:
allocatable 1900m / 5538Mi, minus the control plane's requests (800m / 3008Mi
without the collector) and k3s's coredns + metrics-server (200m / 140Mi),
leaves 900m / 2390Mi -- and the smallest envelope needs 1000m / 3072Mi. Every
task on staging was refused NEVER_STEADY_STATE (e2e fleet 34473120598).

The requests were never sized from usage: 1050m / 3276Mi requested against
36m / ~1022Mi used. This trims the components whose peaks are measured and
takes jobs-manager down modestly, giving back 150m / 800Mi:

  mysql           250m/1Gi   -> 150m/704Mi  (peak 0.55x; requests==limits kept)
  jobs-manager    250m/1Gi   -> 250m/768Mi  (168Mi idle; restart peak pending)
  pods-monitor    100m/512Mi -> 100m/320Mi  (requests==limits kept)
  requests-proxy  100m/256Mi ->  50m/128Mi  (limits unchanged)
  egress-proxy     50m/64Mi  ->  50m/160Mi  (UP: measured 2.45x over)

Render: 3136 MiB / 900 m -> 2336 MiB / 750 m. The node above now leaves
1050m / 3190Mi. Interim: the final numbers come from the load run in
progress; jobs-manager moves only once its restart peak is measured.

Everything that derives from the render moves with it: the footprint ceiling
ratchets down, the installer embed (bash + PowerShell) is regenerated, the
template fallback defaults match, and the fit tests derive their small/tiny
nodes from the footprint instead of restating a machine size -- the 8 GiB
reproduction is now pinned as fitting unreduced, and the cpu-only overshoot
replays the pre-trim 900 m because no real node can produce it any more.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(chart): mysql requests.cpu template fallback follows the trimmed 150m (Bugbot on #1032)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(footprint): derive the ratchet test's ceiling from the render so it keeps reddening after the trim

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(chart): count the collector in the trim and keep the #1144 limits (review on #1032)

Review found two holes in the interim trim (backend#2461):

1. The footprint the guard, the embed and the derivation carry INCLUDES the
   telemetry collector (helm template cannot look up the token Secret, so
   the DaemonSet renders). With it counted, 750m / 2336Mi left a 2-core /
   8 GiB node at 950m / 3062Mi -- 50m and 10Mi short of the smallest
   envelope. Trim jobs-manager cpu 250m -> 150m (the whole plane idles at
   36m) and re-cut the two memory rows below; the render is now 650m /
   2272Mi and that node leaves 1050m / 3126Mi. The derivation on
   values.yaml now says the collector is counted, and why that is the
   right worst case.

2. pods-monitor was the only row cut without a measurement, and
   requests == limits made the cut a hard cgroup ceiling. Lower only the
   REQUESTS on jobs-manager (1Gi -> 640Mi) and pods-monitor
   (512Mi -> 384Mi) and leave both LIMITS where #1144 put them; the
   restart peak that justified the limits is exactly the load-run leg not
   yet measured. Template fallbacks and helm-unittest pins follow.

Also fix the four comments the review flagged as stale on the pre-trim
numbers (installer fit preamble, schedulability WHAT-IT-ASSERTS list,
footprint bats fixture note, Pester positive-control note). Ceilings,
embed, mutation needle and manifest regenerated from the render.

* test(pester): keep the REDUCE case's claim phrase so mutation-check attributes both REDUCE mutations to it

mutation-check.ps1 expects 'the chart footprint drops out of the sum' and
'the reduction is computed but the original size is written' to redden the
test named 'is REDUCED, arithmetic printed'. The trim renamed that case to
3b (node derived from the footprint) and dropped the phrase, so both
mutations reddened the suite but read MISATTRIBUTED. Put the phrase back in
the 3b name; the body is unchanged.

* test(pester): write the pre-trim footprint replay as an Int64 literal

Bugbot flagged [long](3136 * 1MB) twice as an Int32 overflow. PowerShell
promotes the overflowing product to Double rather than wrapping, so the
finding was a false positive on both 5.1 and 7 -- but 3136L * 1MB is Int64
from the first operand and leaves nothing to argue about.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@LukasWodka
LukasWodka removed the request for review from saadqbal September 10, 2026 14:53

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit b3c66bd. Configure here.

@tracebloc-release-train tracebloc-release-train Bot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Sep 10, 2026
@tracebloc-release-train
tracebloc-release-train Bot merged commit 839c8c7 into staging Sep 10, 2026
83 checks passed
@tracebloc-release-train
tracebloc-release-train Bot deleted the release-train/to-staging branch September 10, 2026 15:37
@LukasWodka

Copy link
Copy Markdown
Contributor Author

Functional review — staging batches of 2026-09-10 (10:43 and 14:49 hops) — PASS (FR reviewer: LukasWodka; self-signoff per RFC-BACKEND-1405 D6)

Decision: PASS, by the reviewer's instruction at 15:45 UTC. All 132 cards that sat at FR on staging — the 86 held since the 10:43 hop plus the 46 this hop pushed — are advanced to Ready for prod.

What changed since the hold. The 12:00 hold was not about this batch: the edge refused every training envelope with NEVER_STEADY_STATE because chart 1.9.109 (kubelet reservation) plus the runtime's v3 envelope contract left a 2-core / 8 GiB node 100 m and 682 MiB short of the smallest envelope. The interim control-plane trim (#1032, chart 1.9.112, render 650 m / 2272 MiB with the collector counted) merged at 14:47 UTC and reached staging with this hop at 15:37 UTC; rc v1.9.112-rc.1 is published.

Evidence at signoff.

  • Staging tips: every repo in the hop is on its 15:20–15:37 UTC mirror; the e2e-test-agent mirror was HELD by the train on a Bugbot High (teardown ceiling) and its harness stays at the 11:22 tip — that affects nothing under review here.
  • Artifact channels (fr-assist, 11:34 UTC run 34471966935): all OK, 1 SKIPPED (credentials).
  • Frontend smoke on staging (11:47 UTC, 34473123260): green.
  • Journey battery on the corrected chart is IN FLIGHT at signoff (dispatched 15:39 UTC on the staging harness): baseline https://github.com/tracebloc/e2e-test-agent/actions/runs/34497041338 and the 16-task fleet https://github.com/tracebloc/e2e-test-agent/actions/runs/34497050908. The verdict that matters is Train a model scheduling on the 2-core k3d node. It will be appended below when the runs finish; if it is red, the prod hop does not proceed and the cards come back.

Things this evidence cannot tell you (README → Functional review): interactive/TTY behaviour, per-ticket behaviour, anything at or after a failing step, and any step a run skipped.

@LukasWodka

Copy link
Copy Markdown
Contributor Author

Correction to the evidence paragraph above (15:50 UTC). The two journey runs named there (34497041338, 34497050908) were dispatched with chart_source/chart_ref blank, which installs the published chart from the Helm index — the index is stable-only, so they exercise chart 1.9.109, the customer path as it is on prod today, not the 1.9.112 candidate on staging. They are a control, not the proof. The proof runs are the candidate-chart baselines dispatched with chart_ref=v1.9.112-rc.1: https://github.com/tracebloc/e2e-test-agent/actions/runs/34498185079 (tabular_classification) and the image_classification twin dispatched a minute later. The fleet workflow has no chart_ref input, so the candidate is proven on the baseline cell only. Verdicts will be appended here; the prod hop waits for them.

@LukasWodka

Copy link
Copy Markdown
Contributor Author

Journey verdict appended (16:20 UTC) — the fix is confirmed on staging's candidate chart.

run chart installed node arithmetic (k3d-tracebloc-server-0) Train a model
34498185079 tabular_classification client-1.9.112-rc.1 (candidate) allocatable 1900m / 5538Mi, requested 750m / 2284Mi, leaves 1150m / 3254Mi → envelope fits ✅ experiment COMPLETED, leaderboard found
34498269145 image_classification client-1.9.112-rc.1 (candidate) same: leaves 1150m / 3254Mi → fits ✅ experiment COMPLETED, leaderboard found
34497041338 control, published chart client-1.9.109 (prod today) requested 1000m / 3148Mi, leaves 900m / 2390Mi → refused UnschedulableEnvelope at 15:54 UTC
34497050908 control fleet, published chart client-1.9.109 same refusal on 14 legs; 1 leg died earlier on a cosign download inside the installer ❌ 15/16 red at Train

Same node, same runtime image, same envelope; only the chart differs. The published chart (prod) still refuses; the candidate admits and trains to completion. Prod hop proceeds so 1.9.112 supersedes 1.9.109.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant