1. 为什么我给Qwen-Image-Edit-F2P加持续集成做ComfyUI自定义节点的开发者大概都有过这种经历本地跑得好好的节点拉取最新代码后突然加载不出来或者换一台机器、换一个Python版本之前能出的图就开始报错。Qwen-Image-Edit-F2P这个节点包也不例外。它本质上是把Qwen图像编辑能力封装成ComfyUI节点本身要处理模型加载、图像编码、文本条件、采样调度和VAE解码这一整条链路任何一个环节出问题最直接的表现就是工作流完全断掉。我最初也是靠纯手动测试改完代码启动ComfyUI打开工作流点执行盯着进度条看几分钟再等图片输出然后肉眼判断“图正不正常”。这套流程在开发阶段勉强够用但一旦开始频繁提交、多人协作或者要给用户发测试版手动验证就成了最大的瓶颈。很多问题不是逻辑写错了而是环境差异造成的本机有某个依赖别人没有你是Python 3.10用户是3.12你的ComfyUI是最新版用户还在旧版。这些环境型问题手动根本测不过来。所以我把目光放到持续集成上。GitHub Actions本身免费额度对开源项目很友好跑一个Linux或Windows虚拟环境装依赖、启动ComfyUI、提交工作流、检查输出全部可以自动化。之所以专门为Qwen-Image-Edit-F2P设计一套CI流程是因为这种图像编辑类节点跟普通WEB应用测试不一样它既要验证接口能不能调用又要验证ComfyUI加载节点时不会抛异常还得验证真正走一遍推理之后输出图片是否满足预期。这里面每一步都有坑不是简单跑一个pytest就行。这篇文章我从零开始拆解这套工作流的完整实现。不讲太多理论重点放在可复现的配置、命令和测试脚本上。适合正在维护ComfyUI自定义节点、或者想在本地做类似自动化验证的开发者参考。就算你维护的不是Qwen-Image-Edit-F2P这套思路也可以直接平移到你自己的节点项目上。2. 项目整体拆解与自动化方案选型2.1 Qwen-Image-Edit-F2P这个节点到底测什么先说清楚项目结构。Qwen-Image-Edit-F2P是一个ComfyUI自定义节点包通常包含__init__.py、核心节点实现文件、配置文件和依赖清单。__init__.py里暴露NODE_CLASS_MAPPINGSComfyUI启动时会扫描custom_nodes目录按包名加载并注册节点。如果__init__.py里import了不存在的模块或者某个依赖和ComfyUI已有依赖冲突整个ComfyUI可能连启动都失败这是最严重的一类问题。F2P这个后缀不同人有不同理解我对它的定位是“免费使用、非商业用途”的约定。不管命名含义如何从持续集成角度看我们要验证的事情是一样的模型权重能不能被正确加载CLIP和文本编码器是否正常工作输入图像是否经过正确的尺寸预处理编辑指令能否被转换成条件向量最终采样和VAE解码能不能落盘成有效图片。比普通节点多做一层的原因是图像编辑模型通常输入输出都要求图像而且对张量形状非常敏感。Qwen系列是自回归多模态模型输入图片要通过视觉编码器得到视觉token指令文本要通过语言模型编码成文本条件任何一个维度错误都会在推理阶段报shape mismatch。这类错误往往在本地特定显存配置下不出现换一个推理后端或换一张卡就出现所以自动化测试里必须包含真实的推理链路。2.2 ComfyUI自定义节点测试难在哪如果只是测普通Python函数直接对节点内部逻辑做单测就够了。但ComfyUI节点不是普通函数它被框架以特定的生命周期调用先通过NODE_CLASS_MAPPINGS注册然后在工作流执行时实例化再根据INPUT_TYPES里的定义接收输入最后执行FUNCTION指定的方法。节点内部还可能直接调用torch的GPU算子没法在纯逻辑层面验证行为是否正确。另一个难点是ComfyUI本身迭代速度很快。不同版本之间后端API地址变过前端保存工作流JSON的格式也变过有些节点还使用了内部装饰器。如果你不锁定ComfyUI版本就做CI今天能过的测试可能明天就挂而且挂的位置不是你写的那几行代码而是框架升级导致的兼容性问题。反过来讲这也是CI的价值所在它能第一时间暴露出“你的节点跟最新版ComfyUI不兼容”这个问题。图像模型测试还涉及权重下载。Qwen-Image-Edit-F2P所需的模型权重动辄几G字节CI服务器如果每次都重新下载一套流程跑完可能拖到十几分钟甚至因为下载中断直接失败。所以CI方案里必须规划缓存策略哪些模型放缓存哪些用测试专用的小模型替代哪些场景允许跳过推理只做静态校验。2.3 选型为什么用GitHub Actions而不是本地脚本方案对比下来GitHub Actions有几点优势。首先它对开源仓库免费并且支持Linux、Windows、macOS三种runner做跨平台验证不用自己准备机器。其次它天然集成在Git托管工作流里push和pull request都能触发测试还能在PR页面直接看到通过或失败的状态团队协作时沟通成本很低。有人可能会说我本地写一个shell脚本不也能自动启动ComfyUI再跑测试吗确实可以但本地脚本的可重复性差每个人的Python环境、显卡、依赖版本都不一样你今天跑通了不代表提交到仓库的代码能在别人机器上跑通。GitHub Actions每次都是干净环境从零安装依赖这恰恰能模拟用户拿到新机器后的体验。我最终确定的方案是在GitHub Actions上用CPU模式的ComfyUI跑冒烟测试和轻量级端到端测试。免费runner没有GPU但图像编辑模型的推理链路在CPU上是可以运行的只是慢。处理好超时时间和测试规模CPU测试完全够用。真正的大规模批量验证仍然留给本地GPUCI只负责守住“能不能跑、结果对不对”这条底线。2.4 测试分三层静态检查、冒烟验证、端到端回归整套自动化测试没有只写一个脚本而是拆成三层。最外层是静态检查只验证节点注册信息和输入输出类型是否符合约定速度快能在几秒内发现代码级错误。这一层不需要启动任何东西也没有网络依赖适合每次提交都跑。中间层是冒烟验证启动一个真正的ComfyUI服务端检查自定义节点是否被成功加载再调用系统接口确认服务在线。这层能发现依赖冲突、初始化异常、端口占用等问题。它不执行完整的图像生成整体耗时可以控制在1到2分钟。最内层是端到端回归用一份最少步骤的API-format工作流提交给ComfyUI执行等待输出图片再校验输出文件是否存在且非空图像尺寸是否符合预期。这一层最严格也最慢我会让它只在主分支push和发布tag时运行避免每次PR都耗费太多时间。三个层次互相配合既保证反馈速度又保证关键路径的可靠性。3. 环境准备与GitHub Actions工作流编写3.1 workflow文件结构与触发条件CI工作流文件放在仓库的.github/workflows/目录下通常命名为ci.yml。我先写一个最基础的骨架name: CI on: push: branches: [ main ] pull_request: jobs: test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest ] python-version: [ 3.10, 3.11 ] timeout-minutes: 60触发条件里push到主分支和所有pull request都会跑测试。fail-fast: false很关键它保证矩阵里多个任务互不影响即使其中一项失败其他任务也会继续跑完。这样你能看到矩阵全貌而不是等第一个任务失败后剩下的全部取消。有些开发者习惯用push:不带branches过滤这样所有分支推送都触发会浪费大量构建时长我一般只保留主干分支和PR。timeout-minutes: 60是防止任务卡死。ComfyUI启动失败时如果脚本在等待端口就绪循环里没有退出条件整个任务可能一直挂着。设置超时至少保证CI不会无限占用。3.2 在干净环境里准备ComfyUI运行环境GitHub Actions的runner是干净的需要从零拉取ComfyUI源码。具体步骤如下git clone --depth 1 https://github.com/ComfyUI/ComfyUI.git comfyui cd comfyui python -m venv venv source venv/bin/activate pip install --upgrade pip pip install -r requirements.txt这套命令看起来简单但有几个坑。--depth 1是为了只拉取最新提交加快速度如果你需要锁定特定版本可以加上--branch v0.2.x之类的参数。Python虚拟环境必须创建否则runner全局环境里可能已经装了其他Python包污染ComfyUI的依赖解析。之后把Qwen-Image-Edit-F2P节点仓库放到ComfyUI的custom_nodes目录下。注意在CI里我们clone的是当前项目本身但actions/checkout已经把仓库代码放在了工作目录所以要通过相对路径或环境变量指向它- uses: actions/checkoutv4 - name: Setup ComfyUI run: | git clone --depth 1 https://github.com/ComfyUI/ComfyUI.git comfyui cd comfyui python -m venv venv source venv/bin/activate pip install -r requirements.txt mkdir -p custom_nodes cp -r $GITHUB_WORKSPACE custom_nodes/Qwen-Image-Edit-F2P安装节点依赖时我不直接跑pip install -r requirements.txt因为节点依赖可能和ComfyUI已有依赖版本冲突。更好的做法是让ComfyUI在启动时执行它自身的依赖安装逻辑或者单独创建虚拟环境后再安装。实际测试下来比较稳定的是先在ComfyUI的虚拟环境里安装节点固定的依赖然后用pip check检查冲突source comfyui/venv/bin/activate cd comfyui/custom_nodes/Qwen-Image-Edit-F2P pip install -r requirements.txt pip checkpip check会列出所有依赖冲突这个检查往往能提前暴露一些“本机能跑但别人装不上”的根源。3.3 启动ComfyUI服务端的正确方式测试时ComfyUI必须以服务端模式启动。我这边的标准命令是cd comfyui source venv/bin/activate python main.py --cpu --port 8188 --disable-auto-launch --preview-method none server.log 21 --cpu强制使用CPU模式。如果省略这个参数ComfyUI在无GPU的runner上会自动尝试CUDA然后报错退出。--disable-auto-launch是防止它尝试打开浏览器CI环境里没有显示服务。--preview-method none可以关掉前端预览减少不必要的资源占用。后台运行用但GitHub Actions默认shell在处理后台任务时有个特点如果后台进程跟当前命令仍在同一个shell进程组GitHub Actions会一直等待进程结束任务就卡在启动这一步。我习惯在启动后立刻记录PID并设置一个完整的就绪等待逻辑而不是让命令直接退出。更稳的做法是用nohup配合disown或者把它放到另一个明确的后台会话里。实测下来在Ubuntu runner上用nohup python main.py ... 是最不容易出问题的。启动后不能马上跑测试必须等服务真正就绪。只靠sleep 10或sleep 30不靠谱模型加载慢时30秒都不够加载快时10秒又太长。我写一个简单的端口探测脚本每2秒尝试请求一次/system_stats接口最多等120秒import time import requests import sys for i in range(60): try: r requests.get(http://127.0.0.1:8188/system_stats, timeout5) if r.status_code 200: print(ComfyUI is ready) sys.exit(0) except Exception as e: print(fwaiting... {i}: {e}) time.sleep(2) sys.exit(1)这个脚本会作为CI的一个步骤运行。等它成功退出再执行测试用例。如果ComfyUI启动失败端口始终不通脚本会在120秒后退出并返回非零状态码整个CI立刻失败。这样能直接把启动阶段的问题暴露在日志里。3.4 模型下载与缓存策略端到端测试要加载真正的模型权重。Qwen-Image-Edit相关模型权重从几GB到十几GB不等每次CI都重新下载会慢到没法用。我用GitHub Actions的actions/cache把模型目录缓存起来- name: Cache ComfyUI models uses: actions/cachev4 with: path: comfyui/models key: comfyui-models-${{ matrix.os }}-${{ hashFiles(models.lock) }}hashFiles里引用一个名为models.lock的文件这个文件记录当前测试需要哪些模型以及对应版本。权重文件本身不放进仓库但依赖清单放进仓库这样当模型版本变更时缓存key也会变化自动重新下载并生成新缓存。模型放在哪里要按ComfyUI的目录规则来。checkpoint类模型放在models/checkpointsdiffusers类模型放在models/diffusersVAE放在models/vae。如果你的节点从自定义路径读取模型那就要在CI启动时设置环境变量指向缓存目录。我推荐优先遵循ComfyUI的标准目录划分这样不依赖额外的路径配置用户在本地用起来也最顺手。下载模型时我用脚本先从配置好的模型仓库获取。为了不让CI过于依赖外部网络我会在本地准备好一个最小的测试权重上传到私有对象存储CI里只下载这一个文件。这个文件可能比完整模型小很多端到端测试只验证链路是否通畅不追求图像质量和完整模型效果。完整权重留给发布包的用户自行下载。4. 自动化测试用例设计与实现4.1 节点加载与注册断言第一类测试是最基础的节点注册检查。在ComfyUI启动后查询系统接口拿不到自定义节点列表但可以从启动日志里判断。更直接的办法是在测试代码里导入节点模块检查NODE_CLASS_MAPPINGSimport sys sys.path.append(comfyui/custom_nodes/Qwen-Image-Edit-F2P) import importlib pkg importlib.import_module(Qwen-Image-Edit-F2P) assert QwenImageEdit in pkg.NODE_CLASS_MAPPINGS assert QwenImageEditLoader in pkg.NODE_CLASS_MAPPINGS这段代码只验证了Python层面的注册表还没验证ComfyUI真的能加载。更强的断言是检查NODE_DISPLAY_NAME_MAPPINGS和NODE_FUNCTION是否存在确保节点在前端面板能正常显示。不过要注意直接import节点模块时它可能会尝试初始化模型路径或读取配置文件所以测试代码里最好设置好环境变量再执行import。ComfyUI加载自定义节点时会执行custom_nodes目录下每个包的可发现逻辑。如果节点模块在import阶段就会下载权重那这种设计从测试角度讲是很糟糕的。我自己的习惯是import阶段只做映射注册权重加载全部延迟到节点实例化时再执行。4.2 用ComfyUI API格式提交工作流图像生成类功能单靠加载检查还不够必须真正提交一次任务。ComfyUI前端界面里可以把工作流导出成API格式得到一份精简的JSON。这份JSON只用节点id连接没有前端布局信息非常适合自动化测试。我通常在项目里维护一份tests/assets/edit_workflow_api.json里面只保留最少节点加载图像节点加载模型节点Qwen-Image-Edit-F2P节点VAE解码节点保存图像节点测试脚本读取JSON修改图像输入路径然后POST到ComfyUI的接口import json import requests def submit(server_url, workflow_path): with open(workflow_path, r, encodingutf-8) as f: prompt json.load(f) resp requests.post(f{server_url}/prompt, json{prompt: prompt}) if resp.status_code ! 200: raise AssertionError(fsubmit failed: {resp.text}) data resp.json() return data.get(prompt_id)接口端点需要注意版本差异。新版ComfyUI的提交接口通常是/prompt旧版本是/api/prompt。我在CI脚本里做成兼容处理先请求新版路径如果返回404再降级到旧版路径。这样ComfyUI更新后测试不会立刻崩。提交成功后会拿到一个prompt_id之后要用它查询执行历史。4.3 生成结果校验与断言端到端测试不能只看提交成功还要等到任务真正执行完成。我写了一个轮询函数定时请求/history/{prompt_id}判断状态字段def wait_complete(server_url, prompt_id, timeout600): start time.time() while time.time() - start timeout: r requests.get(f{server_url}/history/{prompt_id}, timeout10) data r.json() if prompt_id in data: item data[prompt_id] status item.get(status, {}) if status.get(completed): return item if status.get(status_str) error: raise AssertionError(fprompt failed: {json.dumps(item.get(messages, []))}) time.sleep(5) raise TimeoutError(fprompt {prompt_id} not finished within {timeout}s)这里有一个需要注意的地方不同ComfyUI版本里status的字段结构略有不同。我调试时遇到过一个情况任务已经成功跑完了但返回的JSON里没有completed字段只有status_str等于success。所以我的判断逻辑同时兼容两种标识只要其中一个表示完成就算通过。任务完成后检查输出图片是否存在。保存图像节点会输出到ComfyUI/output/目录下图片文件名是随机的。为了断言方便我在workflow JSON里把保存图像节点的filename_prefix固定为ci_test_output这样输出的文件名会带上前缀可以直接用glob匹配import glob outputs glob.glob(comfyui/output/ci_test_output*.png) assert len(outputs) 0, no output image generated img_path outputs[-1] assert os.path.getsize(img_path) 1024, output image is too small进一步可以校验图片尺寸。用PIL读入图片断言宽高和原始输入一致。图像编辑任务如果连尺寸都变了可能是模型输出分布不对也可能是后端解码参数错了。这种断言简单有效能过滤掉相当一部分“看起来跑了但实际上输出没写对”的情况。4.4 失败时如何留证据CI失败后最怕的是没有任何证据。只能看到“任务超时”或“断言失败”但不知道ComfyUI日志输出到底是什么。我为此单独开了一个“上传日志”步骤使用GitHub Actions的actions/upload-artifact- name: Upload debug logs if: always() uses: actions/upload-artifactv4 with: name: comfyui-logs-${{ matrix.os }}-${{ matrix.python-version }} path: | comfyui/server.log comfyui/custom_nodes/Qwen-Image-Edit-F2P/*.logif: always()保证即使前一步测试失败日志上传步骤仍会执行。这个设置非常重要否则任务失败后runner销毁所有日志丢失你只能本地复现那就丧失了远程CI的大部分意义。我还会把测试输出目录一起上传包含生成的错误图片排查时可以直接看到模型输出成什么样了。5. 踩坑实录常见问题与排查技巧5.1 进程没起来端口为空的坑我遇到过最多次的问题是ComfyUI进程根本没有成功启动但脚本还在端口探测循环里一直等到超时。这类情况的根因有很多最常见的是依赖没装齐。ComfyUI的requirements.txt只装基础依赖部分可选能力需要额外安装。比如某些图像处理库不在基础依赖里启动时就会在import阶段报错进程直接退出。排查方法很简单端口探测脚本启动之前先输出一段server.log的尾部内容。就算进程退出了日志文件也已经写了内容。我习惯把日志检查拆成两步if ! kill -0 $PID 2/dev/null; then echo ComfyUI process exited tail -100 comfyui/server.log exit 1 fi这样能快速区分“进程还在但没就绪”和“进程已经挂了”两种情况。如果是后者日志里通常会直接出现ModuleNotFoundError或者Traceback顺着日志就能定位到具体依赖。5.2 无GPU环境下推理太慢免费runner没有GPUQwen-Image-Edit-F2P这种模型在CPU上推理会非常慢。我一开始把端到端测试放进PR流程结果每个PR都要跑接近二十分钟开发体验极差。后来我直接把端到端测试从PR触发中剥离只在主分支push和tag发布时跑PR只跑静态检查和冒烟验证。这个改动让PR反馈时间从二十分钟降到了三分钟以内。另外一个技巧是缩小测试输入图像。CI里用的测试图我会提前用脚本压缩到512x512甚至256x256。图像分辨率越低视觉编码和采样阶段耗时越少。虽然不能代表真实用户场景但足够验证链路是否通畅。如果某次改动导致维度处理出错小图也会照样暴露。如果确实需要验证复杂工作流还有一招把一次CI任务拆成多份并行每份用不同的随机种子跑同一个轻量工作流然后汇总结果。但免费runner的并行额度有限我一般只在发布前手动触发一次大规模验证。5.3 测试污染本地能过CI挂最开始我的测试用例在本地跑得好好的推到GitHub Actions却挂在节点加载阶段。原因是我的本地ComfyUI已经运行过其他节点项目custom_nodes目录里有别的依赖间接满足了我的节点依赖。CI里是干净环境只有Qwen-Image-Edit-F2P缺少了那些间接依赖所以直接报错。这个经历让我养成了两个习惯。第一在需求文件里把依赖声明完整不要依赖“环境里碰巧有”的包。第二CI环境尽可能模拟用户环境也就是只安装ComfyUI基础依赖和节点自己的依赖不去额外安装任何方便调试的东西。干净环境虽然暴露问题时会让人头疼但这类问题恰恰是手动测试最难发现的。依赖版本也需要锁定。如果requirements.txt里写的是torch2.0那CI每次装的PyTorch版本可能不同有些版本之间的API有细微变化结果就是“昨天过今天挂”。我会把依赖锁定到一个经过验证的版本范围至少把pip freeze的输出作参考避免完全放任版本漂移。5.4 流水线超时和日志截断端到端测试跑得慢超时是常见问题。GitHub Actions单任务超时上限可以设很大但等待时间太长会拖慢发布节奏。我一般会为不同阶段设置各自的超时端口就绪探测120秒工作流执行等待600秒整个任务兜底60分钟。分阶段超时比单一任务超时更容易定位问题。日志截断是另一个容易被忽略的坑。ComfyUI在启动时会打印大量初始化日志模型加载时还会输出进度条这些内容会让server.log变得非常大。上传日志时如果artifact过大下载和查看都麻烦。我习惯在启动参数里加--quiet之类的降噪选项并且在上传前执行一次tail -200 server.log只保留最近200行确保小体积、可读、信息足够。5.5 常见问题速查表现象可能原因解决思路端口探测超时server.log为空进程启动即崩溃依赖缺失或Python版本不兼容先查看日志尾部确认Traceback再补全依赖或调整矩阵版本节点未出现在NODE_CLASS_MAPPINGS包名导入失败或者__init__.py里映射定义有误直接在测试代码中import包查看具体import错误提交工作流返回400workflow JSON格式与当前ComfyUI版本不一致用当前装的ComfyUI重新导出API格式替换测试资产输出图片为空模型加载失败或采样步数被设置为0检查models目录文件是否存在检查采样器步数配置本地能过但CI挂测试依赖不完整或版本漂移锁定依赖版本在干净环境重新验证任务长时间不结束某个测试脚本没有退出条件或推理卡死分层设置timeout并在日志中定期输出进度标记这张表是我自己在调试过程中沉淀下来的。多数问题不是代码逻辑错误而是环境和版本差异。所以在CI里多打印一条路径、多记录一个版本号排查起来都会快很多。6. 从自动测试到自动发布6.1 打tag自动生成Release包持续集成的下一步是持续发布。当主分支测试全部通过后我手动在仓库打一个格式如v0.4.1的tag。GitHub Actions里新增一个发布任务监听tags事件构建一个zip包把节点代码、依赖清单和README打进Release资产里。release: runs-on: ubuntu-latest if: startsWith(github.ref, refs/tags/) steps: - uses: actions/checkoutv4 - name: Build package run: | python -m pip install --upgrade pip python -m pip install build python -m build - uses: softprops/action-gh-releasev2 with: files: dist/*发布包跟源码包不同它不带custom_nodes目录路径用户只需要解压到ComfyUI的custom_nodes下再重启ComfyUI即可。把发布和测试串到同一条流水线里能保证只有通过完整测试的版本才会被推送避免“源码能跑、release包缺少文件”这种尴尬。在发布工作流里我会额外跑一遍端到端测试而不是复用PR里的冒烟测试。因为Release对应的代码已经过了PR检查再跑一次完整端到端是为了验证打包后的目录结构、依赖文件是否完整。打包遗漏是最容易出的问题经常是README或者某个子模块没进包用户装完才发现缺东西。6.2 这套流程还能往哪里扩展现在这套CI已经让Qwen-Image-Edit-F2P处于一个比较健康的状态每次提交有快速检查主分支有端到端回归发布有完整验证。但还可以继续扩展有些想法我列在这里打算后续逐步加上。第一个是模型变化时自动触发测试。模型仓库更新后通过webhook触发CI重新跑一次全套测试能提前发现“新模型权重格式变了节点代码不兼容”的问题。第二个是性能回归看板。每次端到端测试记录推理耗时攒一段时间就能画出趋势图如果某次提交后耗时明显增加就能及早发现性能退化。第三个是兼容多个ComfyUI版本的测试矩阵。现在只锁定一个版本未来可以定期跑latest、stable和上一个稳定版保证节点不跟随框架升级而失效。矩阵的代价是时间会成倍增加所以需要合理搭配缓存。模型缓存按不同ComfyUI版本分别打key避免共用一个模型目录时出现版本差异导致的误判。最后分享一点个人体会这套持续集成做完之后我最大的感触是ComfyUI节点项目要维持质量靠的不是“我很小心地写代码”而是把验证流程固化到每一次提交里。Qwen-Image-Edit-F2P涉及的链路太长模型、框架、依赖、工作流格式、输出格式任何一个变动都可能引发问题。手动测试只能覆盖你当前机器、当前版本、当前模型这一条路径CI把路径从一条变成了很多条矩阵虽然慢但每一分钟都在查漏补缺。我自己踩过最深的坑是环境污染。本地ComfyUI装了太多插件导致节点依赖冲突被掩盖推到CI才暴露。所以我现在特别强调干净环境复现宁可CI每次从零装环境多花两分钟也不要在本地“碰巧能过”的状态下盲目发布。用GitHub Actions跑ComfyUI并不复杂关键是把启动过程、端口探测、日志留存这几个基础模块做扎实后面无论是加测试用例还是加发布流程都会很顺。如果你也在维护ComfyUI自定义节点建议先从一个最小的冒烟测试开始等跑通了再加端到端再谈自动发布。一步一步来稳定性自然就上来了。