Files
gitea-infrastructure/lessons-learned.md
Alex Mikhalev de9f6bc3ff docs: Update handover and add lessons learned
- Update HANDOVER.md with AI agent skill section, API gotchas, session log
- Add lessons-learned.md with Gitea API findings and debugging insights

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:01:38 +01:00

3.8 KiB

Lessons Learned

Session: 2026-02-18 -- Gitea Agent Skill Implementation

Technical Discoveries

  1. Gitea 1.22.6 has no project board REST API

    • /api/v1/user/projects returns 404
    • The existing SKILL.md had endpoints that do not exist
    • Project board API is tracked in Gitea issue #14299, targeted for 1.26+
    • Mitigation: Use milestones as project containers -- they have built-in progress tracking
  2. Scoped label exclusivity is UI-only in Gitea 1.22.6

    • Labels with exclusive: true display mutual exclusivity in the web UI
    • The API POST /repos/{owner}/{repo}/issues/{index}/labels only appends -- it does NOT remove conflicting scoped labels
    • Fix: Use a swap pattern: GET current labels, filter out old scope, add new label ID, PUT full set atomically
    • This was the single biggest "gotcha" -- the documentation implies API enforcement that does not exist
  3. POST /issues/{index}/assignees does not exist in Gitea 1.22.6

    • Returns 404
    • Fix: Use PATCH /repos/{owner}/{repo}/issues/{index} with {"assignees": ["username"]}
    • This is a general issue edit endpoint, not a dedicated assignee endpoint
  4. Issue dependency format is IssueMeta, not simple ID

    • Wrong: {"depends_on_id": 2} -- returns "repository does not exist [id: 0]"
    • Correct: {"owner": "terraphim", "repo": "agent-tasks", "index": 2}
    • Must check the Swagger spec for exact body format rather than guessing

Debugging Approaches That Worked

  1. Test against live API first, then write code

    • Verified all 7 open questions against the live Gitea instance before writing any helper functions
    • This caught the project board API gap before writing fake endpoints
  2. Integration tests with real cleanup

    • Each test run creates a timestamped repo (skill-test-{timestamp}), runs all tests, then deletes it
    • Trap on EXIT ensures cleanup even on failure
    • No mocks -- tests prove the actual API behavior
  3. Incremental testing (run, fail, fix, rerun)

    • First test run: 23/26 pass, 3 fail -- immediately identified the label/assignee issues
    • Fixed the swap pattern and PATCH approach, second run: 26/26 pass

Pitfalls to Avoid

  1. Do not trust Gitea documentation for API behavior -- always verify against the live instance. The swagger spec is the source of truth, but even that can be misleading for edge cases like scoped label exclusivity.

  2. Do not assume POST endpoints exist for every resource subpath -- Gitea's API is inconsistent. Some resources (labels) have POST, others (assignees) only work via PATCH on the parent resource.

  3. Do not rely on UBS scanner for infrastructure projects -- UBS found no scannable language files (expected for a project with only shell scripts, YAML, and markdown). Pre-commit hooks are more useful here.

  4. Pre-commit python version -- The system may not have the Python version specified in .pre-commit-config.yaml. Changed from python3.9 to python3.12 to match the system. Also needed python3.12-venv apt package for virtualenv support.

Best Practices Discovered

  1. Disciplined development phases work well for API integration

    • Phase 1 (Research): Discovered the project board API gap before design
    • Phase 2 (Design): Created the label swap architecture before implementation
    • Phase 3 (Implementation): Tests caught 3 API bugs on first run
  2. Default repository pattern -- Using env vars with defaults (GITEA_OWNER=${GITEA_OWNER:-terraphim}) lets agents work out of the box while remaining configurable.

  3. JSON output from all helpers -- Every shell function outputs valid JSON, making it trivial for agents to parse results with jq.

  4. Idempotent setup scripts -- setup-labels.sh checks for existing resources before creating, making it safe to run repeatedly.