feat: add npm publish workflow for @comfyorg/design-system - #14080
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds package publishing metadata and automated workflows for version bumps, pack validation, npm publication, release comments, and Slack notifications. ChangesDesign system release automation
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ReleaseWorkflow
participant PublishWorkflow
participant PackageRepository
participant NpmRegistry
participant Slack
ReleaseWorkflow->>PackageRepository: Resolve merged package version and dist-tag
ReleaseWorkflow->>PublishWorkflow: Pass version, ref, dist-tag, and npm token
PublishWorkflow->>PackageRepository: Validate ref and package manifest
PublishWorkflow->>NpmRegistry: Query package version
NpmRegistry-->>PublishWorkflow: Return version existence
PublishWorkflow->>NpmRegistry: Publish missing version
ReleaseWorkflow->>Slack: Send successful publication details
Possibly related PRs
Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1764 passed, 0 failed · 3 flaky📊 Browser Reports
📦 Bundle: 8.18 MB gzip ⚪ 0 BDetailsSummary
Category Glance App Entry Points — 3.66 kB (baseline 3.66 kB) • ⚪ 0 BMain entry bundles and manifests Status: 1 unchanged Graph Workspace — 1.29 MB (baseline 1.29 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration Status: 2 unchanged Views & Navigation — 112 kB (baseline 112 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces Status: 16 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens Status: 26 unchanged User & Accounts — 29.1 kB (baseline 29.1 kB) • ⚪ 0 BAuthentication, profile, and account management bundles Status: 10 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors Status: 7 unchanged UI Components — 70.7 kB (baseline 70.7 kB) • ⚪ 0 BReusable component library chunks Status: 15 unchanged Data & Services — 3.43 MB (baseline 3.43 MB) • ⚪ 0 BStores, services, APIs, and repositories Status: 17 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • ⚪ 0 BHelpers, composables, and utility bundles Status: 36 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.6 MB (baseline 12.6 MB) • ⚪ 0 BBundles that do not match a named category Status: 278 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-30T08:07:12.048Z",
"gitSha": "93f613e5a598c6dcad27c4fc96edb2501962add8",
"branch": "feat/publish-design-system-clean",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2111.2150000000156,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.790000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 654.2669999999999,
"heapDeltaBytes": 4561828,
"heapUsedBytes": 72178928,
"domNodes": 14,
"jsHeapTotalBytes": 20574208,
"scriptDurationMs": 26.477,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-idle",
"durationMs": 2049.1460000000643,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.799,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 498.383,
"heapDeltaBytes": 5151812,
"heapUsedBytes": 73013176,
"domNodes": 18,
"jsHeapTotalBytes": 20574208,
"scriptDurationMs": 21.679999999999996,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1907.5960000000123,
"styleRecalcs": 76,
"styleRecalcDurationMs": 42.193,
"layouts": 12,
"layoutDurationMs": 3.842,
"taskDurationMs": 929.2289999999999,
"heapDeltaBytes": -15282684,
"heapUsedBytes": 52461316,
"domNodes": -281,
"jsHeapTotalBytes": 20701184,
"scriptDurationMs": 122.764,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1904.6100000000479,
"styleRecalcs": 75,
"styleRecalcDurationMs": 43.473,
"layouts": 12,
"layoutDurationMs": 3.6729999999999996,
"taskDurationMs": 955.2610000000001,
"heapDeltaBytes": -16089276,
"heapUsedBytes": 51806000,
"domNodes": -284,
"jsHeapTotalBytes": 20701184,
"scriptDurationMs": 129.054,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1754.5470000000023,
"styleRecalcs": 33,
"styleRecalcDurationMs": 20.557000000000002,
"layouts": 6,
"layoutDurationMs": 0.7750000000000001,
"taskDurationMs": 436.624,
"heapDeltaBytes": 7904652,
"heapUsedBytes": 75837900,
"domNodes": 78,
"jsHeapTotalBytes": 20049920,
"scriptDurationMs": 26.461000000000002,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1754.8610000000053,
"styleRecalcs": 32,
"styleRecalcDurationMs": 20.509,
"layouts": 6,
"layoutDurationMs": 0.7789999999999999,
"taskDurationMs": 466.797,
"heapDeltaBytes": 7971772,
"heapUsedBytes": 75871848,
"domNodes": 78,
"jsHeapTotalBytes": 20574208,
"scriptDurationMs": 29.652000000000005,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 663.8340000000085,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.774000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 419.36699999999996,
"heapDeltaBytes": -12233072,
"heapUsedBytes": 55648880,
"domNodes": 20,
"jsHeapTotalBytes": 21884928,
"scriptDurationMs": 59.861000000000004,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "dom-widget-clipping",
"durationMs": 617.5100000000384,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.93,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 401.6650000000001,
"heapDeltaBytes": -11728144,
"heapUsedBytes": 56247044,
"domNodes": 20,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 60.28,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2047.4820000000022,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.511000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 713.047,
"heapDeltaBytes": 22203292,
"heapUsedBytes": 81073912,
"domNodes": -279,
"jsHeapTotalBytes": 4517888,
"scriptDurationMs": 107.10399999999998,
"eventListeners": -176,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-idle",
"durationMs": 2042.0500000000175,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.177,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 748.043,
"heapDeltaBytes": 8234640,
"heapUsedBytes": 67362036,
"domNodes": -280,
"jsHeapTotalBytes": 4780032,
"scriptDurationMs": 122.17999999999999,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2239.377999999988,
"styleRecalcs": 69,
"styleRecalcDurationMs": 15.385,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1354.08,
"heapDeltaBytes": 5461744,
"heapUsedBytes": 66083324,
"domNodes": -284,
"jsHeapTotalBytes": 4481024,
"scriptDurationMs": 442.966,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2205.1179999999704,
"styleRecalcs": 68,
"styleRecalcDurationMs": 15.980999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1383.276,
"heapDeltaBytes": 5169008,
"heapUsedBytes": 65012716,
"domNodes": -286,
"jsHeapTotalBytes": 4743168,
"scriptDurationMs": 429.724,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-zoom",
"durationMs": 3176.56599999998,
"styleRecalcs": 65,
"styleRecalcDurationMs": 16.753,
"layouts": 60,
"layoutDurationMs": 8.486,
"taskDurationMs": 1527.8960000000002,
"heapDeltaBytes": 23781244,
"heapUsedBytes": 85259708,
"domNodes": 12,
"jsHeapTotalBytes": 7602176,
"scriptDurationMs": 547.852,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3298.5570000000735,
"styleRecalcs": 65,
"styleRecalcDurationMs": 16.753000000000004,
"layouts": 60,
"layoutDurationMs": 8.699,
"taskDurationMs": 1679.6109999999999,
"heapDeltaBytes": 2906100,
"heapUsedBytes": 65297344,
"domNodes": -286,
"jsHeapTotalBytes": 8974336,
"scriptDurationMs": 596.588,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2040.0300000000016,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.289000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 755.858,
"heapDeltaBytes": 8047832,
"heapUsedBytes": 68927052,
"domNodes": -281,
"jsHeapTotalBytes": 4780032,
"scriptDurationMs": 122.03200000000001,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2073.694000000046,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.862999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 824.4830000000001,
"heapDeltaBytes": 8766936,
"heapUsedBytes": 69219032,
"domNodes": -284,
"jsHeapTotalBytes": 4517888,
"scriptDurationMs": 134.327,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 617.3530000000369,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.112000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 408.812,
"heapDeltaBytes": -12016944,
"heapUsedBytes": 55850108,
"domNodes": 20,
"jsHeapTotalBytes": 22147072,
"scriptDurationMs": 125.45599999999999,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 687.9999999999882,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.959000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 458.755,
"heapDeltaBytes": -11504644,
"heapUsedBytes": 56508032,
"domNodes": 20,
"jsHeapTotalBytes": 22147072,
"scriptDurationMs": 133.542,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2023.6409999999978,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.794,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 506.2180000000001,
"heapDeltaBytes": 4643016,
"heapUsedBytes": 72610664,
"domNodes": 20,
"jsHeapTotalBytes": 20574208,
"scriptDurationMs": 19.473,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2038.428999999951,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.381,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 509.752,
"heapDeltaBytes": 4752620,
"heapUsedBytes": 72586144,
"domNodes": 20,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 20.527000000000005,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1727.0209999999793,
"styleRecalcs": 78,
"styleRecalcDurationMs": 42.768,
"layouts": 16,
"layoutDurationMs": 5.038,
"taskDurationMs": 859.515,
"heapDeltaBytes": -20185936,
"heapUsedBytes": 47792868,
"domNodes": -280,
"jsHeapTotalBytes": 19914752,
"scriptDurationMs": 98.512,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1736.5210000000388,
"styleRecalcs": 76,
"styleRecalcDurationMs": 40.173,
"layouts": 16,
"layoutDurationMs": 4.976,
"taskDurationMs": 882.926,
"heapDeltaBytes": -20624952,
"heapUsedBytes": 47378864,
"domNodes": -283,
"jsHeapTotalBytes": 20701184,
"scriptDurationMs": 99.653,
"eventListeners": -148,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-transition-enter",
"durationMs": 1402.078999999958,
"styleRecalcs": 18,
"styleRecalcDurationMs": 30.346999999999998,
"layouts": 14,
"layoutDurationMs": 11.692999999999998,
"taskDurationMs": 1001.57,
"heapDeltaBytes": 29121280,
"heapUsedBytes": 97541304,
"domNodes": 13673,
"jsHeapTotalBytes": 15990784,
"scriptDurationMs": 49.519000000000005,
"eventListeners": 2371,
"totalBlockingTimeMs": 122,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8300.096999999994,
"styleRecalcs": 250,
"styleRecalcDurationMs": 43.204,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4578.563,
"heapDeltaBytes": 7160880,
"heapUsedBytes": 66579700,
"domNodes": -282,
"jsHeapTotalBytes": 7069696,
"scriptDurationMs": 1376.2489999999998,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8574.157000000014,
"styleRecalcs": 251,
"styleRecalcDurationMs": 45.803,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 5151.971,
"heapDeltaBytes": 18434844,
"heapUsedBytes": 77270964,
"domNodes": -280,
"jsHeapTotalBytes": 9428992,
"scriptDurationMs": 1572.051,
"eventListeners": -126,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333338,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 18244.096999999954,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18224.457000000002,
"heapDeltaBytes": -66474024,
"heapUsedBytes": 155642028,
"domNodes": -8312,
"jsHeapTotalBytes": -14360576,
"scriptDurationMs": 612.3190000000001,
"eventListeners": -16385,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 18426.03299999996,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18403.722999999998,
"heapDeltaBytes": -55074708,
"heapUsedBytes": 166028544,
"domNodes": -8312,
"jsHeapTotalBytes": -15409152,
"scriptDurationMs": 592.223,
"eventListeners": -16387,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 22587.136999999984,
"styleRecalcs": 163,
"styleRecalcDurationMs": 25.693999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 22506.404,
"heapDeltaBytes": -44050816,
"heapUsedBytes": 168962440,
"domNodes": -8312,
"jsHeapTotalBytes": -13574144,
"scriptDurationMs": 913.9229999999999,
"eventListeners": -16381,
"totalBlockingTimeMs": 584,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 22930.537999999957,
"styleRecalcs": 169,
"styleRecalcDurationMs": 27.110999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 22904.902,
"heapDeltaBytes": -31581064,
"heapUsedBytes": 177490692,
"domNodes": -8312,
"jsHeapTotalBytes": -16003072,
"scriptDurationMs": 950.897,
"eventListeners": -16383,
"totalBlockingTimeMs": 684,
"frameDurationMs": 18.330000000000048,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 459.25099999999475,
"styleRecalcs": 14,
"styleRecalcDurationMs": 19.904999999999998,
"layouts": 3,
"layoutDurationMs": 0.608,
"taskDurationMs": 120.21799999999999,
"heapDeltaBytes": -16025292,
"heapUsedBytes": 50964356,
"domNodes": 130,
"jsHeapTotalBytes": 7729152,
"scriptDurationMs": 10.755999999999998,
"eventListeners": 67,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 462.509999999952,
"styleRecalcs": 12,
"styleRecalcDurationMs": 18.137,
"layouts": 2,
"layoutDurationMs": 0.45699999999999996,
"taskDurationMs": 110.91799999999999,
"heapDeltaBytes": -16067852,
"heapUsedBytes": 50683792,
"domNodes": 117,
"jsHeapTotalBytes": 7991296,
"scriptDurationMs": 9.600000000000001,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
}
]
} |
🌐 Website E2ETip All tests passed.
🔗 Website PreviewWebsite Preview: https://comfy-website-preview-pr-14080.vercel.app This commit: https://website-frontend-ob2tbqmq1-comfyui.vercel.app Last updated: 2026-07-30T07:54:13Z for |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/publish-design-system.yaml:
- Around line 35-37: Update the concurrency.group in the publish workflow to use
a static package identifier together with inputs.version, removing
github.workflow and inputs.dist_tag from the key so all callers and dist-tags
serialize publishing for the same package version. Keep cancel-in-progress set
to false.
- Around line 104-111: Update the publish workflow’s package validation
alongside the existing VERSION check to assert that NAME equals
"`@comfyorg/design-system`" before publishing. Emit an error and exit nonzero on
mismatch, ensuring the guard runs before pnpm publish while preserving the
existing version validation and GITHUB_OUTPUT behavior.
- Around line 46-55: Extend the “Validate inputs” step to validate DIST_TAG
before publishing, rejecting range-like or otherwise invalid tag values such as
“v1.4”. Pass the workflow’s dist_tag input into the step environment and add a
simple validation that accepts only a valid non-range tag, exiting with a clear
GitHub Actions error before pnpm publish runs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a4e7cbe4-9fd1-40ca-88f8-11e1ba038201
📒 Files selected for processing (2)
.github/workflows/publish-design-system.yamlpackages/design-system/package.json
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14080 +/- ##
==========================================
- Coverage 79.23% 78.77% -0.47%
==========================================
Files 1754 1760 +6
Lines 101608 103413 +1805
Branches 34201 34652 +451
==========================================
+ Hits 80510 81461 +951
- Misses 20663 21504 +841
- Partials 435 448 +13
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Adds the GitHub Actions publish workflow and proper package.json fields (files, exports, publishConfig, license, repository) so the design system can be published to npm and consumed by external repos (platform.comfy.org, docs.comfy.org, etc.) without requiring monorepo membership. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Serialize publishing by version only (drop github.workflow/dist_tag from the concurrency key to prevent two runs racing to publish the same version). Assert package name before publishing. Validate the dist-tag using node-semver's validRange() directly, matching npm's own internal rejection logic exactly instead of an incomplete regex.
Release-labeled merges to packages/design-system/package.json now trigger an automatic publish, matching the existing desktop-ui pattern: version-bump-design-system.yaml opens a labeled version-bump PR; merging it runs publish-design-system-on-merge.yaml, which resolves the dist-tag, publishes, posts a PR comment via the shared comment-release-links action, and notifies Slack. Slack channel ID is a placeholder pending the real #product-design channel ID.
New workflow scoped to packages/design-system/** runs the package's typecheck script and asserts the npm tarball only contains src/css/src/icons, catching a future files-field misconfiguration before merge rather than at publish time. Also gitignore *.tsbuildinfo, generated by this new typecheck step under the repo's incremental TS config but never previously ignored.
d248abc to
af346ae
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/publish-design-system-on-merge.yaml:
- Around line 94-113: Update the “Post to Slack” workflow step to replace
SLACK_CHANNEL_ID’s TODO_PRODUCT_DESIGN_CHANNEL_ID value with the real
product-design channel ID. Capture and parse the chat.postMessage response from
curl, then validate its .ok field and fail the step when Slack reports false,
while preserving the existing notification payload and authentication.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2cd27799-5627-478e-8b16-c90b2049bb88
📒 Files selected for processing (7)
.github/actions/comment-release-links/action.yaml.github/workflows/ci-design-system-pack.yaml.github/workflows/publish-design-system-on-merge.yaml.github/workflows/publish-design-system.yaml.github/workflows/version-bump-design-system.yaml.gitignorepackages/design-system/package.json
Replaces the placeholder with the real channel ID for design-system release notifications.
Slack's chat.postMessage always returns HTTP 200, even on API-level errors like an invalid channel ID — curl -f can't detect that. Check the response body's ok field instead.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/publish-design-system-on-merge.yaml:
- Around line 107-111: Add explicit curl connection and total request timeouts
to the Slack API call assigning RESPONSE in the publish workflow, using the
existing request unchanged otherwise. Do not add retries, since they could
create duplicate Slack messages.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: bb5fce38-8dd1-4734-a186-f9693fb72ea0
📒 Files selected for processing (1)
.github/workflows/publish-design-system-on-merge.yaml
A stalled Slack API could otherwise hang the release workflow indefinitely. No retries, to avoid duplicate Slack messages.
DrJKL
left a comment
There was a problem hiding this comment.
Okay, like, overall this is totally sound and already reuses the important release pieces: the merge workflow calls the reusable publisher, release comments use comment-release-links, and version bumps follow the existing Desktop UI pattern. There is no existing generic package publisher or version-bump workflow to reuse without adding, like, a whole configurable abstraction. Also, please do not move these jobs onto comfyui-ci-container:0.0.21: that image is a heavyweight Playwright/ComfyUI environment, still needs pnpm install, lacks npm registry authentication, loses the setup-node cache, and requires GHCR permissions. So the regular runner is actually the simpler choice. Just three tiny cleanup notes below; net reduction is about nine lines, or roughly seventeen if --ignore-scripts is not required.
| cache: 'pnpm' | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile --ignore-scripts |
There was a problem hiding this comment.
❓ q: This Node/pnpm/install block is, like, basically what .github/actions/setup-frontend already does. If --ignore-scripts is not intentional, replace lines 22–32 with that composite action; otherwise keep this explicit because the shared action changes install behavior.
There was a problem hiding this comment.
Intentional — setup-frontend's install step doesn't support --ignore-scripts, and this check only needs typecheck + pack, not a full build, so skipping scripts keeps it fast. Keeping the explicit block here.
Generated by Claude Code
There was a problem hiding this comment.
How much faster is it, with concrete measurements. @claude
There was a problem hiding this comment.
Also, speed isn't as important as simplicity for infrequent workflows like this. Don't optimize prematurely.
There was a problem hiding this comment.
Retracting the "faster" claim — it was never actually measured, so it wasn't a real justification. Checked what --ignore-scripts was actually skipping here: the only lifecycle script is root prepare (husky install + a git config, both || true), which has no effect on typecheck or pack correctness — so there was no real correctness reason for it either. Switched this job to ./.github/actions/setup-frontend in ea88f49, dropping the duplicated manual block.
Generated by Claude Code
| run: | | ||
| set -euo pipefail | ||
| UNEXPECTED=$(pnpm -C packages/design-system pack --dry-run --json 2>/dev/null \ | ||
| | node -pe " |
There was a problem hiding this comment.
Node script inside a bash script in the yaml...
There was a problem hiding this comment.
Not uncommon
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| SEMVER_REGEX='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' |
- reuse the semver package for version validation instead of a hand-rolled regex, consistent with the existing dist-tag check - drop the unused id on the release-comment step - drop the PR-body capitalization step and use the raw input directly
de6779a
DrJKL
left a comment
There was a problem hiding this comment.
Like, one tiny cleanup for the pack check: let the JSON tool do the JSON work.
| UNEXPECTED=$(pnpm -C packages/design-system pack --dry-run --json 2>/dev/null \ | ||
| | node -pe " | ||
| const pkg = JSON.parse(require('fs').readFileSync(0, 'utf8')) | ||
| pkg.files | ||
| .map(f => f.path) | ||
| .filter(p => p !== 'package.json' && p !== 'LICENSE' && !p.startsWith('src/css/') && !p.startsWith('src/icons/')) | ||
| .join('\n') | ||
| ") |
There was a problem hiding this comment.
Like, can we please not nest JavaScript inside Bash inside YAML? jq already ships on the Ubuntu runner and says exactly which paths we reject. Dropping 2>/dev/null also keeps pack failures visible. This is, honestly, way easier to read:
| UNEXPECTED=$(pnpm -C packages/design-system pack --dry-run --json 2>/dev/null \ | |
| | node -pe " | |
| const pkg = JSON.parse(require('fs').readFileSync(0, 'utf8')) | |
| pkg.files | |
| .map(f => f.path) | |
| .filter(p => p !== 'package.json' && p !== 'LICENSE' && !p.startsWith('src/css/') && !p.startsWith('src/icons/')) | |
| .join('\n') | |
| ") | |
| UNEXPECTED=$( | |
| pnpm -C packages/design-system pack --dry-run --json | | |
| jq -r ' | |
| .files[].path | |
| | select( | |
| . != "package.json" | |
| and . != "LICENSE" | |
| and (startswith("src/css/") | not) | |
| and (startswith("src/icons/") | not) | |
| ) | |
| ' | |
| ) |
There was a problem hiding this comment.
Fixed — replaced the node -pe JSON parsing with the suggested jq -r pipeline and dropped 2>/dev/null so pack failures stay visible, in ef2aec6.
Generated by Claude Code
DrJKL
left a comment
There was a problem hiding this comment.
Like, one follow-up simplification for version validation.
| - name: Validate version input | ||
| env: | ||
| VERSION: ${{ inputs.version }} | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| if ! node -e "process.exit(require('semver').valid(process.argv[1]) ? 0 : 1)" "$VERSION"; then | ||
| echo "::error title=Invalid version::Version '$VERSION' must follow semantic versioning (x.y.z[-suffix][+build])" >&2 | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
Like, the giant regex is gone, but now we're maintaining the same redundant check with inline Node. Verify package already requires the input to equal package.json, and pnpm publish validates that package version. Can we just delete this step? If early validation really matters, pnpm exec semver "$VERSION" > /dev/null is the cleaner fallback.
| - name: Validate version input | |
| env: | |
| VERSION: ${{ inputs.version }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if ! node -e "process.exit(require('semver').valid(process.argv[1]) ? 0 : 1)" "$VERSION"; then | |
| echo "::error title=Invalid version::Version '$VERSION' must follow semantic versioning (x.y.z[-suffix][+build])" >&2 | |
| exit 1 | |
| fi |
There was a problem hiding this comment.
Agreed, deleted the "Validate version input" step in 4b07452 — Verify package already pins the input to packages/design-system/package.json's version and pnpm publish validates it too, so the extra semver check was redundant.
Generated by Claude Code
…flow The Verify package step already requires the version input to exactly match packages/design-system/package.json, and pnpm publish validates the package version itself, making the separate semver check redundant.
The manual node/pnpm/install block duplicated setup-frontend without a real correctness need for --ignore-scripts; the only skipped lifecycle script is a fail-open husky/git-config prepare step.
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
…ckage (Comfy-Org#14417) Follow-up to Comfy-Org#14080. Two packaging gaps found while diagnosing the failed first publish of `@comfyorg/design-system` ([run 30579592610](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/30579592610)). - **No README in the tarball.** `pnpm pack` produced `package.json`, `LICENSE`, `src/css`, `src/icons` — nothing else. The npm page would render empty, which defeats the point of publishing this for platform.comfy.org to align on. - **`tailwindcss` was only a devDependency.** `src/css/style.css` imports `tailwindcss/theme` and `tailwindcss/utilities`, and both `iconifyDynamicPlugin.ts` and `lucideStrokePlugin.js` import `tailwindcss/plugin`. Consumers must supply Tailwind, but nothing declared it. Now a peer dep at `^4.1.0` — `@source inline()` in `style.css` requires 4.1+. Verified by packing the tarball: `README.md` is included and `peerDependencies` survives the `catalog:` rewrite. Not included here: `id-token: write` for npm trusted publishing. That can only land after `@comfyorg/design-system` exists on the registry, since npm requires the package to exist before a trusted publisher can be configured ([npm/cli#8544](npm/cli#8544)). Separate PR once the first version is up. Also bumps to **1.0.1** and carries the `Release` label, so merging publishes via `publish-design-system-on-merge`. That doubles as the first end-to-end test of the rotated `NPM_TOKEN` — a manual dispatch would have been a no-op, since the workflow's `Check if version already on npm` step finds 1.0.0 and skips publishing entirely.
Follow-up to Comfy-Org#14080 / Comfy-Org#14417. Writes down what the `@comfyorg/design-system` rollout actually cost, so the next package doesn't rediscover it. The expensive parts, all of which happen *after* the workflow looks correct: - **The first-publish 404.** npm returns `404 Not Found - PUT` when a token can publish existing packages in a scope but can't create a new name. It reads as "package doesn't exist" and sends you hunting for a workflow bug. Trusted publishing can't bootstrap either — npm needs the package to exist before you can configure a trusted publisher, so the ordering is fixed. - **`pnpm publish`, never `npm publish`.** Workspace packages use `catalog:` specifiers. pnpm rewrites them at pack time; npm ships the literal string and every consumer install breaks. Includes the unpack-and-check command. - **The pack guard needs `README.md`.** npm force-includes `package.json`, `LICENSE`, and `README.md` regardless of `files`. A guard allowlisting only the first two rejects any package with a readme — which is exactly what happened on Comfy-Org#14417. - **The consumer smoke test.** A green publish proves nothing. Install from a different repo, build, and grep the output to confirm the values landed. Also documents the trusted-publisher form fields (blank environment name, `npm publish` only) and why the token has to stay until an OIDC publish actually succeeds. --------- Co-authored-by: GitHub Action <action@github.com>
…4430) The trusted publisher for `@comfyorg/design-system` is now configured on npmjs.com, but the job can't mint an OIDC token without `id-token: write`. Every run so far has logged: ``` [WARN] Skipped OIDC: ERR_PNPM_ID_TOKEN_GITHUB_WORKFLOW_INCORRECT_PERMISSIONS ``` and silently fallen back to `NODE_AUTH_TOKEN`. **Two places need it, not one.** A reusable workflow cannot hold a permission its caller lacks. `publish-design-system-on-merge.yaml`'s `publish` job had no `permissions` block at all, so granting `id-token: write` only on the reusable job would still have produced a silent token fallback on the on-merge path — the one that actually ships releases. The `workflow_dispatch` path would have worked, which is exactly how this stays hidden. **Deliberately not removing `NODE_AUTH_TOKEN` yet.** There is no dry run — the workflow refuses to republish an existing version, so proving OIDC costs a real version number. Keeping the token means a broken exchange degrades to the path verified by 1.0.1 in [run 30589514181](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/30589514181) rather than failing a release. How to know it worked: on the next publish, `Skipped OIDC` should be gone from the log. To prove it before a real release, dispatch `publish-design-system.yaml` against this branch with a prerelease version and `dist_tag: next`. Revert is two lines. **Possible blocker worth knowing about.** [pnpm#11513](pnpm/pnpm#11513) (pnpm publish + OIDC failing) was closed in May 2026 — but it was closed when the reporter moved off a specific `pnpm/action-setup` commit, not by a pnpm release. This repo pins that exact SHA (`fc06bc1257f3…`, v4.4.0) in every workflow; latest is v6.0.9. If OIDC still falls back after this merges, that pin is the first suspect, and it would affect `desktop-ui` publishing too. Bumping it repo-wide is a major-version jump and belongs in its own PR. Context: follow-up to Comfy-Org#14080 and Comfy-Org#14417.
Summary
Add a GitHub Actions publish workflow and proper package.json metadata so
@comfyorg/design-systemcan be published to npm and consumed by external repos.Changes
.github/workflows/publish-design-system.yaml— manual (workflow_dispatch) and composable (workflow_call) publish workflow for@comfyorg/design-system; addsfiles,exports(icons),publishConfig,license,repository,homepage,authortopackages/design-system/package.jsonReview Focus
Workflow follows the existing
publish-desktop-bridge-typespattern exactly: semver validation → version/npm existence check → publish withNPM_TOKEN. Thefilesfield scopes the tarball tosrc/cssandsrc/iconsonly (no tsconfig, no devDependencies, no root package.json noise).To trigger a first publish: bump
versioninpackages/design-system/package.json, then run "Publish Design System" from Actions with that version.