Files
GiteaCustomApi/PROJECT_PLAN.md
2026-04-14 09:10:55 +00:00

5.5 KiB

GiteaCustomApi

Gitea repository metadata cache + query API for git.hangman-lab.top.

Overview

A lightweight Go service that:

  • Caches repository metadata (id, name, owner, visibility, url) from Gitea MySQL database
  • Refreshes every 5 hours via full sync
  • Listens for Gitea webhook events (repo create/delete) for real-time cache updates
  • Exposes a /list?username=xxx endpoint that queries cached repos + live collaborator permissions from MySQL

Architecture

┌─────────────────────────────────────────────────────────────┐
│                        VPS.git                               │
│  ┌──────────────┐   ┌─────────────┐   ┌──────────────────┐ │
│  │  Gitea DB    │   │ go-server   │   │    Nginx         │ │
│  │  (MySQL)     │◄──│ (cache+api) │   │ /c-api -> :8080  │ │
│  └──────────────┘   └─────────────┘   └──────────────────┘ │
│                              ▲                              │
│                     ┌────────┴────────┐                     │
│                     │  Gitea Webhook  │                     │
│                     │  (create/delete)│                     │
│                     └─────────────────┘                     │
└─────────────────────────────────────────────────────────────┘

Tech Stack

  • Language: Go
  • Database: SQLite (local cache)
  • Source DB: Gitea MySQL (read-only, same docker network)
  • HTTP: Standard library net/http
  • Deployment: Docker + Docker Compose on vps.git

API

GET /list?username={username}

Returns all repositories visible to the given Gitea user.

Response (JSON):

[
  {
    "name": "ClawSkills",
    "owner": "lyn",
    "url": "https://git.hangman-lab.top/lyn/ClawSkills.git",
    "is_private": false,
    "can_write": true
  }
]

can_write is determined at query time by checking:

  • User is the repo owner, OR
  • User has explicit access via access table, OR
  • User is a member of a team that has access to the repo

POST /webhook/gitea

Receives Gitea webhook events (requires X-Gitea-Event header).

Supported events:

  • repository.create — insert new repo into cache
  • repository.delete — remove repo from cache

GET /health

Returns {"status": "ok"}.

Data Model

SQLite cache table: repos

Column Type Notes
id INTEGER Gitea repo ID (primary key)
name TEXT
owner TEXT Gitea username of owner
is_private INTEGER 0 or 1
url TEXT Full .git HTTPS URL
updated_at INTEGER Unix timestamp of last sync

Configuration

Environment variables:

Variable Default Description
DB_HOST mysql MySQL container hostname
DB_USER root MySQL username
DB_PASS MySQL password
DB_NAME giteadb MySQL database name
SQLITE_PATH cache.db SQLite file path
WEBHOOK_SECRET Gitea webhook secret token
PORT 8080 HTTP listen port

Docker

Dockerfile

FROM golang:1.22-alpine AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o server .
CMD ["./server"]

docker-compose.yml (fragment to merge into vps.git compose)

services:
  gitea-custom-api:
    build: ./gitea-custom-api
    container_name: gitea-custom-api
    restart: unless-stopped
    environment:
      DB_HOST: mysql
      DB_USER: root
      DB_PASS: ${MYSQL_ROOT_PASSWORD}
      DB_NAME: giteadb
      SQLITE_PATH: /data/cache.db
      WEBHOOK_SECRET: ${GITEA_WEBHOOK_SECRET}
      PORT: 8080
    volumes:
      - ./gitea-custom-api/data:/data
    networks:
      - git-network

networks:
  git-network:
    external: true

Nginx location (merge into vps.git nginx config)

location /c-api/ {
    proxy_pass http://localhost:8080/;
}

Gitea Webhook Setup

In Gitea admin panel → Webhooks → Add webhook:

  • URL: https://git.hangman-lab.top/c-api/webhook/gitea
  • HTTP Method: POST
  • Content Type: application/json
  • Secret: set a strong token, pass via WEBHOOK_SECRET
  • Events: Repository: Create, Repository: Delete

Refresh Strategy

  1. Startup: full sync of all non-archived repos from repository table
  2. Every 5 hours: full sync (upsert based on repo id)
  3. Webhook: incremental create/delete for real-time updates
  4. On cache miss during query: fall back to live MySQL query

Out of Scope

  • Authentication on the API endpoint (internal service, only accessible via nginx on vps.git)
  • Caching collaborator permissions (queried live per request)
  • Handling repo rename/transfer (caught by 5h refresh)