import json import os import requests # Configuration TOKEN = os.getenv("GITEA_TOKEN") URL = os.getenv("GITEA_URL") REPO = os.getenv("REPO_NAME") HEADERS = {"Authorization": f"token {TOKEN}", "Content-Type": "application/json"} def get_gitea_issues(): """Fetch all issues from Gitea to map by their Beads ID.""" url = f"{URL}/api/v1/repos/{REPO}/issues?state=all" resp = requests.get(url, headers=HEADERS) resp.raise_for_status() # We store the Beads ID in the title or a hidden comment to track them return {issue['title'].split(']')[0][1:]: issue for issue in resp.json() if ']' in issue['title']} def sync(): beads_file = ".beads/issues.jsonl" if not os.path.exists(beads_file): print("No beads found.") return gitea_issues = get_gitea_issues() with open(beads_file, "r") as f: for line in f: data = json.loads(line) bid = data.get("id") title = data.get("title") desc = data.get("description", "") # Mapping Beads status to Gitea states is_closed = data.get("status") in ["closed", "done", "finished"] target_state = "closed" if is_closed else "open" payload = { "title": f"[{bid}] {title}", "body": f"{desc}\n\n---\n**Beads ID:** `{bid}`\n**Priority:** {data.get('priority', 'N/A')}", "state": target_state } if bid in gitea_issues: # Update existing issue if state or title changed issue_number = gitea_issues[bid]['number'] print(f"Updating Issue #{issue_number} ({bid})") requests.patch(f"{URL}/api/v1/repos/{REPO}/issues/{issue_number}", headers=HEADERS, json=payload) else: # Create new issue print(f"Creating New Issue for {bid}") requests.post(f"{URL}/api/v1/repos/{REPO}/issues", headers=HEADERS, json=payload) if __name__ == "__main__": sync()