Skip to content

release-train: staging -> main - #645

Merged
tracebloc-release-train[bot] merged 6 commits into
mainfrom
release-train/to-main
Sep 8, 2026
Merged

release-train: staging -> main#645
tracebloc-release-train[bot] merged 6 commits into
mainfrom
release-train/to-main

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

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


Note

Medium Risk
Changes doctor exit codes and rollup precedence across many Kubernetes edge cases; mistakes could mislead operators during training outages, but scope is diagnostic CLI logic rather than auth or data paths.

Overview
Release train promotion bumps VERSION to 0.10.24 and extends the version-bump gate publish-paths to include the install scripts.

tb doctor readiness rollup is reworked so measured problems beat inferred ones: image-pull and dataset PVC Fails rank above generic stuck-Pending and “wait for capacity” Warns; pending pod + running job holding compute surfaces a wait-for-job Warn instead of a resize Fail; scheduled-but-wedged training pods get a dedicated Fail (not “wait for a job”). Can't-read probes (RBAC, timeouts) use a structural Result.CantCheck flag and shared cantCheckReady instead of matching Detail prefixes.

Underlying checks distinguish permanent over-commit vs transient “job holds the room” in checkNodeFit, treat assigned Pending job pods with wedged kubelet reasons as StuckJobPod, classify PVC/image-pull read errors as can't-checks, and stop the machine-capacity chain from going green when the pod list is unreadable. User-facing strings and broad tests/goldens follow.

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

LukasWodka and others added 6 commits September 6, 2026 05:18
…ady computes, and tells a permanent shortage from a transient one (backend#2870) (#639)

* fix(doctor): the node-capacity check compares the free memory it already computes, and tells a permanent shortage from a transient one (backend#2870)

Node capacity: batch-Job pods (the `job-name` label the CLI already uses to
find a training pod) go into their own per-node sum instead of being dropped.
The steady-state fit still decides the PERMANENT Fail (OverCommitted, now with
the node's free figures); a node that fits beside the platform but not beside
its running Jobs is the new TRANSIENT Warn (HeldByRunningJob) with the
opposite remedy — wait or stop the job, do not resize. The rollup gets a
matching arm so the top line says the next run waits instead of a green.

Machine capacity: requestedMemory returns its read error instead of 0, so an
unreadable pod list renders "unrequested: unknown" and StatusUnknown rather
than the whole VM as free under a check-mark. The over-commit Warn, which
needs no pod list, still fires.

VERSION 0.10.24 (v0.10.23 is tagged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(doctor): a Pending pod beside a running job names the job, not "not enough compute" (backend#2870)

Bugbot High on #639: the transient shortage's own symptom is a second
training pod Pending until the running job frees the room, and the
stuck-Pending Fail arm matched it first -- "Not ready ... not enough free
compute" with `resources set max` at exit 2, in exactly the case the
HeldByRunningJob Warn was written for.

A combined arm now sits above the stuck-Pending arm: when Pod health reports
a pod Pending past grace AND Node capacity has measured that a running job
holds the room, the top line says the next training is waiting for the
running one, the remedy says wait or stop the job and that resizing will
not help, and -- since checkPods cannot see WHY a pod is Pending -- what to
do if the wait outlives the job. Warn, not Fail: the inference "Pending so
cannot schedule" is refuted by the measured cause, and a Fail would exit 2
on healthy training (the Bugbot High on #628). A Pod-health FAIL and the
OverCommitted Fail still outrank it; a Pending pod with no running job keeps
the generic Fail and its sizing advice.

Mutation: moving the combined arm back below the stuck-Pending arm reddens
the new both-signals test with Bugbot's exact output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…2953) (#640)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…nning job (backend#3247) (#642)

* fix(doctor): don't treat an assigned-but-Pending training pod as a running job (backend#3247)

checkNodeFit counted every non-terminal `job-name` pod with a NodeName into
the "a running job holds the room" sum. A training pod scheduled to a node but
still Pending (ImagePullBackOff / ContainerCreating) was therefore reported as
HeldByRunningJob, and combined with the same pod showing up stuck-Pending in
Pod health, summarizeDoctor rolled it up to "a training is already running,
wait for it to finish" at exit 0 — on a pod that is wedged and never will. The
operator waits forever on a dead pod.

A Pending pod (even with a NodeName) is not running:
- checkNodeFit routes a `job-name` pod into the running-job sums only when it
  is genuinely Running; an assigned-but-Pending one feeds neither sum, so it
  can no longer emit HeldByRunningJob.
- past the same grace window checkPods uses, such a pod is recorded and
  surfaced as an actionable Fail (new StuckJobPod prefix) that names its real
  state (ImagePullBackOff / ContainerCreating / Pending) and says to inspect
  the pod, not wait. A run legitimately waiting for a running job has no
  NodeName, so it is never mistaken for a wedged one.
- summarizeDoctor gains a matching arm above the inferred stuck-Pending arm
  (measured beats inferred), so the wedged pod fails at exit 2 with the right
  remedy instead of the "wait for the running job" Warn at exit 0.

The genuinely-running case is unchanged. Tests pin each pod state (Running vs
assigned-Pending vs ImagePullBackOff/ContainerCreating vs within-grace) at both
the checkNodeFit and summarizeDoctor levels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(doctor): scope the stuck-pod Fail to wedged reasons; keep the rollup plain-terms (backend#3247)

Addresses Saqlain's review on cli#642:

- summarizeDoctor's stuck-pod ready line no longer names `kubectl` — it ends at
  "… names the pod", restoring the plain-terms invariant the function documents
  three times. The kubectl form stays in the granular checkNodeFit remedy, one
  --verbose away.
- checkNodeFit escalates to the StuckJobPod Fail only for a genuinely-wedged
  waiting reason (ImagePullBackOff / ErrImagePull / ErrImageNeverPull /
  InvalidImageName / CreateContainerConfigError / CreateContainerError), via a
  new stuckReasonWedged allowlist. A pod still pulling/creating past the grace
  window (ContainerCreating / Pulling / bare Pending) is left to checkPods'
  age-based inference, so "waiting will not clear it" is only asserted where the
  kubelet has actually reported a failure — a large first pull on a cold node no
  longer trips the confident Fail.

Tests updated to pin wedged reasons (→ stuck Fail) apart from still-progressing
ones (→ deferred, node OK), and to guard the rolled-up line against Kubernetes
vocabulary. Copy-catalog golden regenerated. go build/vet/test ./... green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…apacity Warn (backend#3248) (#643)

* fix(doctor): measured image-pull/dataset Fail outranks the wait-for-capacity Warn (backend#3248)

The `stuckPending && heldByJob` arm in summarizeDoctor returned StatusWarn
above the Image-pull-secret and Dataset-volume StatusFail arms. checkImagePull
and checkPVC are independent of Pod health and Node capacity, so either can be
Fail while a pod is Pending past grace beside a running job — the exact
co-occurrence the Wait-Warn matches. Sitting below the Warn, those measured
failures were shadowed: `doctor` exited 0 (Warn) instead of 2 (Fail), hiding a
real training-blocker behind a "wait for the job" warning.

Reorder so the two measured Fail arms are read before the Wait-Warn. The
Wait-Warn must stay above the plain stuck-Pending Fail (backend#2870), so the
measured Fails necessarily move above stuck-Pending too — consistent with the
switch's measured-beats-inferred rule. A test pins that an image-pull-secret or
dataset-volume Fail beside a running job now wins (exit 2), while the Wait-Warn
still applies when there is no measured Fail.

Closes tracebloc/backend#3248

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(doctor): classify pull-secret/PVC read failures as can't-checks, not measured Fails (backend#3248)

Addresses LukasWodka's review on cli#643. checkImagePull and checkPVC returned
StatusFail for ANY error from the secret/PVC read — Forbidden, timeout,
transient — conflating a can't-check with a measured absence. Once the reorder
promoted those Fail arms above the wait-for-capacity Warn, a read blip beside a
running job flipped a healthy environment from exit 0 to exit 2 with a detail
that falsely said "not found".

- checkImagePull: a non-NotFound Get error is now a StatusWarn can't-check
  (CantReadImagePullSecret prefix); StatusFail only for a genuine not-found /
  wrong-type / malformed secret.
- checkPVC: a DiscoverSharedPVC read failure (PVCReadErrPrefix, now a shared
  constant) is a StatusWarn can't-check; StatusFail only for a read-and-found
  missing / unbound PVC.
- summarizeDoctor: two new can't-check Unknown arms drop those reads to the
  honest "couldn't check ..." tier instead of the promoted measured Fail.
- Update the StuckJobPod arm comment (backend#3247), now stale: the image-pull
  and dataset Fails sit above it too.
- Thread 3: the over-commit Warn can't be lifted above the Wait-Warn in the
  Pending variant (the stuck-Pending Fail sits between them), so pin the
  current message-only behavior rather than add a fragile special-case arm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(doctor): close the jobs-manager-unreadable false green; tighten the Wait-Warn precondition (backend#3248)

Two review points from cli#643:

- Saqlain: checkImagePull's OTHER can't-read path — the jobs-manager Deployment
  itself unreadable (dep == nil) — returned a StatusWarn with no
  CantReadImagePullSecret prefix, so summarizeDoctor matched no arm and it fell
  through to the OK default: a false green at exit 0, the same class this PR
  closes for the secret read. Route it to the Unknown tier by carrying the
  prefix. Producer test added.
- LukasWodka: the co-occurrence test's precondition asserted only StatusWarn, so
  a fall-through to the bare heldByJob Warn (also exit 0) would keep it green if
  the reorder were undone — leaving the exit-0 → exit-2 claim unpinned. Assert
  the Wait-Warn's own top line instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(doctor): plain-terms wording for the image-pull can't-check rollup line (backend#3248)

Bugbot on cli#643: the new image-pull can't-check ready line said "image pull
secret" — Kubernetes jargon. The rolled-up summarizeDoctor lines stay in plain
terms (renderDoctorDetails is the only place k8s vocabulary appears), and the
twin PVC line already says "dataset storage". Reword to mirror the Fail arm's
"training images can't be pulled". Test assertion + golden updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…t N prefix-matched arms (backend#3282) (#644)

Follow-up to Saqlain's review on cli#643. summarizeDoctor classified "a check
couldn't READ its subject" into the Unknown tier with four near-identical
prefix-matched arms, each needing three coordinated edits across three packages
(an exported prefix constant, a checkX branch stamping it into Detail, and a
matching CLI arm) coupled by fragile cross-package strings.

Add a structural doctor.Result.CantCheck, set by the checkX producers on their
can't-read paths, and replace the four arms with one rule (cantCheckReady) that
surfaces the first flagged check's line. The per-check messages stay CLI copy in
an ordered table (healthLine values, so the copy backstop still harvests them),
so no user-facing output changes — both goldens are a zero diff — and
stuckPending's can't-check exclusion moves from a Detail-prefix to the marker
too. A new can't-read probe now needs only "producer sets CantCheck" plus a
table row, with no shared prefix constant to keep in lockstep.

Producer tests assert the marker on the can't-read paths (and its absence on the
HeldByRunningJob soft finding); a rollup test pins the arm order and the
unmapped-check fall-through.

Closes tracebloc/backend#3282

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@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 d071ab1. 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 7, 2026
@tracebloc-release-train
tracebloc-release-train Bot merged commit f25666c into main Sep 8, 2026
59 of 66 checks passed
@tracebloc-release-train
tracebloc-release-train Bot deleted the release-train/to-main branch September 8, 2026 05:30
@tracebloc-release-train
tracebloc-release-train Bot restored the release-train/to-main branch September 8, 2026 14:04
@tracebloc-release-train
tracebloc-release-train Bot deleted the release-train/to-main branch September 8, 2026 14:04
@tracebloc-release-train
tracebloc-release-train Bot restored the release-train/to-main branch September 8, 2026 15:23
@tracebloc-release-train
tracebloc-release-train Bot deleted the release-train/to-main branch September 8, 2026 15:23
@tracebloc-release-train
tracebloc-release-train Bot restored the release-train/to-main branch September 8, 2026 18:29
@tracebloc-release-train
tracebloc-release-train Bot deleted the release-train/to-main branch September 8, 2026 18:29
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.

2 participants