feat(deploy): add comfy deploy run - #805
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
5206427 to
6020153
Compare
6020153 to
dbbaf14
Compare
dbbaf14 to
0b53121
Compare
0b53121 to
984b8b6
Compare
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.
984b8b6 to
1dd0c56
Compare
skishore23
left a comment
There was a problem hiding this comment.
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.
Stack of 6 — review bottom-up (this is 805)
feat(build): packaging, sync and Builder client primitives — basemainfeat(build)!: replace the legacy build and distribution surface (breaking)feat(deploy): the deployment control planefeat(deploy): the asset and job data-plane clientscomfy deploy run#805 —feat(deploy):comfy deploy run← this PRfix(build): a pull no longer deletes definition data silentlyEach 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.deploy_missing_inputregains itscomfy deploy runclause now that the verb exists for the help-string guard to resolve, anddeploy_job_canceled/deploy_workflow_format_uiare registered here with the run and workflow-reader call sites that raise them.Python 3.10 compatibility:
deploy_workflow.pyanddeploy_auth_support.pyimportassert_neverfromtyping_extensions;test_deploy_run.pytakes bothNotRequiredandTypedDictfromtyping_extensions, since mixingtyping.TypedDictwith an extension-suppliedNotRequiredcomputes the wrong required-key set on 3.10. The declared floor stays>=3.10.Validation
buildjob, Python 3.10) at this commit: 6800 passed, 38 skipped, 0 failed.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.pyanddeploy_status.pyprintcomfy 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 theenvelope/1payload, so no machine consumer acts on them, but they fire on thestop_failedpath. Happy to fold that one in here if a reviewer would rather it not ship.