跳轉到主要內容
文件建構工作流程模組化與復用

模組化與復用

sub_workflow、把一段邏輯封裝成模組、Promote / Demote 一鍵重構 —— 讓工作流程不再一則複製貼上。

當你做到第二、第三條工作流時,會發現某段邏輯反覆出現 —— 拉 ASA 數據、發 Telegram 消息、生成 Excel 報表。再複製粘貼下去,改一處要改三處、測試重複、版本失控。這時候就該做模塊化了。

模板 vs 模塊 再強調一次

模板 = 起始文檔的快照,克隆後獨立演化;模塊 = 可被引用的子流程,升級後調用方自動受益。兩者不是替代關係,是互補的。本頁講模塊。

什麼是「模塊」

一個"模塊"本質上就是一個聲明瞭 WorkflowModuleContract 頂層字段的 workflow。它額外公開了:

  • inputs — 調用方必須傳入的參數(帶名稱、類型、必填、默認值、描述)
  • outputs — 執行完產生的結構化結果(調用方可直接引用)
  • version — 語義化版本號,便於調用方鎖定
yaml
name: my-team-slack-notifier
version: "1.0.0"

module:
  enabled: true
  inputs:
    webhook_url:
      type: string
      required: true
      description: Slack incoming webhook URL
    channel:
      type: string
      required: false
      default: "#general"
    message:
      type: string
      required: true
    mentions:
      type: array
      items: { type: string }
      required: false
  outputs:
    message_ts:
      type: string
      description: Slack 返回的 message timestamp,可用于后续更新消息
    status:
      type: string
      enum: [sent, failed]

# 模块自己的步骤(内部细节,对调用方黑盒)
steps:
  - id: format_text
    type: code
    language: node
    code: |
      const msg = process.env.WF_VAR_MESSAGE;
      const mentions = JSON.parse(process.env.WF_VAR_MENTIONS || '[]');
      return { text: mentions.map(u => `<@${u}>`).join(' ') + ' ' + msg };

  - id: post
    type: code
    depends_on: [format_text]
    credentials: [slack_oauth]
    code: |
      //  Slack API,返回 message_ts / status 

有了契約之後,調用方(父 workflow)的 sub_workflow step 會:

  • 在保存時靜態校驗 —— 必填 inputs 缺一項就不讓保存;
  • 在運行時校驗 —— 類型不符 / 枚舉不在列表裡,直接報錯;
  • 在編輯器裡自動補全 —— 你寫 inputs: 時能下拉看到模塊公開了哪些字段。

父工作流如何調用模塊

yaml
steps:
  - id: build_report
    type: code
    # ...

  - id: notify
    type: sub_workflow
    module: my-team-slack-notifier    # 引用我们上面定义的模块
    version: "^1.0.0"                  # 锁主版本
    inputs:
      webhook_url: "{{credentials.slack_webhook}}"
      channel: "#ops-alerts"
      message: "日报已生成:{{steps.build_report.data.summary}}"
      mentions: ["U1234", "U5678"]

  - id: record
    type: code
    depends_on: [notify]
    code: |
      const ts = process.env.STEP_OUTPUT_NOTIFY_MESSAGE_TS;
      // 把 ts 存到你自己的数据库,方便后续更新那条消息 ...

要點:

  • module: dingyue-module-slack-deliver 是模塊 id,平臺會按名字 + version 解析。
  • inputs: 和模塊契約裡的 inputs 一一對應。
  • 調用完成後,可通過 {{steps.deliver.outputs.message_id}} 讀模塊輸出。

讓已有工作流變成模塊:Promote to module

大部分時候你不會從零寫一個模塊,而是從現有工作流裡抽。流程:

  1. 打開一個你覺得"這段邏輯值得複用"的工作流。
  2. 在畫布裡用鼠標框選或 Shift+點擊選中若干連續 step。
  3. 右鍵菜單 →「Promote to module」,或頂部工具欄同名按鈕。
  4. 彈窗裡:
    • 起一個有意義的模塊名字(全局唯一,建議前綴你團隊名,例:my-team-slack-notifier);
    • 平臺會自動根據選中片段推斷 inputs / outputs 初稿,你可以編輯;
    • 確認後點「創建模塊」。
  5. 原工作流裡這幾步會被替換成一個 sub_workflow 節點 —— 參數和連線自動對齊。
Promote 的心智模型

就像 IDE 裡的"提取函數"重構。你選一段代碼,IDE 幫你抽成一個帶參數和返回值的函數,並把原位置替換成調用。Braidrun 做的是完全一樣的事 —— 只不過對象是 workflow step。

模塊升級與版本兼容

每次保存一個模塊都會創建一個新版本。父 workflow 在 sub_workflow step 裡可以選擇:

  • version: latest — 自動用最新版(適合你自己維護的模塊)
  • version: "1.2.0" — 鎖定到具體版本(適合引用別人的模塊、怕升級破壞兼容)
  • version: "^1.2.0" — 允許小版本升級,禁止跨大版本

什麼是"兼容的變更"?

  • ✓ 加一個 optional input(必填 / 默認值都不算破壞)
  • ✓ 加一個 output 字段
  • ✗ 刪 / 改名 input
  • ✗ 刪 / 改名 output
  • ✗ 改 input 類型

做破壞兼容的改動時,語義版本應該升到下一個 MAJOR。平臺不會強制,但調用方鎖 ^X.Y.Z 時會受保護。

環路檢測

模塊 A 不能間接引用自己。平臺在兩層做了檢測:

  1. 發佈時靜態檢測 — 保存模塊時,DFS 掃所有它引用的其它模塊的依賴圖,有環則拒絕保存。
  2. 運行時動態檢測 — 執行期間如果出現 runtime 解析到的環(譬如條件分支後才被引用),會立刻拋錯。

最大遞歸深度默認 8 層。這是"父調子調孫"的深度,不是單次調用的 fanout。

變量隔離

模塊跑起來是一個"子 WorkflowExecutionContext",和父上下文完全隔離:

  • 父的 variables / steps outputs / agents 默認不繼承給子;
  • 子的內部 step 輸出也不會溢出到父 —— 父只能看到契約裡聲明的 outputs;
  • 跨父子傳數據的唯一方式是 inputs / outputs(顯式契約)。

這種隔離是模塊化可靠性的基石 —— "黑盒"不是比喻,是字面意義上的。

Demote from module:把模塊還原為內聯 step

如果你改著改著發現某段邏輯其實只有一處在用,做成模塊反而增加了理解成本,可以反向 Demote:

  1. 在父 workflow 裡選中那個 sub_workflow 節點;
  2. 右鍵 →「Demote inline」;
  3. 平臺把模塊的 step 展開回父 workflow,sub_workflow 節點消失。

原模塊本身不會被刪除 —— 如果還有其它工作流引用它,那些仍然有效。

在哪裡管理所有模塊

左側主導航「模塊庫」是你的總管視圖。這裡可以:

  • 看所有模塊列表(自帶的 12 個 + 你團隊創建的)
  • 按 "誰在引用我" 反向查詢 —— 改模塊前先看誰會受影響
  • 看模塊的版本歷史 / diff
  • 發佈 / 歸檔 / 轉移所有權

什麼時候該做模塊

  • ✓ 同一段邏輯在 2 個以上 workflow 裡出現過
  • ✓ 一段邏輯穩定且對外有清晰契約(典型的 "發消息 / 查報表 / 生成 Markdown")
  • ✓ 一個單 workflow 已經超過 15 個 step,可讀性下降
  • ✗ 一段邏輯只用一次且未來不會複用 —— 直接內聯
  • ✗ 一段 2–3 行的小工具函數 —— 用 code step 的代碼複用比模塊更自然

下一步