fix: Gitea push 404 — add branch:main payload, handle 409 empty repo, clearer settings

- lib/git.ts: add branch:"main" to Gitea POST payload (required when repo has no
  branch yet or is freshly initialized); treat 409 on GET same as 404 (empty repo
  has no tree, Gitea returns 409 Conflict — proceed to create first file)
- lib/git.ts: improve 404 error hint with actionable checklist (URL format,
  owner/repo names, token scope, repo existence)
- settings.tsx: add Gitea info card clarifying URL format (no /api/v1), token
  format (raw value only, no "Bearer" prefix), repo initialization requirement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 14:12:09 +02:00
parent c915d5f2ad
commit fe1fdb9f9c
2 changed files with 31 additions and 4 deletions
+10 -2
View File
@@ -71,7 +71,10 @@ async function pushGitea(
if (existing.ok) {
const data = await existing.json() as { sha?: string };
sha = data.sha;
} else if (existing.status !== 404) {
} else if (existing.status === 404 || existing.status === 409) {
// 404 = file not found (normal for first push)
// 409 = repo is empty / no branch yet — proceed, we'll create with branch:"main"
} else {
const body = await existing.text();
return { success: false, error: `GET ${existing.status}: ${body.slice(0, 200)}` };
}
@@ -79,6 +82,7 @@ async function pushGitea(
const payload: Record<string, string> = {
message: `incident: ${incident.title}`,
content: base64Content,
branch: "main",
};
if (sha) payload.sha = sha;
@@ -94,7 +98,11 @@ async function pushGitea(
if (!res.ok) {
const body = await res.text();
return { success: false, error: `HTTP ${res.status}: ${body.slice(0, 300)}` };
let hint = "";
if (res.status === 404) {
hint = "\n\nCheck: instance URL (no /api/v1), owner and repo names are exact, token has write:repository scope, and the repo exists on Gitea.";
}
return { success: false, error: `HTTP ${res.status}: ${body.slice(0, 300)}${hint}` };
}
const data = await res.json() as { content?: { html_url?: string } };
return { success: true, url: data.content?.html_url };