Pipeline/backend/.learnings/neo/LEARNINGS.md

2.6 KiB

LEARNINGS.md - Neo's Insights

2026-05-19 - Issue 5-8 Implementation

Issue 5: Backend Connection/Repository Validation API

  • Created /backend/app/schemas/forgejo_validation.py with validation response schemas
  • Added POST /api/v1/forgejo/connections/{connection_id}/validate endpoint
  • Added POST /api/v1/forgejo/repositories/{repository_id}/validate endpoint
  • Validation tests authentication with Forgejo API
  • Errors are safe for display (no tokens exposed)

Issue 6: Cached Issue Database Model

  • Created /backend/app/models/forgejo_issues.py with ForgejoIssue model
  • Created /backend/app/schemas/forgejo_issues.py with read/create/list schemas
  • Created migration /backend/migrations/versions/a1b2c3d4e5f7_add_forgejo_issues.py
  • Model includes JSON fields for labels and assignees using sa_column=Column(JSON)
  • Unique constraint on (repository_id, forgejo_issue_number)

Issue 7: Issue Sync Service and Manual Sync API

  • Created /backend/app/services/forgejo_issue_sync.py with IssueSyncService
  • Service fetches issues via ForgejoAPIClient with pagination
  • Handles upsert of issues into database
  • Excludes pull requests from sync (type=issues filter)
  • Updates repository.last_sync_at on success
  • Updates repository.last_sync_error on failure
  • Admin-only endpoint at POST /api/v1/forgejo/repositories/{repository_id}/sync

Issue 8: Human Issue List and Read APIs

  • Created /backend/app/api/forgejo_issues.py with issue endpoints
  • GET /api/v1/forgejo/issues - paginated list with filters:
    • repository_id, state, label, assignee, search text
  • GET /api/v1/forgejo/issues/{issue_id} - single issue read
  • Cross-organization access returns 404
  • Pull requests excluded from responses (sync service filters them)

Errors Encountered

  • Import path truncated in forgejo_connections.py - fixed by proper import ordering
  • Schema file had duplicate content - rewritten cleanly
  • API file corruption during incremental edits - rewritten completely for forgejo_issues.py
  • JSON field type error: TypeError: issubclass() arg 1 must be a class - caused by using sa_column=JSON instead of sa_column=Column(JSON). Fixed by following existing pattern in other models (approvals.py, agents.py, board_onboarding.py)

Notes

  • All endpoints follow existing patterns in forgejo_connections.py and forgejo_repositories.py
  • Auth context via require_org_admin decorator ensures organization isolation
  • SQLModel relationships cannot be set directly - use fetch + assign pattern
  • JSON fields use sa_column=Column(JSON) for SQLAlchemy JSON type
  • Issue sync excludes pull requests with if issue_data.get("pull_request") is not None: continue