🐛 fix(vscode): GitHub 请求和 gh auth token 加超时,设置页连不上 GitHub 时不再显示成未登录

This commit is contained in:
cruldra committed 2026-10-19 08:55:49 +11:00
1 parent 9c7c9d8636
commit a8d922f3ba
16 files changed
+267 -44

No files matched your search

+35 -4
View File
@@ -4,6 +4,10 @@
import { execFile } from 'node:child_process'
import { findExecutable } from '../../shared/executable'
import { ForgeApiError } from '../types'
/** 等 `gh auth token` 返回的最长时间;gh 卡在钥匙串等地方时不能让看板一直等下去。 */
const GH_TOKEN_TIMEOUT_MS = 10_000
/** 没取到 gh 登录凭据时给人看的提示。 */
export const GH_LOGIN_HINT = '未登录 GitHub CLI,请在终端运行 `gh auth login` 登录后重试'
@@ -11,16 +15,43 @@ export const GH_LOGIN_HINT = '未登录 GitHub CLI,请在终端运行 `gh auth
/** gh 登录已失效(GitHub 回 401)时给人看的提示。 */
export const GH_RELOGIN_HINT = 'GitHub CLI 的登录已失效,请在终端运行 `gh auth login` 重新登录后重试'
/** `gh auth token` 超时时给人看的提示,和没登录分开说,免得用户白白重新登录。 */
const GH_TIMEOUT_HINT = `\`gh auth token\` 超时(${GH_TOKEN_TIMEOUT_MS / 1000} 秒内没有返回),取不到 GitHub 凭据;请在终端运行 \`gh auth status\` 看看 gh 是否卡住,然后重试`
/** PATH 里找不到 gh 时再试的安装位置:Homebrew(Apple 芯片、Intel)和系统包管理器。 */
const GH_FALLBACKS = ['/opt/homebrew/bin/gh', '/usr/local/bin/gh', '/usr/bin/gh']
/** 取 gh 在 github.com 上登录的 token;gh 没装、没登录、执行失败或输出为空都返回 `undefined`。 */
export function readGhToken(): Promise<string | undefined> {
/** [readGhToken] 的结果:取到了给 `token`,取不到给可以直接给人看的 `message`。 */
export type GhToken = { ok: true, token: string } | { ok: false, message: string }
/**
* 取 gh 在 github.com 上登录的 token。
*
* gh 没装、没登录、执行失败或输出为空,`message` 是 [GH_LOGIN_HINT];超时被结束时是超时的说明。
*/
export function readGhToken(): Promise<GhToken> {
const gh = findExecutable('gh', GH_FALLBACKS) ?? 'gh'
return new Promise((resolve) => {
execFile(gh, ['auth', 'token', '--hostname', 'github.com'], { timeout: 10_000, encoding: 'utf8' }, (err, stdout) => {
execFile(gh, ['auth', 'token', '--hostname', 'github.com'], { timeout: GH_TOKEN_TIMEOUT_MS, encoding: 'utf8' }, (err, stdout) => {
// `killed` 只在超时被 execFile 结束时为真。
if (err?.killed) {
resolve({ ok: false, message: GH_TIMEOUT_HINT })
return
}
const token = err ? '' : String(stdout).trim()
resolve(token || undefined)
resolve(token ? { ok: true, token } : { ok: false, message: GH_LOGIN_HINT })
})
})
}
/**
* 设置页查 gh 账号失败时显示的说明;GitHub 回 401 说明登录失效,返回 `undefined`,让设置页按未登录显示。
*
* 其它失败(超时、连不上、GitHub 自己出错)都说成连不上,这时登录可能还有效,不能叫用户重新登录。
*/
export function ghLoginCheckError(err: unknown): string | undefined {
if (err instanceof ForgeApiError && err.status === 401)
return undefined
const reason = err instanceof Error ? err.message : String(err)
return `无法连接 GitHub,暂时确认不了登录状态:${reason}`
}