docs(ISSUE-WP-0006): Forgejo-only language and projection boundary
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 34s

Prefer Forgejo as the self-hosted forge product. Keep Gitea only as the
Gitea-compatible API identifier (module backends/gitea, type string
gitea). FORGEJO_TOKEN is preferred; GITEA_* remains a deprecated alias.

INTENT/SCOPE quote ACT-ADR-005: issue-core is not the fleet ops claim
queue. Connector docs describe repo work record → hub index → optional
Forgejo projection, not activity-core → issue-core → harness.

Assistant: grok
Assistant-Session: 01a09dc6-3f0d-7c93-8b11-8e83c0623d49
This commit is contained in:
tegwick 2026-09-14 04:52:58 +02:00
parent f9d276dadf
commit ee9b85215d
34 changed files with 410 additions and 263 deletions

View file

@ -7,5 +7,5 @@ API regardless of the underlying issue tracking system.
Available Backends:
- local: SQLite-based local backend for offline use
- gitea: Gitea API backend for GitHub-compatible systems
- gitea: Forgejo backend (Gitea-compatible API)
"""

View file

@ -1,12 +1,11 @@
"""
Gitea Backend
Forgejo backend (Gitea-compatible API).
A backend implementation for Gitea issue tracking systems.
This backend provides integration with Gitea API for remote issue management.
Talks to the self-hosted Forgejo HTTP API. Gitea is not a second supported
product. The backend type string remains `gitea`.
Features:
- Full Gitea API integration
- GitHub-compatible operations
- Full Forgejo / Gitea-compatible API integration
- Remote synchronization
- Authentication support
- Rate limiting compliance

View file

@ -1,8 +1,9 @@
"""
Gitea Backend Implementation
Forgejo backend (Gitea-compatible API).
Provides integration with Gitea API for remote issue tracking.
This backend adapts the Gitea API to our unified issue model.
Talks to the self-hosted Forgejo HTTP API, which is Gitea-compatible.
Gitea is not a second supported product. The backend type string remains
`gitea` for compatibility.
"""
import requests
@ -16,7 +17,7 @@ from ...core.models import Issue, Label, User, Milestone, Comment, IssueState, P
class GiteaAPIError(Exception):
"""Gitea API specific errors."""
"""Forgejo (Gitea-compatible API) errors."""
pass
@ -26,7 +27,7 @@ class GiteaRateLimitError(GiteaAPIError):
class GiteaBackend(RemoteBackend, SyncableBackend):
"""Gitea API backend for remote issue tracking."""
"""Forgejo backend using the Gitea-compatible HTTP API."""
def __init__(self):
self.base_url: Optional[str] = None
@ -44,7 +45,7 @@ class GiteaBackend(RemoteBackend, SyncableBackend):
supports_webhooks=True,
supports_real_time=False,
max_labels_per_issue=None,
max_assignees_per_issue=10 # Gitea typical limit
max_assignees_per_issue=10 # Forgejo / Gitea-compatible typical limit
)
@property
@ -56,7 +57,7 @@ class GiteaBackend(RemoteBackend, SyncableBackend):
return self._capabilities
def connect(self, config: Dict[str, Any]) -> None:
"""Connect to Gitea API."""
"""Connect to Forgejo (Gitea-compatible API)."""
self.base_url = config['base_url'].rstrip('/')
self.token = config['token']
self.owner = config['owner']
@ -71,10 +72,10 @@ class GiteaBackend(RemoteBackend, SyncableBackend):
# Test connection
if not self.test_connection():
raise GiteaAPIError("Failed to connect to Gitea API")
raise GiteaAPIError("Failed to connect to Forgejo (Gitea-compatible API)")
def disconnect(self) -> None:
"""Disconnect from Gitea API."""
"""Disconnect from Forgejo."""
self.session.close()
self.base_url = None
self.token = None
@ -195,20 +196,20 @@ class GiteaBackend(RemoteBackend, SyncableBackend):
if issue.milestone:
data['milestone'] = int(issue.milestone.backend_id) if issue.milestone.backend_id else None
# Gitea expects numeric label IDs on issue create/update. Name-only
# labels are preserved in issue-core metadata but omitted from the API
# payload until a label-resolution step exists.
label_ids = []
for label in issue.labels:
if not label.backend_id:
continue
try:
label_ids.append(int(label.backend_id))
except (TypeError, ValueError):
continue
if label_ids:
data['labels'] = label_ids
# Gitea expects numeric label IDs on issue create/update. Name-only
# labels are preserved in issue-core metadata but omitted from the API
# payload until a label-resolution step exists.
label_ids = []
for label in issue.labels:
if not label.backend_id:
continue
try:
label_ids.append(int(label.backend_id))
except (TypeError, ValueError):
continue
if label_ids:
data['labels'] = label_ids
return data
# Issue CRUD Operations