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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions