diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 6e7134c..e862c59 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,4 +1,4 @@ -{"id":"gitea-welcome-0kp","title":"Reverse-sync Test","status":"tombstone","priority":2,"issue_type":"task","owner":"chris@rootiest.com","created_at":"2026-01-19T21:09:52.497127424-05:00","created_by":"rootiest","updated_at":"2026-01-19T21:20:34.407061892-05:00","comments":[{"id":2,"issue_id":"gitea-welcome-0kp","author":"rootiest","text":"It","created_at":"2026-01-20T02:11:02Z"}],"deleted_at":"2026-01-19T21:20:34.407061892-05:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"gitea-welcome-0kp","title":"Reverse-sync Test","status":"tombstone","priority":2,"issue_type":"task","owner":"chris@rootiest.com","created_at":"2026-01-19T21:09:52.497127424-05:00","created_by":"rootiest","updated_at":"2026-01-19T21:21:27.951350534-05:00","comments":[{"id":2,"issue_id":"gitea-welcome-0kp","author":"rootiest","text":"It","created_at":"2026-01-20T02:11:02Z"}],"deleted_at":"2026-01-19T21:21:27.951350534-05:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"gitea-welcome-24k","title":"Reverse-sync Test","status":"tombstone","priority":2,"issue_type":"task","owner":"chris@rootiest.com","created_at":"2026-01-19T21:13:44.940389131-05:00","created_by":"rootiest","updated_at":"2026-01-19T21:20:45.766584302-05:00","deleted_at":"2026-01-19T21:20:45.766584302-05:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"gitea-welcome-5a4","title":"Test Issue","status":"closed","priority":2,"issue_type":"task","owner":"chris@rootiest.com","created_at":"2026-01-19T19:24:28.988421899-05:00","created_by":"rootiest","updated_at":"2026-01-19T20:08:24.331722606-05:00","closed_at":"2026-01-19T20:08:24.331722606-05:00","close_reason":"Closed","comments":[{"id":1,"issue_id":"gitea-welcome-5a4","author":"rootiest","text":"Completed!","created_at":"2026-01-20T01:07:50Z"}]} {"id":"gitea-welcome-d6r","title":"Reverse-sync Test #2","status":"tombstone","priority":2,"issue_type":"task","owner":"chris@rootiest.com","created_at":"2026-01-19T21:13:44.746027824-05:00","created_by":"rootiest","updated_at":"2026-01-19T21:20:56.083051681-05:00","deleted_at":"2026-01-19T21:20:56.083051681-05:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} diff --git a/.gitea/sync_beads.py b/.gitea/sync_beads.py index 9bc9b53..47698f1 100644 --- a/.gitea/sync_beads.py +++ b/.gitea/sync_beads.py @@ -5,7 +5,7 @@ import sys # Configuration from Environment TOKEN = os.getenv("GITEA_TOKEN") -URL = os.getenv("GITEA_URL") +URL = os.getenv("URL") # Ensure your Gitea Action uses this variable name REPO = os.getenv("REPO_NAME") HEADERS = {"Authorization": f"token {TOKEN}", "Content-Type": "application/json"} @@ -21,11 +21,9 @@ def sync(): # 1. Fetch existing issues from Gitea try: - # state=all includes closed issues so we don't create duplicates of finished tasks api_url = f"{URL}/api/v1/repos/{REPO}/issues?state=all" resp = requests.get(api_url, headers=HEADERS) resp.raise_for_status() - # Map by [ID] to identify existing ones existing = { i["title"].split("]")[0][1:]: i for i in resp.json() if "]" in i["title"] } @@ -36,38 +34,44 @@ def sync(): # 2. Parse the Beads JSONL file processed_count = 0 + skipped_count = 0 + with open(beads_path, "r") as f: for line in f: - processed_count += 1 line = line.strip() if not line: continue - print(f"DEBUG: Processing line -> {line}") try: data = json.loads(line) bid = data.get("id") + status = data.get("status") title = data.get("title") - # Matches your 'cat' output: "issue_type":"task" itype = data.get("issue_type", "unknown") + # --- THE FIX: FILTER TOMBSTONES --- + if status == "tombstone": + print(f"👻 Skipping tombstone: {bid} ({title})") + skipped_count += 1 + continue + # ---------------------------------- + if not bid: print("⚠️ Skipping line: No ID found.") continue + processed_count += 1 unique_title = f"[{bid}] {title}" payload = { "title": unique_title, "body": f"{data.get('description', 'No description provided.')}\n\n---\n**Beads ID:** `{bid}`\n**Type:** `{itype}`", "state": "closed" - if data.get("status") in ["closed", "done"] + if status in ["closed", "done"] else "open", } if bid in existing: - print( - f"✅ Updating Gitea Issue #{existing[bid]['number']} for {bid}" - ) + print(f"✅ Updating Gitea Issue #{existing[bid]['number']} for {bid}") requests.patch( f"{URL}/api/v1/repos/{REPO}/issues/{existing[bid]['number']}", headers=HEADERS, @@ -84,9 +88,12 @@ def sync(): except Exception as e: print(f"⚠️ Error processing bead: {e}") - print(f"🏁 Finished. Processed {processed_count} beads.") - if processed_count == 0: - print("❌ ERROR: File was found but it was EMPTY. Check your git push.") + + print(f"🏁 Finished. Active: {processed_count}, Skipped: {skipped_count}") + + # We check if we have ANY beads (active or tombstone) to validate the file isn't broken + if (processed_count + skipped_count) == 0: + print("❌ ERROR: File was found but it was EMPTY.") sys.exit(1)