🐛 fix(vscode): GitHub 请求和 gh auth token 加超时,设置页连不上 GitHub 时不再显示成未登录
This commit is contained in:
1 parent
9c7c9d8636
commit
a8d922f3ba
16 files changed
+267
-44
No files matched your search
@@ -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}`
|
||||
}
|
||||
Reference in new issue
Block a user