# Gitea API Client (Shared) Common Gitea API functions for issue comments, checkbox updates, and issue management. ## IMPORTANT: Target Project Resolution **NEVER hardcode `UniqueSoft/APAW` in API calls.** Always detect the target project from git remote. ### How to Detect Target Project ```python import re, subprocess def get_target_repo(): """Detect target project from git remote - NEVER hardcode""" result = subprocess.run( ['git', 'remote', 'get-url', 'origin'], capture_output=True, text=True ) remote_url = result.stdout.strip().rstrip('/') # HTTPS: https://git.softuniq.eu/Owner/Repo.git # SSH: git@git.softuniq.eu:Owner/Repo.git match = re.search(r'[:/]([^/]+/[^/]+?)(?:\.git)?$', remote_url) if match: return match.group(1) # Fallback: use env var or default return os.environ.get('GITEA_TARGET_REPO', 'UniqueSoft/APAW') ``` ## Python Client ```python import urllib.request, json, base64, os, re, subprocess def gitea_api(path, data=None, method='GET', repo=None): """Call Gitea API. Uses get_gitea_token() from gitea-auth.md. Auto-detects target repo.""" target_repo = repo or get_target_repo() token = get_gitea_token() # From .kilo/shared/gitea-auth.md url = f"{os.environ.get('GITEA_API_URL', 'https://git.softuniq.eu/api/v1')}/repos/{target_repo}{path}" headers = {'Content-Type': 'application/json', 'Authorization': f'token {token}'} req = urllib.request.Request(url, data=json.dumps(data).encode() if data else None, headers=headers, method=method) with urllib.request.urlopen(req) as r: return json.loads(r.read()) def get_target_repo(): """Detect target project from git remote - NEVER hardcode""" try: result = subprocess.run( ['git', 'remote', 'get-url', 'origin'], capture_output=True, text=True ) remote_url = result.stdout.strip().rstrip('/') match = re.search(r'[:/]([^/]+/[^/]+?)(?:\.git)?$', remote_url) if match: return match.group(1) except Exception: pass return os.environ.get('GITEA_TARGET_REPO', 'UniqueSoft/APAW') def post_gitea_comment(issue_number, body, repo=None): """Post comment to Gitea issue in the correct project.""" target_repo = repo or get_target_repo() return gitea_api(f"/issues/{issue_number}/comments", {"body": body}, 'POST', target_repo) def update_issue_checkboxes(issue_number, repo=None): """Mark all checkboxes as done and close issue.""" target_repo = repo or get_target_repo() import re issue = gitea_api(f"/issues/{issue_number}", repo=target_repo) body = issue['body'] body = re.sub(r'- \[ \] ', '- [x] ', body) body = re.sub(r'\* \[ \] ', '* [x] ', body) gitea_api(f"/issues/{issue_number}", {"body": body, "state": "closed"}, 'PATCH', target_repo) def close_issue(issue_number, repo=None): """Close a Gitea issue in the correct project.""" target_repo = repo or get_target_repo() gitea_api(f"/issues/{issue_number}", {"state": "closed"}, 'PATCH', target_repo) def create_issue(title, body, labels=None, repo=None): """Create a Gitea issue in the correct project.""" target_repo = repo or get_target_repo() return gitea_api("/issues", {"title": title, "body": body, "labels": labels or []}, 'POST', target_repo) ``` ## Bash Client ```bash # Auto-detect target repo TARGET_REPO=$(git remote get-url origin | sed 's:/*$::' | sed -E 's|.*[:/]([^/]+/[^/]+?)(\.git)?$|\1|') # Post comment curl -X POST -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"body":"comment body"}' \ "https://git.softuniq.eu/api/v1/repos/${TARGET_REPO}/issues/{issue_number}/comments" # Create issue curl -X POST -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"title":"Issue title","body":"Issue body"}' \ "https://git.softuniq.eu/api/v1/repos/${TARGET_REPO}/issues" ``` ## CRITICAL REMINDERS 1. **NEVER hardcode `UniqueSoft/APAW`** - always use `get_target_repo()` 2. **Issues belong in the target project** - the project being worked on 3. **APAW is the agent framework** - not the default target for all issues 4. **Use `GITEA_TARGET_REPO` env var** for explicit override when needed