5.5 KiB
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=xxxendpoint 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
accesstable, 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 cacherepository.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
- Startup: full sync of all non-archived repos from
repositorytable - Every 5 hours: full sync (upsert based on repo id)
- Webhook: incremental create/delete for real-time updates
- 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)