grantforge-api / DEPLOYMENT.md
GrantForge Bot
Deploy to Hugging Face
3b7f713
# 🚀 Deployment Guide — GrantForge AI Enterprise (v1.3.0)
> **Sprint 9 — Instrukcja produkcyjna**
> Aktualizacja: kwiecień 2026 | Stack: Render.com + PostgreSQL + GitHub Actions CI/CD
---
## Architektura Deploymentu
```
GitHub (main) → GitHub Actions CI/CD → Render.com
├── grantforge-api (FastAPI + Gunicorn)
├── grantforge-frontend (React SPA)
└── grantforge-db (PostgreSQL 16)
```
---
## KROK 1: GitHub Repository Secrets
Przejdź do: `GitHub → Settings → Secrets and variables → Actions`
### Wymagane Secrets (CI/CD + Deploy):
| Secret Name | Skąd wziąć | Ważny? |
|---|---|---|
| `GOOGLE_API_KEY` | [Google AI Studio](https://aistudio.google.com/app/apikey) | ✅ Wymagany |
| `VITE_CLERK_PUBLISHABLE_KEY` | Clerk Dashboard → API Keys → Publishable Key | ✅ Wymagany |
| `RENDER_DEPLOY_HOOK_BACKEND` | Render → API service → Settings → Deploy Hook | ✅ Wymagany |
| `RENDER_DEPLOY_HOOK_FRONTEND` | Render → Static service → Settings → Deploy Hook | ✅ Wymagany |
| `PINECONE_API_KEY` | [Pinecone Console](https://app.pinecone.io) | RAG optional |
| `PINECONE_INDEX_NAME` | Pinecone Console → Index name | RAG optional |
| `LANGCHAIN_API_KEY` | [LangSmith](https://smith.langchain.com) → Settings | Monitoring |
### Jak dodać secret:
```
GitHub repo → Settings → Secrets → Actions → New repository secret
```
#### Render Deploy Hook (backend):
1. Render Dashboard → `grantforge-api` → Settings
2. Scroll do sekcji **Deploy Hooks**
3. Kliknij **Add Deploy Hook** → Nazwa: `ci-deploy`
4. Skopiuj URL (format: `https://api.render.com/deploy/srv-xxx?key=yyy`)
5. Zapisz jako secret `RENDER_DEPLOY_HOOK_BACKEND`
#### Render Deploy Hook (frontend):
1. Render Dashboard → `grantforge-frontend` → Settings
2. Kliknij **Add Deploy Hook** → Nazwa: `ci-frontend`
3. Skopiuj URL → Zapisz jako `RENDER_DEPLOY_HOOK_FRONTEND`
---
## KROK 2: Render → Environment Variables
Przejdź do: `Render → grantforge-api → Environment`
Ustaw następujące zmienne (kliknij **Add Environment Variable** dla każdej):
```bash
# ── LLM ─────────────────────────────
GOOGLE_API_KEY= # Klucz Google Gemini
BIELIK_MODE=disabled # disabled / huggingface / ollama
# ── Autentykacja Clerk ───────────────
CLERK_SECRET_KEY= # sk_live_... (Clerk Dashboard → API Keys)
CLERK_PUBLISHABLE_KEY= # pk_live_... (Clerk Dashboard → API Keys)
# ── RAG / Pinecone ───────────────────
PINECONE_API_KEY= # Opcjonalne — bez tego RAG działa lokalnie
PINECONE_INDEX_NAME= # Nazwa indeksu
PINECONE_ENVIRONMENT= # Np. "gcp-starter"
# ── LangSmith (monitoring) ───────────
LANGCHAIN_API_KEY= # ls_... ze smith.langchain.com
LANGCHAIN_TRACING_V2=true
LANGCHAIN_PROJECT=grantforge-production
# ── Stripe (płatności) ───────────────
STRIPE_SECRET_KEY= # sk_live_...
STRIPE_WEBHOOK_SECRET= # whsec_...
STRIPE_PRICE_ID_PRO= # price_...
# ── Dysk danych ──────────────────────
UPLOAD_DIR=/data/uploads
VECTOR_STORE_DIR=/data/vector_store
LLAMAPARSE_CACHE_DIR=/data/llamaparse_cache
```
> **Uwaga:** `DATABASE_URL` jest automatycznie wstrzyknięty przez Render Blueprint z bloku `databases`.
---
## KROK 3: Pierwsza Migracja Bazy Danych
Po pierwszym deploymencie na Render, uruchom one-off job alembic:
1. Render → `grantforge-api` → **Shell** (lub: one-off command)
2. Wpisz:
```bash
alembic upgrade head
```
3. Sprawdź czy tabele zostały stworzone (w tym `project_documents` z Sprint 8).
### Lokalnie (przed deploy):
```bash
cd backend
alembic upgrade head
```
Jeśli błąd — sprawdź `DATABASE_URL` w `.env`.
---
## KROK 4: Weryfikacja po Deploy
Po uruchomieniu, zweryfikuj każdy endpoint:
```bash
# 1. Health check (podstawowy)
curl https://grantforge-api.onrender.com/api/health
# Oczekiwana odpowiedź:
# {"status": "ok", "db": "connected", "version": "1.3.0", ...}
# 2. Sprawdź czy upload PDF działa
curl -X POST https://grantforge-api.onrender.com/api/projects/TEST_PROJECT_ID/documents \
-F "file=@test.pdf"
# Oczekiwane: 202 Accepted
# 3. Sprawdź listę dokumentów z kwotą
curl https://grantforge-api.onrender.com/api/projects/TEST_PROJECT_ID/documents
# Oczekiwane: {"documents": [], "quota": {"current": 0, "limit": 3, "plan": "free", "can_upload": true}}
# 4. Sprawdź nabory
curl https://grantforge-api.onrender.com/api/grants/nabory
# Oczekiwane: {"total": N, "sources": [...]}
```
---
## KROK 5: CI/CD — Pierwszy Push
Po skonfigurowaniu secrets, każdy push na `main` uruchomi pipeline:
```bash
git add -A
git commit -m "chore: Sprint 9 — upload limits + E2E tests"
git push origin main
```
Pipeline (`.github/workflows/ci.yml`):
1. 🔍 **Lint & Type Check** (ruff + mypy)
2. 🧪 **Backend Tests** (pytest)
3. 🎯 **DeepEval RAG** (tylko main)
4. 🏗️ **Frontend Build** (Vite)
5. 🐳 **Docker Build & Push** (ghcr.io)
6. 🚀 **Deploy to Render** (webhook)
Monitor pipeline: `GitHub → Actions → CI/CD — GrantForge AI`
---
## Limity Upload PDF (Sprint 9)
| Plan | Max pliki/projekt | Hard limit |
|---|---|---|
| Free | 3 PDF | 10 PDF |
| Pro | 50 PDF | 10 PDF |
| Enterprise | 50 PDF | 10 PDF |
> Hard limit (10) jest bezwzględny — dotyczy wszystkich planów.
> Soft limit jest egzekwowany przez `_check_upload_limits()` w `endpoints/documents.py`.
---
## Troubleshooting
### Backend nie startuje
```bash
# Sprawdź logi Render → Logs
# Najczęstszy błąd: brak DATABASE_URL lub import error
```
### Alembic error: "Can't locate revision"
```bash
cd backend
alembic stamp head # jeśli tabele już istnieją
alembic upgrade head
```
### Upload 429 Too Many Requests
Użytkownik osiągnął limit planu. Opcje:
1. Usuń stary dokument w zakładce "Dokumenty RAG"
2. Przejdź na plan Pro (`/cennik`)
### RAG nie indeksuje (status: error)
Sprawdź w Render Shell:
```bash
# W logach szukaj [RAG Upload] ❌
# Najprawdopodobniejsza przyczyna: Pinecone key / pusty PDF
```