- approval gate now honors latest review state per reviewer; a reviewer
who later submits CHANGES_REQUESTED or has their approval dismissed no
longer counts as approved. Plain COMMENTED follow-ups don't override
an existing approval (matches GitHub's own behavior).
- success summary links to the tag's tree URL instead of /releases/tag/,
which would 404 because this workflow creates an annotated git tag,
not a GitHub Release object.
The workflow now does its own gating rather than trusting the operator
to pre-stage a clean candidate, and creates the version-bump commit
itself so the candidate branch can be a pure cherry-pick chain.
Operator flow (changed):
- Locally cherry-pick the backport commits onto the previous stable
tag. NO version-bump commit.
- Push the candidate branch and open a PR against `master`.
- Wait for CI green; get an APPROVED review from a user listed in the
repo variable `STABLE_RELEASE_APPROVERS`.
- Run the workflow with `source_branch` = candidate branch.
Workflow now verifies, in order:
1. `source_branch` matches a safe ref-name regex.
2. `STABLE_RELEASE_APPROVERS` repo variable is configured.
3. Latest stable tag = highest semver `vX.Y.Z`; next version is
`last_tag_patch + 1` (computed; no longer a workflow input).
4. Source branch exists on origin; target release branch and tag
do NOT exist (refuse to overwrite).
5. Branch is rooted at the latest stable tag:
* tag is an ancestor of source HEAD,
* `merge-base(source, master) == tag commit` (no master commits
sneaked in via merge/rebase),
* no merge commits in `tag..source` (linear cherry-picks only).
6. Version files on the candidate still equal the previous tag's
version (operator must NOT include a version bump). Read via
`git show | python3 -c '...'` so candidate code is never executed,
and `comfyui_version.py` is statically AST-parsed for `__version__`.
7. PR for the source branch exists, targets master, head SHA matches
the candidate, has an APPROVED review on that exact SHA from an
allow-listed user (stale approvals on older commits don't count),
and all check-runs / commit-statuses on the SHA are success /
neutral / skipped. `mergeable_state` is intentionally not used —
backport branches by definition aren't "up-to-date with master".
After all gates pass, the workflow creates the version-bump commit
itself (edits `pyproject.toml` + `comfyui_version.py` via stdlib regex,
commits as `github-actions[bot]`), then atomically pushes
`release/v<version>` + `v<version>` annotated tag using
`RELEASE_BOT_TOKEN`.
Kept from the previous revision: atomic ref push, `persist-credentials:
false` checkout, AST-based version-file parse (never `exec()`), all
inputs flow through `env:` vars (no command injection), `dry_run`
short-circuits the push step, pre-flight existence checks, step summary
linking to `release-stable-all.yml`.
Verified end-to-end against Kosinkadink/ComfyUI with sentinel `v0.99.99`
→ `v0.99.100`: dry-run passed all 11 steps; real run created
`release/v0.99.100` + `v0.99.100` atomically. Negative cases for the
approval gate and version-file gate also exercised.
Split GLB save logic out of nodes_hunyuan3d.py into a new nodes_save_3d.py, and extend the writer to support UVs, per-vertex colors, and embedded baseColor textures.
Extend the MESH type with optional uvs, vertex_colors, and texture fields so meshes can carry texture data through the graph.
Add pack_variable_mesh_batch / get_mesh_batch_item helpers and switch VoxelToMesh / VoxelToMeshBasic to use them so batches with differing vertex/face counts no longer fail at torch.stack.
The /ws path uses HTTP 101 (Switching Protocols), which is the correct
response for a WebSocket upgrade but not a 2xx. The built-in
operation-success-response rule fires as a false positive because
OpenAPI 3.x has no native WebSocket support.
Add a path-scoped override in .spectral.yaml to disable the rule for
/ws only, leaving it active for all other operations.
* Mark deprecated cloud-runtime endpoints in openapi.yaml
Add five cloud-runtime FE-facing endpoints to the OSS spec with
deprecated: true and standardized description prefixes:
- GET /api/history_v2 — superseded by GET /api/jobs
- GET /api/history_v2/{prompt_id} — superseded by GET /api/jobs/{prompt_id}
- GET /api/logs — returns static placeholder; no real log data
- GET /api/viewvideo — alias of GET /api/view for legacy video playback
- GET /api/job/{job_id}/status — superseded by GET /api/jobs/{job_id}
Each endpoint is tagged x-runtime: [cloud] and follows the same
deprecation convention established for /api/history endpoints.
Co-authored-by: Matt Miller <MillerMedia@users.noreply.github.com>
* fix(spec): consolidate duplicate path entries on deprecated cloud-runtime endpoints
Previous commit added new path entries with `deprecated: true` for
`/api/job/{job_id}/status`, `/api/history_v2`, `/api/history_v2/{prompt_id}`,
`/api/logs`, and `/api/viewvideo`, but the canonical entries already existed
elsewhere in the file. Result: 5 duplicate path keys (Spectral parser errors),
and the deprecation flag did not land on the operations that FE clients
consume by operationId.
This commit moves `deprecated: true` plus the standardized "Deprecated."
description onto the canonical operations (`getCloudJobStatus`, `getHistoryV2`,
`getHistoryV2ByPromptId`, `getCloudLogs`, `viewVideo`) and removes the
duplicate entries. Operation IDs and response schemas are unchanged.
Spectral lint passes with zero new warnings.
* Initial HiDream01-image support
* Cleanup nodes
* Cleaner handling of empty placeholder models
* Remove snap_to_predefined, prefer tooltip for the trained resolutions
* Add model and block wrappers
* Fix shift tooltip
* Add node to work around the patch tile issue
Experimental, runs multiple passes with the patch grid offset and blends with various different methods.
* Qwen35 vision rotary_pos_emb cast fix
* Fix embedding layout type
* Some small optimizations
* Cleanup, don't need this fallback
* Prefix KV cache, cleanup
Bit of speed, reduce redundant code
* Get rid of redundant custom sampler, refactor noise scaling
Our existing lcm sampler is mathematically same, just added the missing options to it instead and a node to control them. Refactored the noise scaling and fix it for the stochastic samplers, add a generic node to control the initial noise scale.
* Update nodes_hidream_o1.py
* Fix some cache validation cases
* Keep existing sampling params
* Remove redundant video vision path
* Replace some numpy ops with torch
* Fx RoPE index for batch size > 1
* Prefer torch preprocessing
* Rename block_type to be compatible with existing patch nodes
* Fixes and tweaks
* Add new blueprints
* Add Image Segmentation
* Add blueprint Get Video Last Frame (#13613)
* Add Video segment
* Fix Video Stitch subgraph issue
* Update get last frame to get any frame
* Add Frame Interpolate blueprint
* Correct typo
* Name blueprints
* Update and add new blueprints
* blueprints: add subgraph descriptions for previously undocumented workflows
Fill missing definitions.subgraphs[].description across ERNIE, Flux.2,
Z-Image base/default, Qwen edit 2509, Wan I2V, SAM3 image/video,
and align wording with existing blueprint style.
* Add new blueprint
* remove Image to Video
* Update ZIB blueprint
* Refine description
* Remove duplicate model entries from Image Edit blueprint
* Fix typos
* Update IDs