首页
/ Langflow Nightly 发布机制详解:协调式 .devN 版本链、发布顺序与安装验证指南

Langflow Nightly 发布机制详解:协调式 .devN 版本链、发布顺序与安装验证指南

2026-09-06 13:08:37作者:咎竹峻Karen

本文围绕 Langflow 仓库中的 nightly(夜间版)发布规范文档 src/bundles/NIGHTLY.md 展开,系统讲解 Langflow 及其配套包(langflow-baselfxlangflow-sdklfx-* 扩展)的协调式 .devN 版本号计算方式、依赖发布顺序、nightly 安装方法、dry run 演练机制与发布前验证清单,并结合仓库内的版本计算脚本与 CI 工作流源码,说明每一环节的实际实现与可验证依据。读完本文,你可以完整理解 Langflow nightly 的版本设计原则,并能独立安装、演练和审计一个 nightly 发布。

一、什么是“规范名 nightly”:不发布平行的 *-nightly 包

Langflow 的 nightly 发布遵循一条与常规项目不同的设计决策:nightly 使用规范包名(canonical package names)配合协调一致的 .devN 版本号发布,而不是另起炉灶发布 langflow-nightlylangflow-base-nightly 这类平行的 Python 发行版

这一原则直接体现在版本计算脚本 scripts/ci/pypi_nightly_tag.py 的模块注释中:nightly 以规范 .devN 预发布版本(例如 langflow==X.Y.Z.devN)的形式发布,dev 计数器是相对规范包 langflow / langflow-base 在 PyPI 上的历史计算的(其中 .devN 预发布版本才计数,稳定正式版永不参与计数)。这样做的好处是:

  • 下游用户无需改变依赖声明中的包名,只需允许预发布版本解析,即可拿到最新 nightly;
  • 规范 PyPI 项目名上的版本历史保持单一、连续,避免 -nightly 影子项目造成的版本碎片化;
  • 版本号与稳定版共享同一条 X.Y.Z 基线,语义上与 RELEASE.md 中“Langflow 与 LFX 共享 major.minor 版本线”的兼容契约保持一致。

脚本中定义的两个 PyPI 查询端点即对应这两个规范项目:

# 针对规范项目计数(而不是 `*-nightly`),因为 nightly
# 就是规范 .devN 预发布版本
PYPI_LANGFLOW_URL = "https://pypi.org/pypi/langflow/json"
PYPI_LANGFLOW_BASE_URL = "https://pypi.org/pypi/langflow-base/json"

二、版本链:一条精确到 .devN 的依赖锁

文档 src/bundles/NIGHTLY.md 定义了 nightly 的核心版本链:workflow 从 langflowlangflow-baselfxlangflow-sdk 四个包的规范发布历史中推导出一个协调的 Langflow 开发版本,且这条依赖链在 nightly 场景下是精确(exact)的

langflow==X.Y.Z.devN
  -> langflow-base==X.Y.Z.devN
      -> lfx==X.Y.Z.devN

其中:

  • SDK(langflow-sdk)使用同一协调版本,保证 lfx 对 SDK 的依赖可被本地 wheel 解析;
  • 独立的扩展发行版(lfx-* bundles)保持规范包名和带边界的 LFX 兼容范围(bounded LFX compatibility ranges)。这一点可以从仓库根 pyproject.toml 看到当前主干的稳定依赖写法,如 lfx-ibm>=0.1.5,<1.0.0lfx-docling>=0.1.0,<1.0.0lfx-datastax>=0.1.3,<1.0.0 等——扩展包各自独立演进,不跟随 nightly 的 .devN 版本号;
  • 受影响的扩展 wheel 先于 langflow-base 构建并发布,确保 base 发布时其依赖的扩展版本已在 PyPI 上可解析。

2.1 共享 dev 号的计算规则

dev 号 N 的计算逻辑在 scripts/ci/pypi_nightly_tag.py 中,核心规则可以概括为:

  1. 以根 pyproject.tomlbase_version 为基准(例如 1.10.0)。脚本从根目录 pyproject.toml 读取版本号并取其 base_version,脚本注释特别强调:full 与 base 的 nightly 刻意都从根 pyproject 取基线版本,如果 base 改读 src/backend/base/pyproject.toml,两个包的 dev 计数器可能分叉,导致某个精确 == pin 指向一个从未发布的版本;
  2. 只统计同系列、带 dev 号的版本:遍历两个规范项目(langflowlangflow-base)的 PyPI 发布历史,仅当 version.base_version 与基准版本一致且 version.dev is not None 时才计入。稳定正式版(如 1.10.0)与旧系列(如 1.9.x 的 dev)都不参与计数;
  3. 取两包最大值加一next_dev = max(dev_numbers) + 1,首个 nightly 则从 dev0 开始。这保证结果严格领先于两个包中最新的同系列 dev 版本,避免重复发布;
  4. fail closed(失败即中止):PyPI 查询中,404 表示该项目尚无发布(例如历史首个 nightly),贡献空列表;但任何其他失败——网络错误、5xx/403 等非 404 HTTP 状态、200 但响应缺少 releases 字段的畸形响应——都会抛出异常中止 nightly 任务。源码注释解释了原因:如果高版本号一侧的包查询临时失败,max(dev) + 1 会被压低,从而重新生成一个已经发布过的版本号;在修改 tag 之前中止,正是为了防止这种回退。

测试文件 scripts/ci/test_pypi_nightly_tag.py 对上述规则做了全量覆盖(所有 PyPI 流量均被 mock,无网络访问),典型断言包括:

  • 两包历史错位时(langflow 最新 dev54langflow-base 最新 dev48),mainbaseboth 三种 build type 均返回同一标签 v1.10.0.dev55,即 max(54, 48) + 1
  • 基准版本从 1.10.0 升到 1.10.1 时,旧系列的 dev 不泄漏进新系列,结果重置为 v1.10.1.dev0
  • 仅有正式版发布时计数器从 dev0 起步;正式版发布不推进 dev 计数器;
  • 畸形响应、500/503 错误、网络异常均抛出异常(对应文档中“构建前确认版本”的防线之一);
  • 无法解析的版本字符串(如 not-a-version)被静默跳过。

2.2 “both” 模式:一次快照,杜绝跨调用漂移

脚本的 main 入口接受 basemainboth 三种 build type,其中 both 模式会把同一标签打印两次。这是 nightly workflow nightly_build.ymlcreate-nightly-tag 任务的实际用法:

TAGS_OUTPUT="$(uv run ./scripts/ci/pypi_nightly_tag.py both)"
RELEASE_TAG="$(printf '%s\n' "$TAGS_OUTPUT" | sed -n '1p')"
BASE_TAG="$(printf '%s\n' "$TAGS_OUTPUT" | sed -n '2p')"
# 若两个标签不一致则直接失败

“main”与“base”构建类型返回完全相同的版本是设计使然(lockstep versioning);both 模式让 workflow 从**一次调用(一个 PyPI 快照)**中同时读取 release 与 base 两个标签,从根上避免两次独立查询之间 PyPI 状态变化导致的标签漂移。

2.3 协调版本号如何写入各包

nightly 任务计算出四个标签后,通过 scripts/ci/update_pyproject_combined.py 把协调版本链写入各 pyproject.toml

  • 更新 src/backend/base/pyproject.tomllangflow-base 版本号为 base_version
  • langflow-base 中写入对 lfx精确 dev pinupdate_lfx_dep_in_base);
  • 更新根 pyproject.tomllangflow 版本号为 main_version,并把其对 langflow-base 的 uv workspace 依赖重新 pin 到协调的 base 版本。

随后 workflow 执行 uv lock(根目录与 src/lfx 各自锁定)、git commit 并打上 vX.Y.Z.devN 标注(annotated tag)推送到远端。需要留意 nightly_build.yml 中提交前的一条注释:nightly 保持规范包名,且稳定的 lfx-* bundles 不被修改,因此没有任何 bundle 的 pyproject 参与这个 nightly 提交——这正是第一节约束在版本管理上的落地。当前主干版本为 1.12.0(见 pyproject.tomlsrc/backend/base/pyproject.tomlsrc/lfx/pyproject.toml),因此当前版本线下的 nightly 形如 v1.12.0.devN

三、发布顺序:按依赖拓扑从底向上

文档给出的发布顺序是:

  1. langflow-sdk
  2. lfx
  3. 受影响的 lfx-* 扩展发行版
  4. langflow-base
  5. langflow

并有一条硬性不变量:langflow-baselangflow 的版本号必须一致,不支持“仅 base”或“仅 full”的 nightly 版本

这条顺序在 nightly 发布工作流 release_nightly.yml 的 job 依赖图中被逐字实现。各 publish 任务的 needs 链为:

发布任务 前置任务(needs) 说明
publish-nightly-sdk build-nightly-lfxtest-cross-platform 最先发布 SDK
publish-nightly-lfx 上一项 + publish-nightly-sdk LFX 依赖 SDK 的精确 dev 版本
publish-nightly-bundles 上一项 + build-nightly-maintest-cross-platform 扩展先于 base,满足“扩展 wheel 先于 langflow-base 发布”
publish-nightly-base 上一项 + 两个 build 任务 + 跨平台测试 base 在扩展之后
check-nightly-main-pypi-dependencies 上一项 + bundle 发布 等待 PyPI 传播(见下)
publish-nightly-main 上一项 + base 发布 最后发布 langflow

几个值得展开的实现细节:

(1)bundle 发布的幂等与限流处理。 publish-nightly-bundles 任务先运行一段内嵌 Python 生成“发布计划”:逐个读取 bundle wheel 的 METADATA,向 PyPI 查询该版本是否已发布,已存在则跳过(“重新运行 nightly 但 bundle 版本未变应当是 no-op”),最终按根 pyproject.toml 中依赖声明的顺序排序输出。逐个 uv publish 时,每个 wheel 之间固定 sleep 60 秒;遇到 HTTP 429(PyPI 限流)会退避重试,最多 5 次;遇到 already exists 类错误则视为跳过而非失败。

(2)发布 full 前的 PyPI 传播等待。 check-nightly-main-pypi-dependencies 任务解析根 pyproject.tomllangflow-base 与所有 lfx-* 的直接依赖,然后在 20 分钟超时内、以 15 秒间隔轮询 PyPI(最多 60 次),确认每个要求都至少有一个已发布的版本能满足 spec,并且请求头携带 Cache-Control: no-cache 与缓存破坏参数。只有全部就绪,publish-nightly-main 才会执行——这保证了 langflow==X.Y.Z.devN 发布到 PyPI 后,用户 uv pip install --pre langflow 能立即解析出完整可安装的依赖链。

(3)跨平台安装测试先于一切发布。 三个 build 任务(LFX / base / main)各自构建 wheel 并通过 actions/upload-artifact 产出 dist-nightly-sdkdist-nightly-lfxdist-nightly-basedist-nightly-maindist-nightly-bundles 工件;test-cross-platform 任务随后调用 .github/workflows/cross-platform-test.yml 子工作流(pre_release: true)在多平台上安装并校验这些本地 wheel。所有 publish 任务都把它列在 needs 中——没有通过跨平台安装测试,一个 wheel 都不会发布

3.1 构建阶段的关键校验

构建任务本身内嵌了文档“验证”一节要求的大部分检查:

  • LFX 构建build-nightly-lfx):先用 grep 断言 src/sdk/pyproject.toml 的包名必须是 langflow-sdk、版本必须等于传入的 nightly_tag_sdk;再用 uv tree --package lfx 断言 LFX 包名与 nightly_tag_lfx 一致(源码注释解释了为何要 --package 定根:直接 grep lfx 会先命中 lfx-ibm 这类 bundle)。然后 uv build --wheel 构建 SDK 与 LFX 两个 wheel,并在干净 venv 中同时安装两个 wheel、运行 lfx --help 验证 CLI;
  • Base 构建build-nightly-base):从工件 --force-reinstall --no-deps 装回刚构建的 LFX wheel(注释说明:workspace 解析装的是源码,这里要测试的正是即将发布到 PyPI 的 wheel),校验 langflow-base 包名/版本后执行 make build base=true args="--no-sources --wheel";随后安装 ${WHEEL_FILE}[complete] 启动 python -m langflow run --host localhost --port 7860 --backend-only,轮询 http://localhost:7860/api/v1/auto_login 直到服务就绪(120 秒超时),再确认进程能被正常终止;
  • Main 构建build-nightly-main):同样强制重装 LFX 与 base 两个构建产物 wheel,用 uv tree 校验 langflow 的版本等于 nightly_tag_release,执行 make build main=true,安装 main wheel 后以 /health_check 端点做同样的启动/关闭冒烟;最后遍历 src/bundles/*/pyproject.toml每个 bundle 构建 wheel 到 bundles-dist/,供跨平台测试与发布使用。

构建全程使用 Python 3.13(工作流 env: PYTHON_VERSION: "3.13"),而 nightly 流水线上游的后端单元测试矩阵覆盖 3.10–3.14。

四、Nightly 流水线的触发与门禁

nightly 的入口是 nightly_build.yml,它由每日 00:00 UTC 的 cron 定时触发(注释注明对应美西下午 4/5 点)或手动 workflow_dispatch(可选 runs_onskip_frontend_testsskip_backend_testspush_to_registry 等输入)驱动。其 create-nightly-tag 任务仅在主仓库生效,流程为:

  1. 解析最新的 release-* 分支(git ls-remote 按版本号排序取最高者)作为 nightly 基线;
  2. 调用 pypi_nightly_tag.py both 生成共享的 full/base 标签,并分别生成 LFX、SDK 标签;
  3. 删除远端已存在的同名标签后,用 update_sdk_version.pyupdate_lfx_version.pyupdate_pyproject_combined.py 写版本,uv lock 两次(根目录与 src/lfx),提交并推送 annotated tag;
  4. 前端测试(Linux 阻塞、Windows 非阻塞)、后端单元测试(3.10–3.14)、压力测试通过后,release-nightly-build 调用 release_nightly.yml 完成构建与发布;
  5. 随后执行数据库迁移验证(db-migration-validation,使用规范仓库 langflowai/langflow 下的 nightly .devX 镜像);任何阻塞任务失败或被取消都会向 Slack 发送包含失败 job 名与运行日志链接的通知。

五、安装 Nightly:预发布解析 + 规范包名

文档给出的安装方式是使用预发布解析(prerelease resolution)配合规范包名

uv pip install --pre langflow

如果只需要不带 provider 扩展的可运行应用:

uv pip install --pre langflow-base

两个包都提供 langflow 命令——这与 release 工作流中的冒烟测试相互印证:build-nightly-base 任务正是安装 base wheel 后运行 python -m langflow run ... 验证 CLI 可用的。

理解这两条命令的前提:

  • 不加 --pre 时,pip/uv 默认不选择 .devN 预发布版本,因此该参数是拿到 nightly 的必要条件;
  • langflow-base 依赖 lfx~=X.Y.0(当前主干为 lfx~=1.12.0,见 src/backend/base/pyproject.toml),其 provider 相关能力以 extras(如 beautifulsoupsandboxtoolguard 等映射到 lfx[...])或独立 lfx-* 扩展的形式提供;
  • langflow 则把 langflow-base 与一组精选 lfx-* 扩展声明为直接依赖(见 pyproject.tomllangflow-base~=1.12.0lfx-* 依赖清单)。nightly 场景下这些 pin 会被 update_pyproject_combined.py 精确重写为当次的 dev 版本,因此 --pre 安装 full 包时能整链解析到同一 nightly 版本线。

六、Dry Run:完整演练但不发布

规范文档保留了一个 dry_run 入口:发布工作流 .github/workflows/release.ymlrelease_tag 输入描述明确写道,该参数可以是发布 tag,也可以在 dry_run 为 true 时使用不可变的 commit SHA 或 pull request refdry_run 输入本身控制着全部“写外部世界”的动作。

dry run 的语义是:构建并验证每一个选中的 wheel 与镜像,但禁用以下操作——

  • PyPI 发布(各 publish step 均以 if: ${{ !inputs.dry_run }} 门控);
  • 容器镜像 registry 推送(push_to_registry: ${{ !inputs.dry_run }} 传递给 docker 构建子工作流);
  • tag 创建;
  • GitHub Release 写入。

这使得 nightly 流程的任何改动都可以先在 PR 或特定 commit 上完整走一遍构建与校验路径,而不产生任何版本副作用。

七、发布前验证清单

文档“Verification”一节的六项检查是启用正式发布前的验收标准,结合仓库证据逐条说明:

  1. 构建前确认 root 与 base 版本一致——由 pypi_nightly_tag.py both 的单快照机制与 create-nightly-tag 中的“两标签不一致即失败”断言共同保证;
  2. 检查 wheel 元数据中的精确 nightly pin——沿 SDK/LFX/base/full 依赖链核验。publish-nightly-bundles 的发布计划脚本本身就是“读取 wheel 内 *.dist-info/METADATA 中 Name/Version”的实现范例;
  3. 把本地 wheel 一起安装并运行 pip check——跨平台测试子工作流接收全部五个 dist 工件(含 pre_release: true)做本地安装解析,等价于在发布前暴露依赖冲突;
  4. 确认 base 不包含任何 provider 的 lfx-*、PyTorch、TorchVision 发行版——从源码结构看,provider 扩展被声明在 full 包 pyproject.toml 的依赖列表中,而 src/backend/base/pyproject.toml 只声明 lfx~=1.12.0 及将部分 extras 转发到 lfx[...] 的兼容层,与“base 精简、扩展独立”的架构一致;
  5. 确认 full 包能发现(discover)其精选扩展——full 的直接依赖清单(lfx-ibmlfx-doclinglfx-datastaxlfx-toolguard 等)即“精选扩展”的权威列表,且 check-nightly-main-pypi-dependencies 会在发布前逐一确认它们在 PyPI 上可解析;
  6. 启用发布前运行 scripts/ci/test_pypi_nightly_tag.py 与发布工作流契约测试——前者验证 lockstep 版本计算的全部边界行为,后者(如 scripts/ci/test_release_workflow.py)守护工作流合同,两者均在仓库的 CI 脚本测试中可运行。

八、关键文件索引

主题 路径
nightly 规范文档(本文依据) src/bundles/NIGHTLY.md
稳定发布流程与版本管理 RELEASE.md
共享 dev 号计算 scripts/ci/pypi_nightly_tag.py
dev 号计算单元测试 scripts/ci/test_pypi_nightly_tag.py
协调版本写入 pyproject scripts/ci/update_pyproject_combined.py
nightly 触发与打标(含定时任务) .github/workflows/nightly_build.yml
nightly 构建与 PyPI 发布 .github/workflows/release_nightly.yml
正式发布工作流(dry run 入口) .github/workflows/release.yml
跨平台安装测试 .github/workflows/cross-platform-test.yml
nightly Docker 镜像构建 .github/workflows/docker-nightly-build.yml

适用前提小结:以上机制基于当前仓库主干(版本线 1.12.0,构建环境 Python 3.13)的实际内容;安装 nightly 需要工具链支持预发布解析(如 uv pip install --pre),且 nightly 作为预发布版本,其稳定性预期低于按 RELEASE.md 中 4–6 周节奏发布的稳定版。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388