/** * Gitea Automation CLI & API Client for DBK Platform / HomAroma * Usage: bun tools/gitea.ts [args] */ const GITEA_URL = process.env.GITEA_URL || 'https://git.kittisak.com'; const GITEA_API = process.env.GITEA_API_URL || `${GITEA_URL}/api/v1`; const GITEA_TOKEN = process.env.GITEA_TOKEN || ''; const OWNER = process.env.GITEA_OWNER || 'admin'; const REPO = process.env.GITEA_REPO || 'homaroma'; if (!GITEA_TOKEN) { console.error('Error: GITEA_TOKEN is not set. Please check .env.local'); process.exit(1); } const headers = { 'Authorization': `token ${GITEA_TOKEN}`, 'Content-Type': 'application/json', 'Accept': 'application/json', }; async function api(path: string, options: RequestInit = {}) { const url = `${GITEA_API}${path.startsWith('/') ? path : `/${path}`}`; const res = await fetch(url, { ...options, headers: { ...headers, ...(options.headers || {}) }, }); if (!res.ok) { const errorText = await res.text(); throw new Error(`Gitea API Error (${res.status} ${res.statusText}): ${errorText}`); } const contentType = res.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await res.json(); } return await res.text(); } async function main() { const [,, cmd, ...args] = process.argv; try { switch (cmd) { case 'whoami': { const user = await api('/user'); console.log(`Logged in as: ${user.username} (${user.email}) [Admin: ${user.is_admin}]`); break; } case 'repo': { const repo = await api(`/repos/${OWNER}/${REPO}`); console.log(`Repository: ${repo.full_name}`); console.log(`URL: ${repo.html_url}`); console.log(`Default Branch: ${repo.default_branch}`); console.log(`Open Issues: ${repo.open_issues_count} | Open PRs: ${repo.open_pr_counter}`); break; } case 'issues': { const sub = args[0] || 'list'; if (sub === 'list') { const state = args[1] || 'open'; const issues = await api(`/repos/${OWNER}/${REPO}/issues?state=${state}`); if (issues.length === 0) { console.log(`No ${state} issues found.`); } else { console.log(`Found ${issues.length} ${state} issues:`); for (const iss of issues) { console.log(` #${iss.number} [${iss.state.toUpperCase()}] ${iss.title} (${iss.html_url})`); } } } else if (sub === 'create') { const title = args[1]; const body = args[2] || ''; if (!title) { console.error('Usage: bun tools/gitea.ts issues create [body]'); process.exit(1); } const issue = await api(`/repos/${OWNER}/${REPO}/issues`, { method: 'POST', body: JSON.stringify({ title, body }), }); console.log(`Created Issue #${issue.number}: ${issue.title}`); console.log(`URL: ${issue.html_url}`); } break; } case 'prs': { const sub = args[0] || 'list'; if (sub === 'list') { const state = args[1] || 'open'; const prs = await api(`/repos/${OWNER}/${REPO}/pulls?state=${state}`); if (prs.length === 0) { console.log(`No ${state} pull requests found.`); } else { console.log(`Found ${prs.length} ${state} pull requests:`); for (const pr of prs) { console.log(` #${pr.number} [${pr.state.toUpperCase()}] ${pr.title} (${pr.head.ref} -> ${pr.base.ref})`); console.log(` URL: ${pr.html_url}`); } } } else if (sub === 'create') { const [, head, base, title, ...bodyParts] = args; const body = bodyParts.join(' ') || ''; if (!head || !base || !title) { console.error('Usage: bun tools/gitea.ts prs create <head_branch> <base_branch> <title> [body]'); process.exit(1); } const pr = await api(`/repos/${OWNER}/${REPO}/pulls`, { method: 'POST', body: JSON.stringify({ head, base, title, body }), }); console.log(`Created Pull Request #${pr.number}: ${pr.title}`); console.log(`URL: ${pr.html_url}`); } break; } case 'releases': { const sub = args[0] || 'list'; if (sub === 'list') { const releases = await api(`/repos/${OWNER}/${REPO}/releases`); if (releases.length === 0) { console.log('No releases found.'); } else { for (const rel of releases) { console.log(` ${rel.tag_name} - ${rel.name} (${rel.html_url})`); } } } else if (sub === 'create') { const tag_name = args[1]; const name = args[2] || tag_name; const body = args[3] || ''; if (!tag_name) { console.error('Usage: bun tools/gitea.ts releases create <tag_name> [title] [notes]'); process.exit(1); } const rel = await api(`/repos/${OWNER}/${REPO}/releases`, { method: 'POST', body: JSON.stringify({ tag_name, name, body }), }); console.log(`Created Release ${rel.tag_name}: ${rel.name}`); console.log(`URL: ${rel.html_url}`); } break; } case 'projects': { const sub = args[0] || 'list'; if (sub === 'list') { const projects = await api(`/repos/${OWNER}/${REPO}/projects`); if (projects.length === 0) { console.log('No projects found.'); } else { console.log(`Found ${projects.length} projects:`); for (const p of projects) { console.log(` #${p.id} ${p.title}`); } } } else if (sub === 'create') { const title = args[1]; const description = args.slice(2).join(' ') || ''; if (!title) { console.error('Usage: bun tools/gitea.ts projects create <title> [description]'); process.exit(1); } const project = await api(`/repos/${OWNER}/${REPO}/projects`, { method: 'POST', body: JSON.stringify({ title, description }), }); console.log(`Created Project #${project.id}: ${project.title}`); } break; } default: { console.log(`Gitea Helper CLI for ${OWNER}/${REPO}`); console.log('Available commands:'); console.log(' bun tools/gitea.ts whoami'); console.log(' bun tools/gitea.ts repo'); console.log(' bun tools/gitea.ts projects [list|create]'); console.log(' bun tools/gitea.ts issues [list|create]'); console.log(' bun tools/gitea.ts prs [list|create]'); console.log(' bun tools/gitea.ts releases [list|create]'); break; } } } catch (err: any) { console.error(err.message || err); process.exit(1); } } main();