Skip to content

feat(deploy): add comfy deploy run - #805

Open
guill wants to merge 1 commit into
stack/07-deploy-data-planefrom
stack/08-deploy-run
Open

feat(deploy): add comfy deploy run#805
guill wants to merge 1 commit into
stack/07-deploy-data-planefrom
stack/08-deploy-run

Conversation

@guill

@guill guill commented Aug 27, 2026

Copy link
Copy Markdown
Member
Stack of 6 — review bottom-up (this is 805)
  1. feat(build): add packaging, sync and Builder client primitives #801feat(build): packaging, sync and Builder client primitives — base main
  2. feat(build)!: replace the legacy build and distribution surface #802feat(build)!: replace the legacy build and distribution surface (breaking)
  3. feat(deploy): add the deployment control plane #803feat(deploy): the deployment control plane
  4. feat(deploy): add the asset and job data-plane clients #804feat(deploy): the asset and job data-plane clients
  5. feat(deploy): add comfy deploy run #805feat(deploy): comfy deploy run   ← this PR
  6. fix(build): a pull no longer deletes definition data silently #810fix(build): a pull no longer deletes definition data silently

Each PR is based on the branch below it, so its own diff is only its commit. Merge in order.

Rebased onto main @ c1fa1f4. The original bottom PR (#800, raising the Python floor to 3.11) was closed — see that thread for why; the stack is 3.10-compatible instead.

TL;DR: comfy deploy run — submit an API-format workflow to a ready deployment: resolve the deployment, read and validate the workflow, dedupe/upload its local assets, submit the job, follow its events and download the outputs. Stacked on #804; #810 sits on top of this one.

Stacked on #804. Review from the bottom up.

What changed

  • comfy deploy run, wiring the data-plane clients from the PR below into one command.
  • Closes the two staging seams the split left open: deploy_missing_input regains its comfy deploy run clause now that the verb exists for the help-string guard to resolve, and deploy_job_canceled / deploy_workflow_format_ui are registered here with the run and workflow-reader call sites that raise them.
  • The exact-27 completeness latch on the deploy code registry. It is a feature-completion assertion, so it could not live in an earlier layer without failing on a deliberately partial registry.
  • The auth matrix regains its deploy half, restoring the full build+deploy contract table.

Python 3.10 compatibility: deploy_workflow.py and deploy_auth_support.py import assert_never from typing_extensions; test_deploy_run.py takes both NotRequired and TypedDict from typing_extensions, since mixing typing.TypedDict with an extension-supplied NotRequired computes the wrong required-key set on 3.10. The declared floor stays >=3.10.

Validation

  • CI (build job, Python 3.10) at this commit: 6800 passed, 38 skipped, 0 failed.
  • Full suite on Python 3.11 locally: 6768 passed, 38 skipped, 0 failed. CI's matrix only covers 3.10, so 3.11 is verified here.
  • All 162 modules compile and import cleanly under CPython 3.10.20.
  • ruff check . / ruff format --diff . clean at CI's pin (0.15.15).

Contradicts: nothing.


Known follow-ups. A deep review of this stack cleared it apart from one blocking defect, which is fixed in #803 (worker bounds on create). Seven MINOR items were triaged and deliberately deferred rather than folded in, so they do not enlarge these diffs. The highest-value one: the remediation hints in deploy_up.py and deploy_status.py print comfy deploy stop <id> / comfy deploy scale <id>, but both verbs take the deployment via --deployment — the positional is a build path. The hints go to stderr only and never enter the envelope/1 payload, so no machine consumer acts on them, but they fire on the stop_failed path. Happy to fold that one in here if a reviewer would rather it not ship.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d3bf8935-0b37-4009-909f-d751de83bdcf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

Submits an API-format workflow to a ready deployment: resolve the deployment,
read and validate the workflow, dedupe/upload its local assets, submit the
job, follow its events and download the outputs.

Completes the deploy surface, so this change also closes the two staging seams
the split left open:

- deploy_missing_input regains its `comfy deploy run` clause, now that the verb
  exists for the help-string guard to resolve.
- deploy_job_canceled and deploy_workflow_format_ui are registered here, with
  the run and workflow-reader call sites that raise them.

With all 27 deploy codes present, the exact-27 completeness latch is added.
It is a feature-completion assertion, so it could not live in an earlier layer
without failing on a deliberately partial registry.

The auth matrix regains its deploy half, restoring the full build+deploy
contract table.

@skishore23 skishore23 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The containment story holds where it matters: _resolve_local_file resolves every candidate (symlinks followed) and only returns paths under an allowed root, and in experiment /etc/passwd, ~/.ssh/config, .env and README.md in cwd, and a symlink inside input/ pointing at ~/.ssh/config were all refused loudly with deploy_workflow_asset_outside_root. The job body matches what public-api jobs.go reads, outputs go through safe_output_path + collision-safe naming, Ctrl-C after submit issues exactly one cancel. Three small fixes before merge:

1. deploy_workflow.py:157 — with no build PATH, cwd/{models,input,output} silently become allowlisted roots. resolve_asset_roots calls resolve_build_paths(None, require_spec=False), which anchors on Path.cwd(), so comfy deploy run --deployment <id> --workflow downloaded.json from any project directory with an output/ folder uploads output/results.csv if the workflow names it — and in --json mode there's no pre-upload announcement, only the post-hoc assets.files disclosure. The module docstring says the allowlist exists precisely so nothing under the cwd is reachable. Confirmed: PATH=None, cwd=project → roots == [project/output] and the scan returned local-asset:0 -> project/output/results.csv. Only derive install roots when a PATH was given or a spec exists; the tracked workspace and --asset-root cover the rest.

2. _scan_api_workflow (deploy_workflow.py:276) — a non-object JSON root is a traceback. _load_workflow_file returns whatever json.load produced and the scan calls .items(); --workflow list.json containing [1,2] (or a string/number/null) yields AttributeError: 'list' object has no attribute 'items' on stderr, exit 1, no envelope. comfy run routes through _classify_api_workflow for this; reuse it.

3. run_deploy (deploy_run.py:214-219) — Ctrl-C in --json mode emits nothing. The handler cancels and raises typer.Exit(130), which bypasses cmdline's global cancelled envelope, and unlike comfy run no renderer.error(code="cancelled") is called. Confirmed: SIGINT after submit → exit 130, empty stdout and stderr — an agent gets no outcome and no job id to reconcile. test_deploy_run_cancel.py only asserts the exit code.

Non-blocking: RecursionError from a deeply nested workflow escapes every except in run_deploy (shared loader with comfy run); client-side --timeout expiry is reported as deploy_server_error, which the registry describes as a data-plane fault; the completeness latch is 30, not the 27 the body says.

Tests on the branch (typer 0.19 venv): 55 + 369 passed; ruff clean. Note the new deploy_auth_support.py:189 asserts isinstance(command, click.Group), which fails under typer ≥ 0.27's vendored click — same env hazard as the mix_stderr sites in #802.

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

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants