Skip to content

feat: Push 失败时自动降级重试(CLI 回退 + 指数退避 + SSH 切换) #9

Description

@nookery

问题描述

当用户推送代码时,可能会遇到 SecureTransport error: -9806 + LibGit2Swift error code 5 的网络/SSL 错误。这类错误通常由以下原因引起:

  • macOS SecureTransport 与远程服务器的 TLS 协商失败
  • VPN/代理干扰 SSL 握手
  • 网络抖动或防火墙策略

目前 GitOK 直接将原始错误通过 alert_error(error) 展示给用户,用户只能看到一个晦涩的错误码,不知道如何解决,也不知道 GitOK 提供了其他推送途径。

用户视角

用户期望:点击推送 → 推送成功。不关心底层是 libgit2、curl 还是 git CLI。

当前体验:点击推送 → 弹窗 SecureTransport error: -9806 → 不知所措。

建议方案

实现一个自动降级推送策略链,当 libgit2 原生推送失败时,按顺序自动尝试备选方案,直到成功或所有方案耗尽:

1️⃣ 指数退避重试(静默)

尝试 1 → 失败 → 等待 2s → 尝试 2 → 失败 → 等待 4s → 尝试 3

适用于瞬态网络抖动。

2️⃣ CLI 回退(静默降级)⭐

当 libgit2 持续失败时,自动回退到系统 git push 命令执行推送:

  • macOS 自带的 git 使用 curl/OpenSSL,与 SecureTransport 完全独立
  • GitOK 已有 GitRepositoryCLI 基础设施,实现成本低
  • 解决率接近 100%

3️⃣ SSH 协议切换(用户可选)

当 HTTPS 完全不通时,在 UI 提示用户可一键切换到 SSH 协议推送(利用已有的 SSHHelperperformWithConvertedSSHURL)。

4️⃣ 代理/配置引导(用户可选)

提供快速入口配置 HTTP 代理或刷新凭据。

预期交互流程

用户点击推送
    ↓
libgit2 push 尝试
    ↓ 失败(SSL/网络错误)
自动重试 2 次(指数退避)
    ↓ 仍然失败
静默降级:调用 git CLI push
    ↓ 成功 → ✅ 显示推送成功
    ↓ 失败 → 弹窗提供备选操作:
              [🔄 重试] [🔒 切换 SSH] [✋ 取消]

技术要点

  • 错误识别:在 WorkingStateView.swift 中新增 isNetworkError(_:) 方法,识别 SSL/网络错误
  • 策略模式:将 push 逻辑抽象为 PushStrategy 协议,支持 libgit2、CLI 等多种实现
  • 用户体验:静默降级阶段不弹窗打扰用户,仅在全部方案失败时提供引导
  • 已有基础设施利用GitRepositoryCLISSHHelperperformWithConvertedSSHURL

优先级

🔴 高优先级 — 这是影响用户核心工作流(推送代码)的阻断性问题,优化后能显著提升 GitOK 的稳定性和用户满意度。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions