跳转至

发布与打包工作流 (Publishing a Workflow)

“发布 (Publishing)”能够将一个已保存的工作流转换为一个高度自洽、独立可运行的完整分发包(Bundle)——其中包含了工作流拓扑、其所引用的所有算子库、锁定的 Python 依赖环境、系统配置以及所需的多媒体资产——并将其精准递送分发至能够运行它的宿主目标:本地磁盘上的独立目录、Griptape Cloud 上的云端 Structure 结构体,或是 Foundry Nuke 影视合成软件内部的动态 Gizmo 节点。

负责打包与递送这个分发包的核心组件称为 发布器 (Publisher),不同的发布目标拥有专属的发布器实现。

所有发布器均遵循高度统一的生命周期与依赖发现算法。本文档首先解析通用的发布流程与底层打包机制,随后深入各发布器的专属特性。若你在发布后发现工作流缺少了某些媒体素材文件(图片、音频、文本),请直接跳转查阅 静态资产文件:确保其被正确打包。


官方发布器生态 (Publishers)

工作流发布能力直接内置于执行引擎内核中,但具体的发布器是由各个算子库按需注册注入的。因此,界面上可见的发布选项取决于当前环境中安装了哪些算子库。官方预置了以下核心发布器:

发布器名称 提供来源库 工作流最终交付分发的目标形态
Publish To Folder (发布到本地文件夹) Griptape Nodes 官方标准库 本地磁盘上的一个全自洽目录,支持在无图形界面的服务器或命令行中静默无头运行。
Griptape Cloud (发布至云端) Griptape Cloud 官方云库 部署为 Griptape Cloud 上的生产级云端 Structure,支持远程 Webhook 触发与跨服务 API 混编。
Publish To Nuke (发布至 Foundry Nuke) Foundry Nuke 官方集成库 封装为带版本号的 .gizmo 资产,一键安装至 Nuke 影视后期合成软件中,供合成师直接在 Nuke 界面中交互调用。

触发发布时,你可以自由选择所需的发布器。每个发布器会在弹窗中要求你提供对应的部署参数——例如 Publish To Folder 要求指定落盘目标目录;Griptape Cloud 从已绑定的云端存储桶与工作流内的 Griptape Cloud Start Flow 节点读取配置;Publish To Nuke 则要求指定目标 Nuke 安装目录、Gizmo 脚本路径以及是覆盖旧版还是发布全新版本。


发布前准备事项

在编辑器顶部工具栏的最右侧、侧边栏面板上方(紧邻引擎运行状态指示灯),常驻着 Publish Workflow(发布工作流)按钮。这是一个全局顶层操作——无论最终在弹窗中选择哪一个发布器,均由此按钮唤起:

顶部工具栏最右侧、侧边栏上方紧邻引擎状态指示灯的 Publish Workflow 按钮

  1. 工作流必须在本地至少保存过一次:确保其在磁盘上拥有对应的真实工程文件路径。发布时引擎会自动将所有未保存的最新修改同步刷盘,因此无需在点击发布前刻意手动保存;但若是一个从未命名的全新工作流,因缺失磁盘路径,必须先保存一次方可唤起发布;
  2. 选择目标发布器:在弹窗下拉列表中选择发布目标。若当前系统仅安装了一个提供发布器的库,系统会自动预选;
  3. 填写发布器配置选项:发布弹窗会动态渲染所选发布器所需的表单项(系统会自动预填上一次发布的历史参数,提升操作效率)。

点击发布后底层发生的时序全景

无论选用何种发布器,其底层生命周期高度统一:引擎首先将工作流修改刷盘,随后将控制权移交给选定的发布器;发布器自动遍历整个工作流拓扑图,全面发现、收集并打包其依赖的所有环境与文件,最后递送至目标容器:

flowchart TD
    A[用户点击 Publish 按钮] --> B[引擎自动将未保存的修改写入磁盘工作流文件]
    B --> C[引擎将调度权移交至选定的发布器 (Publisher)]
    C --> D[发布器深度遍历图谱中的每一个算子节点]
    D --> E[自动化发现依赖项:<br/>算子库代码、Pip 依赖包、静态素材文件]
    E --> F[全自洽装配:工作流 + 依赖环境 + 配置文件]
    F --> G{分发递送目标 (Destination)}
    G -->|Publish To Folder| H[磁盘独立文件夹 + run.py 启动脚本]
    G -->|Griptape Cloud| I[打包上传为云端已部署的 Structure 架构]
    G -->|Publish To Nuke| J[安装为带版本号的 Nuke Gizmo 节点]

在执行打包期间,发布器会在界面实时输出阶段日志(如 Copying libraries...、Deploying workflow to Griptape Cloud...),让用户对底层装配进度保持透明。


分发包内部包含哪些核心要素? (What ends up in the bundle)

为了确保工作流脱离当前开发机后能够在任何目标宿主上独立运转,每个发布器都会自动拼装以下核心基石:

  • 工作流文件实体:包含完整节点拓扑与参数配置;
  • 直接与间接引用的算子库:不仅包括直接使用的节点库,还包括这些库所递归依赖的下游库,确保不会遗漏任何间接算子代码;
  • 运行时配置文件:指示引擎在启动时应当动态加载哪些算子库;
  • .env 环境变量文件:包含你工作区的全量环境变量与机密(请务必注意下文的安全告警!);
  • 项目模板 (Project Template):确保项目中的目录动态宏 (Macros)与文件落盘场景策略 (Situations)在脱机运行时依然能够正常解析;
  • 强类型锁定的 Python 依赖:精确锁定构建该流时所用的引擎版本与各算子库 Pip 依赖版本;
  • Hugging Face 模型自动下载指令:若工作流使用了 Hugging Face 权重,打包器会附带对应的模型拉取定义。

高危安全警告:分发包默认以明文包含你的全量机密!

打包器生成的 .env 文件不会智能过滤只属于该工作流的 Key!它会将你本地工作区 .env 以及机密管理器(Secrets Manager)中配置的所有 Secrets 明文合并打入包内——甚至包括该工作流从未调用的第三方商业 API 密钥!同时,如果你在启动终端的 Shell 中通过环境变量导出了同名机密,也会被一并捕获写入。

这意味着:任何人只要拿到了你导出的发布文件夹(或拥有安装了该 Gizmo 的 Nuke 机台访问权),就能读取到你的全部 API 密钥! 在将发布包对外共享分发或上传至公共代码库之前,请务必手动打开打包生成的 .env 文件,手动剔除所有无关的敏感机密!

在交付形态上,各发布器的输出表现各具特色:

  • Publish To Folder:生成包含所有依赖的文件夹,附带 run.py 入口脚本与一份 README.md。README 详细记录了如何使用现代工具链恢复环境(uv sync)以及如何通过命令行执行工作流(uv run python run.py --help);
  • Griptape Cloud:将全套产物压缩为 Structure 部署包并上传至云端组织,自动激活云端实例,生成用于外部调用的 Webhook 与辅助调度的本地 Executor 工作流,并返回云端控制台管理直链;
  • Publish To Nuke:将依赖封装为带版本号的 .gizmo 与专用 Runner 启动脚本注入到 Nuke 的 Gizmo 目录,并在 Nuke 顶部菜单栏追加 Griptape 专用菜单,使电影合成师能在 Nuke 中一键启动渲染。

依赖关系是如何被自动化发现的?

发布器通过深度自省图谱中的每一个节点,自动汇聚以下三类维度的依赖项:

  1. 算子库依赖 (Libraries):提取所涉及算子库的名称与精确版本,并递归提取下游级联依赖;
  2. Python (pip) 依赖:提取各个算子库在清单中声明的 Pip 依赖,生成环境锁定配置;
  3. 静态资产文件 (Static files):节点从本地项目读取的参考图像、音频、视频或语料。请特别注意:静态文件仅在算子节点显式声明了该依赖时才会被打包器感知并收录!

静态资产文件:确保其被正确打包 (Static files)

引用的本地文件可能意外漏包!

静态多媒体文件被纳入分发包的唯一前提是:读取该文件的算子节点在其代码中主动向引擎声明了该文件依赖。由于并非所有开源节点的作者都规范实现了该声明,如果一个节点加载了外部素材却未向系统声明,该文件就会在发布时被静默遗漏,导致导出的工作流在远端因找不到文件而直接崩溃!

官方推荐黄金解决方案:使用 SelectFromProject 节点

为了 100% 确保任何本地多媒体素材都能稳定打包带走,最稳健的做法是在工作流中引入官方标准库提供的 SelectFromProject 节点:

  1. 在画布中添加一个 SelectFromProject 节点,将其 selected_path 参数配置为你想引入的文件(或文件夹);
  2. 将该节点的 project_path 输出端口连接到下游实际需要使用该素材的算子节点上。

SelectFromProject 节点在底层显式将其 selected_path 声明为系统的静态文件依赖项。只要将文件通过该节点中转,打包器就会强制将该文件收录并打包带走。

项目内部文件的无缝可移植性

当选中的素材文件位于当前项目工程目录内部时,SelectFromProject 会自动将其解析为基于动态路径宏 (Macros)的相对路径而非机器绝对路径。这保证了打包工程迁移到其他机器、机房或云端时,引用路径依然绝对有效。

项目外部的文件绝不会被打包复制

如果引用的文件位于当前项目目录之外(例如另一块独立外接移动硬盘、或者挂载的网络共享路径),打包器绝对不会将其物理拷贝至包内。发布后的工作流在运行时依然会通过原有的机器绝对路径去寻址该文件——在挂载了同名网络盘的农场机器上可以正常运行,但在路径不存在的机器上则会报错。

若希望外部文件随分发包一起打包分发,请先将该素材手动拷贝复制进当前项目目录内部,然后再进行节点连线引用!

任何被打包器判定为跳过打包的文件,均会在引擎控制台输出明确日志:will not be bundled because ...(并附带跳过的具体原因)。排障时可重点审查引擎日志,详见 导出引擎日志排障。


面向算子库开发者:扩展自定义发布器与规范声明

工作流发布架构具备完全的开放可扩展性:任何自定义算子库均可扩展注册全新的发布目标,也可以让自定义节点完美声明文件依赖。

1. 注册专有发布器 (Registering a publisher)

算子库继承 AdvancedNodeLibrary 类,并在 after_library_nodes_loaded 生命周期钩子中通过 LibraryManager.on_register_event_handler(...) 注册处理 PublishWorkflowRequest 的回调函数。注册时还可以指定专有的起始/终止节点类型,以及通过 get_publish_options 回调为发布弹窗提供自定义字段。

官方标准库中的 griptape_nodes_library_advanced.py、云端库中的 griptape_cloud_library_advanced.py 以及 Nuke 库中的 nuke_library_advanced.py 均为标准的开源参考范例。

发布器可以复用引擎内置的 WorkflowPackager 打包套件完成通用依赖分析与环境归集,专注于目标容器的特定适配逻辑:

# 将工作流与通用依赖打包落盘至目标目录
packaged = self._packager.package_to_folder(destination, workflow)
workflow_in_bundle = destination / packaged.entrypoint_workflow_path

保留发布器专有文件名:若你的发布器需要向包内写入专有的脚本文件(如 run.py 或 README.md),请通过 additional_reserved_paths 参数告知打包器,避免同名文件在冲突时被工作流文件静默覆盖:

self._packager.package_to_folder(
    destination,
    workflow,
    additional_reserved_paths=[Path("run.py"), Path("README.md")],
)

2. 在自定义算子节点中显式声明静态文件依赖

为了从根本上免去终端用户使用 SelectFromProject 绕道配置的繁琐,算子节点应当在其类实现中主动声明自己所使用的文件。

重写 get_node_dependencies() 方法并将文件路径加入 deps.static_files 集合中:

def get_node_dependencies(self) -> NodeDependencies | None:
    # 务必首先调用父类方法,确保算子库和 Widget 依赖完好保留
    deps = super().get_node_dependencies()
    if deps is None:
        deps = NodeDependencies()
    value = self.get_parameter_value("path")
    if value and isinstance(value, str):
        deps.static_files.add(value)
    return deps

只要节点实现了上述规范声明,任何发布器在打包时均能全自动、零遗漏地将输入素材打包进分发包中。关于自定义节点开发的更多规范,请参阅 自定义算子开发总览。