feat(gitea): G7 一键接线——新建仓库后本地 init/origin/首推一键完成
绑定完成但本地未连通时(无 .git 或无 origin),Gitea 绑定区显示接线引导: - 无 git → init + 首次提交 + 关联 origin + 推送 - 有 git 无 origin → 关联 origin + 推送当前分支 复用 publish.rs 存量命令(git_init_and_commit/git_remote_set/git_push), 补齐 GitHub 退役时遗落的"本地接线"半程(接线/放风筝边界裁决的落地)。 Rules-Applied: R01
This commit is contained in:
parent
09410cc35f
commit
4cd941c975
@ -124,8 +124,8 @@ Gitea push → POST /webhook/gitea/:project_id
|
||||
- complexity: M
|
||||
- acceptance: TBD —— remote 切换 + 推送,安全增量,不丢历史
|
||||
|
||||
### 📋 G7. 新建仓库后一键接线(本地 init + 首次 push)
|
||||
- status: todo
|
||||
### ✅ G7. 新建仓库后一键接线(本地 init + 首次 push)
|
||||
- status: done
|
||||
- complexity: M
|
||||
- depends: G2
|
||||
- files: src/components/dashboard/GiteaPanel.tsx, src/lib/commands.ts
|
||||
|
||||
@ -1372,7 +1372,7 @@ function GovernancePanel({
|
||||
<AgentInfraPanel projectPath={projectPath} projectId={projectId} />
|
||||
|
||||
{/* ── Gitea 集成(统一 git 后端)─────────────────────────── */}
|
||||
{projectId && <GiteaPanel projectId={projectId} projectName={projectName} />}
|
||||
{projectId && <GiteaPanel projectId={projectId} projectName={projectName} projectPath={projectPath} />}
|
||||
|
||||
{/* 项目信息 */}
|
||||
<div className="pt-2 border-t border-gray-100">
|
||||
|
||||
@ -18,6 +18,10 @@ import {
|
||||
giteaSetupWebhook,
|
||||
giteaUnlinkRepo,
|
||||
giteaPollNow,
|
||||
scanLocalGit,
|
||||
gitInitAndCommit,
|
||||
gitRemoteSet,
|
||||
gitPush,
|
||||
type GiteaInstance,
|
||||
} from "../../lib/commands";
|
||||
import { useUIStore } from "../../store/ui";
|
||||
@ -186,9 +190,10 @@ export function GiteaInstancesSection() {
|
||||
interface Props {
|
||||
projectId: string;
|
||||
projectName: string;
|
||||
projectPath?: string;
|
||||
}
|
||||
|
||||
export function GiteaPanel({ projectId, projectName }: Props) {
|
||||
export function GiteaPanel({ projectId, projectName, projectPath }: Props) {
|
||||
const qc = useQueryClient();
|
||||
const showToast = useUIStore((s) => s.showToast);
|
||||
|
||||
@ -207,6 +212,36 @@ export function GiteaPanel({ projectId, projectName }: Props) {
|
||||
queryFn: giteaListLinkedRepos,
|
||||
});
|
||||
|
||||
// G7 一键接线:绑定后检测本地 git 状态(无 git / 无 origin / 已接线)
|
||||
const { data: localGit, refetch: refetchLocalGit } = useQuery({
|
||||
queryKey: ["gitea-local-git", projectId],
|
||||
queryFn: () => scanLocalGit(projectPath!),
|
||||
enabled: !!link && !!projectPath,
|
||||
staleTime: 30000,
|
||||
retry: false,
|
||||
});
|
||||
const hasOrigin = localGit?.remotes.some((r) => r.name === "origin") ?? false;
|
||||
const needsWiring = !!link && !!projectPath && localGit != null && (!localGit.has_git || !hasOrigin);
|
||||
const [wiring, setWiring] = useState(false);
|
||||
|
||||
const handleWireUp = async () => {
|
||||
if (!projectPath || !link?.clone_url) return;
|
||||
setWiring(true);
|
||||
try {
|
||||
if (!localGit?.has_git || !localGit?.has_commits) {
|
||||
await gitInitAndCommit(projectPath, "chore: 项目初始化(炼境接线)");
|
||||
}
|
||||
await gitRemoteSet(projectPath, link.clone_url);
|
||||
const msg = await gitPush(projectPath);
|
||||
showToast(`✓ 接线完成:${msg}`);
|
||||
refetchLocalGit();
|
||||
} catch (e) {
|
||||
showToast(`❌ 接线失败: ${e}`);
|
||||
} finally {
|
||||
setWiring(false);
|
||||
}
|
||||
};
|
||||
|
||||
const refresh = () => {
|
||||
qc.invalidateQueries({ queryKey: ["gitea-link", projectId] });
|
||||
qc.invalidateQueries({ queryKey: ["gitea-linked-repos"] });
|
||||
@ -326,6 +361,32 @@ export function GiteaPanel({ projectId, projectName }: Props) {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* G7 本地接线:仓库已建但本地未连通时的一次性引导 */}
|
||||
{needsWiring && (
|
||||
<div className="bg-indigo-50 border border-indigo-100 rounded p-2 space-y-1.5">
|
||||
<p className="text-[11px] text-indigo-700 font-medium">
|
||||
{!localGit?.has_git ? "本地目录还不是 git 仓库" : "本地仓库尚未关联远端 origin"}
|
||||
</p>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<p className="flex-1 text-[10px] text-indigo-400 leading-relaxed">
|
||||
{!localGit?.has_git
|
||||
? "将执行:git init + 首次提交 + 关联 origin + 推送"
|
||||
: "将执行:关联 origin + 推送当前分支"}
|
||||
</p>
|
||||
<button
|
||||
onClick={handleWireUp}
|
||||
disabled={wiring}
|
||||
className="px-2.5 py-1 rounded text-[11px] bg-indigo-600 text-white hover:bg-indigo-700 disabled:opacity-50 shrink-0"
|
||||
>
|
||||
{wiring ? "接线中…" : "🔌 一键接线"}
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-[10px] text-indigo-300 leading-relaxed">
|
||||
接线是一次性动作;日常 commit / push 在项目自己的 AI 会话中进行。
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* webhook 状态与注册 */}
|
||||
<div className="bg-gray-50 rounded p-2 space-y-1.5">
|
||||
<div className="flex items-center gap-1.5 text-[11px]">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user