first commit

This commit is contained in:
Space-Banane
2026-05-29 19:15:00 +02:00
commit a54d1cfeaf
25 changed files with 1183 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
Metadata-Version: 2.4
Name: git-activity-merge
Version: 0.1.0
Summary: FastAPI service that merges GitHub and Gitea contribution heatmaps and renders embeddable images.
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: fastapi>=0.115.0
Requires-Dist: uvicorn[standard]>=0.30.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic-settings>=2.4.0
Requires-Dist: cairosvg>=2.7.1
Provides-Extra: dev
Requires-Dist: pytest>=8.3.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
Requires-Dist: anyio>=4.4.0; extra == "dev"
# git-activity-merge
Small self-hosted FastAPI service that merges GitHub + Gitea contribution data and returns embeddable contribution heatmap images.
Example for GitHub profile README:
```md
![Activity](https://example.com/activity.svg)
```
## What It Does
- Fetches contribution data from:
- GitHub GraphQL API (`GITHUB_USERNAME`, optional `GITHUB_TOKEN`)
- Gitea heatmap API (`{GITEA_BASE_URL}/api/v1/users/{GITEA_USERNAME}/heatmap`)
- Normalizes into date-based counts:
- `github`
- `gitea`
- `total`
- Caches source responses and rendered images on disk.
- Returns:
- merged JSON
- GitHub-style SVG heatmap
- PNG heatmap
## API Routes
- `GET /health`
- `GET /activity.json`
- `GET /activity.svg`
- `GET /activity.png`
Supported query params:
- `year=YYYY` or `days=365` (mutually exclusive)
- `theme=dark|light`
- `source=all|github|gitea`
Examples:
```bash
curl "http://localhost:8000/activity.json?days=365&source=all"
curl "http://localhost:8000/activity.svg?year=2026&theme=dark"
curl "http://localhost:8000/activity.png?days=180&source=gitea"
```
## Setup
### 1. Install
```bash
python -m venv .venv
. .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
```
### 2. Configure
Copy `.env.example` to `.env` and edit values.
Required:
- `GITHUB_USERNAME`
- `GITEA_BASE_URL`
- `GITEA_USERNAME`
Optional:
- `GITHUB_TOKEN`
- `GITEA_TOKEN`
- `CACHE_TTL_SECONDS` (default: `3600`)
- `CACHE_DIR` (default: `./cache` locally, `/app/cache` in container)
- `DEFAULT_THEME` (`light` or `dark`, default: `light`)
- `SERVICE_TITLE` (default: `git-activity-merge`)
### 3. Run
```bash
uvicorn app.main:app --reload --port 8000
```
## Docker
```bash
docker compose up --build
```
Container serves on port `8000` and mounts a named cache volume at `/app/cache`.
## Reverse Proxy Example (Nginx)
```nginx
server {
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Then embed directly:
```md
![Activity](https://example.com/activity.svg?days=365&theme=dark)
```
## Notes
- GitHub GraphQL without token is possible but lower-rate/less reliable. Set `GITHUB_TOKEN` for stability.
- Gitea instances may require `GITEA_TOKEN` for private activity or stricter rate limits.
- If upstream APIs fail and stale cache exists, `/activity.json` includes `"stale": true` and stale data is served.