Spaces:
Running
Running
| # 🚀 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 | |
| ``` | |