✨ feat(vscode): 新增 GitHub provider,凭据借 gh 登录,删工单走 GraphQL、依赖按内部 id 换算

This commit is contained in:
cruldra committed 2026-10-19 08:18:27 +11:00
1 parent 451bc91a6b
commit 7351b6247f
12 files changed
+1010 -47

No files matched your search

+18 -21
View File
@@ -11,6 +11,9 @@ import { workspace } from 'vscode'
import { getToken } from '../auth/secrets'
import { detectRepo } from '../git/remote'
import { GiteaProvider } from './gitea/provider'
import { GH_LOGIN_HINT, readGhToken } from './github/ghAuth'
import { GitHubProvider } from './github/provider'
import { forgeKindForHost } from './types'
/** 一个工作区对应的代码托管仓库,和访问它用的 [ForgeProvider]。 */
export interface ForgeContext {
@@ -24,37 +27,31 @@ export interface ForgeContext {
/**
* 解析结果;失败时 `message` 是可以直接给人看的原因,`reason` 给需要分情况处理的调用方:
* `no-workspace` 没打开工作区,`no-remote` 没有能认出的 origin,`no-credentials` 没有凭据,`unsupported` 这一家还不支持。
* `no-workspace` 没打开工作区,`no-remote` 没有能认出的 origin,`no-credentials` 没有凭据。
*/
export type ForgeResolution
= | { ok: true, forge: ForgeContext }
| { ok: false, reason: 'no-workspace' | 'no-remote', message: string }
| { ok: false, reason: 'no-credentials' | 'unsupported', message: string, kind: ForgeKind, host: string }
| { ok: false, reason: 'no-credentials', message: string, kind: ForgeKind, host: string }
/** host 小写后是 `github.com` 的是 GitHub,其余都当 Gitea;不认 GitHub Enterprise。 */
export function forgeKindForHost(host: string): ForgeKind {
return host.toLowerCase() === 'github.com' ? 'github' : 'gitea'
}
/** 给指定的仓库造 [ForgeContext];webhook 记下的仓库不一定是当前工作区的 origin,所以单独开放。 */
/**
* 给指定的仓库造 [ForgeContext];webhook 记下的仓库不一定是当前工作区的 origin,所以单独开放。
*
* GitHub 的凭据现取 gh 的登录,Gitea 的凭据是用户在设置里填、存在 SecretStorage 里的 token。
*/
export async function openForge(ctx: ExtensionContext, workspaceRoot: string, remote: Remote): Promise<ForgeResolution> {
const kind = forgeKindForHost(remote.host)
if (kind === 'github')
return { ok: false, reason: 'unsupported', kind, host: remote.host, message: '暂未支持 GitHub 仓库' }
const repo = { workspaceRoot, kind, host: remote.host, owner: remote.owner, repo: remote.repo }
if (kind === 'github') {
const token = await readGhToken()
if (!token)
return { ok: false, reason: 'no-credentials', kind, host: remote.host, message: GH_LOGIN_HINT }
return { ok: true, forge: { ...repo, provider: new GitHubProvider({ owner: remote.owner, repo: remote.repo, token }) } }
}
const token = await getToken(ctx, remote.host)
if (!token)
return { ok: false, reason: 'no-credentials', kind, host: remote.host, message: `请先配置 ${remote.host} 的访问令牌` }
return {
ok: true,
forge: {
workspaceRoot,
kind,
host: remote.host,
owner: remote.owner,
repo: remote.repo,
provider: new GiteaProvider({ ...remote, token }),
},
}
return { ok: true, forge: { ...repo, provider: new GiteaProvider({ ...remote, token }) } }
}
/** 解析当前工作区(第一个工作区文件夹)的代码托管仓库。 */