Skip to content

webhook 接收端与隧道解耦:可配置隧道命令 + Quick Tunnel 默认(三模式) #50

Description

@ghbvf

现状 / 根因

webhook 接收端(#9 / PR #49)把隧道命令写死成 Cloudflare Quick Tunnel:

  • src-tauri/src/pr/webhook.rs 的 spawn_quick_tunnel 硬编码 cloudflared tunnel --no-autoupdate --url http://127.0.0.1:<port>,唯一可配的只有 cloudflaredBin(二进制路径)。
  • start() 在 cloudflared 未装时直接短路、隧道起不来就 abort 掉本地监听——接收端与隧道强耦合,无法只监听。

后果:

  1. URL 不固定 — Quick Tunnel 每次重启换随机 *.trycloudflare.com,GitHub webhook 的 Payload URL 要反复改。
  2. 职责错位 — "用哪个隧道 / 什么域名 / 什么凭证 / URL 固不固定" 本是隧道工具的事,却因为 App 自己 spawn 隧道而被拽进了接收端。接收端本应只需要 port + secret。

目标

把接收端与隧道解耦:接收端只负责 bind 127.0.0.1:port → HMAC 验签 → 解析 → 派发;隧道如何暴露到公网变成可配置、可外置。落地为三种模式供用户选:

  1. Quick Tunnel(默认,零配置) — 维持现状行为,random URL。图省事的人不用动任何配置。
  2. 自定义隧道命令 — App spawn 用户配置的命令(如 cloudflared tunnel run my-tunnel / tailscale funnel / ngrok http),指向 127.0.0.1:port。配合官方工具一次性带外登录,拿到固定 URL。
  3. Listener-only — App 只 bind 本地端口、不 spawn 任何隧道;用户在 App 外完全自管隧道。面板提示"请将隧道指向 127.0.0.1:port"。

非目标(治理红线)

  • 不在 App 内做登录 / OAuth / 持有隧道凭证,不自动建 DNS / 注册隧道。理由:与本仓既有姿态一致——webhook 当初特意不自动注册 GitHub webhook(守 gh 只读红线),隧道侧同理不持凭证、不替用户 mutate 外部基础设施。登录是官方工具一次性带外完成的事,App 只编排"已认证好的命令"。
  • 不绑死 Cloudflare:自定义命令模式对 Cloudflare 命名隧道 / Tailscale Funnel / ngrok 一视同仁。

设计要点(细化形态在 ship 计划阶段确认)

  • 新增 config 字段走既有 serde camelCase golden 契约(config/model.rs ↔ src/config/types.ts + golden 测试 + fields.ts + SettingsView/OnboardingWizard);#[serde(default)] 前向兼容旧持久化。
  • 自定义命令需注入 port({port} 占位替换);命令直接 exec、不过 shell(沿用现有防注入约定)。
  • 自定义 / listener-only 模式下公网 URL 是用户的固定域名、App 难以从输出可靠抓取 → Payload URL 的来源(用户显式配固定 URL vs 不显示)在计划阶段定。
  • 拆 start() 对隧道的强依赖:listener-only 时只起 axum 监听,不要求 cloudflared 存在。

Files

  • src-tauri/src/pr/webhook.rs(spawn 逻辑解耦 + start 拆隧道强依赖)
  • src-tauri/src/config/model.rs(新 config 字段 + golden 测试)
  • src-tauri/src/pr/commands.rs(start_webhook 传参)
  • src/config/types.ts / src/config/fields.ts / src/config/SettingsView.vue / src/config/OnboardingWizard.vue(前端镜像 + 表单)
  • src/pr/WebhookPanel.vue / src/pr/types.ts(面板模式展示 + 提示文案)

Source

Discovered via 设计讨论(接收端 ≠ 隧道的职责边界)。与 #9 / PR #49 同一 webhook 切片;PR #49 将一并 Closes 本 issue(基线确认:直接在 Feature/9-webhook-cloudflare 分支上落地)。

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