Conversation
A template that calls a Partner Node is marked in two independent,
hand-authored places, and nothing derived either from the workflow JSON:
- "openSource": false — ComfyUI_frontend derives the subscription badge
from this exact value (isPartnerNode: template.openSource === false)
- the "API" tag — templates.comfy.org renders it as "Partner Nodes" and
scripts/mcp/sync_index.py turns it into the `api` MCP capability
So a Partner Node template could ship advertised as free, which is what
happened to the three templates fixed in #1124 — two of which were also
missing the "API" tag, in the same repo where 303 others had both.
Add check 8 to validate_templates.py: cross-reference every workflow
(including subgraph nodes, where #1124's Gemini nodes hid) against the
API node classes in scripts/data/mcp/api_node_ids.json, and require both
markers on any template that calls one. Also require the two markers to
agree with each other, in either direction, and require every locale index
to match index.json — the auto-sync workflow skips fork PRs.
The reverse is deliberately not an error: 8 templates legitimately carry
both markers with no detectable node because the committed node list lags
a newly shipped vendor. An unusable node list is a hard error rather than
a silent pass, so the gate cannot no-op itself.
The new check found one pre-existing violation on main:
utility-gan_upscaler, a local Real-ESRGAN video upscaler with no Partner
Node at all, carried the "API" tag alongside "openSource": true. It was
being shown as a Partner Node template on templates.comfy.org and
published to the MCP index with the `api` capability. Tag removed and
propagated to the 11 locale indexes via sync_data.py --index-only.
|
Important Review skippedDraft detected. 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:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔤 Spellcheck Results
|
|
@coderabbitai review Re: the "Review skipped — Draft detected" status above — that is an automated status message, not feedback on the diff, so there is nothing to address from it. Triggering a real pass on the draft with the command above. For context while you look, the diff is three things:
Two design decisions worth reviewing specifically, both deliberate:
One finding from the earlier review pass, already fixed in this commit: CI status so far on |
validate_templates.py called sys.exit(1) at import time if jsonschema
was absent. packages/core/tests now imports the module, and build-test.yml
installs only `build pytest ruff aiohttp twine` — so pytest raised
SystemExit during collection and the job died with
INTERNALERROR> SystemExit: 1
mainloop: caught unexpected SystemExit!
exiting 3 rather than reporting a test result.
Set jsonschema to None on ImportError and report it from main() instead.
CLI behaviour is unchanged: same message, same exit 1, no traceback. The
Validate Templates workflow installs jsonschema explicitly, so the schema
check itself is unaffected. validate_schema() also returns the error
rather than dereferencing None if it is ever called directly.
Verified in a venv built from build-test.yml's exact install list (no
jsonschema, pytest 9.1.1, ruff 0.16.3): pytest goes from exit 3 with zero
tests run to 106 passed, and ruff on the CI file list is clean.
|
Update: This one is worth reading even if you skim the rest, because the failure had nothing to do with the new check's logic and everything to do with a latent trap in this script. What happened. Root cause. It passed locally purely because my sandbox had Fix. Same message, same exit code, no traceback. The I deliberately did not add Verified against CI's exact environment, a fresh venv built from
The remaining exit-1 failure is Also worth noting for the earlier concern about auto-sync races: |
PR Created by the Glary-Bot Agent
PR Created by the Glary-Bot Agent
Follow-up to #1124, which fixed three mislabelled Partner Node templates by hand. This adds the CI gate that catches the next one.
The gap
A template that calls a Partner Node is marked in two independent, hand-authored places, and nothing derives either one from the workflow JSON:
"openSource": falseisPartnerNode: template.openSource === falsedrives the subscription badge and the "Runs on" filterAPItagsite/src/lib/tag-aliases.ts);scripts/mcp/sync_index.pyturns it into theapiMCP capabilitySo a Partner Node template can ship advertised as free. That is exactly what happened in #1124 — and two of those three were also missing the
APItag, in a repo where 303 other templates had both.The check
New check 8 in
scripts/validate/validate_templates.pycross-references every workflow against the API node classes inscripts/data/mcp/api_node_ids.json(generated byscripts/mcp/scan_api_nodes.pyfrom ComfyUI'scomfy_api_nodes— living in that directory is what makes a node billable, so the list is complete by construction). It fails when:"openSource": false;APItag;index.jsonon either marker.Subgraph nodes are scanned too — in #1124 the Gemini nodes were nested inside
definitions.subgraphs[], invisible to a top-level scan.The reverse is deliberately not an error. Eight templates (
api_ltx2_5_*,api_flux2,api_bfl_flux_1_kontext_*, …) legitimately carry both markers with no detectable node, because the committed node list lags a newly shipped vendor. Requiring a detectable node would reddenmain. Rule 3 still keeps them honest with each other.The gate cannot no-op itself. An unusable
api_node_ids.jsonis a hard error, not a silent pass. Verified by deleting the file in a simulated CI checkout:Locale parity matters because
sync-template-index.ymlonly auto-syncs same-repo PRs (if: github.event.pull_request.head.repo.full_name == github.repository) — a fork PR can leave 11 locale files behind, and non-English users read those files directly.What it caught on main
One pre-existing violation, unrelated to #1124:
utility-gan_upscaler("Fast GAN Video Upscaler") carried theAPItag alongside"openSource": true. It contains no Partner Node at all — it is a local Real-ESRGAN workflow (UpscaleModelLoader,ImageUpscaleWithModel,LoadVideo,SaveVideo). Consequences of the stray tag:index.mcp.jsonwith theapicapability, so agents saw a local GAN upscaler as API-backed — its generated description even claims "API execution is supported for server-side upscaling".Fixed by removing the tag (not by setting
openSource: false— that would put a subscription badge on a genuinely free local workflow). Propagated to the 11 locale indexes withsync_data.py --index-only; the diff is exactly one line per index file.manifest.jsonis checksum-only, regenerated withsync_bundles.pyasbuild-test.ymlrequires.index.mcp.jsonis intentionally not regenerated here:sync_index.pyalso rewrites time-dependentfreshness/recommendvalues for 16 unrelated templates.publish.ymlandversion-check.ymlboth regenerate it, so it self-heals on the next release.Verification
Locally
validate_templates.py→ all 8 checks pass (2.1s; check 8 adds ~0.4s)validate_manifests.py→ no errors (82 warnings, all pre-existing)pytest packages/core/tests→ 106 passed. The 1 failure (test_sync_is_app.py::test_unreadable_permissions_are_reported) is environment-only — itchmod 000s a file and this sandbox runs as uid 0; it fails identically on unmodifiedmainand will pass on a CI runner.ruff→ my code adds 0 findings.validate_templates.pyhas the same 14 pre-existing errors as onmain; the new test file is clean, which matters becausebuild-test.ymllintspackages/core.yaml-linton the changed workflow → pass26 new tests in
packages/core/tests/test_partner_node_markers.py, run bybuild-test.ymlon every PR. Confirmed non-vacuous by mutation: neuteringfind_partner_nodesto return[]fails 5 of them.Simulated CI checkout. Copied only the paths in the workflow's
sparse-checkoutinto a bare directory and ran the script there — passes, proving the addedscripts/data/mcp/api_node_ids.jsonentry is sufficient. Then injected a new template calling a Partner Node inside a subgraph withopenSource: trueand no tag:In a real browser. Served this branch's
index.jsonto a ComfyUI backend + frontend dev server.Fast GAN Video Upscalerstill appears, now with only theVideo Upscalechip and no badge — and searching "Upscaler" inside the Partner Nodes category returns the 22 real partner upscalers (Topaz, Magnific, WaveSpeed, HitPaw, Recraft) with the GAN upscaler correctly absent.Screenshots below also cover the post-merge re-verification of #1124 on
mainthat was requested alongside this: all three templates render the crown badge frommain's data, and reverting justopenSourceto its pre-#1124 value makes the badge disappear on all three — while theAPItags stay present, confirming the badge is driven solely byopenSource: false.Reviewer note
Removing the
APItag fromutility-gan_upscalerchanges what appears under "Partner Nodes" on templates.comfy.org. That is the intended correction, but it is a user-visible data change, so please sanity-check that call.Screenshots