fix: track expected pipelines correctly - #88
Conversation
HereThereBeDragons
left a comment
There was a problem hiding this comment.
status_json_reference.jsonc is missing the new pytorch_enabled / jax_enabled just after the orchestrator_conclusion (do we need to bump the version to v2.1?)
| doc.completed_at = None | ||
| doc.orchestrator_conclusion = None | ||
| doc.created_at = None | ||
| # Reset to the default-enabled state; `_apply_pipeline_enable_flags` |
There was a problem hiding this comment.
dont think we need the explict comment here. if you want add a sentence to the docstring
There was a problem hiding this comment.
removed the inline comment on _reset_document_for_new_owner's pytorch_enabled/jax_enabled reset and moved it into docstring
| urls["deb"] = next(iter(workflow_run.deb_urls.values())) | ||
|
|
||
|
|
||
| def _input_bool(inputs: dict[str, object], key: str) -> bool | None: |
There was a problem hiding this comment.
wondering if that shouldnt be better put in therock_types as general helper and just making it work on the string:
claude:
def _parse_bool(value: Any) -> bool | None:
if isinstance(value, bool):
return value
if isinstance(value, str) and value.strip().lower() in ("true", "false"):
return value.strip().lower() == "true"
return None
and have #88 call _parse_bool(inputs.get("build_pytorch"))
|
|
||
|
|
||
| def _disable_pytorch_and_jax(doc: StatusDocument) -> None: | ||
| """Mark pytorch/jax disabled (as if `build_pytorch`/`build_jax` were |
There was a problem hiding this comment.
comment not needed
| # `summary.overall_status` so an aborted or failed release is never reported | ||
| # as `success` just because the leaves that happened to report all passed. | ||
| orchestrator_conclusion: Status | None = None | ||
| # Whether this release's own dispatch enabled the pytorch / jax pipeline |
There was a problem hiding this comment.
can we shorten this a bit? little bit less verbose
| def _pipeline_enabled(doc: StatusDocument, pipeline_type: str) -> bool: | ||
| """Whether `pipeline_type` is expected to run this release. | ||
|
|
||
| Defaults to enabled for rocm/native_packages (no flag exists) and for |
There was a problem hiding this comment.
dont htink this paragraph is needed
|
|
||
|
|
||
| def test_orchestrator_start_captures_pytorch_jax_enable_flags(tmp_path: Path) -> None: | ||
| # The top-level orchestrator's own dispatch inputs (build_pytorch / |
There was a problem hiding this comment.
not a test description
There was a problem hiding this comment.
should sound better now
| rpm=BuildRollup(status=unstarted_status), | ||
| deb=BuildRollup(status=unstarted_status), | ||
| ) | ||
| gate_status = _unstarted_pipeline_status(doc, platform, empty_platform_status) |
There was a problem hiding this comment.
gate_status is confusing. maybe better: unstarted_status ?
| A cancelled/failed rocm *test* gates nothing downstream, so the children stay | ||
| `in_progress` and the platform stays `in_progress` (in_progress outranks | ||
| cancelled in the worst-of). | ||
| Each pipeline (rocm, pytorch, jax, native_packages) first rolls its own |
There was a problem hiding this comment.
by now i find the entire function rather difficult to read. i iterated with claude over an easier to read version.
here is what it came up with. let me know what you think:
Details
# --- module scope, next to _pipeline_enabled / _unstarted_pipeline_status ---
def _pipeline_disabled(doc: StatusDocument, pipeline_type: str) -> bool:
"""Explicitly turned off for this release (pytorch/jax `build_*` = false).
rocm/native_packages have no such flag, so they are never disabled."""
return pipeline_type in _PIPELINE_ENABLE_FLAGS and not _pipeline_enabled(
doc, pipeline_type
)
# --- the function ---
def _build_platform_summary(
doc: StatusDocument, platform: str
) -> tuple[PlatformSummary, bool]:
"""Build a platform's rollup; the bool flags whether it carries any data.
rocm/pytorch run on both platforms and are always projected; an unstarted
pipeline collapses to an `unstarted_status` placeholder. jax and
native_packages are linux-only: pass them only when they carry data and let
`for_platform` supply the linux placeholder (and the windows `None`).
... (docstring body unchanged) ...
"""
architectures = (
doc.linux_architectures if platform == "linux" else doc.windows_architectures
)
urls = doc.linux_urls if platform == "linux" else doc.windows_urls
# Roll each pipeline's own leaves to a status; `*_seen` collect the raw
# leaf statuses so the sibling rollup can re-weigh them (in_progress vs
# a sibling's failure) differently from the within-pipeline rollup.
rocm_seen: list[Status] = []
pytorch_seen: list[Status] = []
jax_seen: list[Status] = []
native_seen: list[Status] = []
rocm = _pipeline_rollup(doc.pipelines.rocm, platform, rocm_seen)
pytorch = _pipeline_rollup(doc.pipelines.pytorch, platform, pytorch_seen)
jax = _pipeline_rollup(doc.pipelines.jax, platform, jax_seen)
native_packages = _native_rollup(doc, platform, native_seen)
# Status a still-gated, unreported pipeline inherits from the rocm build
# (in_progress while live / skipped on failed build / cancelled / skipped
# when no arches requested).
empty_platform_status = Status.in_progress if architectures else Status.skipped
unstarted_status = _unstarted_pipeline_status(doc, platform, empty_platform_status)
rollups = {
"rocm": (rocm, rocm_seen),
"pytorch": (pytorch, pytorch_seen),
"jax": (jax, jax_seen),
"native_packages": (native_packages, native_seen),
}
# Stand-in rollup for a pipeline that reported nothing yet, so the summary
# still shows an entry. Captures `doc`/`unstarted_status` (both immutable).
def _placeholder(pipeline_type: str) -> PipelineRollup:
status = (
Status.skipped
if _pipeline_disabled(doc, pipeline_type)
else unstarted_status
)
return PipelineRollup(build=BuildRollup(status=status))
# Combine the expected pipelines into the platform worst-of. An unreported
# pipeline contributes `unstarted_status` unless it was disabled. No
# `completed_at` guard is needed: rocm/native_packages are serialized
# workflows the orchestrator waits on, so a finalized release only leaves
# them unreported when a failed/cancelled rocm build gated them -- and then
# `unstarted_status` is skipped/cancelled (bottom precedence), so it can
# never wrongly hold a finalized platform.
sibling_statuses: list[Status] = []
has_data = bool(architectures)
for pipeline_type in EXPECTED_PIPELINE_TYPES[platform]:
rollup_obj, seen = rollups[pipeline_type]
if rollup_obj is not None:
has_data = True
sibling_statuses.append(rollup_statuses(seen, empty_platform_status))
elif not _pipeline_disabled(doc, pipeline_type):
sibling_statuses.append(unstarted_status)
fields: dict[str, object] = {
"status": rollup_sibling_statuses(sibling_statuses, empty_platform_status),
"architectures": list(architectures),
"urls": dict(urls),
# rocm/pytorch always project: real rollup, or a placeholder if unreported.
"rocm": rocm or _placeholder("rocm"),
"pytorch": pytorch or _placeholder("pytorch"),
}
if platform == "linux":
# jax/native_packages are linux-only.
fields["jax"] = jax or _placeholder("jax")
if native_packages is not None:
fields["native_packages"] = native_packages
else:
# native has no PipelineRollup shape; hand-build its rpm/deb placeholder.
native_status = (
Status.skipped
if _pipeline_disabled(doc, "native_packages")
else unstarted_status
)
fields["native_packages"] = NativePackagesRollup(
rpm=BuildRollup(status=native_status),
deb=BuildRollup(status=native_status),
)
return PlatformSummary.for_platform(platform, **fields), has_data
There was a problem hiding this comment.
extracted _pipeline_disabled(doc, pipeline_type) as a named helper and used it in place of the inline pipeline_type in _PIPELINE_ENABLE_FLAGS. should make it a bit more clear
HereThereBeDragons
left a comment
There was a problem hiding this comment.
other than the comment below lgtm.
but please also discuss if we need then to bump the schema to version 2.1 or not?
| return True | ||
|
|
||
|
|
||
| def _pipeline_disabled(doc: StatusDocument, pipeline_type: str) -> bool: |
There was a problem hiding this comment.
can we now combine _pipeline_enabled and this one here?
i would porbably go for _pipeline_enabled as positive flags are easier to understand
8e53fde to
7bdd348
Compare
7bdd348 to
dcc2fbf
Compare
Would do it with #93 |
HereThereBeDragons
left a comment
There was a problem hiding this comment.
sadly a force push :(
please address the comment below then it should be fine
| def _pipeline_enabled(doc: StatusDocument, pipeline_type: str) -> bool: | ||
| """Whether `pipeline_type` is expected to run this release. | ||
|
|
||
| rocm/native_packages have no enable-flag, so they are always enabled. |
There was a problem hiding this comment.
this is not correct. native_packages and jax is only enabled on linux. they do not exist on windows. i would argue the check needs to be done here
i know we have
for pipeline_type in EXPECTED_PIPELINE_TYPES[platform]:
below but that you cannot expect users to correctly use. this functions needs the platform to take a reasonable decision
jax and native_packages are linux-only and never run on windows, but _pipeline_enabled didn't account for platform, relying on callers to pre-filter via EXPECTED_PIPELINE_TYPES[platform] first.
Motivation
Fixes #57:
EXPECTED_PIPELINE_TYPEStreats pytorch/jax as always expected on every release, regardless of whether this release's own dispatch actually enabled them (build_pytorch/build_jax). Since #66's fix (this PR is stacked on #86 ), a platform correctly waits for every expected sibling pipeline to report before crystallizing, but a genuinely disabled pytorch/jax has no way to signal that, so it renders a wedgingin_progressplaceholder and holds the platform pending for the entire live window.Technical Details
rollup_sibling_statuses()and the per-pipelinesibling_statusesstructure introduced there, so it should be merged after fix: platform status stays in_progress #86.Test Plan
skippedimmediately and doesn't hold the platform; enabled pytorch/jax holds the platform pending pastcompleted_at; resolves cleanly once it actually reports.therock_update_status_json_test.pyfor the input-capture path: orchestrator-start capture, setup-run capture, missing-input default, string-bool parsing, and new-owner reset.Test Result
442 passed
Submission Checklist