Commit Graph

331 Commits

Author SHA1 Message Date
Wei Hai
f5f1e69cd8 feat(auth): Cloudflare Turnstile on email signup (origin-gated) (#12924)
Adds a Cloudflare Turnstile widget to the email/password signup form
(web + desktop). The frontend renders the widget and attaches its token
to the signup request; the verification decision is made server-side.

## Design — config-driven, no origin sniffing

* The widget renders **iff** the `signup_turnstile` mode is `shadow` or
`enforce` **and** a `turnstile_sitekey` is present — both delivered via
cloud remote config. OSS / local builds receive no remote config, so it
never renders. Gating is a pure `isTurnstileEnabled(mode, siteKey)`; an
unknown mode normalizes to `off`.
* Submit is blocked only in **enforce**; **shadow** never blocks.
* The token is sent as `turnstile_token` (snake_case, optional) on the
customer-creation request.
* **OAuth** never renders the widget or sends a token (federated
providers are exempt).

## Behavior

* **Decision is server-side** — the frontend only renders the widget and
attaches the token; the backend verifies it and decides allow/block.
* **Mode-driven** — `off` (no-op) / `shadow` (render + attach, never
blocks) / `enforce` (blocks submit until solved).
* **Config-gated** — no `isCloud`/origin check in the client; the widget
is driven purely by the presence of the mode flag + sitekey in remote
config.
* **Fail-safe to off** — an unknown/missing mode or a missing sitekey
resolves to "don't render", so the feature is a no-op until both are
configured.
* The sitekey is a public, client-side value delivered per environment
via remote config; in dev it falls back to Cloudflare's always-pass test
sitekey.

## Files

New: `config/turnstile.ts`, `composables/auth/useTurnstile.ts` (+ test),
`composables/auth/turnstileScript.ts`,
`components/dialog/content/signin/TurnstileWidget.vue`. Edited:
`SignUpForm.vue`, `SignInContent.vue`, `useAuthActions.ts`,
`authStore.ts` (+ test), `remoteConfig/types.ts`,
`locales/en/main.json`.

## Flow

```mermaid
sequenceDiagram
    actor U as User
    participant FE as Signup form
    participant CF as Cloudflare Turnstile
    participant API as Backend signup API

    Note over FE: renders only when mode is shadow or enforce<br/>and a sitekey is present
    U->>FE: open email/password signup
    FE->>CF: load widget with sitekey
    CF-->>U: challenge (usually invisible)
    U-->>CF: solve
    CF-->>FE: token (single-use, short-lived)
    U->>FE: submit
    FE->>API: signup request with turnstile_token
    Note over API: verifies the token server-side and<br/>decides allow/block (shadow never blocks)
    API-->>FE: allowed, or blocked in enforce
```

## Rollout

Config-driven and a no-op until enabled:

1. **Merge + deploy** the FE — no visible change while the mode is `off`
/ no sitekey.
2. **Set** the `turnstile_sitekey` in remote config per environment.
3. **`signup_turnstile=shadow`** — the widget renders and attaches the
token; the server observes and never blocks.
4. → **`enforce`** — the FE blocks submit until the challenge is solved.

Kill switch: set the mode back to `off` and the widget stops rendering.

## Refactor: shared script loader

The Turnstile script loader was extracted to
`utils/loadExternalScript.ts` (`createScriptLoader`) and now also backs
the existing Typeform embed loader, removing duplicated
singleton/timeout/cleanup logic. Minor behavioral change: when a
matching `<script>` tag already exists in the DOM, the loader polls for
the global to become ready instead of attaching a `load` listener (which
may have already fired).

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-06-25 23:03:48 +00:00
Simon Pinfold
c202e3cc2d Allow Glary Bot through CLA (#13149)
## Summary

- Add `Glary Bot` to the CLA Assistant allowlist.

## Context

PR #13146 is blocked because its commit author is `Glary Bot
<bot@glary.dev>`, which GitHub does not resolve to a GitHub user. The
CLA action checks the unresolved commit author name after failing to
find a linked GitHub account, so the existing `*[bot]` GitHub App
allowlist does not apply.

## Validation

- Ran `git diff --check`.
2026-06-25 22:48:19 +00:00
AustinMroz
5b62ec2431 Update CLA allowlist (#13141)
It's `github-actions` without the `[bot]`. This was blocking every PR
that contained updated browser test expectations.

Additionally, the action already included an allow list for every
account ending in `[bot]`. This made half the entries redundant.
2026-06-25 18:30:48 +00:00
Alexander Brown
e37f168eaa Add merge_group event to CLA workflow (#13093)
## Summary

So it runs in the merge queue.
2026-06-24 08:34:29 -07:00
Alexis Rolland
a95dab2f59 Update allowlist in CLA workflow (#13091)
Update `allowlist` in CLA workflow to add
[actions-user](https://github.com/actions-user)
2026-06-24 10:14:16 +00:00
Alexis Rolland
5f90bacb73 ci: add CLA Assistant workflow (#13058)
Adds the CLA Assistant GitHub Actions workflow at
`.github/workflows/cla.yml`, copied from
https://github.com/Comfy-Org/comfy-cla/blob/main/.github/workflows/cla.yml

---------

Co-authored-by: GitHub Action <action@github.com>
2026-06-24 06:53:53 +00:00
Wei Hai
c304f206a6 fix(ci): strip served bundle scripts from e2e coverage before genhtml (#13077)
## Problem

The **CI: E2E Coverage** `merge` job fails in the *Generate HTML
coverage report* step ([example
run](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/28051468752)):

```
genhtml: ERROR: localhost-8188/assets/nodeDefs-BNhq_6cm.js is not readable or doesn't exist.
##[error]Process completed with exit code 1.
```

V8/Playwright coverage records scripts the test server serves at
`localhost-8188/assets/*.js` (built bundles), which are not source files
on disk. `genhtml` aborts on the missing source even with
`--ignore-errors source`, so the whole job fails.

## Change

Add a *Strip non-source entries from coverage* step that runs `lcov
--remove '*localhost-8188*'` on the merged lcov. It is placed **after**
the data-loss validation (so the merged-vs-shard integrity check stays
consistent) and **before** the Codecov upload and genhtml — which also
makes the Codecov report more accurate, since those served bundles
aren't repo source.

## Validation

- YAML parses cleanly; pre-commit lint/format/typecheck pass.
- The removed paths are non-source served assets only; real `src/**`
entries (absolute paths under the repo workspace) are untouched by the
`*localhost-8188*` pattern.
- `--ignore-errors unused` guards against runs where no such entries
exist.
2026-06-23 20:27:07 +00:00
Christian Byrne
b4b95980da fix: publish core/* releases immediately to create tags (#12995)
## Summary
- Fix release pipeline where core/* releases hang indefinitely waiting
for tags

## Problem
Draft releases don't create git tags, but `publish-pypi` workflow waits
for the tag to exist. For `core/*` branches, releases were always
created as drafts, causing the pipeline to wait forever.

## Solution
Only use draft releases for prereleases (alpha/beta/rc). Publish all
stable releases (main and core/*) immediately so tags are created.

## Test plan
- [x] Verify workflow change logic is correct
- [ ] Test on next core/1.45 release

Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-06-19 14:28:49 -07:00
Benjamin Lu
05efee07ce Move Comfy Desktop bridge types into frontend (#12857)
## Summary

Adds `@comfyorg/comfyui-desktop-bridge-types` as a workspace package in
the frontend monorepo and changes the frontend app dependency to
`workspace:*`.

Adds a dedicated `Publish Desktop Bridge Types` workflow for publishing
`packages/comfyui-desktop-bridge-types` by its own package version,
without coupling it to the generated `@comfyorg/comfyui-frontend-types`
release. The generated frontend types package still emits a concrete
`@comfyorg/comfyui-desktop-bridge-types@0.1.2` dependency instead of
leaking workspace/catalog protocol references.

The Desktop2 missing-model path uses `window.__comfyDesktop2.isRemote()`
when available, but falls back to the legacy
`window.__comfyDesktop2Remote` marker so frontend rollout stays
compatible with older Desktop builds.

Paired Desktop PR: https://github.com/Comfy-Org/Comfy-Desktop/pull/1112
2026-06-18 18:02:13 -07:00
Alexis Rolland
cf7c68cd50 Update default workflow (#12804)
## Summary

Update the default workflow to use a more modern model than SD1.5. This
new workflow uses Z-Image Turbo and is the same workflow as the one in
the README for consistency.

## Changes

- **What**: `src/scripts/defaultGraph.ts`

## Screenshots (if applicable)

<img width="1920" height="1152"
alt="{2DD28B9F-A9E7-4DD7-8F07-AF7241F5702E}"
src="https://github.com/user-attachments/assets/6e6ee298-a786-4a8c-adf3-6452df08a995"
/>

---------

Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-06-18 13:46:02 -07:00
Christian Byrne
4f60d09420 ci: consolidate PR bot comments into one unified comment (#11935)
## Summary

- Merges the separate Playwright and Storybook bot comments into the
existing `<!-- COMFYUI_FRONTEND_PR_REPORT -->` unified comment, using
named sections via `upsert-comment-section`
- Each workflow independently upserts its own section without clobbering
others
- `pr-report.yaml` cleans up legacy `<!-- PLAYWRIGHT_TEST_STATUS -->`
and `<!-- STORYBOOK_BUILD_STATUS -->` comments on first run
- Perf report: collapses detailed metric tables in `<details>` by
default — only headline FPS/TBT/heap summary and a brief regression
count are visible inline

## Before → After

**Before:** 4–5 separate bot comments per PR (Playwright, Storybook,
Bundle/Perf/Coverage, Chromatic URLs) + CodeRabbit + Codecov

**After:** 1 unified comment with collapsible sections:
```
<!-- COMFYUI_FRONTEND_PR_REPORT -->
<!-- section:playwright:start --> ... <!-- section:playwright:end -->
<!-- section:storybook:start --> ... <!-- section:storybook:end -->
<!-- section:ci-metrics:start --> ... <!-- section:ci-metrics:end -->
<!-- section:chromatic:start --> ... <!-- section:chromatic:end -->
```
(CodeRabbit and Codecov are external and can't be merged)

## How it works

`upsert-comment-section` already existed for the website CI comment.
This PR extends that pattern to the main PR report comment:

1. **Playwright** — shell script writes to `SUMMARY_FILE` when set, CI
workflow uses `upsert-comment-section` with `section-name: playwright`
2. **Storybook** — same pattern, `section-name: storybook`
3. **Bundle/Perf/Coverage** — `pr-report.yaml` now also uses
`upsert-comment-section` instead of replacing the whole comment,
`section-name: ci-metrics`
4. **Chromatic** — `section-name: chromatic`, no script change needed

Both fork and non-fork PR paths updated.

## Perf report noise fix

Previously the full per-metric regression table was shown inline. Now:
- **Visible:** headline summary (avg FPS, P5 FPS, TBT, heap per test) +
"⚠️ N regressions detected" count
- **Collapsed by default:** regression detail table, all-metrics table,
historical variance, trend data

## Test plan

- [ ] Open a PR with frontend changes — confirm single unified bot
comment appears
- [ ] Confirm Playwright section appears with  then updates to results
- [ ] Confirm Storybook section appears only when storybook-relevant
files change
- [ ] Confirm legacy standalone Playwright/Storybook comments are
deleted by `pr-report.yaml`
- [ ] Confirm perf report shows headline only, details collapsed
- [ ] Test with a fork PR — confirm fork path also works

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11935-ci-consolidate-PR-bot-comments-into-one-unified-comment-3566d73d36508173964cdf596cfae1f8)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-06-17 18:02:28 -07:00
Matt Miller
810ada61fb ci: add team-gated Cursor review (thin caller for github-workflows) (#12859)
## Summary

Adds a team-gated, label-triggered multi-model Cursor review as a **thin
caller** for the reusable workflow in `Comfy-Org/github-workflows` — the
single source of truth for the panel, judge, prompts, and scripts. This
repo carries only the ~50-line caller, so there's no review logic to
drift out of sync.

## Changes

- **What**: `.github/workflows/pr-cursor-review.yaml` triggers on the
`cursor-review` label and calls
`Comfy-Org/github-workflows/.github/workflows/cursor-review.yml`, pinned
to `047ca48` (github-workflows#9, current main). Inheriting the reusable
workflow brings severity badges, line-anchored inline comments,
diff-size caps, prompt-injection hardening, and optional Slack DMs.
- **Config**: `diff_excludes` restated (overriding replaces the default
wholesale) with this repo's heavy paths added (Playwright snapshots,
generated manager types). Judge and panel both default to Opus 4.8 via
the reusable workflow — no overrides needed.

## Review Focus

- **Access control (the point).** Two layers, no allowlist: (1) only
triage+ users can apply a label in a public repo; (2) the reusable
workflow's secret-bearing jobs don't run on fork PRs, so
`CURSOR_API_KEY` is reachable only on internal branches.
- **Replaces a standalone draft.** Earlier revisions of this branch
carried a self-contained workflow + review/judge scripts; that
duplicated the reusable workflow, so it's been swapped for the thin
caller.

## Prerequisites (already done)

- `CURSOR_API_KEY` secret set on this repo.
- `cursor-review` label created.
- `SLACK_BOT_TOKEN` already present (enables the DM feature).

---------

Co-authored-by: GitHub Action <action@github.com>
2026-06-17 20:38:14 +00:00
pythongosssss
36b57f1e83 feat: implement customer.io SDK & telemetry provider (#12878)
## Summary

Adds a cloud-only Customer.io telemetry provider that forwards key
frontend lifecycle events and registers the in-app messaging plugin,
enabling low-latency intent-moment campaigns.

## Changes

- **What**: 
- new `CustomerIoTelemetryProvider` (matching impl. and registration of
other telemetry, dynamic import, tree shaken)
- Triggered from 9 initial sources
- Update telemetry scanner
- **Dependencies**: `@customerio/cdp-analytics-browser`

## Review Focus

- Matches other telemetry providers & is correctly removed from OSS
builds

## Screenshots (if applicable)
2026-06-16 21:55:48 +00:00
Alexander Brown
11a621152c ci: skip PR Unified Report on main branch (#12631)
*PR Created by the Glary-Bot Agent*

---

## Summary

The
[`pr-report.yaml`](https://github.com/Comfy-Org/ComfyUI_frontend/blob/main/.github/workflows/pr-report.yaml)
workflow is dispatched via `workflow_run` after `CI: Size Data`, `CI:
Performance Report`, or `CI: E2E Coverage` complete. Those upstream
workflows also run on push to `main`, which dispatches `PR: Unified
Report` on the `main` branch head, producing failed runs like [run
26913874399](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/26913874399/job/79398707144).

The existing job-level guard (`github.event.workflow_run.event ==
'pull_request'`) doesn't always prevent the runner from spinning up, so
noisy failed runs still appear under the workflow's history on `main`.

## Change

Add `branches-ignore: [main]` to the `workflow_run` trigger so the
workflow no longer dispatches when the upstream run's head branch is
`main`.

```yaml
on:
  workflow_run:
    workflows: ['CI: Size Data', 'CI: Performance Report', 'CI: E2E Coverage']
    types:
      - completed
    branches-ignore:
      - main
```

## Tradeoff to flag

`workflow_run.branches-ignore` filters on the triggering workflow run's
head branch. For PRs, that's the PR's source branch. A fork PR whose
source branch is literally named `main` (e.g., a fork opened from its
default branch) will no longer get a unified report comment. This is
uncommon for contributors who follow the usual feature-branch workflow,
but if preserving comments for fork-from-`main` PRs matters, the
alternative is to leave the dispatch in place and rely solely on the
existing job-level `if` guard.

Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com>
2026-06-03 21:58:39 +00:00
Luke Mino-Altherr
cc29a3d72d Add unreviewed merge detector for SOC 2 compliance (#12497)
## Summary

- Adds a GitHub Actions workflow that detects PRs merged to `main`
without an approving review
- Creates tracking issues in
[`Comfy-Org/unreviewed-merges`](https://github.com/Comfy-Org/unreviewed-merges)
(private) for SOC 2 audit purposes
- Supports inline justification via `Justification: <reason>` in PR body
or comments

## How it works

Triggers on `push` to `main`. Uses the GitHub API to find the associated
PR and check for approving reviews. If none found, creates a tracking
issue with the `unreviewed-merge` label. No code checkout required — API
calls only.

## Test plan

- [ ] Verify workflow YAML is valid
- [ ] Merge a test PR without approval and confirm issue creation in
`unreviewed-merges` repo

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-05-28 19:22:46 +00:00
Alexander Brown
c703db5f6c chore: remove Nx and migrate monorepo workflows to pnpm (#12355)
## Summary
- remove Nx root/config artifacts and workspace 
x metadata
- replace Nx-based root scripts with direct pnpm workspace + native
Vite/Vitest/Playwright commands
- remove Nx dependencies/catalog entries and regenerate lockfile
- clean residual Nx references from CI workflows, tooling config, and
docs

## Validation
- pnpm install --frozen-lockfile
- pnpm lint
- pnpm typecheck
- pnpm build
- pnpm build:cloud
- pnpm build:desktop
- pnpm build:types
- pnpm test:browser -- --list
- pnpm test:unit *(4 pre-existing failing tests)*

ΓöåIssue is synchronized with this [Notion
page](https://www.notion.so/PR-12355-chore-remove-Nx-and-migrate-monorepo-workflows-to-pnpm-3666d73d3650817888b9e85e24a10b22)
by [Unito](https://www.unito.io)

---

**For keeping Nx**
- Better monorepo orchestration (task graph, affected runs, caching).
- Can reduce CI/runtime cost at larger scale.
- Unified interface across tools and packages.

**Against keeping Nx**
- Extra abstraction layer and config complexity.
- Higher maintenance/debugging cost (plugins, cache behavior, drift).
- Native `pnpm` + tool CLIs are simpler and clearer today.

**Bottom line**
- If current pain is low: prefer simplicity and remove Nx.
- If measured scale pain is high: orchestration may be worth it (Nx or
another tool later).

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-05-22 05:37:10 +00:00
Alexander Brown
b0144db644 build: migrate pnpm config to v11 (#12195)
## Summary

Migrate pnpm configuration to the v11 layout and clean up stale v10-era
references.

## Changes

- **What**: Moves pnpm settings into `pnpm-workspace.yaml`, converts
build dependency policy to `allowBuilds`, removes stale workspace
`packageManager` pins, and updates global install commands in CI.
- **Dependencies**: No new dependencies.

## Review Focus

- Confirm pnpm v11 workspace settings match the former `.npmrc`
behavior.
- Confirm CI global install syntax is compatible with pnpm v11.

## Test Plan

- `pnpm install --frozen-lockfile`
- `pnpm exec oxfmt --check pnpm-workspace.yaml
packages/shared-frontend-utils/package.json
packages/registry-types/package.json packages/ingest-types/package.json
packages/design-system/package.json
.github/workflows/weekly-docs-check.yaml
.github/workflows/pr-claude-review.yaml`
- commit hook: `pnpm typecheck`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-12195-build-migrate-pnpm-config-to-v11-35e6d73d36508116a821dbc71db94cd1)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-05-21 01:53:09 +00:00
Christian Byrne
b578147714 fix(ci): add unmapped to genhtml ignore-errors, remove unreachable placeholder (#12273)
## Summary

- Add `unmapped` to genhtml `--ignore-errors` flag to fix GH Pages
deploy failure
- Remove unreachable placeholder block (dead code cleanup)

## Problem

PR #11381 added `--ignore-errors source` but genhtml is now failing with
a different error:

```
genhtml: ERROR: no data for line:4291, TLA:GNC, file:src/lib/litegraph/src/LGraphNode.ts
(use "genhtml --ignore-errors unmapped ..." to bypass this error)
```

This happens when LCOV data references lines that don't map to source
(from V8 coverage instrumentation).

## Changes

1. **Add `unmapped` to ignore-errors** — `--ignore-errors
source,unmapped` handles both missing source files and unmapped line
data

2. **Remove unreachable placeholder block** — The `if [ ! -s
coverage/playwright/coverage.lcov ]` check is dead code because the step
is already gated on `has-coverage == 'true'`, which only triggers when
the merged LCOV exists and is non-empty

## Test plan

- [ ] Verify workflow completes successfully on next push to main
- [ ] Verify https://comfy-org.github.io/ComfyUI_frontend/ returns 200

Fixes #12229

🤖 Generated with [Claude Code](https://claude.com/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-12273-fix-ci-add-unmapped-to-genhtml-ignore-errors-remove-unreachable-placeholder-3606d73d36508198a4ffddfce3354d4a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-05-14 20:11:45 +00:00
Christian Byrne
f176d18fe0 fix(website): refresh cloud nodes snapshot in release workflow + strict production builds (#12219)
*PR Created by the Glary-Bot Agent*

---

## Summary

`Release: Website` only refreshed the Ashby snapshot, so the cloud-nodes
snapshot (`apps/website/src/data/cloud-nodes.snapshot.json`) was stale
on every release. `loadPacksForBuild()` then silently fell back to that
snapshot because `WEBSITE_CLOUD_API_KEY` was never plumbed through CI or
Vercel, leaving production at `/cloud/supported-nodes` with placeholder
data (e.g. `rgthree-comfy` listed as supported when it isn't — visible
at line 104 of the committed snapshot, last fetched 2026-05-04).

## Changes

- **New composite action `.github/actions/cloud-nodes-pull`** mirroring
`ashby-pull`: runs `pnpm --filter @comfyorg/website
cloud-nodes:refresh-snapshot` with `WEBSITE_CLOUD_API_KEY`. The script
already `process.exit(1)`s on any non-`fresh` outcome, so refresh
failures are loud.
- **`release-website.yaml`** now runs both refreshes and opens a single
PR with both updated snapshots. Renamed the job to `refresh-snapshots`,
updated branch/commit/title/body for the wider scope, and kept the
existing `Release:Website` label so downstream automation is unaffected.
- **`cloudNodes.build.ts`** throws when the outcome is `'stale'` **and**
`VERCEL_ENV === 'production'`. Preview / local builds keep the snapshot
fallback so contributors without key access are unaffected. The CI
reporter still runs first so the GitHub annotation explaining *why* it's
stale is visible in the failed job.
- **`ci-vercel-website-preview.yaml`**: passes `WEBSITE_CLOUD_API_KEY`
to `vercel build` in both preview and production jobs, and adds a
preflight step on `deploy-production` that hard-fails before `vercel
build --prod` if the secret is missing — surfacing config drift with a
maintainer-friendly error annotation instead of mid-build.
- **`apps/website/README.md`**: documents the production-strictness
behavior, the new required secret (GitHub Actions + Vercel env), and the
manual refresh path.
- **New unit tests** in `cloudNodes.build.test.ts` (6 cases): fresh,
stale-no-VERCEL_ENV, stale-on-preview, stale-on-production,
failed-regardless, and "still reports on stale-in-production before
throwing".

## Manual / one-time steps required before merging

This PR cannot finish the job alone. A maintainer must also:

1. Add `WEBSITE_CLOUD_API_KEY` as a **GitHub Actions repo secret** in
`Comfy-Org/ComfyUI_frontend`.
2. Add `WEBSITE_CLOUD_API_KEY` to the **Vercel project environment**
(`production` env at minimum; `preview` recommended).
3. Investigate why `rgthree-comfy` is in the current snapshot — either
the Cloud API was actually returning it on 2026-05-04, the snapshot was
generated against a non-production environment, or it was hand-edited.
The first manual run of `Release: Website` after this PR merges will
confirm.

Without step 1, the new `Release: Website` job will fail loudly (the
refresh script exits 1 with `missing WEBSITE_CLOUD_API_KEY`). Without
step 2, the new preflight will fail the production deploy with a clear
error annotation pointing at `apps/website/README.md`. Both failure
modes are intentional — they replace today's silent stale snapshot.

## Related (out of scope for this PR)

The other half of the original report — production 404s on
`/p/supported-models/*`, `/cloud/supported-nodes/*`,
`/demos/community-workflows` from PRs #11892 / #11903 / #11942 — is a
`comfy-router` allow-list gap (those paths exist in the Vercel build as
pre-rendered static HTML). That fix needs to land in
`Comfy-Org/comfy-router` and is being handled separately since glary
doesn't have access to that repo.

## Verification

- `pnpm --filter @comfyorg/website test:unit` — 75/75 pass (6 new in
`cloudNodes.build.test.ts`)
- `pnpm --filter @comfyorg/website typecheck` — 0 errors, 0 warnings (2
pre-existing hints unrelated to this PR)
- `pnpm format` + `pnpm exec eslint` on changed files — clean
- `js-yaml` validates `release-website.yaml`,
`cloud-nodes-pull/action.yaml`, `ci-vercel-website-preview.yaml`
- Oracle code review (round 1) raised 1 warning + 1 suggestion; both
addressed in commit 2.

**Manual verification not applicable**: the runtime changes are GitHub
Actions workflows and a Vercel-env-gated branch in a build-time module —
they cannot meaningfully run outside of GitHub Actions / Vercel, and the
strict-on-stale path is exhaustively covered by the 6 unit tests
(including the exact assertions a manual run would check: throws on
`VERCEL_ENV=production` + stale, passes on preview, reports
observability annotation before throwing). The end-to-end behavior will
be verified by the first `Release: Website` dispatch and the next
production deploy after the maintainer adds the secret.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-12219-fix-website-refresh-cloud-nodes-snapshot-in-release-workflow-strict-production-build-35f6d73d3650816d8f32d403cb39d733)
by [Unito](https://www.unito.io)

---------

Co-authored-by: glary <bot@glary.dev>
2026-05-14 09:49:00 +00:00
Christian Byrne
8abfa678a3 fix: harden e2e coverage workflow and fix GH Pages deploy (#11381)
## Problem

The GH Pages coverage deploy has been failing since #11291 merged —
every `CI: E2E Coverage` workflow run errors out and
https://comfy-org.github.io/ComfyUI_frontend/ returns 404.

Additionally, two correctness/security issues were identified in the
workflow (filed as #11374 and #11375).

## Changes

1. **`--ignore-errors source` on genhtml** — merged LCOV data includes
paths like `localhost-8188/assets/main-BRkC1B8m.js` from Playwright V8
coverage instrumented runtime bundles that don't exist as source files
in CI, causing genhtml to error out
2. **Pin checkout to `workflow_run.head_sha`** — in `workflow_run`
context, the default checkout ref points to the default branch, not the
commit that triggered the upstream run; genhtml could annotate against
wrong source files (#11375)
3. **Gate deploy on `event == 'push'`** — a fork branch named `main`
could satisfy the branch check and overwrite production coverage; adding
the event guard prevents this (#11375)
4. **Include workflow run link in placeholder HTML** — when no coverage
data is available, the placeholder page now links back to the workflow
run for debugging (#11374)

## Fixes

- Fixes the GH Pages 404 caused by #11291
- Fixes #11374
- Fixes #11375
2026-05-13 23:06:36 +00:00
Christian Byrne
35443e94f5 feat(website): SEO model pages — 207 models, FAQ JSON-LD, partner node support (#11892)
## Summary

- Adds programmatic SEO model pages at `/p/supported-models/[slug]` for
**207 models** auto-generated from `workflow_templates` (180 local + 27
partner nodes)
- 3-file architecture: `generated-models.json` (auto-generated, checked
in) + `model-metadata.ts` (editorial overrides) + `models.ts` (65-line
merger)
- Full JSON-LD per page: `SoftwareApplication` + `BreadcrumbList` +
`FAQPage` (targeting AI Overviews / People Also Ask)
- Partner node support: `directory: 'partner_nodes'` hides Download
button, shows VIEW TUTORIAL
- `generate-models.ts`: walks `workflow_templates` for local models +
`API_PROVIDER_MAP` for 30+ partner integrations (Kling, Meshy, Luma,
Runway, Stability AI, ByteDance, Google, etc.)
- Weekly GH Actions workflow opens issue when new models appear in
`workflow_templates` but not in `generated-models.json`
- `add-model-page` Claude skill for Slack-driven model page PRs

## Files changed

| File | Purpose |
|------|---------|
| `apps/website/src/config/generated-models.json` | Auto-generated, 207
models (27 partner + 180 local) |
| `apps/website/src/config/model-metadata.ts` | Editorial overrides:
docsUrl, blogUrl, featured (9 entries) |
| `apps/website/src/config/models.ts` | 65-line merger — imports JSON +
overrides, exports `models` + `getModelBySlug` |
| `apps/website/scripts/generate-models.ts` | Build-time parser; run
with `pnpm generate:models` |
| `apps/website/src/i18n/translations.ts` | ~30 UI keys added (no
per-model keys — displayName is plain string) |
| `apps/website/src/pages/p/supported-models/[slug].astro` | Dynamic
route with 3x JSON-LD schemas |
| `apps/website/src/pages/p/supported-models/index.astro` | Model grid
index page |
| `apps/website/src/components/models/ModelHeroSection.vue` | Hero
component |
| `.github/workflows/model-page-discovery.yaml` | Weekly auto-discovery
workflow |
| `.claude/skills/add-model-page/SKILL.md` | Claude skill for
adding/updating model pages |

## Test plan

- [ ] `pnpm build` passes in `apps/website`
- [ ] `/p/supported-models` index renders 207 model cards
- [ ] `/p/supported-models/kling-ai` shows Partner Node eyebrow, no
Download button, VIEW TUTORIAL CTA
- [ ] `/p/supported-models/flux-1-dev` shows Diffusion Model eyebrow,
Download + Tutorial buttons
- [ ] `/p/supported-models/umt5-xxl-fp8-e4m3fn-scaled` redirects 301 to
`umt5-xxl-fp16` (canonicalSlug)
- [ ] Structured data validator shows FAQPage + SoftwareApplication +
BreadcrumbList valid

Fixes FE-421

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 14:50:23 +00:00
Benjamin Lu
f0e16cdf46 ci: handle skipped e2e workflow consumers (#11575)
## Summary

Follow-up to #11568 and #11785. Keeps the E2E coverage workflow clean
when `CI: Tests E2E` is intentionally skipped and no coverage shard
artifacts are produced.

## Changes

- Detect whether downloaded E2E coverage shard artifacts contain any
`coverage.lcov` files.
- Treat missing coverage shards as an intentionally skipped coverage run
instead of running lcov, Codecov, or Pages deployment on missing files.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11575-ci-handle-skipped-e2e-workflow-consumers-34b6d73d3650813f92e1d7d6af0bf958)
by [Unito](https://www.unito.io)
2026-05-07 04:20:36 -07:00
Christian Byrne
aa4343a98b test: add perf test for subgraph transition bottleneck (#10480)
## Summary

Add a `@perf` test measuring the cost of entering a subgraph containing
80 interior nodes. Establishes a CI baseline for the synchronous
mount/unmount bottleneck.

## Changes

- **What**: Add `subgraph transition (enter and exit)` perf test to
`performance.spec.ts` and a test workflow asset
(`large-subgraph-80-nodes.json`) with a single subgraph node containing
80 Note nodes.

## Review Focus

This is PR 1 of 2. The test establishes a baseline on main so the
optimization PR (PR 2) can show a CI-proven delta for `taskDurationMs`
and `totalBlockingTimeMs`.

The test:
1. Loads the 80-node subgraph workflow
2. Enters and exits once to warm up
3. Measures a fresh enter transition (start → 80 nodes mounted → layout
settled)
4. Records `taskDurationMs`, `layouts`, and `TBT`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10480-test-add-perf-test-for-subgraph-transition-bottleneck-32d6d73d3650811b9b6eec03a9591f82)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Connor Byrne <c.byrne@comfy.org>
2026-05-06 01:54:18 -07:00
Alexander Brown
32984459bf ci: exclude release branches from website previews (#11952)
## Summary

Exclude core and cloud minor release branches from Vercel website
preview deployments.

## Changes

- **What**: Added `pull_request.branches-ignore` entries for `core/*`
and `cloud/*` to the Vercel Website Preview workflow.

## Review Focus

Confirm the branch exclusion patterns match the minor release branch
naming convention.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11952-ci-exclude-release-branches-from-website-previews-3576d73d36508194b835eda9bc12f174)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-05-05 17:20:33 +00:00
Christian Byrne
c1954028d1 feat(ci): add Release:Website workflow to refresh Ashby snapshot (#11829)
## Summary

Adds a unified manual-trigger release flow for the `apps/website`
package
(careers/marketing site at comfy.org), mirroring how main-app releases
work.

**User-facing flow:**

```
workflow_dispatch ──► fresh Ashby pull ──► auto-PR with snapshot bump
                                                      │
                                                      ▼
                              existing CI / Vercel preview deploy
                                                      │
                                                      ▼
                                  human merges ──► auto prod deploy
```

The careers data on comfy.org comes from Ashby and is fetched at build
time by
`apps/website/src/utils/ashby.ts`. Without `WEBSITE_ASHBY_API_KEY`, the
build
falls back to a committed snapshot at
`apps/website/src/data/ashby-roles.snapshot.json`. That snapshot has
been
going stale because no CI workflow was passing the API key. This PR
fixes
both: a manual refresh workflow + day-to-day secrets wiring.

## Files

**Added**
- `.github/actions/ashby-pull/action.yaml` — composite action that runs
`pnpm --filter @comfyorg/website ashby:refresh-snapshot` with the Ashby
  secrets piped in. Uses the existing `setup-frontend` composite for
  pnpm/Node setup.
- `.github/workflows/release-website.yaml` — `workflow_dispatch`-only
  release workflow. Checks out `main`, refreshes the snapshot via the
  composite action, opens a PR labelled `Release:Website` via
  `peter-evans/create-pull-request@c0f553fe…` (the same SHA pin used by
  `release-version-bump.yaml`).

**Modified**
- `.github/workflows/ci-website-build.yaml` — adds
`WEBSITE_ASHBY_API_KEY`
  and `WEBSITE_ASHBY_JOB_BOARD_NAME` env to the `Build website` step.
- `.github/workflows/ci-vercel-website-preview.yaml` — adds the same env
  to both `vercel build` steps (preview + production).

## Snapshot fallback preserved

`apps/website/src/utils/ashby.ts` keeps using the committed snapshot
when
the API key is absent (e.g. fork PRs, secret rotation). Verified
locally:

```
$ pnpm --filter @comfyorg/website ashby:refresh-snapshot
Snapshot refresh aborted. Outcome: stale; reason: missing WEBSITE_ASHBY_API_KEY...
```

The release workflow surfaces this as a job failure, which is the
desired
behavior for a manual release trigger.

## Validation

- `yamllint --config-file .yamllint` on all changed YAML — clean
- `./scripts/cicd/check-yaml.sh` — clean
- `pinact run --check` on new files — clean (matches `.pinact.yaml`
policy)
- `pnpm install --frozen-lockfile` — works with `.nvmrc` Node 24
- Husky pre-commit hooks (eslint + typecheck + lint-staged) passed

## Caveats

- **Cannot fully end-to-end test until merged.** `workflow_dispatch`
  workflows only run from branches that exist on `main`. The first
  manual run can only happen after this PR lands. The pieces that
  *can* be tested pre-merge — yamllint, pinact pin validation, and
  the existing `CI: Website Build` / `CI: Vercel Website Preview`
  workflows now picking up the secret — will run on this PR.
- **`Release:Website` label needs to be created** in the repo before
the auto-PR step will successfully apply it.
`peter-evans/create-pull-request`
  will warn but not fail if the label doesn't exist. Suggested color:
  `#4f6ef5` (matches `cloud/*` family in `release-branch-create.yaml`).
- The release workflow uses `secrets.PR_GH_TOKEN` (matching
  `release-version-bump.yaml`) so the auto-PR can be authored by a
  PAT and trigger downstream CI workflows. Without `PR_GH_TOKEN` it
  will fall back behavior is up to GitHub Actions defaults — confirm
  the secret exists before the first run.

## Context

Came out of work on `comfy-router#22` + `ComfyUI_frontend#11823`
(comfy.org/countdown subpage / website refresh). Discovered the
8+-day-stale snapshot while auditing the website build path.

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11829-feat-ci-add-Release-Website-workflow-to-refresh-Ashby-snapshot-3546d73d3650811eb300d8bcb593c652)
by [Unito](https://www.unito.io)
2026-05-02 05:31:00 +00:00
Alexander Brown
f566abdd6e ci: extract changes-filter composite action; fix docs-only PR stall (#11785)
## Summary

Extract a `.github/actions/changes-filter` composite action and adopt it
across path-gated CI workflows, fixing the docs-only PR stall and
removing duplicated `paths:` / `paths-ignore:` filtering across 8
workflows.

## Background

Docs-only PRs stalled on required status checks because workflows using
`paths-ignore: ['**/*.md']` never created a check run, while branch
protection still required it. Observed on #11776 (the `test` check from
`ci-tests-unit.yaml` never appeared).

The fix pattern: keep the workflow triggered, gate downstream jobs on a
`changes` job whose outputs are computed from a path filter. Skipped
jobs count as passing under branch protection.

## What the action emits

| Output | Meaning |
|---|---|
| `should-run` | Any file outside `apps/`, `docs/`, `.storybook/`,
`**/*.md` changed. |
| `app-website-changes` | Shared deps or `apps/website/**` changed. |
| `app-desktop-changes` | Shared deps or `apps/desktop-ui/**` changed. |
| `app-frontend-changes` | Shared deps or `src/**` changed. |
| `packages-changes` | Shared deps or `packages/**` changed. |
| `storybook-changes` | Shared deps or `.storybook/**` changed. |
| `docs-changes` | `docs/**` or any `**/*.md` changed (deps NOT folded
in). |
| `dependency-changes` | Root `package.json`, `pnpm-lock.yaml`, or
`pnpm-workspace.yaml` changed. |

Shared deps are folded into every `app-*`, `packages-changes`, and
`storybook-changes` output so a lockfile bump correctly invalidates each
granular gate. Outputs default to `'true'` for non-`pull_request` events
to avoid the silent-skip footgun on push / merge_group.

## Workflows migrated

| Workflow | Gate | Notes |
|---|---|---|
| `ci-tests-unit.yaml` | `should-run` | Required check (`test`). Fixes
the original stall. |
| `ci-tests-e2e.yaml` | `should-run` | Required check (`e2e-status`).
Replaces inline filter. |
| `ci-perf-report.yaml` | `should-run` | Removes `paths-ignore`. |
| `ci-website-build.yaml` | `app-website-changes \|\| packages-changes`
| Refactor — not a required check, but moves to job-level gating. Filter
scope broadens from `packages/{design-system}` to all `packages/**`
(strictly safer). |
| `ci-website-e2e.yaml` | `app-website-changes \|\| packages-changes` |
Same restructure; `post-starting-comment` also gated to avoid spurious
"tests are running" when E2E is skipped. |
| `ci-dist-telemetry-scan.yaml` | `should-run` | New gate; was
previously running on every PR including docs-only. |
| `ci-oss-assets-validation.yaml` | `should-run` | Same. |
| `ci-size-data.yaml` | `should-run` | Preserves existing repository
guard on the new `changes` job. |
| `ci-tests-storybook.yaml` | `storybook-changes \|\|
app-frontend-changes \|\| packages-changes` | Gates 4 of 6 jobs.
`deploy-production` (push to main) left ungated;
`update-comment-with-chromatic` cascades naturally. |

## Branch protection (verified)

Required status checks on `main` and `core/**`/`cloud/**`: `test`,
`lint-and-format`, `e2e-status`. Only `test` and `e2e-status` use the
composite — `lint-and-format` correctly stays unfiltered (must run on
docs/apps too). The other 6 migrations are refactor wins (less wasted CI
on docs/apps-only PRs), not stall fixes.

## Changes

- **What**: New `.github/actions/changes-filter` composite + 8 workflow
migrations to consume it.
- **Breaking**: None.
- **Dependencies**: New pin on `dorny/paths-filter@de90cc6` — already
covered by `ci-validate-action-pins`.

## Review Focus

- The `should-run` filter excludes `.storybook/**` (granular
`storybook-changes` covers it instead). Storybook's gate combines all
three: `storybook-changes || app-frontend-changes || packages-changes`.
- Two `dorny/paths-filter` steps inside the composite —
`predicate-quantifier=every` is required for the negated globs in
`should-run` but breaks the multi-pattern OR filters.
- The website filter scope intentionally broadens from
`packages/{design-system,tailwind-utils}/**` to all `packages/**` for
consistency and safety.

Fixes #11776

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11785-ci-extract-changes-filter-composite-action-fix-docs-only-PR-stall-3526d73d36508172a1d7fe8c30fa6453)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-05-01 18:06:29 +00:00
Benjamin Lu
26ac1eece1 Allow website screenshot workflow to remove its label (#11725)
## Summary

Allows the website screenshot update workflow to remove its own trigger
label when a label-triggered run completes.

## Changes

- **What**: Grants the screenshot update job `issues: write`, which is
required for `issues.removeLabel`, and keeps the cleanup scoped to
`Update Website Screenshots`.
- **Dependencies**: None.

## Review Focus

Confirm the workflow permission scope is appropriate and that unexpected
label cleanup failures should fail the workflow instead of being
silently swallowed.

## Validation

- `/Users/ben/go/bin/actionlint
.github/workflows/pr-update-website-screenshots.yaml`
- `/Users/ben/Library/Python/3.9/bin/yamllint --config-file .yamllint
.github/workflows/pr-update-website-screenshots.yaml`
- `git diff --check HEAD~1 HEAD`

No browser e2e regression was added because this change only adjusts
GitHub Actions token permissions and label cleanup behavior; it does not
change shipped app/runtime behavior.

Fixes FE-487
2026-04-30 04:57:00 +00:00
Benjamin Lu
810381ab63 Stabilize website GitHub stars in visual snapshots (#11771)
## Summary

Stabilize the website nav GitHub star count in visual-test builds so
snapshot comparisons do not drift as the live GitHub count changes.

## Changes

- **What**: Added `WEBSITE_GITHUB_STARS_OVERRIDE` for build-time
star-count overrides and set it to `111000` in the website E2E and
screenshot-update workflows.
- **Dependencies**: None.

## Review Focus

Confirm the deterministic build-time override is preferable to
screenshot masking, since Playwright masks draw a colored rectangle
whose geometry can also drift when masked content changes size.

## Screenshots (if applicable)

Not included; this keeps visual-test input data stable rather than
changing the UI.
2026-04-29 21:57:30 -07:00
Alexander Brown
c168c37c94 chore: update comfyui-ci-container to 0.0.17 (#11569)
Update `comfyui-ci-container` image to `0.0.17` across all CI workflows.

| Workflow | Before | After |
|---|---|---|
| `ci-perf-report.yaml` | `0.0.12` | `0.0.17` |
| `ci-tests-e2e.yaml` (×2) | `0.0.16` | `0.0.17` |
| `pr-update-playwright-expectations.yaml` | `0.0.16` | `0.0.17` |

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11569-chore-update-comfyui-ci-container-to-0-0-17-34b6d73d365081b8a52ac995855354cb)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-04-28 22:05:28 +00:00
Alexander Brown
9c0edd0048 fix: prevent duplicate website-e2e CI runs on PRs (#11607)
## Summary

Fix duplicate `CI: Website E2E` workflow runs on pull requests.

## Problem

Two runs were triggered for every PR touching website files:
- `website-e2e (pull_request)` — from the PR event
- `website-e2e (push)` — from the push to a `website/*` branch

The concurrency key used `github.ref`, which evaluates differently for
push (`refs/heads/...`) vs pull_request (`refs/pull/N/merge`), so they
couldn't cancel each other.

## Changes

1. Scope `push` trigger to `main` only (removes `website/*`)
2. Use `github.head_ref || github.ref` in the concurrency group so push
and PR events for the same branch share a group

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11607-fix-prevent-duplicate-website-e2e-CI-runs-on-PRs-34c6d73d3650814c9d24c77b1591e94a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-04-27 19:55:05 +00:00
Alexander Brown
8e3041aa2f ci: add e2e-status gate job for required checks (#11587)
## Summary

Follow-up to #11568. Fixes Playwright required checks hanging as
"Waiting for status to be reported" on PRs with no e2e-relevant file
changes.

## Problem

PR #11568 added a `changes` filter to skip E2E when only
docs/apps/storybook files are touched. The E2E workflow skips correctly,
but branch rulesets require the 11 matrix-expanded check names (e.g.
`playwright-tests-chromium-sharded (1, 8)`). When a matrix job is
skipped via dependency, GitHub only reports the parent job name — the
individual matrix entries are never reported, so required checks hang
forever.

## Fix

Add a single `e2e-status` gate job that:
- Uses `if: always()` so it always runs regardless of skipped
dependencies
- Passes when E2E was intentionally skipped (no relevant changes)
- Passes when all matrix jobs succeeded
- Fails when any matrix job failed

**After merging**, the ProtectMain and Core release branches rulesets
should be updated to require `e2e-status` instead of the 11 individual
matrix check names.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11587-ci-add-e2e-status-gate-job-for-required-checks-34c6d73d365081b59c01e8d61d0b808d)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-04-24 05:43:45 +00:00
Alexander Brown
0b2e605dee content: website copy and pricing updates (#11567)
## Summary

Update website copy: fix branding ("Comfy" → "ComfyUI"), correct pricing
runtime, remove "coming soon" seat features, and shorten use-case label.

## Changes

- **What**: Copy corrections in `translations.ts` (branding, runtime "60
min" → "30 min" for Standard plan, remove placeholder seat features for
Creator/Pro plans); trim feature arrays in `PriceSection.vue`

## Review Focus

Verify zh-CN translations still make sense after the English copy
changes (runtime string not updated in zh-CN).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11567-content-website-copy-and-pricing-updates-34b6d73d365081c29af8ee1469b08358)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-04-24 04:25:15 +00:00
Alexander Brown
39e1877065 ci: filter e2e workflow on PRs to skip unrelated changes (#11568)
## Summary

Skip the main e2e test suite on PRs that only touch unrelated paths
(website, docs, storybook, markdown).

## Changes

- **What**: Replace the broad `paths-ignore: ['**/*.md']` on the
`pull_request` trigger with a more targeted `paths-ignore` list covering
`apps/**`, `docs/**`, `**/*.md`, and `.storybook/**`. The `push` (to
main), `merge_group`, and `workflow_dispatch` triggers remain
unconditional.

## Review Focus

- The `merge_group` trigger has no path filter, so the merge queue
always runs e2e as a safety net before merge.
- Using `paths-ignore` (denylist) rather than `paths` (allowlist) so new
top-level directories trigger e2e by default.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11568-ci-filter-e2e-workflow-on-PRs-to-skip-unrelated-changes-34b6d73d365081ea8603ef94bc86b6e6)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-04-23 23:02:03 +00:00
Alexander Brown
68798d8e37 feat(website): website mise en place (#11552)
## Summary

Assorted website copy and content refinements — tidying up loose ends
across the site.

## Changes

- **What**: Remove placeholder doc links from custom nodes feature
description on pricing page

## Review Focus

Low-risk copy changes only; no logic or layout modifications.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11552-feat-website-website-mise-en-place-34b6d73d3650813b954afbc965e4dc74)
by [Unito](https://www.unito.io)

> **Note:** The `PR: Vercel Website Preview` workflow is
`workflow_run`-triggered, so it always runs the **main branch version**
of the workflow file. Until this PR is merged, the preview workflow will
continue posting standalone comments using the old `<!--
VERCEL_WEBSITE_PREVIEW -->` marker instead of writing to the
consolidated `<!-- WEBSITE_CI_REPORT -->` comment. This is expected and
resolves itself on merge.

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Yourz <crazilou@vip.qq.com>
2026-04-23 17:26:06 +00:00
Yourz
bbb043c9cc feat(website): Polish and fix UI (#11363)
## Summary

<!-- One sentence describing what changed and why. -->

Polish and fix UI for new website

## Changes

- **What**: <!-- Core functionality added/modified -->
  - [x] update about video
  - [x] update Moment factory story content
  - [x] update homepage visual
  - [x] update customer story visual
  - [x] put images and videos to bucket

## Review Focus

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11363-feat-website-Polish-and-fix-UI-3466d73d365081f895aff84b594450c9)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL0424@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: github-actions <github-actions@github.com>
2026-04-22 18:45:27 -07:00
Alexander Brown
55c5fce522 ci: stabilize Vercel website preview URLs per PR (#11478)
## Summary

Make the website preview URL stable per PR and make deployments show up
correctly in the Vercel dashboard.

## Changes

- **What**:
- Pass git metadata (`githubCommitRef`, `githubCommitSha`,
`githubCommitAuthorLogin`, `githubCommitMessage`, `githubPrId`,
`githubRepo`) via `vercel deploy --meta` so deployments group by
branch/PR in the dashboard and pick up branch-scoped env vars.
- Alias each preview deploy to a stable per-PR hostname:
`comfy-website-preview-pr-<N>.vercel.app`. URL no longer changes between
pushes on the same PR.
- PR comment now shows the stable URL prominently, the per-commit URL as
subtext, plus a last-updated timestamp and short SHA so reviewers can
tell if the preview is current.
- User-controlled PR fields routed through env vars (no shell
interpolation of untrusted strings).

## Review Focus

- `PREVIEW_ALIAS_PREFIX` is set to `comfy-website-preview` — confirm
this subdomain pattern is free within the Vercel team (first deploy will
claim it).
- Production job is untouched.
- `vercel.json` keeps `github.enabled: false` — intentional, we stay
CLI-driven.

### Known limitation (out of scope)

Vercel Shareable Links are bound to a specific deployment ID. Aliasing
the stable hostname to a new deployment does **not** carry over
previously-issued share links. If the team needs share links to persist
across pushes, follow-up options: Protection Bypass for Automation
(project-level token) or Deployment Protection Exceptions (Pro+).

### Follow-ups

- Optional `vercel alias rm` on PR close to clean up stale aliases.

## Screenshots (if applicable)

N/A — CI config only. Verification will land on this PR's own preview
run.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11478-ci-stabilize-Vercel-website-preview-URLs-per-PR-3486d73d3650815ab24be1f7895cecc5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:27:44 +00:00
Alexander Brown
c1c3fba1ac refactor: extract shared resolve-pr-from-workflow-run action (#11336)
## Summary

Extract duplicated PR-number-resolution logic from
`workflow_run`-triggered workflows into a shared composite action at
`.github/actions/resolve-pr-from-workflow-run/`.

## Changes

- **What**: New composite action that resolves PR number from
`workflow_run` context using `pull_requests[0]` with
`listPullRequestsAssociatedWithCommit` fallback. Updated 4 consumer
workflows; removed dead artifact-stored PR metadata from 2 CI workflows.
- **Files touched**:
  - `.github/actions/resolve-pr-from-workflow-run/action.yaml` (new)
- `.github/workflows/pr-vercel-website-preview.yaml` (uses shared
action)
- `.github/workflows/pr-report.yaml` (uses shared action with
`check-staleness: true`)
- `.github/workflows/ci-tests-storybook-forks.yaml` (replaced
`pulls.list` scan)
- `.github/workflows/ci-tests-e2e-forks.yaml` (replaced `pulls.list`
scan)
- `.github/workflows/ci-size-data.yaml` (removed dead
`number.txt`/`base.txt`/`head-sha.txt` writes)
- `.github/workflows/ci-perf-report.yaml` (removed dead `perf-meta`
artifact)

## Review Focus

- The fork workflows previously used `pulls.list` (fetches all open PRs,
linear scan by SHA). The shared action uses the more targeted
`workflow_run.pull_requests[0]` + `listPullRequestsAssociatedWithCommit`
fallback.
- `coverage-slack-notify.yaml` was intentionally left unchanged — it
parses merged commit messages on `main` pushes, which is a different use
case.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11336-refactor-extract-shared-resolve-pr-from-workflow-run-action-3456d73d365081e5b8f5ea29c020763e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: bymyself <cbyrne@comfy.org>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-20 10:20:41 -07:00
Christian Byrne
3b4811b00d feat: deploy E2E coverage HTML report to GitHub Pages (#11291)
## Summary

Browsable E2E coverage report deployed to GitHub Pages on every main
merge, replacing the current workflow of downloading LCOV artifacts and
using an external viewer.

## Changes

- **What**: After merging shard LCOVs, run `genhtml` to produce an HTML
report with per-file line coverage. On `main`, deploy to GitHub Pages
via `actions/deploy-pages`. For PR runs, the HTML report is still
available as the `e2e-coverage-html` artifact.
- **Dependencies**: None new — `genhtml` is part of the `lcov` package
already installed in the workflow.

## Review Focus

- **GitHub Pages must be enabled**: Settings → Pages → Source → "GitHub
Actions". Without this the deploy job will fail silently.
- The deploy job only runs for `main` branch (`if:
github.event.workflow_run.head_branch == 'main'`) so PR coverage doesn't
clobber the deployed report.
- Added `pages: write` and `id-token: write` permissions to the workflow
for the Pages deployment.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11291-feat-deploy-E2E-coverage-HTML-report-to-GitHub-Pages-3446d73d36508136ba6fd806690c9cfc)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-04-18 15:40:59 -07:00
Christian Byrne
836cab1b38 fix: deploy website previews via GitHub Actions instead of Vercel auto-deploy (#11289)
## Summary

Vercel's auto-deploy triggers on every PR because files outside
workspace packages (e.g. `browser_tests/`, `src/`) are treated as global
changes by the monorepo skip logic.

## Changes

- **What**: Replace Vercel's GitHub integration with a GitHub Action
(`ci-vercel-website-preview.yaml`) that uses `paths:` filtering to only
deploy when `apps/website/`, `packages/design-system/`, or
`packages/tailwind-utils/` change. Add `vercel.json` with
`github.enabled: false` to disable Vercel's automatic GitHub
integration.

## Setup required after merge

Three GitHub repo secrets are needed. All secrets are scoped per-project
using the `VERCEL_WEBSITE_*` prefix. Future Vercel projects would follow
the same convention (e.g. `VERCEL_DOCS_*`).

### Step 1: Create a Vercel API Token

1. Go to [vercel.com/account/tokens](https://vercel.com/account/tokens)
2. Click **Create Token**
3. Fill in the form:
   - **Token Name**: `github-actions-website`
- **Scope**: Select the **Comfy-Org** team (not "Full Account" — scope
it to the team that owns the project)
- **Expiration**: Choose **No Expiration** (or set a long expiration
like 1 year — if it expires the workflow will silently fail)
4. Click **Create**
5. **Copy the token immediately** — it is only shown once

### Step 2: Get Vercel Org ID and Project ID

1. Go to
[vercel.com/comfyui/website-frontend/settings](https://vercel.com/comfyui/website-frontend/settings)
2. Scroll down to the **Project ID** field — copy this value
3. Go to
[vercel.com/teams/comfyui/settings](https://vercel.com/teams/comfyui/settings)
(Team Settings → General)
4. Find the **Vercel ID** field (also called Team ID / Org ID) — copy
this value

### Step 3: Add secrets to GitHub

1. Go to
[github.com/Comfy-Org/ComfyUI_frontend/settings/secrets/actions](https://github.com/Comfy-Org/ComfyUI_frontend/settings/secrets/actions)
2. Click **New repository secret** and add each of the three secrets:

| Secret name | Value |
|---|---|
| `VERCEL_WEBSITE_TOKEN` | The token from Step 1 |
| `VERCEL_WEBSITE_ORG_ID` | The team/org ID from Step 2 |
| `VERCEL_WEBSITE_PROJECT_ID` | The project ID from Step 2 |

> **Note:** The `vercel.json` added by this PR (`github.enabled: false`)
automatically disables Vercel's built-in auto-deploy — no dashboard
changes needed.

## Review Focus

- Verify the `paths:` filter covers all dependencies of `apps/website`
- Confirm the PR comment logic is sound (creates once, updates on
subsequent pushes)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-04-17 17:54:26 +00:00
Christian Byrne
5c07198acb fix: add validation to E2E coverage shard merge (#11290)
## Summary

Add a validation step after merging E2E coverage shards to detect data
loss and improve observability.

## Changes

- **What**: After `lcov -a` merges shard LCOVs, a new step parses merged
+ per-shard stats (source files, lines hit) and writes them to the
**GitHub Actions job summary** as a markdown table. If merged `LH`
(lines hit) is less than any single shard's `LH`, an error annotation is
emitted — this invariant should never be violated since merging should
only add coverage.
- Helps diagnose the 68% → 42% E2E coverage drop after sharding was
introduced.

## Review Focus

The step is informational — it emits `::error::` annotations but does
not `exit 1`, so it won't block the workflow. We can make it a hard
failure once we're confident the merge is stable.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11290-fix-add-validation-to-E2E-coverage-shard-merge-3446d73d365081c8a942e92deba92006)
by [Unito](https://www.unito.io)
2026-04-15 21:39:51 -07:00
Christian Byrne
033b3dad3a feat: add Slack notification workflow for coverage improvements (#10977)
## Summary

Adds a GitHub Actions workflow + TypeScript script that posts to Slack
when a merged PR improves unit or E2E test coverage.

## Changes

- **What**: New `coverage-slack-notify.yaml` workflow triggered on push
to main. Compares current coverage against previous baselines, generates
Slack Block Kit payload with progress bars and milestone celebrations,
posts to `#p-frontend-automated-testing`.
- **Script**: `scripts/coverage-slack-notify.ts` — parses lcov files,
computes deltas, detects milestone crossings (every 5%), builds Slack
payload. Pure functions exported for testability.
- **Tests**: 26 unit tests in `scripts/coverage-slack-notify.test.ts`
covering all pure functions including edge cases (malformed lcov, exact
boundaries, zero coverage).

### Security hardening
- All `${{ }}` expressions moved from `run:` blocks to `env:` variables
- `SLACK_BOT_TOKEN` passed via env var, not inline
- Unique heredoc delimiter (timestamp-based) prevents payload injection
- `parseInt` fallback (`|| 0`) guards against malformed lcov
- PR regex anchored to first line of commit message

### Robustness
- `continue-on-error: true` on Slack post step (outage does not fail the
job)
- Baseline save guarded by `steps.unit-tests.outcome == success`
(prevents corrupt baselines on test failure)
- Channel ID commented for maintainability
- Top-level `text` field added for Slack mobile push notifications
- Author linked to GitHub profile instead of bare `@username`

## Review Focus

- Workflow step ordering and conditional logic
- Security of expression handling and secret management
- Slack payload structure and Block Kit formatting

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10977-feat-add-Slack-notification-workflow-for-coverage-improvements-33d6d73d3650819c8950f483c83f297c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-14 20:58:47 -07:00
Christian Byrne
aeedb60628 fix(ci): resolve pnpm version in release workflow for frontend/ checkout path (#11224)
The release workflow checks out to `frontend/` subdirectory, but
`pnpm/action-setup` looks for `package.json` at the repo root by
default. This causes `No pnpm version is specified` failures.

Adds `package_json_file: frontend/package.json` so the action can read
the `packageManager` field. Same pattern used in #10972 for the
version-bump workflow.

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11224-fix-ci-resolve-pnpm-version-in-release-workflow-for-frontend-checkout-path-3426d73d365081c28d16cb01bf8218ef)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-13 21:41:22 -07:00
Christian Byrne
43fb5a8b19 ops: add patch release support to ComfyUI release workflow (#11223)
## Summary

Add `release_type` input (`minor`/`patch`) to the release workflow so
patch releases can target the current production branch instead of
always preferring the next minor.

## Problem

When a patch release is needed for `core/1.42` but `core/1.43` already
exists, the resolver always prefers `1.43`. There was no way to do a
patch release with PyPI publish + ComfyUI PR for the current production
version.

## Changes

- Rename workflow from "Release: Bi-weekly ComfyUI" → "Release: ComfyUI"
(serves both cadences)
- Add `release_type` choice input: `minor` (default, bi-weekly) vs
`patch` (hotfix for current production version)
- Update `resolve-comfyui-release.ts` to read `RELEASE_TYPE` env var for
branch targeting
- Scheduled runs continue to work as before (default to `minor`)

## Usage

```bash
# Bi-weekly minor release (or just let the schedule run)
gh workflow run release-biweekly-comfyui.yaml --ref main

# Patch release for current production version
gh workflow run release-biweekly-comfyui.yaml --ref main --field release_type=patch
```

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11223-ops-add-patch-release-support-to-ComfyUI-release-workflow-3426d73d365081498c15ff978a7f1116)
by [Unito](https://www.unito.io)
2026-04-13 21:10:17 -07:00
pythongosssss
c0871ba219 ci: Update actions for queue merge validation (#11114)
## Summary

PR merge queue was enabled but actions were not updated to trigger on
`merge_group`:

https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue#triggering-merge-group-checks-with-github-actions

## Changes

- **What**: 
- `.github/actions/lint-format-verify/action.yml` extrated shared Verify
lint and format steps
- `.github/workflows/ci-lint-format.yaml` updated to use shared
composite action
- `.github/workflows/ci-lint-format-queue.yaml` new action that triggers
on merge_group to validate format
- `.github/workflows/ci-tests-e2e.yaml` triggers on merge_group
- `.github/workflows/ci-tests-unit.yaml` triggers on merge_group

## Review Focus

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11114-ci-Update-actions-for-queue-merge-validation-33e6d73d3650815f8c88f40736b513ec)
by [Unito](https://www.unito.io)
2026-04-10 17:09:48 +00:00
Christian Byrne
c671a33182 fix(ci): resolve pnpm version conflict in version bump workflow (#10972)
## Summary

Removes hardcoded `version: 10` from `pnpm/action-setup` and instead
injects the `packageManager` field into `package.json` when absent
(legacy `core/*` branches).

## Why

PR #10952 re-added `version: 10` to fix old branches lacking
`packageManager`. But `main` now has **both** `version: 10` (workflow)
and `packageManager: pnpm@10.33.0` (`package.json`), causing
`pnpm/action-setup` to error with:

> Multiple versions of pnpm specified

Failed run:
https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/24158869559

This fix handles both cases:
- **`main`**: has `packageManager` → action reads it directly, no
conflict
- **`core/1.42` etc**: missing `packageManager` → step injects it before
the action runs

E2E test not applicable — this is a CI workflow configuration change
with no user-facing behavior.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10972-fix-ci-resolve-pnpm-version-conflict-in-version-bump-workflow-33c6d73d36508112802df75c0dd5ea50)
by [Unito](https://www.unito.io)
2026-04-08 15:13:33 -07:00
Christian Byrne
194baf7aee fix(ci): restore pnpm version input for core/* branch compatibility (#10952)
## Summary

Restores `version: 10` to the `pnpm/action-setup` step in
`release-version-bump.yaml`.

## Why

PR #10687 removed the explicit `version: 10` input, relying on
`packageManager` in `package.json` instead. However, this workflow
checks out a **target branch** (e.g. `core/1.42`, `core/1.41`) that
predates #10687 and lacks the `packageManager` field — causing the
action to fail with:

> Error: No pnpm version is specified.

Failed run:
https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/24110739586

Adding `version: 10` back is safe — the action only errors when
`version` and `packageManager` **conflict**, and `pnpm@10.x` is
compatible.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10952-fix-ci-restore-pnpm-version-input-for-core-branch-compatibility-33c6d73d3650819282bbf6c194d0d2f1)
by [Unito](https://www.unito.io)
2026-04-07 17:45:42 -07:00
Christian Byrne
ff0453416a ci: pass CODECOV_TOKEN and add codecov.yml for PR comments (#10774)
## What

Follow-up to #10575. Pass `CODECOV_TOKEN` secret to codecov upload
action and add `codecov.yml` config so Codecov posts coverage diff
comments on PRs.

## Changes

- `ci-tests-unit.yaml`: add `token: ${{ secrets.CODECOV_TOKEN }}`
- `codecov.yml`: configure PR comment layout (header, diff, flags,
files)

## Manual Step Required

An admin needs to add the `CODECOV_TOKEN` secret to the repo:

1. Go to [codecov.io](https://app.codecov.io) → sign in → find
`Comfy-Org/ComfyUI_frontend` → Settings → General → copy the Repository
Upload Token
2. Go to [repo
secrets](https://github.com/Comfy-Org/ComfyUI_frontend/settings/secrets/actions)
→ New repository secret → name: `CODECOV_TOKEN`, value: the token

## Testing

Config-only change. Once the secret is added, the next PR will get a
Codecov coverage comment.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10774-ci-pass-CODECOV_TOKEN-and-add-codecov-yml-for-PR-comments-3346d73d36508169bac5e61eecc94063)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-07 15:52:34 -07:00
Christian Byrne
0b689a3c3c chore: remove pull-model registry type gen workflow (#9957)
## Summary

Removes `api-update-registry-api-types.yaml` — the workflow that cloned
the private `comfy-api` repo using a PAT to generate registry API types.
This is a security risk: a PAT with private repo access stored on a
public repo.

Type generation now happens in `comfy-api` and pushes PRs to this repo
instead.

### Action needed after merge

- Remove the `COMFY_API_PAT` secret from this repo's settings (Settings
→ Secrets → Actions)

### Depends on

- https://github.com/Comfy-Org/comfy-api/pull/937 (must merge first)
- Refs: COM-16785

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9957-chore-remove-pull-model-registry-type-gen-workflow-3246d73d365081cd9dbad03597817f05)
by [Unito](https://www.unito.io)
2026-04-06 18:21:38 -07:00
Christian Byrne
32ff1a5bdb feat(website): add SEO, sitemap, redirects, CI workflow, and Vercel config (#10156)
## Summary

<!-- One sentence describing what changed and why. -->

## Changes

- **What**: <!-- Core functionality added/modified -->
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

## Review Focus

<!-- Critical design decisions or edge cases that need attention -->

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10156-feat-website-add-SEO-sitemap-redirects-CI-workflow-and-Vercel-config-3266d73d3650816ab9eaebd11072d481)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-06 18:20:28 -07:00
Christian Byrne
1ffd92f910 config: add vitest coverage include pattern + lcov reporter (#10575)
## What

- Add `include: ['src/**/*.{ts,vue}']` to vitest coverage config so ALL
source files appear in reports (previously only imported files showed
up)
- Add `lcov` reporter for CI integration and VS Code coverage gutter
- Add `exclude` patterns for test files, locales, litegraph, assets,
declarations, stories
- Add `test:coverage` npm script

## Why

Coverage reports currently only show files that are imported during test
runs. Adding the `include` pattern reveals the true gap — files with
zero coverage that were previously invisible. The lcov reporter enables
IDE integration and future CI coverage comments (Codecov/Coveralls).

## Testing

`npx tsc --noEmit` passes. No behavioral changes — this only affects
coverage reporting configuration.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10575-config-add-vitest-coverage-include-pattern-lcov-reporter-32f6d73d365081c8b59ad2316dd2b198)
by [Unito](https://www.unito.io)
2026-03-29 16:05:45 -07:00