[ModelDeploy] Runtime variants created through the API can never be deployed
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
## Goal
The revision merge chain must always be able to produce a resolvable model definition, so a preset-driven deploy cannot fail for want of a field no layer supplies.
## Background
*Rewritten after investigation — the original framing ("validate presets and runtime variants at write time") did not survive contact with the code. See the closing note.*
`ModelConfig` requires both `name` and `model_path` (`common/config.py:323`). The lowest-priority draft in the merge chain, `_model_mount_path_default_draft` (`sokovan/deployment/revision_draft/reader.py:145`), supplied only `model_path`. Everything above it is optional, so `name` had to come from the runtime variant's `default_model_definition`, the preset, a vfolder yaml, or the request.
For a model-store deploy none of those apply except the variant baseline — and **that baseline is empty for every runtime variant created through the API**:
- `RuntimeVariantCreatorSpec.build_row()` hardcodes `default_model_definition = ModelDefinitionDraft()` (`repositories/runtime_variant/creators.py:35`).
- `RuntimeVariantUpdaterSpec` exposes only `name` and `description` (`repositories/runtime_variant/updaters.py`).
- The field appears on the response DTO and the GQL node, on no input anywhere.
Only the alembic seed (b5c6d7e8f9a0) writes real values, so the built-in variants work and every API-created one is permanently undeployable: `to_resolved()` raises at `deployment_controller.py:436`, after the endpoint row is already committed.
The fix is one layer down from the symptom: the baseline draft now supplies `name` as well as `model_path`, so the chain always resolves regardless of what the variant carries. Any higher layer still overrides it.
## Acceptance Criteria
- A revision built on a runtime variant with an empty `default_model_definition` resolves, and names the model `model`.
- A `name` supplied by the variant baseline, the preset, a vfolder yaml, or the request still wins over the default.
- No change to `model_path` resolution.
## Dropped from the original scope
**Preset resource-slot validation at write time.** #13392 makes a preset that omits a required slot fail cleanly with a good error and no leftover endpoint. Duplicating `RequiredResourceSlotRule` at preset-write time would mean giving the preset service a dependency on `resource_slot_types.required` for defence in depth of marginal value.
## Follow-up worth filing separately
`runtime_variants.default_model_definition` is not writable through any API. This change makes such variants deployable, but a custom variant still cannot ship its own baseline model definition — a genuine API gap, and a feature rather than a fix.
JIRA Issue: BA-XXXX
Contributor guide
Research direction
Start with sokovan/deployment/revision_draft/reader.py:145 and trace the merge chain into common/config.py:323 and deployment_controller.py:436. Verify the empty-baseline case and check that higher-priority values from the variant, preset, vfolder YAML, or request continue to win; done means resolution succeeds with name model without changing model_path resolution.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100