Skip to content

feat(pipeline-run): fall back to file stem for a nameless submit spec#33

Open
Silin144 wants to merge 1 commit into
TangleML:masterfrom
Silin144:feat/submit-name-fallback
Open

feat(pipeline-run): fall back to file stem for a nameless submit spec#33
Silin144 wants to merge 1 commit into
TangleML:masterfrom
Silin144:feat/submit-name-fallback

Conversation

@Silin144

Copy link
Copy Markdown
Collaborator

What

Relaxes OSS submit-time validation so a pipeline spec with no declared name falls back to the pipeline file stem instead of hard-failing with name must be a non-empty string. A declared, non-empty name always wins; only the genuinely-nameless case is filled.

This restores the long-standing tangle-deploy behaviour (submitting my_pipeline.yaml with no name produces a run named my_pipeline) after submit-time validation was consolidated upstream (#28/#30).

Approach — resolve-then-validate

Rather than loosening the schema (which would let genuinely-invalid specs through), the fallback name is resolved into the spec first, and then the fully-resolved spec is validated. Everything else stays strict.

A single shared helper does the resolution:

@staticmethod
def _resolve_fallback_pipeline_name(pipeline_spec, fallback_name):
    # A declared non-empty name always wins.
    # No-op when the spec is not a mapping or no fallback is available.

It is wired into both submit code paths so OSS CLI and downstream (tangle-deploy) submits behave identically:

  1. PipelineRunner.prepare_pipeline_for_run (pipeline_runner.py) — validates first in the run lifecycle; passes the hook-resolved pipeline_name (which already honours any initial_pipeline_name override) so it can't reject a nameless-but-otherwise-valid spec before path 2.
  2. PipelineRunManager.prepare_submit_payload_from_spec (pipeline_run_manager.py) — the shared submit chokepoint; resolves after apply_run_name_template, before validation.

The run name flows from the spec's name (root_task.componentRef.spec.name), so injecting name into the spec is the correct mechanism — the resulting run is named after the stem.

Worked example

my_pipeline.yaml:

implementation:
  graph:
    tasks: {}

tangle pipeline-runs submit my_pipeline.yaml --no-hydrate → submitted spec name = "my_pipeline" (file stem). If the file instead declares name: Demo Pipeline, the run is named Demo Pipeline (declared name wins over the config stem).

Changes

  • pipeline_run_manager.py — shared _resolve_fallback_pipeline_name helper + resolve step in the submit chokepoint.
  • pipeline_runner.py — resolve step before first-path validation.
  • tests/test_pipeline_runs_cli.py — two tests: stem fallback when nameless, and declared-name-wins-over-stem.

Testing

  • Full OSS suite green (774 standalone); ruff clean.

🤖 Generated with Claude Code

A file-based submit whose spec omits a usable top-level `name` is now
resolved to the source-file stem before submit-time validation runs,
rather than being rejected outright. This restores the long-standing
downstream behavior where `submit my_pipeline.yaml` runs under the name
`my_pipeline` when the spec itself declares no name.

The fallback is applied at the single shared submit chokepoint
(`PipelineRunManager.prepare_submit_payload_from_spec`) and in the
higher-level `PipelineRunner.prepare_pipeline_for_run` (which validates
first in the full run lifecycle), via a small shared helper
`_resolve_fallback_pipeline_name`. A declared non-empty `name` always
wins; only the genuinely-nameless case is filled, so specs that are
malformed for any other reason (missing/!object `implementation`, etc.)
still fail validation exactly as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Silin144
Silin144 requested review from Ark-kun and Volv-G as code owners July 17, 2026 14:05
if not isinstance(pipeline_spec, dict):
return pipeline_spec
name = pipeline_spec.get("name")
if isinstance(name, str) and name:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(AI-assisted) [nit] A whitespace-only declared name skips the fallback. isinstance(name, str) and name treats " " as a valid declared name, so a blank-ish name is kept and the file-stem fallback isn't applied. Matches the literal "non-empty" contract, but a whitespace-only name arguably should also fall back to the stem (name.strip()). Trivial.

@Volv-G Volv-G left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(AI-assisted) Correct resolve-then-validate approach — injects the file-stem fallback into the spec and keeps validation strict rather than loosening the schema. Verified the shared _resolve_fallback_pipeline_name on PipelineRunManager is reached from both submit paths (PipelineRunner inherits it), and declared-name-wins vs stem-fallback are both tested end-to-end. One trivial nit inline (whitespace-only name). LGTM.

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