Skip to content

支持离线开发 Flow 按 Git 分支发布到 Kestra #42

Description

@dododcdc

背景

当前离线开发模块已经支持:

  • Flow 编辑与保存到本地离线仓库。
  • Git 提交与推送。
  • 调试执行通过 Kestra API upsertFlow + createExecution 触发。
  • 调度配置写入 Flow YAML 的 triggers

但当前"推送"只负责 git push,不会将正式 Flow 发布到 Kestra。后续需要支持:当前 Git 分支推送后,可以明确发布到 Kestra,使该分支的正式调度生效。

离线开发存在多分支需求,例如 maindevfeature/order-etl 都可能需要各自的正式调度。不同分支不能在 Kestra 中互相覆盖。

目标

  • 用户可以选择"仅推送 Git"或"推送并发布到 Kestra"。
  • 正式发布按 Git 分支隔离 Kestra namespace。
  • 调试执行按 Git 分支隔离 namespace 和 flowId。
  • Git 中的 Flow YAML 保持逻辑定义,不写入分支物理 namespace。
  • 发布结果可追踪,UI 可以看到当前分支发布到了哪个 Kestra namespace、对应哪个 commit。

非目标

  • 本 issue 不把 io.kestra.plugin.git.SyncFlows 作为主发布链路。
  • 本 issue 不实现完整的 GitOps 自动同步模式。
  • 本 issue 不要求 Kestra 主动感知 Git 推送。

原因:当前产品需要由 WB-Data 控制多分支 namespace 映射、发布状态、错误反馈和 UI 展示。SyncFlows 可以作为后续可选 GitOps 模式单独设计。

现状问题

假设项目组 18 下有一个 Flow:

id: daily_sales
namespace: pg-18
tasks:
  - id: extract
    type: io.kestra.plugin.core.log.Log
    message: extract sales
triggers:
  - id: schedule
    type: io.kestra.plugin.core.trigger.Schedule
    cron: "0 2 * * *"

如果 main 和 dev 分支都保留同样内容,并且原样发布到 Kestra,则两者在 Kestra 中都是 namespace: pg-18 / flowId: daily_sales,结果是:

  • dev 发布会覆盖 main 的 Flow。
  • dev 的调度可能影响 main 分支对应的任务。
  • 同 namespace 下的脚本文件也可能互相覆盖。
  • 执行历史难以判断来自哪个分支。

方案设计

1. UI 改造

将当前"推送"按钮改造成一个带下拉菜单的动作按钮。

按钮展示:[ 推送 v ]

下拉选项:

  • 推送:仅将当前分支提交推送到远端 Git 仓库。
  • 推送并发布:先推送当前分支,再发布到 Kestra,使当前分支的调度生效。

行为定义:

  • 推送:沿用当前 POST /api/v1/offline/repo/push,只执行 Git push,不调用 Kestra。
  • 推送并发布:先执行 Git push,再执行新的 Kestra 发布接口。
  • 如果 Git push 成功但 Kestra 发布失败,UI 必须提示:Git 推送成功,但发布到 Kestra 失败:<原因>
  • 如果存在未提交改动,应阻止"推送并发布",提示用户先提交当前 Flow 或仓库改动。

2. 正式发布 namespace 映射

Git 中的 YAML 保持逻辑 namespace(如 pg-18),发布到 Kestra 时,临时转换为物理 namespace:

物理 namespace = <逻辑 namespace>.branch_<branchSlug>
branchSlug = <normalizedBranch>_<hash8>

分支名规范化规则:

  • 原始分支名转小写。
  • 非字母、数字字符替换为 _
  • 连续 _ 合并为一个。
  • 去掉首尾 _
  • hash8 为原始分支名 SHA-256 的前 8 位。

示例:

Git 分支 branchSlug 示例 发布 namespace
main main_0d6e4079 pg-18.branch_main_0d6e4079
dev dev_34f2ab19 pg-18.branch_dev_34f2ab19
feature/order-etl feature_order_etl_a1b2c3d4 pg-18.branch_feature_order_etl_a1b2c3d4

正式发布时,flowId 保持原始值(如 daily_sales),分支隔离由 namespace 完成。

3. 多分支真实例子

项目组: 18

Flow 文件: _flows/sales/daily_sales/flow.yaml

main 分支发布后

Kestra 中:

  • namespace: pg-18.branch_main_0d6e4079
  • flowId: daily_sales
  • cron: 0 2 * * *

dev 分支发布后

Kestra 中:

  • namespace: pg-18.branch_dev_34f2ab19
  • flowId: daily_sales
  • cron: 0 3 * * *(dev 把时间改成了凌晨 3 点)

隔离结果: Kestra 同时存在两个正式调度,互不覆盖。

4. 调试执行隔离

原始 Flow:id: daily_sales / namespace: pg-18

用户 7 在项目组 18 的 dev 分支调试时,发布到 Kestra 的调试 Flow 应为:

  • namespace: wb-debug-g18-u7-bdev_34f2ab19
  • flowId: daily_sales__debug

调试执行 labels(必须记录):

{
  "wbdataMode": "DEBUG",
  "wbdataGroupId": "18",
  "wbdataRequestedBy": "7",
  "wbdataBranch": "dev",
  "wbdataOriginalNamespace": "pg-18",
  "wbdataOriginalFlowId": "daily_sales",
  "wbdataDebugNamespace": "wb-debug-g18-u7-bdev_34f2ab19",
  "wbdataDebugFlowId": "daily_sales__debug",
  "wbdataFlowPath": "_flows/sales/daily_sales/flow.yaml",
  "wbdataSourceRevision": "<content-sha256>",
  "wbdataCommitId": "<current-head-commit>"
}

调试发布规则:

  • 调试 namespace 必须包含 groupIduserIdbranchSlug
  • 调试 flowId 使用 {logicalFlowId}__debug
  • 调试 Flow 不保留正式调度触发器。
  • 调试执行不影响正式发布 Flow。

5. 后端接口建议

新增接口: POST /api/v1/offline/publish/kestra

请求:

{
  "groupId": 18,
  "flowPath": "_flows/sales/daily_sales/flow.yaml"
}

响应:

{
  "groupId": 18,
  "branch": "dev",
  "commitId": "abc123",
  "flowPath": "_flows/sales/daily_sales/flow.yaml",
  "logicalNamespace": "pg-18",
  "logicalFlowId": "daily_sales",
  "publishedNamespace": "pg-18.branch_dev_34f2ab19",
  "publishedFlowId": "daily_sales",
  "scheduleEnabled": true,
  "publishedAt": "2026-05-11T10:00:00Z"
}

建议新增发布记录表,至少记录:
group_id, branch, commit_sha, flow_path, logical_namespace, logical_flow_id, published_namespace, published_flow_id, schedule_enabled, published_by, published_at, status, error_message

6. 发布流程

推送并发布 执行顺序:

  1. 检查当前仓库是否存在未提交改动
  2. 执行 Git push
  3. 读取当前分支名和 HEAD commit
  4. 读取当前 Flow YAML
  5. 编译/校验 Flow
  6. 将逻辑 namespace 转换为分支物理 namespace
  7. 上传 namespace files 到物理 namespace
  8. upsertFlow 到 Kestra
  9. 写入发布记录
  10. 返回发布结果给前端

7. 错误处理

Git push 失败

  • 结果:不调用 Kestra 发布接口。
  • UI 提示:推送失败:<原因>

Git push 成功,Kestra 发布失败

  • 结果:Git 远端已经更新,但当前分支未成功发布到 Kestra。
  • UI 提示:Git 推送成功,但发布到 Kestra 失败:<原因>
  • 发布记录:status = FAILED / error_message = <Kestra error>

当前仓库存在未提交改动

  • 结果:阻止"推送并发布"。
  • UI 提示:当前分支存在未提交改动,请先提交后再发布。

8. 验收标准

  • 在 main 和 dev 分支发布同一个 Flow,不会互相覆盖。
  • main 和 dev 的 schedule 可以同时存在,并按各自 cron 运行。
  • Git 中的 Flow YAML 不会被写入 branch_* 物理 namespace。
  • 推送 只执行 Git push,不调用 Kestra。
  • 推送并发布 会先 Git push,再发布当前分支到 Kestra。
  • 如果 Git push 成功但 Kestra 发布失败,UI 必须明确展示部分成功状态。
  • 调试执行的 namespace 包含 group、user、branch。
  • 调试执行的 flowId 使用 {logicalFlowId}__debug
  • 调试执行的 labels 可以看出 group、user、branch、flowPath、commitId 和 sourceRevision。
  • 发布记录可以查询到当前分支最近一次发布的 namespace、flowId、commitId、发布人、发布时间和状态。
  • io.kestra.plugin.git.SyncFlows 不作为本 issue 的主实现路径。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions