mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
local setup (#1898)
Signed-off-by: Saurabh Misra <misra.saurabh1@gmail.com> Co-authored-by: saga4 <saga4@codeflashs-MacBook-Air.local> Co-authored-by: Sarthak Agarwal <sarthak.saga@gmail.com> Co-authored-by: Mohamed Ashraf <mohamedashrraf222@gmail.com> Co-authored-by: Aseem Saxena <aseem.bits@gmail.com>
This commit is contained in:
parent
0a49cd32c7
commit
7c1933180a
40 changed files with 2513 additions and 127 deletions
136
.dockerignore
Normal file
136
.dockerignore
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# Python virtual environments
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
django/aiservice/.venv/
|
||||
django/aiservice/venv/
|
||||
django/aiservice/__pycache__/
|
||||
|
||||
# Node.js dependencies
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
build/
|
||||
.next/
|
||||
.nuxt/
|
||||
.vuepress/dist/
|
||||
.serverless/
|
||||
.fusebox/
|
||||
.dynamodb/
|
||||
.tern-port/
|
||||
.vscode-test/
|
||||
|
||||
# Cache directories
|
||||
.cache/
|
||||
.parcel-cache/
|
||||
.eslintcache/
|
||||
.stylelintcache/
|
||||
.ruff_cache/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# Testing
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
.tmp/
|
||||
|
||||
# Yarn
|
||||
.yarn/cache/
|
||||
.yarn/unplugged/
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
develop-eggs/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
*.sqlite3
|
||||
|
||||
# Large directories that shouldn't be in build context
|
||||
experiments/
|
||||
node_modules/
|
||||
js/node_modules/
|
||||
js/cf-api/node_modules/
|
||||
js/cf-webapp/node_modules/
|
||||
js/common/node_modules/
|
||||
django/aiservice/venv/
|
||||
django/aiservice/.venv/
|
||||
|
||||
# Additional large files
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
*.7z
|
||||
*.iso
|
||||
*.dmg
|
||||
|
||||
# Lock files (keep package-lock.json but exclude others)
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
2
.github/workflows/django-unit-tests.yaml
vendored
2
.github/workflows/django-unit-tests.yaml
vendored
|
|
@ -51,6 +51,8 @@ jobs:
|
|||
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ jobs:
|
|||
env:
|
||||
CODEFLASH_AIS_SERVER: local
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
|
||||
|
|
|
|||
2
.github/workflows/mypy_aiservice.yml
vendored
2
.github/workflows/mypy_aiservice.yml
vendored
|
|
@ -19,6 +19,8 @@ jobs:
|
|||
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
|
||||
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
|
||||
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
|
|
|||
171
deployment/onprem-simple/Dockerfile.unifiedall
Normal file
171
deployment/onprem-simple/Dockerfile.unifiedall
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
# ============================================================================
|
||||
# Codeflash Unified Container - Self-Contained Build
|
||||
# ============================================================================
|
||||
# This Dockerfile builds everything from source without depending on pre-built
|
||||
# images. Use this for client deployments and teammate onboarding.
|
||||
#
|
||||
# Build command:
|
||||
# docker build -f deployment/onprem-simple/Dockerfile.unified-selfcontained \
|
||||
# -t codeflash/unified:latest .
|
||||
#
|
||||
# ============================================================================
|
||||
|
||||
# ============================================================================
|
||||
# Stage 1: Build aiservice
|
||||
# ============================================================================
|
||||
FROM --platform=$BUILDPLATFORM python:3.12-slim AS aiservice-builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies for aiservice
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install uv
|
||||
RUN pip install uv
|
||||
|
||||
# Copy aiservice source
|
||||
COPY django/aiservice ./
|
||||
|
||||
# Install dependencies
|
||||
RUN uv sync
|
||||
|
||||
# ============================================================================
|
||||
# Stage 2: Build cf-api
|
||||
# ============================================================================
|
||||
FROM node:20-alpine AS cfapi-builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy cf-api and common source
|
||||
COPY js/cf-api ./cf-api
|
||||
COPY js/common ./common
|
||||
|
||||
# Build common package first (cf-api depends on it)
|
||||
WORKDIR /build/common
|
||||
RUN npm ci && npm run build
|
||||
|
||||
# Install ALL dependencies for cf-api (matching Dockerfile.cfapi exactly)
|
||||
WORKDIR /build/cf-api
|
||||
RUN npm ci
|
||||
|
||||
# Replace the common package from registry with local build
|
||||
RUN rm -rf node_modules/@codeflash-ai/common && \
|
||||
cp -r /build/common node_modules/@codeflash-ai/
|
||||
|
||||
# Clean dist folder before build
|
||||
RUN rm -rf dist
|
||||
|
||||
# Build TypeScript (npm run build does: npm install && prisma generate && tsc && copy-assets)
|
||||
RUN npm run build
|
||||
|
||||
# ============================================================================
|
||||
# Stage 3: Build cf-webapp
|
||||
# ============================================================================
|
||||
FROM node:20-alpine AS webapp-builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy cf-webapp and common source
|
||||
COPY js/cf-webapp ./cf-webapp
|
||||
COPY js/common ./common
|
||||
|
||||
# Build common package first (webapp depends on it)
|
||||
WORKDIR /build/common
|
||||
RUN npm ci && npm run build
|
||||
|
||||
# Install ALL dependencies for webapp
|
||||
WORKDIR /build/cf-webapp
|
||||
RUN npm ci
|
||||
|
||||
# Replace the common package from registry with local build
|
||||
RUN rm -rf node_modules/@codeflash-ai/common && \
|
||||
cp -r /build/common node_modules/@codeflash-ai/
|
||||
|
||||
# Build Next.js application
|
||||
RUN npm run build
|
||||
|
||||
# ============================================================================
|
||||
# Stage 4: Final unified container
|
||||
# ============================================================================
|
||||
FROM node:20-alpine
|
||||
|
||||
# Install system dependencies
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
py3-pip \
|
||||
postgresql15 \
|
||||
postgresql15-client \
|
||||
supervisor \
|
||||
bash \
|
||||
openssl \
|
||||
build-base \
|
||||
libpq-dev \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Install Python uv
|
||||
RUN pip3 install --break-system-packages uv
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# ============================================================================
|
||||
# Copy cf-api from builder
|
||||
# ============================================================================
|
||||
COPY --from=cfapi-builder /build/cf-api/dist ./cf-api/dist
|
||||
COPY --from=cfapi-builder /build/cf-api/package.json ./cf-api/package.json
|
||||
COPY --from=cfapi-builder /build/cf-api/package-lock.json ./cf-api/package-lock.json
|
||||
COPY --from=cfapi-builder /build/cf-api/resend ./cf-api/resend
|
||||
COPY --from=cfapi-builder /build/cf-api/github ./cf-api/github
|
||||
COPY --from=cfapi-builder /build/cf-api/node_modules ./cf-api/node_modules
|
||||
COPY --from=cfapi-builder /build/common /common
|
||||
|
||||
# Copy node_modules into dist (Azure deployment structure)
|
||||
RUN cp -rL /app/cf-api/node_modules /app/cf-api/dist/ 2>/dev/null || cp -r /app/cf-api/node_modules /app/cf-api/dist/
|
||||
|
||||
# ============================================================================
|
||||
# Copy aiservice from builder
|
||||
# ============================================================================
|
||||
COPY --from=aiservice-builder /app ./aiservice
|
||||
|
||||
# ============================================================================
|
||||
# Copy cf-webapp from builder
|
||||
# ============================================================================
|
||||
COPY --from=webapp-builder /build/cf-webapp/.next ./cf-webapp/.next
|
||||
COPY --from=webapp-builder /build/cf-webapp/public ./cf-webapp/public
|
||||
COPY --from=webapp-builder /build/cf-webapp/package.json ./cf-webapp/package.json
|
||||
COPY --from=webapp-builder /build/cf-webapp/package-lock.json ./cf-webapp/package-lock.json
|
||||
COPY --from=webapp-builder /build/cf-webapp/next.config.mjs ./cf-webapp/next.config.mjs
|
||||
COPY --from=webapp-builder /build/cf-webapp/node_modules ./cf-webapp/node_modules
|
||||
|
||||
# ============================================================================
|
||||
# Configure PostgreSQL
|
||||
# ============================================================================
|
||||
RUN mkdir -p /var/lib/postgresql/data /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql
|
||||
|
||||
# ============================================================================
|
||||
# Copy configuration files
|
||||
# ============================================================================
|
||||
COPY deployment/onprem-simple/supervisord.conf /etc/supervisord.conf
|
||||
COPY deployment/onprem-simple/init-db.sh /app/init-db.sh
|
||||
COPY deployment/onprem-simple/startup.sh /app/startup.sh
|
||||
|
||||
RUN chmod +x /app/init-db.sh /app/startup.sh
|
||||
|
||||
# ============================================================================
|
||||
# Expose ports
|
||||
# ============================================================================
|
||||
EXPOSE 5432 8000 3001 3000
|
||||
|
||||
# ============================================================================
|
||||
# Environment variables
|
||||
# ============================================================================
|
||||
ENV PGDATA=/var/lib/postgresql/data
|
||||
ENV PATH="/var/lib/postgresql/bin:${PATH}"
|
||||
|
||||
# ============================================================================
|
||||
# Start services
|
||||
# ============================================================================
|
||||
CMD ["/app/startup.sh"]
|
||||
341
deployment/onprem-simple/README.md
Normal file
341
deployment/onprem-simple/README.md
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
# Codeflash On-Premise Deployment
|
||||
|
||||
A single Docker container that runs all Codeflash services for on-premise deployments.
|
||||
|
||||
## What's Inside
|
||||
|
||||
The unified container includes:
|
||||
- **PostgreSQL 15** - Database server (port 5432)
|
||||
- **aiservice** - Python Django optimization service (port 8000)
|
||||
- **cf-api** - Node.js API server (port 3001)
|
||||
- **cf-webapp** - Next.js web interface (port 3000)
|
||||
- **Supervisord** - Process manager for all services
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker installed (version 20.10 or higher)
|
||||
- An AI provider API key (Azure OpenAI, OpenAI, or Anthropic)
|
||||
|
||||
### Step 1: Build the Docker Image
|
||||
|
||||
```bash
|
||||
git clone https://github.com/codeflash-ai/codeflash
|
||||
cd codeflash
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:latest .
|
||||
```
|
||||
|
||||
**Build time:** ~5-10 minutes
|
||||
|
||||
### Step 2: Run the Container
|
||||
|
||||
The simplest way to run Codeflash (only 1 required environment variable!):
|
||||
|
||||
```bash
|
||||
docker run -d --name codeflash \
|
||||
-e AZURE_OPENAI_API_KEY=your-azure-api-key \
|
||||
-p 5432:5432 \
|
||||
-p 8000:8000 \
|
||||
-p 3001:3001 \
|
||||
-p 3000:3000 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
```
|
||||
|
||||
**What happens automatically:**
|
||||
- ✅ DATABASE_URL defaults to built-in PostgreSQL
|
||||
- ✅ SECRET_KEY auto-generated
|
||||
- ✅ URLs default to localhost
|
||||
- ✅ API key auto-generated on first run
|
||||
|
||||
### Step 3: Get Your API Key
|
||||
|
||||
After the container starts (~15 seconds), retrieve your API key:
|
||||
|
||||
```bash
|
||||
# View logs to see the API key
|
||||
docker logs codeflash
|
||||
|
||||
# Or get it from the saved file
|
||||
docker exec codeflash cat /app/API_KEY.txt
|
||||
```
|
||||
|
||||
You'll see output like:
|
||||
```
|
||||
======================================
|
||||
CODEFLASH SETUP COMPLETE!
|
||||
======================================
|
||||
|
||||
Your API Key: cf-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
Save this API key! You'll need it to configure the Codeflash CLI.
|
||||
======================================
|
||||
```
|
||||
|
||||
**Save this API key** - you'll need it for the CLI!
|
||||
|
||||
### Step 4: Install the CLI
|
||||
|
||||
```bash
|
||||
pip install codeflash
|
||||
```
|
||||
|
||||
### Step 5: Configure the CLI
|
||||
|
||||
```bash
|
||||
export CODEFLASH_API_KEY=cf-your-api-key-from-step-3
|
||||
export CODEFLASH_AIS_SERVER=local
|
||||
export CODEFLASH_CFAPI_SERVER=local
|
||||
```
|
||||
|
||||
Or create a `.env` file in your project:
|
||||
```bash
|
||||
CODEFLASH_API_KEY=cf-your-api-key-from-step-3
|
||||
CODEFLASH_AIS_SERVER=local
|
||||
CODEFLASH_CFAPI_SERVER=local
|
||||
```
|
||||
|
||||
### Step 6: Optimize Your Code!
|
||||
|
||||
```bash
|
||||
cd your-python-project
|
||||
codeflash --file path/to/file.py --function function_name --no-pr
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Minimal Configuration (Recommended)
|
||||
|
||||
Only provide your AI provider key:
|
||||
|
||||
```bash
|
||||
docker run -d --name codeflash \
|
||||
-e OPENAI_API_TYPE=azure \
|
||||
-e OPENAI_API_BASE=your-azure-openai-base-url \
|
||||
-e AZURE_OPENAI_API_KEY=your-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
```
|
||||
|
||||
### Full Configuration (Optional)
|
||||
|
||||
You can customize all settings if needed:
|
||||
|
||||
```bash
|
||||
docker run -d --name codeflash \
|
||||
-e OPENAI_API_TYPE=azure \
|
||||
-e OPENAI_API_BASE=your-azure-openai-base-url \
|
||||
-e AZURE_OPENAI_API_KEY=your-azure-key \
|
||||
-e ANTHROPIC_API_KEY=your-anthropic-key \
|
||||
-e SECRET_KEY=your-custom-secret \
|
||||
-e DATABASE_URL=postgresql://user:pass@host:5432/db \
|
||||
-e NEXT_PUBLIC_APP_URL=http://your-domain:3000 \
|
||||
-e WEBAPP_URL=http://your-domain:3000 \
|
||||
-e CODEFLASH_CFAPI_URL=http://your-domain:3001 \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
```
|
||||
|
||||
See `.env.onprem.minimal` for all available options.
|
||||
|
||||
## Container Management
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
# Check if container is running
|
||||
docker ps | grep codeflash
|
||||
|
||||
# View logs
|
||||
docker logs codeflash
|
||||
|
||||
# Follow logs in real-time
|
||||
docker logs -f codeflash
|
||||
|
||||
# Check service status inside container
|
||||
docker exec codeflash supervisorctl status
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
postgres RUNNING pid 40, uptime 0:10:23
|
||||
aiservice RUNNING pid 41, uptime 0:10:23
|
||||
cf-api RUNNING pid 42, uptime 0:10:23
|
||||
cf-webapp RUNNING pid 43, uptime 0:10:23
|
||||
```
|
||||
|
||||
### Stop/Start/Restart
|
||||
|
||||
```bash
|
||||
# Stop container (data persists in volume)
|
||||
docker stop codeflash
|
||||
|
||||
# Start container
|
||||
docker start codeflash
|
||||
|
||||
# Restart container
|
||||
docker restart codeflash
|
||||
```
|
||||
|
||||
### Remove Container
|
||||
|
||||
```bash
|
||||
# Remove container (keeps data volume)
|
||||
docker stop codeflash
|
||||
docker rm codeflash
|
||||
|
||||
# Remove container AND data (⚠️ deletes all data!)
|
||||
docker stop codeflash
|
||||
docker rm codeflash
|
||||
docker volume rm codeflash-data
|
||||
```
|
||||
|
||||
### Upgrade to New Version
|
||||
|
||||
```bash
|
||||
# Pull or build new image
|
||||
docker pull codeflash/unified:latest
|
||||
# OR
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:latest .
|
||||
|
||||
# Stop and remove old container
|
||||
docker stop codeflash
|
||||
docker rm codeflash
|
||||
|
||||
# Start new container (data persists in volume)
|
||||
docker run -d --name codeflash \
|
||||
-e AZURE_OPENAI_API_KEY=your-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
```
|
||||
|
||||
## Accessing Services
|
||||
|
||||
Once running, you can access:
|
||||
|
||||
- **cf-api**: http://localhost:3001
|
||||
- **aiservice**: http://localhost:8000
|
||||
- **cf-webapp**: http://localhost:3000
|
||||
- **PostgreSQL**: localhost:5432 (username: `codeflash`, password: `codeflash`, database: `codeflash`)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container won't start
|
||||
|
||||
```bash
|
||||
# Check logs for errors
|
||||
docker logs codeflash
|
||||
|
||||
# Verify ports are available
|
||||
lsof -i :5432
|
||||
lsof -i :8000
|
||||
lsof -i :3001
|
||||
lsof -i :3000
|
||||
```
|
||||
|
||||
### Services not responding
|
||||
|
||||
```bash
|
||||
# Check service status
|
||||
docker exec codeflash supervisorctl status
|
||||
|
||||
# Restart a specific service
|
||||
docker exec codeflash supervisorctl restart cf-api
|
||||
docker exec codeflash supervisorctl restart aiservice
|
||||
docker exec codeflash supervisorctl restart cf-webapp
|
||||
```
|
||||
|
||||
### CLI can't connect
|
||||
|
||||
```bash
|
||||
# Test service endpoints
|
||||
curl http://localhost:3001/cfapi/healthcheck
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Verify environment variables
|
||||
echo $CODEFLASH_API_KEY
|
||||
echo $CODEFLASH_AIS_SERVER
|
||||
echo $CODEFLASH_CFAPI_SERVER
|
||||
```
|
||||
|
||||
### Database issues
|
||||
|
||||
```bash
|
||||
# Check if PostgreSQL is ready
|
||||
docker exec codeflash pg_isready -h localhost -p 5432 -U codeflash
|
||||
|
||||
# Access database
|
||||
docker exec -it codeflash psql postgresql://codeflash:codeflash@localhost:5432/codeflash
|
||||
|
||||
# Check API keys in database
|
||||
docker exec codeflash psql postgresql://codeflash:codeflash@localhost:5432/codeflash \
|
||||
-c "SELECT key, suffix FROM cf_api_keys;"
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Do I need GitHub App configuration?**
|
||||
A: No, not if you use `--no-pr` mode. GitHub integration is optional.
|
||||
|
||||
**Q: Do I need Stripe configuration?**
|
||||
A: No, billing features are not required for on-premise deployments.
|
||||
|
||||
**Q: What AI providers are supported?**
|
||||
A: Azure OpenAI, OpenAI, and Anthropic Claude. You only need one.
|
||||
|
||||
**Q: Can I use my own PostgreSQL database?**
|
||||
A: Yes, set the `DATABASE_URL` environment variable.
|
||||
|
||||
**Q: What ports need to be accessible?**
|
||||
A: For CLI usage, only ports 3001 (cf-api) and 8000 (aiservice) are required. Port 3000 (webapp) is for the web interface, and 5432 (PostgreSQL) is only if you want direct database access.
|
||||
|
||||
**Q: How much disk space is needed?**
|
||||
A: ~5GB for the image, plus storage for your data (depends on usage).
|
||||
|
||||
**Q: How much memory is needed?**
|
||||
A: Minimum 2GB RAM, recommended 4GB+ for optimal performance.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- **Container size:** ~5GB (includes all services and dependencies)
|
||||
- **Startup time:** ~15-20 seconds for all services
|
||||
- **Memory usage:** ~500MB-2GB (depending on workload)
|
||||
- **CPU:** Works on both x86_64 and ARM64 (Apple Silicon)
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
deployment/onprem-simple/
|
||||
├── Dockerfile.unifiedall # Main unified Docker image
|
||||
├── supervisord.conf # Process manager configuration
|
||||
├── startup.sh # Container startup script
|
||||
├── init-db.sh # Database initialization script
|
||||
├── .env.onprem.minimal # Minimal environment variables template
|
||||
├── .dockerignore # Docker build exclusions
|
||||
├── README.md # This file
|
||||
├── TESTING.md # Testing guide
|
||||
└── archive/ # Old/experimental files
|
||||
├── old-dockerfiles/ # Previous Dockerfile attempts
|
||||
├── old-compose/ # Old docker-compose files
|
||||
└── old-scripts/ # Previous build scripts
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- ✅ Container built and running
|
||||
- ✅ Database initialized
|
||||
- ✅ API key generated
|
||||
- ✅ CLI configured
|
||||
- 🚀 **Ready to optimize code!**
|
||||
|
||||
See `TESTING.md` for a complete testing guide with example workflows.
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
- GitHub Issues: https://github.com/codeflash-ai/codeflash/issues
|
||||
- Documentation: https://docs.codeflash.ai
|
||||
550
deployment/onprem-simple/TESTING.md
Normal file
550
deployment/onprem-simple/TESTING.md
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
# Codeflash On-Premise Testing Guide
|
||||
|
||||
This guide walks through testing the Codeflash on-premise deployment step-by-step.
|
||||
|
||||
## Quick Test (5 minutes)
|
||||
|
||||
This is the fastest way to verify everything works:
|
||||
|
||||
### 1. Build and Run
|
||||
|
||||
```bash
|
||||
# Build the image (from repository root)
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:latest .
|
||||
|
||||
# Run the container
|
||||
docker run -d --name codeflash-test \
|
||||
-e AZURE_OPENAI_API_KEY=your-azure-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-test-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
# Wait ~15 seconds for services to start
|
||||
sleep 15
|
||||
```
|
||||
|
||||
### 2. Verify All Services Are Running
|
||||
|
||||
```bash
|
||||
# Check container status
|
||||
docker ps | grep codeflash-test
|
||||
|
||||
# Check all services
|
||||
docker exec codeflash-test supervisorctl status
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
postgres RUNNING pid 40, uptime 0:00:15
|
||||
aiservice RUNNING pid 41, uptime 0:00:15
|
||||
cf-api RUNNING pid 42, uptime 0:00:15
|
||||
cf-webapp RUNNING pid 43, uptime 0:00:15
|
||||
```
|
||||
|
||||
### 3. Test Service Endpoints
|
||||
|
||||
```bash
|
||||
# Test cf-api
|
||||
curl http://localhost:3001/cfapi/healthcheck
|
||||
# Expected: {"status":"ok"}
|
||||
|
||||
# Test aiservice
|
||||
curl http://localhost:8000/health
|
||||
# Expected: {"status":"healthy"}
|
||||
|
||||
# Test webapp
|
||||
curl http://localhost:3000
|
||||
# Expected: HTML content
|
||||
```
|
||||
|
||||
### 4. Get API Key
|
||||
|
||||
```bash
|
||||
docker logs codeflash-test | grep "Your API Key"
|
||||
# Or
|
||||
docker exec codeflash-test cat /app/API_KEY.txt
|
||||
```
|
||||
|
||||
### 5. Test CLI
|
||||
|
||||
```bash
|
||||
# Install CLI
|
||||
pip install codeflash
|
||||
|
||||
# Configure environment
|
||||
export CODEFLASH_API_KEY=cf-your-key-from-step-4
|
||||
export CODEFLASH_AIS_SERVER=local
|
||||
export CODEFLASH_CFAPI_SERVER=local
|
||||
|
||||
# Test connection
|
||||
codeflash --help
|
||||
```
|
||||
|
||||
### 6. Test Optimization (Optional)
|
||||
|
||||
If you have a Python project to test:
|
||||
|
||||
```bash
|
||||
cd your-python-project
|
||||
codeflash --file path/to/file.py --function function_name --no-pr -v
|
||||
```
|
||||
|
||||
### 7. Cleanup
|
||||
|
||||
```bash
|
||||
docker stop codeflash-test
|
||||
docker rm codeflash-test
|
||||
docker volume rm codeflash-test-data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Detailed Testing Scenarios
|
||||
|
||||
### Scenario 1: Fresh Installation Test
|
||||
|
||||
Tests a brand new installation from scratch.
|
||||
|
||||
```bash
|
||||
# Clean slate
|
||||
docker stop codeflash-test 2>/dev/null || true
|
||||
docker rm codeflash-test 2>/dev/null || true
|
||||
docker volume rm codeflash-test-data 2>/dev/null || true
|
||||
|
||||
# Build
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:latest .
|
||||
|
||||
# Run
|
||||
docker run -d --name codeflash-test \
|
||||
-e AZURE_OPENAI_API_KEY=your-azure-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-test-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
# Wait for startup
|
||||
sleep 20
|
||||
|
||||
# Verify
|
||||
docker logs codeflash-test
|
||||
docker exec codeflash-test supervisorctl status
|
||||
docker exec codeflash-test pg_isready -h localhost -p 5432 -U codeflash
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ All 4 services show "RUNNING"
|
||||
- ✅ PostgreSQL is ready
|
||||
- ✅ API key generated and saved
|
||||
- ✅ No error messages in logs
|
||||
|
||||
### Scenario 2: Persistent Data Test
|
||||
|
||||
Tests that data persists across container restarts.
|
||||
|
||||
```bash
|
||||
# Get initial API key
|
||||
INITIAL_KEY=$(docker exec codeflash-test cat /app/API_KEY.txt)
|
||||
echo "Initial API key: $INITIAL_KEY"
|
||||
|
||||
# Restart container
|
||||
docker restart codeflash-test
|
||||
sleep 15
|
||||
|
||||
# Get API key after restart
|
||||
NEW_KEY=$(docker exec codeflash-test cat /app/API_KEY.txt)
|
||||
echo "API key after restart: $NEW_KEY"
|
||||
|
||||
# Compare
|
||||
if [ "$INITIAL_KEY" = "$NEW_KEY" ]; then
|
||||
echo "✅ Data persisted correctly"
|
||||
else
|
||||
echo "❌ Data did not persist"
|
||||
fi
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ API key remains the same after restart
|
||||
- ✅ All services restart successfully
|
||||
- ✅ Database data is intact
|
||||
|
||||
### Scenario 3: Service Restart Test
|
||||
|
||||
Tests individual service restarts.
|
||||
|
||||
```bash
|
||||
# Restart cf-api
|
||||
docker exec codeflash-test supervisorctl restart cf-api
|
||||
sleep 5
|
||||
curl http://localhost:3001/cfapi/healthcheck
|
||||
|
||||
# Restart aiservice
|
||||
docker exec codeflash-test supervisorctl restart aiservice
|
||||
sleep 5
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Restart cf-webapp
|
||||
docker exec codeflash-test supervisorctl restart cf-webapp
|
||||
sleep 5
|
||||
curl http://localhost:3000
|
||||
|
||||
# Check all services
|
||||
docker exec codeflash-test supervisorctl status
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ Each service restarts without errors
|
||||
- ✅ Endpoints respond after restart
|
||||
- ✅ No cascading failures
|
||||
|
||||
### Scenario 4: Database Test
|
||||
|
||||
Tests database connectivity and data.
|
||||
|
||||
```bash
|
||||
# Check PostgreSQL is running
|
||||
docker exec codeflash-test pg_isready -h localhost -p 5432 -U codeflash
|
||||
|
||||
# Check database exists
|
||||
docker exec codeflash-test psql postgresql://codeflash:codeflash@localhost:5432/codeflash \
|
||||
-c "\l" | grep codeflash
|
||||
|
||||
# Check tables exist
|
||||
docker exec codeflash-test psql postgresql://codeflash:codeflash@localhost:5432/codeflash \
|
||||
-c "\dt" | head -10
|
||||
|
||||
# Check user exists
|
||||
docker exec codeflash-test psql postgresql://codeflash:codeflash@localhost:5432/codeflash \
|
||||
-c "SELECT * FROM users;"
|
||||
|
||||
# Check API key exists
|
||||
docker exec codeflash-test psql postgresql://codeflash:codeflash@localhost:5432/codeflash \
|
||||
-c "SELECT key, suffix FROM cf_api_keys;"
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ Database `codeflash` exists
|
||||
- ✅ All migrations applied (36+ tables)
|
||||
- ✅ User created
|
||||
- ✅ API key stored
|
||||
|
||||
### Scenario 5: CLI Integration Test
|
||||
|
||||
Full end-to-end test with a real Python file.
|
||||
|
||||
```bash
|
||||
# Create test project
|
||||
mkdir -p /tmp/codeflash-test-project
|
||||
cd /tmp/codeflash-test-project
|
||||
|
||||
# Create a simple Python file
|
||||
cat > test.py << 'EOF'
|
||||
def fibonacci(n):
|
||||
"""Calculate fibonacci number recursively (slow)."""
|
||||
if n <= 1:
|
||||
return n
|
||||
return fibonacci(n - 1) + fibonacci(n - 2)
|
||||
|
||||
def main():
|
||||
print(fibonacci(10))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
EOF
|
||||
|
||||
# Get API key
|
||||
export CODEFLASH_API_KEY=$(docker exec codeflash-test cat /app/API_KEY.txt)
|
||||
export CODEFLASH_AIS_SERVER=local
|
||||
export CODEFLASH_CFAPI_SERVER=local
|
||||
|
||||
# Install CLI
|
||||
pip install codeflash
|
||||
|
||||
# Run optimization
|
||||
codeflash --file test.py --function fibonacci --no-pr -v
|
||||
|
||||
# Check if file was modified
|
||||
git diff test.py 2>/dev/null || echo "File modified (no git)"
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ CLI connects successfully
|
||||
- ✅ Optimization completes without errors
|
||||
- ✅ Function is optimized (or determined not optimizable)
|
||||
- ✅ Test file shows improvements
|
||||
|
||||
### Scenario 6: Port Conflict Test
|
||||
|
||||
Tests behavior when ports are already in use.
|
||||
|
||||
```bash
|
||||
# Try to run second container (should fail)
|
||||
docker run -d --name codeflash-test-2 \
|
||||
-e AZURE_OPENAI_API_KEY=your-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
codeflash/unified:latest 2>&1 | grep "address already in use"
|
||||
|
||||
# Run with different ports (should succeed)
|
||||
docker run -d --name codeflash-test-2 \
|
||||
-e AZURE_OPENAI_API_KEY=your-key \
|
||||
-p 15432:5432 -p 18000:8000 -p 13001:3001 -p 13000:3000 \
|
||||
-v codeflash-test-2-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
sleep 15
|
||||
docker exec codeflash-test-2 supervisorctl status
|
||||
|
||||
# Cleanup
|
||||
docker stop codeflash-test-2
|
||||
docker rm codeflash-test-2
|
||||
docker volume rm codeflash-test-2-data
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ Second container with same ports fails gracefully
|
||||
- ✅ Second container with different ports works
|
||||
- ✅ Both containers can run simultaneously
|
||||
|
||||
### Scenario 7: Environment Variable Test
|
||||
|
||||
Tests various environment variable configurations.
|
||||
|
||||
```bash
|
||||
# Test with minimal config
|
||||
docker run -d --name codeflash-minimal \
|
||||
-e AZURE_OPENAI_API_KEY=test-key \
|
||||
-p 25432:5432 -p 28000:8000 -p 23001:3001 -p 23000:3000 \
|
||||
codeflash/unified:latest
|
||||
|
||||
sleep 20
|
||||
docker logs codeflash-minimal | grep "Generated SECRET_KEY"
|
||||
docker logs codeflash-minimal | grep "API Key:"
|
||||
|
||||
# Test with full config
|
||||
docker run -d --name codeflash-full \
|
||||
-e AZURE_OPENAI_API_KEY=test-key \
|
||||
-e SECRET_KEY=my-custom-secret \
|
||||
-e NEXT_PUBLIC_APP_URL=http://custom.domain:3000 \
|
||||
-e WEBAPP_URL=http://custom.domain:3000 \
|
||||
-p 35432:5432 -p 38000:8000 -p 33001:3001 -p 33000:3000 \
|
||||
codeflash/unified:latest
|
||||
|
||||
sleep 20
|
||||
docker logs codeflash-full | grep -v "Generated SECRET_KEY"
|
||||
|
||||
# Cleanup
|
||||
docker stop codeflash-minimal codeflash-full
|
||||
docker rm codeflash-minimal codeflash-full
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ Minimal config works with auto-generated values
|
||||
- ✅ Full config respects custom values
|
||||
- ✅ No required variables missing
|
||||
|
||||
### Scenario 8: Upgrade Test
|
||||
|
||||
Tests upgrading from one version to another.
|
||||
|
||||
```bash
|
||||
# Run old version
|
||||
docker run -d --name codeflash-old \
|
||||
-e AZURE_OPENAI_API_KEY=test-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-upgrade-test:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
sleep 20
|
||||
OLD_KEY=$(docker exec codeflash-old cat /app/API_KEY.txt)
|
||||
|
||||
# Stop old container
|
||||
docker stop codeflash-old
|
||||
docker rm codeflash-old
|
||||
|
||||
# Rebuild image (simulating new version)
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:latest .
|
||||
|
||||
# Run new version with same volume
|
||||
docker run -d --name codeflash-new \
|
||||
-e AZURE_OPENAI_API_KEY=test-key \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-upgrade-test:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
sleep 20
|
||||
NEW_KEY=$(docker exec codeflash-new cat /app/API_KEY.txt)
|
||||
|
||||
# Compare
|
||||
if [ "$OLD_KEY" = "$NEW_KEY" ]; then
|
||||
echo "✅ Upgrade successful - data preserved"
|
||||
else
|
||||
echo "❌ Upgrade failed - data lost"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
docker stop codeflash-new
|
||||
docker rm codeflash-new
|
||||
docker volume rm codeflash-upgrade-test
|
||||
```
|
||||
|
||||
**Success criteria:**
|
||||
- ✅ New version starts successfully
|
||||
- ✅ Data from old version is preserved
|
||||
- ✅ API key remains the same
|
||||
- ✅ No data migration issues
|
||||
|
||||
---
|
||||
|
||||
## Monitoring and Debugging
|
||||
|
||||
### Watch All Logs
|
||||
|
||||
```bash
|
||||
# Follow all logs
|
||||
docker logs -f codeflash-test
|
||||
|
||||
# Filter specific service
|
||||
docker logs codeflash-test | grep "cf-api"
|
||||
docker logs codeflash-test | grep "aiservice"
|
||||
docker logs codeflash-test | grep "postgres"
|
||||
docker logs codeflash-test | grep "webapp"
|
||||
```
|
||||
|
||||
### Check Resource Usage
|
||||
|
||||
```bash
|
||||
# Container stats
|
||||
docker stats codeflash-test
|
||||
|
||||
# Disk usage
|
||||
docker system df
|
||||
du -sh /var/lib/docker/volumes/codeflash-test-data
|
||||
```
|
||||
|
||||
### Interactive Debugging
|
||||
|
||||
```bash
|
||||
# Access container shell
|
||||
docker exec -it codeflash-test bash
|
||||
|
||||
# Check service logs inside container
|
||||
docker exec codeflash-test tail -f /var/log/supervisor/cf-api-stdout.log
|
||||
docker exec codeflash-test tail -f /var/log/supervisor/aiservice-stdout.log
|
||||
docker exec codeflash-test tail -f /var/log/supervisor/postgres-stdout.log
|
||||
docker exec codeflash-test tail -f /var/log/supervisor/webapp-stdout.log
|
||||
|
||||
# Check process tree
|
||||
docker exec codeflash-test ps auxf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Test Failures
|
||||
|
||||
### Container won't start
|
||||
```bash
|
||||
docker logs codeflash-test | grep -i error
|
||||
docker logs codeflash-test | grep -i fail
|
||||
```
|
||||
|
||||
### Service shows FATAL
|
||||
```bash
|
||||
docker exec codeflash-test supervisorctl tail cf-api
|
||||
docker exec codeflash-test supervisorctl tail aiservice
|
||||
```
|
||||
|
||||
### PostgreSQL not ready
|
||||
```bash
|
||||
docker exec codeflash-test pg_isready
|
||||
docker logs codeflash-test | grep postgres
|
||||
```
|
||||
|
||||
### API key not generated
|
||||
```bash
|
||||
docker logs codeflash-test | grep "API Key"
|
||||
docker exec codeflash-test ls -la /app/API_KEY.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Automated Test Script
|
||||
|
||||
Save this as `test-deployment.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🚀 Starting Codeflash deployment test..."
|
||||
|
||||
# Cleanup
|
||||
echo "🧹 Cleaning up old test containers..."
|
||||
docker stop codeflash-test 2>/dev/null || true
|
||||
docker rm codeflash-test 2>/dev/null || true
|
||||
docker volume rm codeflash-test-data 2>/dev/null || true
|
||||
|
||||
# Build
|
||||
echo "🔨 Building image..."
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unifiedall -t codeflash/unified:test .
|
||||
|
||||
# Run
|
||||
echo "🏃 Running container..."
|
||||
docker run -d --name codeflash-test \
|
||||
-e AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY:-test-key} \
|
||||
-p 5432:5432 -p 8000:8000 -p 3001:3001 -p 3000:3000 \
|
||||
-v codeflash-test-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:test
|
||||
|
||||
# Wait
|
||||
echo "⏳ Waiting for services to start..."
|
||||
sleep 20
|
||||
|
||||
# Test
|
||||
echo "🔍 Testing services..."
|
||||
docker exec codeflash-test supervisorctl status | grep RUNNING || (echo "❌ Services not running" && exit 1)
|
||||
curl -f http://localhost:3001/cfapi/healthcheck || (echo "❌ cf-api not responding" && exit 1)
|
||||
curl -f http://localhost:8000/health || (echo "❌ aiservice not responding" && exit 1)
|
||||
docker exec codeflash-test pg_isready || (echo "❌ PostgreSQL not ready" && exit 1)
|
||||
|
||||
# Get API key
|
||||
echo "🔑 Retrieving API key..."
|
||||
API_KEY=$(docker exec codeflash-test cat /app/API_KEY.txt)
|
||||
echo "API Key: $API_KEY"
|
||||
|
||||
echo "✅ All tests passed!"
|
||||
echo ""
|
||||
echo "To clean up: docker stop codeflash-test && docker rm codeflash-test && docker volume rm codeflash-test-data"
|
||||
```
|
||||
|
||||
Make it executable and run:
|
||||
```bash
|
||||
chmod +x test-deployment.sh
|
||||
./test-deployment.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
Expected performance metrics:
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Build time | 5-10 minutes |
|
||||
| Startup time | 15-20 seconds |
|
||||
| Container size | ~5GB |
|
||||
| Memory usage (idle) | ~500MB |
|
||||
| Memory usage (active) | ~1-2GB |
|
||||
| CPU usage (idle) | <5% |
|
||||
| CPU usage (optimizing) | 50-100% |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
After successful testing:
|
||||
1. Update to your actual AI provider keys
|
||||
2. Configure custom domain/URLs if needed
|
||||
3. Set up monitoring and backups
|
||||
4. Deploy to production environment
|
||||
5. Document your specific configuration
|
||||
|
||||
For production deployment best practices, see the main README.md.
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: codeflash-postgres
|
||||
environment:
|
||||
POSTGRES_DB: codeflash
|
||||
POSTGRES_USER: codeflash
|
||||
POSTGRES_PASSWORD: codeflash
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U codeflash"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
db-init:
|
||||
image: codeflash/cf-api:latest
|
||||
container_name: codeflash-db-init
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DATABASE_URL: postgresql://codeflash:codeflash@postgres:5432/codeflash
|
||||
command: >
|
||||
sh -c "
|
||||
echo 'Running Prisma migrations...' &&
|
||||
cd /app/common &&
|
||||
npx prisma migrate deploy &&
|
||||
echo 'Checking for existing users...' &&
|
||||
USER_COUNT=$$(psql postgresql://codeflash:codeflash@postgres:5432/codeflash -t -c 'SELECT COUNT(*) FROM users;' 2>/dev/null | tr -d ' ' || echo '0') &&
|
||||
if [ \"$$USER_COUNT\" = \"0\" ]; then
|
||||
echo 'Creating default user and API key...' &&
|
||||
API_KEY=\"cf_$$(openssl rand -hex 32)\" &&
|
||||
SUFFIX=\"$${API_KEY: -4}\" &&
|
||||
psql postgresql://codeflash:codeflash@postgres:5432/codeflash <<-EOSQL &&
|
||||
INSERT INTO users (user_id, github_username, email, name, onboarding_completed, created_at)
|
||||
VALUES ('local|default-user', 'codeflash-user', 'user@codeflash.local', 'Default User', true, NOW())
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
INSERT INTO cf_api_keys (key, suffix, name, user_id, tier, created_at)
|
||||
VALUES ('$$API_KEY', '$$SUFFIX', 'Default API Key', 'local|default-user', 'free', NOW());
|
||||
EOSQL
|
||||
echo '' &&
|
||||
echo '======================================' &&
|
||||
echo ' CODEFLASH API KEY CREATED' &&
|
||||
echo '======================================' &&
|
||||
echo '' &&
|
||||
echo \"$$API_KEY\" &&
|
||||
echo '' &&
|
||||
echo 'Add to cli/codeflash/.env:' &&
|
||||
echo \"CODEFLASH_API_KEY=$$API_KEY\" &&
|
||||
echo 'CODEFLASH_AIS_SERVER=local' &&
|
||||
echo 'CODEFLASH_CFAPI_SERVER=local' &&
|
||||
echo '' &&
|
||||
echo '======================================';
|
||||
else
|
||||
echo 'Users exist. To get API key run:' &&
|
||||
echo 'docker exec codeflash-postgres psql -U codeflash -d codeflash -c \"SELECT key FROM cf_api_keys LIMIT 1;\"';
|
||||
fi &&
|
||||
echo 'Database ready!'
|
||||
"
|
||||
restart: "no"
|
||||
|
||||
aiservice:
|
||||
image: codeflash/aiservice:latest
|
||||
container_name: codeflash-aiservice
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
db-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
DATABASE_URL: postgresql://codeflash:codeflash@postgres:5432/codeflash
|
||||
SECRET_KEY: development-secret-key
|
||||
OPENAI_API_TYPE: azure
|
||||
AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY}
|
||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
ENVIRONMENT: DEVELOPMENT
|
||||
ports:
|
||||
- "8000:8000"
|
||||
|
||||
cf-api:
|
||||
image: codeflash/cf-api:latest
|
||||
container_name: codeflash-cf-api
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
db-init:
|
||||
condition: service_completed_successfully
|
||||
aiservice:
|
||||
condition: service_started
|
||||
environment:
|
||||
DATABASE_URL: postgresql://codeflash:codeflash@postgres:5432/codeflash
|
||||
AISERVICE_URL: http://aiservice:8000
|
||||
GH_APP_ID: 800528
|
||||
GH_APP_USER_ID: 148906541
|
||||
GH_APP_WEBHOOK_SECRET: dev-webhook-secret
|
||||
SECRET_KEY: development-secret-key
|
||||
NODE_ENV: local
|
||||
ports:
|
||||
- "3001:3001"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-codeflash}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-codeflash}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
aiservice:
|
||||
image: codeflash/aiservice:latest
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-codeflash}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-codeflash}
|
||||
OPENAI_API_KEY: ${OPENAI_API_KEY}
|
||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
SECRET_KEY: ${DJANGO_SECRET_KEY}
|
||||
depends_on:
|
||||
- postgres
|
||||
restart: unless-stopped
|
||||
|
||||
cf-api:
|
||||
image: codeflash/cf-api:latest
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-codeflash}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-codeflash}
|
||||
GH_APP_ID: ${GH_APP_ID}
|
||||
GH_APP_PRIVATE_KEY: ${GH_APP_PRIVATE_KEY}
|
||||
GH_APP_WEBHOOK_SECRET: ${GH_APP_WEBHOOK_SECRET}
|
||||
AISERVICE_URL: http://aiservice:8000
|
||||
depends_on:
|
||||
- postgres
|
||||
- aiservice
|
||||
ports:
|
||||
- "3001:3001"
|
||||
restart: unless-stopped
|
||||
|
||||
cf-webapp:
|
||||
image: codeflash/cf-webapp:latest
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-codeflash}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-codeflash}
|
||||
CODEFLASH_CFAPI_URL: http://cf-api:3001
|
||||
AUTH0_CLIENT_ID: ${AUTH0_CLIENT_ID}
|
||||
AUTH0_CLIENT_SECRET: ${AUTH0_CLIENT_SECRET}
|
||||
AUTH0_ISSUER_BASE_URL: ${AUTH0_ISSUER_BASE_URL}
|
||||
AUTH0_SECRET: ${AUTH0_SECRET}
|
||||
NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL}
|
||||
depends_on:
|
||||
- cf-api
|
||||
ports:
|
||||
- "3000:3000"
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install uv
|
||||
RUN pip install uv
|
||||
|
||||
# Copy entire aiservice directory
|
||||
COPY aiservice ./
|
||||
|
||||
# Install dependencies
|
||||
RUN uv sync
|
||||
|
||||
# Set environment variables
|
||||
ENV ENVIRONMENT=PRODUCTION
|
||||
ENV PORT=8000
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# Use the start script that references gunicorn.conf.py
|
||||
CMD ["uv", "run", "gunicorn", "-c", "gunicorn.conf.py", "aiservice.asgi:application", \
|
||||
"--bind", "0.0.0.0:8000", \
|
||||
"--timeout", "600", \
|
||||
"--workers", "2"]
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy both cf-api and common
|
||||
COPY cf-api ./cf-api
|
||||
COPY common ./common
|
||||
|
||||
# Build common package first (since cf-api depends on it)
|
||||
WORKDIR /build/common
|
||||
RUN npm ci && npm run build
|
||||
|
||||
# Install ALL dependencies for cf-api (including dev dependencies)
|
||||
WORKDIR /build/cf-api
|
||||
RUN npm ci
|
||||
|
||||
# Replace the common package from registry with local build
|
||||
RUN rm -rf node_modules/@codeflash-ai/common && \
|
||||
cp -r /build/common node_modules/@codeflash-ai/
|
||||
|
||||
# Clean dist folder before build to avoid nested dist directories
|
||||
RUN rm -rf dist
|
||||
|
||||
# Build TypeScript
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the built files
|
||||
COPY --from=0 /build/cf-api/dist ./dist
|
||||
COPY --from=0 /build/cf-api/package.json ./package.json
|
||||
COPY --from=0 /build/cf-api/package-lock.json ./package-lock.json
|
||||
COPY --from=0 /build/cf-api/resend ./resend
|
||||
COPY --from=0 /build/cf-api/github ./github
|
||||
|
||||
# Copy common package to parent directory (matching Azure structure)
|
||||
COPY --from=0 /build/common ../common
|
||||
|
||||
# Copy already installed node_modules from build stage
|
||||
COPY --from=0 /build/cf-api/node_modules ./node_modules
|
||||
|
||||
# Copy node_modules into dist to match Azure deployment structure
|
||||
# Use -L to follow symlinks and avoid broken nested structures
|
||||
RUN cp -rL node_modules dist/ 2>/dev/null || cp -r node_modules dist/
|
||||
|
||||
EXPOSE 3001
|
||||
|
||||
CMD ["npm", "start"]
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
# Stage 1: Build cf-api and common
|
||||
FROM node:20-alpine AS js-builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy JavaScript projects
|
||||
COPY js/cf-api ./cf-api
|
||||
COPY js/common ./common
|
||||
|
||||
# Build common package first
|
||||
WORKDIR /build/common
|
||||
RUN npm ci && npm run build
|
||||
|
||||
# Build cf-api
|
||||
WORKDIR /build/cf-api
|
||||
RUN npm ci
|
||||
|
||||
# Replace common package from registry with local build
|
||||
RUN rm -rf node_modules/@codeflash-ai/common && \
|
||||
cp -r /build/common node_modules/@codeflash-ai/
|
||||
|
||||
# Clean and build cf-api
|
||||
RUN rm -rf dist && npm run build
|
||||
|
||||
# Stage 2: Build aiservice
|
||||
FROM python:3.12-slim AS python-builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y build-essential libpq-dev && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install uv
|
||||
RUN pip install uv
|
||||
|
||||
# Copy and build aiservice
|
||||
COPY django/aiservice ./aiservice
|
||||
WORKDIR /build/aiservice
|
||||
RUN uv sync
|
||||
|
||||
# Stage 3: Final unified image
|
||||
FROM node:20-alpine
|
||||
|
||||
# Install Python, PostgreSQL client, and supervisor
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
py3-pip \
|
||||
postgresql15 \
|
||||
postgresql15-client \
|
||||
supervisor \
|
||||
bash \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Install Python dependencies globally
|
||||
RUN pip3 install --break-system-packages uv
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy cf-api from js-builder
|
||||
COPY --from=js-builder /build/cf-api/dist ./cf-api/dist
|
||||
COPY --from=js-builder /build/cf-api/package.json ./cf-api/package.json
|
||||
COPY --from=js-builder /build/cf-api/package-lock.json ./cf-api/package-lock.json
|
||||
COPY --from=js-builder /build/cf-api/node_modules ./cf-api/node_modules
|
||||
COPY --from=js-builder /build/cf-api/resend ./cf-api/resend
|
||||
COPY --from=js-builder /build/cf-api/github ./cf-api/github
|
||||
COPY --from=js-builder /build/common ./common
|
||||
|
||||
# Copy node_modules into dist for ESM resolution
|
||||
RUN cd cf-api && cp -rL node_modules dist/ 2>/dev/null || cp -r node_modules dist/
|
||||
|
||||
# Copy aiservice from python-builder
|
||||
COPY --from=python-builder /build/aiservice ./aiservice
|
||||
|
||||
# Create PostgreSQL data directory
|
||||
RUN mkdir -p /var/lib/postgresql/data /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql
|
||||
|
||||
# Copy configuration files
|
||||
COPY deployment/onprem-simple/supervisord.conf /etc/supervisord.conf
|
||||
COPY deployment/onprem-simple/init-db.sh /app/init-db.sh
|
||||
COPY deployment/onprem-simple/startup.sh /app/startup.sh
|
||||
|
||||
RUN chmod +x /app/init-db.sh /app/startup.sh
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 5432 8000 3001
|
||||
|
||||
# Set environment variables
|
||||
ENV PGDATA=/var/lib/postgresql/data
|
||||
ENV PATH="/var/lib/postgresql/bin:${PATH}"
|
||||
|
||||
# Start supervisor
|
||||
CMD ["/app/startup.sh"]
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Unified Codeflash Container - Using Pre-built Images
|
||||
FROM node:20-alpine
|
||||
|
||||
# Install Python, PostgreSQL, and supervisor
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
py3-pip \
|
||||
postgresql15 \
|
||||
postgresql15-client \
|
||||
supervisor \
|
||||
bash \
|
||||
openssl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Install Python uv
|
||||
RUN pip3 install --break-system-packages uv
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy cf-api from pre-built image
|
||||
COPY --from=codeflash/cf-api:latest /app /app/cf-api
|
||||
COPY --from=codeflash/cf-api:latest /common /common
|
||||
|
||||
# Copy aiservice from pre-built image
|
||||
COPY --from=codeflash/aiservice:latest /app /app/aiservice
|
||||
|
||||
# Create PostgreSQL data directory with correct permissions
|
||||
RUN mkdir -p /var/lib/postgresql/data /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql
|
||||
|
||||
# Copy configuration files
|
||||
COPY deployment/onprem-simple/supervisord.conf /etc/supervisord.conf
|
||||
COPY deployment/onprem-simple/init-db.sh /app/init-db.sh
|
||||
COPY deployment/onprem-simple/startup.sh /app/startup.sh
|
||||
|
||||
RUN chmod +x /app/init-db.sh /app/startup.sh
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 5432 8000 3001
|
||||
|
||||
# Set environment variables
|
||||
ENV PGDATA=/var/lib/postgresql/data
|
||||
ENV PATH="/var/lib/postgresql/bin:${PATH}"
|
||||
|
||||
# Start supervisor
|
||||
CMD ["/app/startup.sh"]
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy both cf-webapp and common
|
||||
COPY cf-webapp ./cf-webapp
|
||||
COPY common ./common
|
||||
|
||||
# Install ALL dependencies for build
|
||||
WORKDIR /build/cf-webapp
|
||||
RUN npm ci
|
||||
|
||||
# Build Next.js
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy entire built application (simpler approach)
|
||||
COPY --from=0 /build/cf-webapp ./
|
||||
COPY --from=0 /build/common ../common
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["npm", "start"]
|
||||
66
deployment/onprem-simple/archive/old-scripts/REBUILD-AND-TEST.sh
Executable file
66
deployment/onprem-simple/archive/old-scripts/REBUILD-AND-TEST.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo " Codeflash Complete Rebuild and Test"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
cd /Users/saga4/orgs/codeflash-internal
|
||||
|
||||
echo "Step 1: Stopping and removing old container..."
|
||||
docker stop codeflash-unified 2>/dev/null || true
|
||||
docker rm codeflash-unified 2>/dev/null || true
|
||||
echo "✓ Old container removed"
|
||||
echo ""
|
||||
|
||||
echo "Step 2: Rebuilding image..."
|
||||
echo "This will take 5-10 minutes..."
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unified-selfcontained -t codeflash/unified:latest .
|
||||
echo "✓ Image rebuilt"
|
||||
echo ""
|
||||
|
||||
echo "Step 3: Starting new container..."
|
||||
docker run -d --name codeflash-unified \
|
||||
-e OPENAI_API_TYPE=azure \
|
||||
-e AZURE_OPENAI_API_KEY=dabd9790e9a54558b4ceafdd74425904 \
|
||||
-e ANTHROPIC_API_KEY=sk-ant-api03-E85T16Zy7bGRo1BxVdFUJG_JRMVdMaePuLUJMFO-EQHqI17z0lWMYRHaHKUU47XeNNwZNHl86h1p-Yoq5vVgzg \
|
||||
-e SECRET_KEY=bla \
|
||||
-e NODE_ENV=local \
|
||||
-e GH_APP_ID=800528 \
|
||||
-e GH_APP_USER_ID=148906541 \
|
||||
-e GH_APP_WEBHOOK_SECRET=dev-webhook-secret-2pjGGmaNy2gyEY4o3aU \
|
||||
-e STRIPE_SECRET_KEY=sk_test_51Pap5bRrNDfNWAM0DpQb8D8sCSYxG9aFzc9N5wXN8pVT0fXLQwrJgZEZq1aRoQ9VZgVK7pXKp5aWQZYW7vXKp00aZX5aWQ \
|
||||
-p 5432:5432 \
|
||||
-p 8000:8000 \
|
||||
-p 3001:3001 \
|
||||
-p 3000:3000 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
echo "✓ Container started"
|
||||
echo ""
|
||||
|
||||
echo "Step 4: Waiting for services to start (30 seconds)..."
|
||||
sleep 30
|
||||
|
||||
echo "Step 5: Checking service status..."
|
||||
docker exec codeflash-unified supervisorctl status
|
||||
echo ""
|
||||
|
||||
echo "Step 6: Getting API key..."
|
||||
API_KEY=$(docker exec codeflash-unified psql postgresql://codeflash:codeflash@localhost:5432/codeflash -t -c "SELECT 'cf-' || key FROM cf_api_keys LIMIT 1;" | tr -d ' ')
|
||||
echo "API Key: $API_KEY"
|
||||
|
||||
echo "Step 7: Testing CLI..."
|
||||
export CODEFLASH_API_KEY=$API_KEY
|
||||
export CODEFLASH_AIS_SERVER=local
|
||||
export CODEFLASH_CFAPI_SERVER=local
|
||||
|
||||
cd /Users/saga4/orgs/optimize-me
|
||||
codeflash --file src/math/computation.py --function gcd_recursive --no-pr -v
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " Test Complete!"
|
||||
echo "=========================================="
|
||||
50
deployment/onprem-simple/archive/old-scripts/build-images.sh
Executable file
50
deployment/onprem-simple/archive/old-scripts/build-images.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
# Simple script to build all images
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building Codeflash Docker images..."
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
# Check if Docker is running
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "ERROR: Docker is not running. Please start Docker Desktop and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
# Build cf-api
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo "Building cf-api..."
|
||||
echo "===================="
|
||||
cd js
|
||||
docker build -t codeflash/cf-api:latest -f ../deployment/onprem-simple/Dockerfile.cfapi cf-api/
|
||||
|
||||
# Build cf-webapp
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo "Building cf-webapp..."
|
||||
echo "===================="
|
||||
docker build -t codeflash/cf-webapp:latest -f ../deployment/onprem-simple/Dockerfile.webapp cf-webapp/
|
||||
|
||||
# Build aiservice
|
||||
echo ""
|
||||
echo "===================="
|
||||
echo "Building aiservice..."
|
||||
echo "===================="
|
||||
cd ../django
|
||||
docker build -t codeflash/aiservice:latest -f ../deployment/onprem-simple/Dockerfile.aiservice aiservice/
|
||||
|
||||
echo ""
|
||||
echo "✓ All images built successfully!"
|
||||
echo ""
|
||||
echo "Images created:"
|
||||
docker images | grep codeflash
|
||||
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Test locally: cd $SCRIPT_DIR && docker-compose up -d"
|
||||
echo "2. Push to registry: docker push codeflash/cf-api:latest"
|
||||
61
deployment/onprem-simple/archive/old-scripts/build.sh
Normal file
61
deployment/onprem-simple/archive/old-scripts/build.sh
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "======================================"
|
||||
echo "Codeflash Unified Container Builder"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
# Get the repository root (2 levels up from this script)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
echo "Repository root: $REPO_ROOT"
|
||||
echo ""
|
||||
|
||||
# Check if we should skip individual builds (for faster rebuilds)
|
||||
SKIP_SERVICE_BUILDS=${SKIP_SERVICE_BUILDS:-false}
|
||||
|
||||
if [ "$SKIP_SERVICE_BUILDS" = "false" ]; then
|
||||
echo "Step 1/3: Building aiservice image..."
|
||||
echo "--------------------------------------"
|
||||
docker build -f deployment/onprem-simple/Dockerfile.aiservice -t codeflash/aiservice:latest .
|
||||
echo "✓ aiservice image built successfully"
|
||||
echo ""
|
||||
|
||||
echo "Step 2/3: Building cf-api image..."
|
||||
echo "--------------------------------------"
|
||||
docker build -f deployment/onprem-simple/Dockerfile.cfapi -t codeflash/cf-api:latest .
|
||||
echo "✓ cf-api image built successfully"
|
||||
echo ""
|
||||
else
|
||||
echo "Skipping individual service builds (SKIP_SERVICE_BUILDS=true)"
|
||||
echo "Using existing codeflash/aiservice:latest and codeflash/cf-api:latest"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Step 3/3: Building unified container..."
|
||||
echo "--------------------------------------"
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unified-simple -t codeflash/unified:latest .
|
||||
echo "✓ unified container built successfully"
|
||||
echo ""
|
||||
|
||||
echo "======================================"
|
||||
echo "✓ Build Complete!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "Image: codeflash/unified:latest"
|
||||
echo ""
|
||||
echo "To run the container, use:"
|
||||
echo " docker run -d --name codeflash \\"
|
||||
echo " --env-file .env \\"
|
||||
echo " -p 5432:5432 \\"
|
||||
echo " -p 8000:8000 \\"
|
||||
echo " -p 3001:3001 \\"
|
||||
echo " -v codeflash-data:/var/lib/postgresql/data \\"
|
||||
echo " codeflash/unified:latest"
|
||||
echo ""
|
||||
echo "Or see deployment/onprem-simple/README.md for detailed instructions."
|
||||
echo ""
|
||||
128
deployment/onprem-simple/archive/old-scripts/run-fresh.sh
Normal file
128
deployment/onprem-simple/archive/old-scripts/run-fresh.sh
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo " Codeflash Fresh Deployment"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Get repository root
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
echo "Repository: $REPO_ROOT"
|
||||
echo ""
|
||||
|
||||
# Step 1: Clean up
|
||||
echo "Step 1: Cleaning up existing containers..."
|
||||
echo "-------------------------------------------"
|
||||
docker stop codeflash-unified 2>/dev/null && echo "✓ Stopped existing container" || echo "→ No existing container to stop"
|
||||
docker rm codeflash-unified 2>/dev/null && echo "✓ Removed existing container" || echo "→ No existing container to remove"
|
||||
docker volume rm codeflash-data 2>/dev/null && echo "✓ Removed data volume" || echo "→ No existing data volume to remove"
|
||||
echo ""
|
||||
|
||||
# Step 2: Build
|
||||
echo "Step 2: Building unified container..."
|
||||
echo "-------------------------------------------"
|
||||
echo "This will take 5-10 minutes on first build..."
|
||||
echo ""
|
||||
|
||||
docker build -f deployment/onprem-simple/Dockerfile.unified-selfcontained \
|
||||
-t codeflash/unified:latest .
|
||||
|
||||
echo ""
|
||||
echo "✓ Build complete!"
|
||||
echo ""
|
||||
|
||||
# Step 3: Run
|
||||
echo "Step 3: Starting container..."
|
||||
echo "-------------------------------------------"
|
||||
|
||||
docker run -d --name codeflash-unified \
|
||||
-e OPENAI_API_TYPE=azure \
|
||||
-e AZURE_OPENAI_API_KEY=dabd9790e9a54558b4ceafdd74425904 \
|
||||
-e ANTHROPIC_API_KEY=sk-ant-api03-E85T16Zy7bGRo1BxVdFUJG_JRMVdMaePuLUJMFO-EQHqI17z0lWMYRHaHKUU47XeNNwZNHl86h1p-Yoq5vVgzg \
|
||||
-e SECRET_KEY=bla \
|
||||
-e NODE_ENV=local \
|
||||
-e GH_APP_ID=800528 \
|
||||
-e GH_APP_USER_ID=148906541 \
|
||||
-e GH_APP_WEBHOOK_SECRET=dev-webhook-secret-2pjGGmaNy2gyEY4o3aU \
|
||||
-e STRIPE_SECRET_KEY=sk_test_51Pap5bRrNDfNWAM0DpQb8D8sCSYxG9aFzc9N5wXN8pVT0fXLQwrJgZEZq1aRoQ9VZgVK7pXKp5aWQZYW7vXKp00aZX5aWQ \
|
||||
-p 5432:5432 \
|
||||
-p 8000:8000 \
|
||||
-p 3001:3001 \
|
||||
-v codeflash-data:/var/lib/postgresql/data \
|
||||
codeflash/unified:latest
|
||||
|
||||
echo ""
|
||||
echo "✓ Container started!"
|
||||
echo ""
|
||||
|
||||
# Step 4: Wait for services to start
|
||||
echo "Step 4: Waiting for services to start..."
|
||||
echo "-------------------------------------------"
|
||||
echo "This may take 15-30 seconds..."
|
||||
echo ""
|
||||
|
||||
sleep 10
|
||||
|
||||
# Wait for the API key file to be created (indicates initialization is complete)
|
||||
for i in {1..30}; do
|
||||
if docker exec codeflash-unified test -f /app/API_KEY.txt 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
echo " Waiting for database initialization... ($i/30)"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# Step 5: Verify services
|
||||
echo "Step 5: Verifying services..."
|
||||
echo "-------------------------------------------"
|
||||
|
||||
# Wait a bit more for services to fully start
|
||||
sleep 5
|
||||
|
||||
docker exec codeflash-unified supervisorctl status
|
||||
|
||||
echo ""
|
||||
|
||||
# Step 6: Show API key
|
||||
echo "=========================================="
|
||||
echo " ✓ DEPLOYMENT COMPLETE!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
API_KEY=$(docker exec codeflash-unified cat /app/API_KEY.txt 2>/dev/null || echo "API key not yet generated")
|
||||
|
||||
if [ "$API_KEY" != "API key not yet generated" ]; then
|
||||
echo "Your API Key: $API_KEY"
|
||||
echo ""
|
||||
echo "To use the CLI, run these commands:"
|
||||
echo ""
|
||||
echo " cd /Users/saga4/orgs/optimize-me"
|
||||
echo " export CODEFLASH_API_KEY=$API_KEY"
|
||||
echo " export CODEFLASH_AIS_SERVER=local"
|
||||
echo " export CODEFLASH_CFAPI_SERVER=local"
|
||||
echo " codeflash --file src/math/computation.py --function gcd_recursive --no-pr -v"
|
||||
echo ""
|
||||
else
|
||||
echo "Services are still initializing. View logs with:"
|
||||
echo " docker logs -f codeflash-unified"
|
||||
echo ""
|
||||
echo "Once you see 'CODEFLASH SETUP COMPLETE!', retrieve your API key with:"
|
||||
echo " docker exec codeflash-unified cat /app/API_KEY.txt"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "Useful commands:"
|
||||
echo " View logs: docker logs -f codeflash-unified"
|
||||
echo " Restart: docker restart codeflash-unified"
|
||||
echo " Stop: docker stop codeflash-unified"
|
||||
echo " Check services: docker exec codeflash-unified supervisorctl status"
|
||||
echo ""
|
||||
138
deployment/onprem-simple/init-db.sh
Normal file
138
deployment/onprem-simple/init-db.sh
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "==================================="
|
||||
echo "Initializing Codeflash Database"
|
||||
echo "==================================="
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
echo "Waiting for PostgreSQL to start..."
|
||||
timeout=60
|
||||
counter=0
|
||||
until pg_isready -h localhost -p 5432 -U codeflash 2>/dev/null; do
|
||||
counter=$((counter + 1))
|
||||
if [ $counter -gt $timeout ]; then
|
||||
echo "ERROR: PostgreSQL did not start within ${timeout} seconds"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "PostgreSQL is ready!"
|
||||
|
||||
# Run Prisma migrations
|
||||
echo ""
|
||||
echo "Running Prisma migrations..."
|
||||
cd /common
|
||||
export DATABASE_URL="${DATABASE_URL:-postgresql://codeflash:codeflash@localhost:5432/codeflash}"
|
||||
npx prisma migrate deploy
|
||||
|
||||
echo ""
|
||||
echo "Checking for existing users..."
|
||||
USER_COUNT=$(psql "$DATABASE_URL" -t -c "SELECT COUNT(*) FROM users;" 2>/dev/null || echo "0")
|
||||
USER_COUNT=$(echo $USER_COUNT | tr -d ' ')
|
||||
|
||||
if [ "$USER_COUNT" = "0" ]; then
|
||||
echo ""
|
||||
echo "No users found. Creating default user and API key..."
|
||||
|
||||
# Hardcoded API key for on-premise deployment
|
||||
# Unhashed key (what users will use): cf-LDKLmsqjcZeX6SvjFPTz66NWgTV25njdWNUxinokmJcfegwRWytqFoJBoCkAKQad
|
||||
# This is the SHA-384 hash stored in the database:
|
||||
API_KEY_UNHASHED="LDKLmsqjcZeX6SvjFPTz66NWgTV25njdWNUxinokmJcfegwRWytqFoJBoCkAKQad"
|
||||
API_KEY_HASHED="uXkhQcmQVmZbOpMtPMUTfeLRZOD3-s6GzYV1IpLMtJeHX4I9P8Ej_Kx3RftkP9yw"
|
||||
SUFFIX="KQad"
|
||||
|
||||
# Use environment variables or defaults for user information
|
||||
DEFAULT_USER_ID="${DEFAULT_USER_ID:-github|10488227}"
|
||||
DEFAULT_USERNAME="${DEFAULT_USERNAME:-Saga4}"
|
||||
DEFAULT_EMAIL="${DEFAULT_EMAIL:-sarthak.agarwal.cse12@iitbhu.ac.in}"
|
||||
DEFAULT_NAME="${DEFAULT_NAME:-$DEFAULT_USERNAME}"
|
||||
|
||||
echo "Creating user: $DEFAULT_USERNAME (ID: $DEFAULT_USER_ID)"
|
||||
|
||||
# Insert user
|
||||
psql "$DATABASE_URL" <<-EOSQL
|
||||
INSERT INTO users (user_id, github_username, email, name, onboarding_completed, created_at)
|
||||
VALUES ('$DEFAULT_USER_ID', '$DEFAULT_USERNAME', '$DEFAULT_EMAIL', '$DEFAULT_NAME', true, NOW())
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
EOSQL
|
||||
|
||||
# Insert API key (HASHED version in database)
|
||||
psql "$DATABASE_URL" <<-EOSQL
|
||||
INSERT INTO cf_api_keys (key, suffix, name, user_id, tier, created_at)
|
||||
VALUES ('$API_KEY_HASHED', '$SUFFIX', 'Default API Key', '$DEFAULT_USER_ID', 'free', NOW());
|
||||
EOSQL
|
||||
|
||||
# Insert subscription with unlimited usage for on-premise deployments
|
||||
echo "Creating unlimited subscription for on-premise deployment..."
|
||||
psql "$DATABASE_URL" <<-EOSQL
|
||||
INSERT INTO subscriptions (
|
||||
id,
|
||||
user_id,
|
||||
stripe_customer_id,
|
||||
stripe_subscription_id,
|
||||
plan_type,
|
||||
optimizations_used,
|
||||
optimizations_limit,
|
||||
subscription_status,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
gen_random_uuid(),
|
||||
'$DEFAULT_USER_ID',
|
||||
NULL,
|
||||
NULL,
|
||||
'enterprise',
|
||||
0,
|
||||
999999999,
|
||||
'active',
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (user_id) DO NOTHING;
|
||||
EOSQL
|
||||
|
||||
# Format API key with cf- prefix for display (UNHASHED version for users)
|
||||
DISPLAY_API_KEY="cf-${API_KEY_UNHASHED}"
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo " CODEFLASH SETUP COMPLETE!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "User: $DEFAULT_USERNAME"
|
||||
echo "Email: $DEFAULT_EMAIL"
|
||||
echo ""
|
||||
echo "Your API Key: $DISPLAY_API_KEY"
|
||||
echo ""
|
||||
echo "Save this API key! You'll need it to configure the Codeflash CLI."
|
||||
echo ""
|
||||
echo "To use the CLI, set these environment variables:"
|
||||
echo " export CODEFLASH_API_KEY=$DISPLAY_API_KEY"
|
||||
echo " export CODEFLASH_AIS_SERVER=local"
|
||||
echo " export CODEFLASH_CFAPI_SERVER=local"
|
||||
echo ""
|
||||
echo "Or create a .env file in your project:"
|
||||
echo " CODEFLASH_API_KEY=$DISPLAY_API_KEY"
|
||||
echo " CODEFLASH_AIS_SERVER=local"
|
||||
echo " CODEFLASH_CFAPI_SERVER=local"
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
# Save API key to file for easy retrieval
|
||||
echo "$DISPLAY_API_KEY" > /app/API_KEY.txt
|
||||
echo "API key also saved to: /app/API_KEY.txt"
|
||||
echo "(Retrieve anytime with: docker exec <container> cat /app/API_KEY.txt)"
|
||||
echo ""
|
||||
else
|
||||
echo "Found $USER_COUNT existing user(s). Skipping user creation."
|
||||
echo ""
|
||||
echo "To retrieve an existing API key, run:"
|
||||
echo " docker exec <container-name> psql \$DATABASE_URL -c \"SELECT key FROM cf_api_keys LIMIT 1;\""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Database initialization complete!"
|
||||
90
deployment/onprem-simple/startup.sh
Normal file
90
deployment/onprem-simple/startup.sh
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "==============================="
|
||||
echo "Starting Codeflash Services"
|
||||
echo "==============================="
|
||||
|
||||
# Initialize PostgreSQL if needed
|
||||
if [ ! -f "/var/lib/postgresql/data/PG_VERSION" ]; then
|
||||
echo "Initializing PostgreSQL database..."
|
||||
su - postgres -c "initdb -D /var/lib/postgresql/data"
|
||||
|
||||
# Configure PostgreSQL
|
||||
echo "Configuring PostgreSQL..."
|
||||
cat >> /var/lib/postgresql/data/postgresql.conf <<EOF
|
||||
listen_addresses = '*'
|
||||
port = 5432
|
||||
max_connections = 100
|
||||
shared_buffers = 128MB
|
||||
EOF
|
||||
|
||||
cat >> /var/lib/postgresql/data/pg_hba.conf <<EOF
|
||||
host all all 0.0.0.0/0 md5
|
||||
host all all ::0/0 md5
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Start PostgreSQL temporarily to ensure user and database exist
|
||||
echo "Starting PostgreSQL for setup..."
|
||||
su - postgres -c "pg_ctl -D /var/lib/postgresql/data start -o '-c logging_collector=off'"
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
for i in {1..30}; do
|
||||
if su - postgres -c "pg_isready" > /dev/null 2>&1; then
|
||||
echo "PostgreSQL is ready!"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Check if codeflash user exists, create if not
|
||||
USER_EXISTS=$(su - postgres -c "psql -tAc \"SELECT 1 FROM pg_roles WHERE rolname='codeflash'\"" 2>/dev/null || echo "0")
|
||||
if [ "$USER_EXISTS" != "1" ]; then
|
||||
echo "Creating database user and database..."
|
||||
su - postgres -c "psql -c \"CREATE USER codeflash WITH PASSWORD 'codeflash';\""
|
||||
su - postgres -c "psql -c \"CREATE DATABASE codeflash OWNER codeflash;\""
|
||||
su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE codeflash TO codeflash;\""
|
||||
echo "User and database created successfully!"
|
||||
else
|
||||
echo "Database user already exists, skipping creation."
|
||||
fi
|
||||
|
||||
# Stop PostgreSQL so supervisord can start it properly
|
||||
echo "Stopping temporary PostgreSQL instance..."
|
||||
su - postgres -c "pg_ctl -D /var/lib/postgresql/data stop -w"
|
||||
sleep 2
|
||||
|
||||
# Set default DATABASE_URL if not provided
|
||||
export DATABASE_URL="${DATABASE_URL:-postgresql://codeflash:codeflash@localhost:5432/codeflash}"
|
||||
|
||||
# Auto-generate SECRET_KEY if not provided
|
||||
if [ -z "$SECRET_KEY" ]; then
|
||||
echo "⚠️ SECRET_KEY not provided, generating random key..."
|
||||
export SECRET_KEY=$(openssl rand -hex 32)
|
||||
echo "✓ Generated SECRET_KEY"
|
||||
fi
|
||||
|
||||
# Set default URLs if not provided
|
||||
export NEXT_PUBLIC_APP_URL="${NEXT_PUBLIC_APP_URL:-http://localhost:3000}"
|
||||
export WEBAPP_URL="${WEBAPP_URL:-http://localhost:3000}"
|
||||
export CODEFLASH_CFAPI_URL="${CODEFLASH_CFAPI_URL:-http://localhost:3001}"
|
||||
|
||||
echo ""
|
||||
echo "Starting services with supervisord..."
|
||||
echo ""
|
||||
|
||||
# Start supervisord in background
|
||||
/usr/bin/supervisord -c /etc/supervisord.conf &
|
||||
SUPERVISOR_PID=$!
|
||||
|
||||
# Wait for PostgreSQL to be ready under supervisord
|
||||
echo "Waiting for PostgreSQL to start under supervisord..."
|
||||
sleep 10
|
||||
|
||||
# Run database initialization (migrations and API key creation)
|
||||
/app/init-db.sh
|
||||
|
||||
# Keep supervisord running
|
||||
wait $SUPERVISOR_PID
|
||||
62
deployment/onprem-simple/supervisord.conf
Normal file
62
deployment/onprem-simple/supervisord.conf
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
logfile=/var/log/supervisord.log
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///var/run/supervisor.sock
|
||||
|
||||
[unix_http_server]
|
||||
file=/var/run/supervisor.sock
|
||||
chmod=0700
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[program:postgres]
|
||||
command=/usr/libexec/postgresql15/postgres -D /var/lib/postgresql/data
|
||||
user=postgres
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=1
|
||||
|
||||
[program:aiservice]
|
||||
command=/bin/sh -c "cd /app/aiservice && uv run gunicorn -c gunicorn.conf.py aiservice.asgi:application --bind 0.0.0.0:8000 --timeout 600 --workers 2"
|
||||
directory=/app/aiservice
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=10
|
||||
environment=PYTHONUNBUFFERED="1",DATABASE_URL="postgresql://codeflash:codeflash@localhost:5432/codeflash"
|
||||
|
||||
[program:cf-api]
|
||||
command=/bin/sh -c "cd /app/cf-api && npm start"
|
||||
directory=/app/cf-api
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=10
|
||||
environment=NODE_ENV="local",DATABASE_URL="postgresql://codeflash:codeflash@localhost:5432/codeflash"
|
||||
|
||||
[program:cf-webapp]
|
||||
command=/bin/sh -c "cd /app/cf-webapp && npm start"
|
||||
directory=/app/cf-webapp
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
priority=10
|
||||
environment=DATABASE_URL="postgresql://codeflash:codeflash@localhost:5432/codeflash",NODE_ENV="production"
|
||||
81
django/.dockerignore
Normal file
81
django/.dockerignore
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Python virtual environments
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
aiservice/.venv/
|
||||
aiservice/venv/
|
||||
aiservice/__pycache__/
|
||||
|
||||
# Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Testing
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# IDEs
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# Database
|
||||
*.db
|
||||
*.sqlite3
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# Temporary files
|
||||
tmp/
|
||||
temp/
|
||||
.tmp/
|
||||
|
|
@ -3,15 +3,15 @@ from __future__ import annotations
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from openai import AsyncOpenAI
|
||||
from openai.lib.azure import AsyncAzureOpenAI
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
IS_PRODUCTION = os.environ.get("ENVIRONMENT", default="") == "PRODUCTION"
|
||||
|
||||
LOGGING_FORMAT = "[%(levelname)s] %(message)s"
|
||||
|
|
@ -41,31 +41,34 @@ def debug_log_sensitive_data_from_callable(message: Callable[[], str | None]) ->
|
|||
logging.debug(message())
|
||||
|
||||
|
||||
def create_openai_client_instance(
|
||||
client_type: str = os.environ.get("OPENAI_API_TYPE", default="azure"),
|
||||
) -> AsyncOpenAI | AsyncAzureOpenAI:
|
||||
if client_type == "azure":
|
||||
logging.info("OpenAIClient: Using Azure OpenAI service.")
|
||||
openai_client: AsyncOpenAI | AsyncAzureOpenAI = AsyncAzureOpenAI(
|
||||
# https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning
|
||||
api_version="2024-08-01-preview",
|
||||
# https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource
|
||||
azure_endpoint="https://codeflash-openai-service-eastus2-0.openai.azure.com",
|
||||
|
||||
def create_llm_client(model_type: Literal["openai", "anthropic", "google"]) -> AsyncOpenAI | None:
|
||||
# use azure or openai
|
||||
openai_api_type = os.environ.get("OPENAI_API_TYPE")
|
||||
openai_api_base_url = os.environ.get(
|
||||
"OPENAI_API_BASE"
|
||||
) # for us it is https://codeflash-openai-service-eastus2-0.openai.azure.com/openai/v1/
|
||||
# we need both of the above to run on azure
|
||||
azure_api_key, openai_key, anthropic_key, google_key = (
|
||||
os.environ.get("AZURE_OPENAI_API_KEY"),
|
||||
os.environ.get("OPENAI_API_KEY"),
|
||||
os.environ.get("ANTHROPIC_API_KEY"),
|
||||
os.environ.get("GEMINI_API_KEY"),
|
||||
)
|
||||
else:
|
||||
logging.info("OpenAIClient: Using OpenAI API.")
|
||||
openai_client = AsyncOpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
|
||||
return openai_client
|
||||
if model_type == "openai" and azure_api_key and openai_api_type == "azure" and openai_api_base_url:
|
||||
# check for azure first
|
||||
return AsyncOpenAI(api_key=azure_api_key, base_url=openai_api_base_url)
|
||||
if model_type == "openai" and openai_key:
|
||||
return AsyncOpenAI(api_key=openai_key) # baseurl not needed for regular openai
|
||||
if model_type == "anthropic" and anthropic_key:
|
||||
return AsyncOpenAI(api_key=anthropic_key, base_url="https://api.anthropic.com/v1/")
|
||||
# # for future use : gemini supported only via GEMINI_API_KEY at the moment, todo for vertex ai
|
||||
if model_type == "google" and google_key:
|
||||
return AsyncOpenAI(api_key=google_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
|
||||
return None
|
||||
|
||||
|
||||
def create_claude_client() -> AsyncOpenAI:
|
||||
logging.info("Claude Client")
|
||||
claude_client: AsyncOpenAI = AsyncOpenAI(
|
||||
api_key=os.environ.get("ANTHROPIC_API_KEY"),
|
||||
base_url="https://api.anthropic.com/v1/",
|
||||
)
|
||||
return claude_client
|
||||
|
||||
|
||||
openai_client = create_openai_client_instance()
|
||||
llm_clients = {
|
||||
"openai": create_llm_client("openai"),
|
||||
"anthropic": create_llm_client("anthropic"),
|
||||
# "google": create_llm_client("google"), # no need to instantiate right now as we're not using it
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
from typing import Any
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ from pydantic.dataclasses import dataclass
|
|||
class LLM:
|
||||
name: str # On Azure OpenAI Service, this is the deployment name
|
||||
max_tokens: int
|
||||
api_version: str = ""
|
||||
model_type: Literal["openai", "anthropic", "google"]
|
||||
# Add new pricing attributes in USD per 1M tokens
|
||||
input_cost: float | None = None
|
||||
output_cost: float | None = None
|
||||
|
|
@ -24,6 +24,7 @@ class LLM:
|
|||
@dataclass
|
||||
class GPT_4_OMNI(LLM):
|
||||
name: str = "gpt-4o-2" if os.environ.get("OPENAI_API_TYPE") == "azure" else "gpt-4o"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 128000
|
||||
input_cost: float = 2.50
|
||||
output_cost: float = 10.00
|
||||
|
|
@ -32,6 +33,7 @@ class GPT_4_OMNI(LLM):
|
|||
@dataclass
|
||||
class GPT_4_128k(LLM):
|
||||
name: str = "gpt-4-1106-preview"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 128000
|
||||
input_cost: float = 10.00
|
||||
output_cost: float = 30.00
|
||||
|
|
@ -40,6 +42,7 @@ class GPT_4_128k(LLM):
|
|||
@dataclass
|
||||
class GPT_4_32k(LLM):
|
||||
name: str = "gpt4-32k"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 32768
|
||||
input_cost: float = 60.00
|
||||
output_cost: float = 120.00
|
||||
|
|
@ -48,6 +51,7 @@ class GPT_4_32k(LLM):
|
|||
@dataclass
|
||||
class GPT_4(LLM):
|
||||
name: str = "gpt-4-0613"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 8192
|
||||
input_cost: float = 30.00
|
||||
output_cost: float = 60.00
|
||||
|
|
@ -56,6 +60,7 @@ class GPT_4(LLM):
|
|||
@dataclass
|
||||
class GPT_3_5_Turbo_16k(LLM):
|
||||
name: str = "gpt-3.5-turbo-16k"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 16384
|
||||
input_cost: float = 3.00
|
||||
output_cost: float = 4.00
|
||||
|
|
@ -64,6 +69,7 @@ class GPT_3_5_Turbo_16k(LLM):
|
|||
@dataclass
|
||||
class GPT_3_5_Turbo(LLM):
|
||||
name: str = "gpt-3.5-turbo"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 4096
|
||||
input_cost: float = 0.50
|
||||
output_cost: float = 1.50
|
||||
|
|
@ -72,6 +78,7 @@ class GPT_3_5_Turbo(LLM):
|
|||
@dataclass
|
||||
class Antropic_Claude_3_7(LLM):
|
||||
name: str = "claude-3-7-sonnet-20250219"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
input_cost: float = 3.00
|
||||
output_cost: float = 15.00
|
||||
|
|
@ -80,8 +87,8 @@ class Antropic_Claude_3_7(LLM):
|
|||
@dataclass
|
||||
class Anthropic_Claude_4(LLM):
|
||||
name: str = "claude-sonnet-4-20250514"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "anthropic"
|
||||
max_tokens: int = 100000
|
||||
api_version: str = ""
|
||||
input_cost: float = 3.00
|
||||
output_cost: float = 15.00
|
||||
|
||||
|
|
@ -90,8 +97,8 @@ class Anthropic_Claude_4(LLM):
|
|||
class OpenAI_GPT_4_1(LLM):
|
||||
# name: str = "azure/gpt-4.1"
|
||||
name: str = "gpt-4.1"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
api_version: str = "2024-12-01-preview"
|
||||
input_cost: float = 2.00
|
||||
output_cost: float = 8.00
|
||||
|
||||
|
|
@ -99,14 +106,15 @@ class OpenAI_GPT_4_1(LLM):
|
|||
@dataclass
|
||||
class Gemini_2_5(LLM):
|
||||
name: str = "gemini/gemini-2.5-pro-preview-03-25"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "google"
|
||||
max_tokens: int = 100000
|
||||
|
||||
|
||||
@dataclass
|
||||
class OpenAI_GPT_O_3(LLM):
|
||||
name: str = "azure/o3"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
api_version = "2025-01-01-preview"
|
||||
input_cost: float = 2.00
|
||||
output_cost: float = 8.00
|
||||
|
||||
|
|
@ -114,15 +122,16 @@ class OpenAI_GPT_O_3(LLM):
|
|||
@dataclass
|
||||
class OpenAI_GPT_O_4_MINI(LLM):
|
||||
name: str = "azure/o4-mini"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
api_version = "2024-12-01-preview"
|
||||
input_cost: float = 1.10
|
||||
output_cost: float = 4.40
|
||||
|
||||
|
||||
@dataclass
|
||||
class GPT_5(LLM):
|
||||
name: str = "gpt-5"
|
||||
class GPT_5(LLM): # IT IS TOO SLOW AT THE MOMENT, just here for documentation
|
||||
name: str = "gpt-5-codex"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
input_cost: float = 1.25
|
||||
output_cost: float = 10.00
|
||||
|
|
@ -131,6 +140,7 @@ class GPT_5(LLM):
|
|||
@dataclass
|
||||
class GPT_4_1_Nano(LLM):
|
||||
name: str = "gpt-4.1-nano"
|
||||
model_type: Literal["openai", "anthropic", "google"] = "openai"
|
||||
max_tokens: int = 100000
|
||||
input_cost: float = 0.10
|
||||
output_cost: float = 0.40
|
||||
|
|
@ -148,8 +158,12 @@ def calculate_llm_cost(response: Any, llm: LLM) -> float | None:
|
|||
"""
|
||||
try:
|
||||
usage = response.usage
|
||||
if hasattr(usage, "prompt_tokens"): # for openai
|
||||
prompt_tokens = usage.prompt_tokens
|
||||
completion_tokens = usage.completion_tokens
|
||||
else: # for claude
|
||||
prompt_tokens = usage.input_tokens
|
||||
completion_tokens = usage.output_tokens
|
||||
|
||||
prompt_cost = (prompt_tokens / 1_000_000) * llm.input_cost
|
||||
completion_cost = (completion_tokens / 1_000_000) * llm.output_cost
|
||||
|
|
@ -163,11 +177,45 @@ def calculate_llm_cost(response: Any, llm: LLM) -> float | None:
|
|||
return None
|
||||
|
||||
|
||||
EXPLAIN_MODEL: LLM = OpenAI_GPT_4_1()
|
||||
PLAN_MODEL: LLM = OpenAI_GPT_4_1()
|
||||
EXECUTE_MODEL: LLM = OpenAI_GPT_4_1()
|
||||
OPTIMIZE_MODEL: LLM = OpenAI_GPT_4_1()
|
||||
REFINEMENT_MODEL: LLM = Anthropic_Claude_4()
|
||||
EXPLANATIONS_MODEL: LLM = Anthropic_Claude_4()
|
||||
RANKING_MODEL: LLM = OpenAI_GPT_4_1()
|
||||
OPTIMIZATION_REVIEW_MODEL: LLM = Anthropic_Claude_4()
|
||||
def _get_openai_model() -> LLM:
|
||||
"""Return OpenAI GPT-4.1 if available, otherwise falls back to Anthropic Claude 4.
|
||||
|
||||
Returns:
|
||||
LLM: The appropriate model instance based on available API keys.
|
||||
|
||||
"""
|
||||
if os.environ.get("AZURE_OPENAI_API_KEY") or os.environ.get("OPENAI_API_KEY"):
|
||||
return OpenAI_GPT_4_1()
|
||||
# Fall back to Anthropic if OpenAI not available
|
||||
if os.environ.get("ANTHROPIC_API_KEY"):
|
||||
return Anthropic_Claude_4()
|
||||
# Default to OpenAI (will fail gracefully with clear error from env_specific.py)
|
||||
return OpenAI_GPT_4_1()
|
||||
|
||||
|
||||
def _get_anthropic_model() -> LLM:
|
||||
"""Returns Anthropic Claude 4 if available, otherwise falls back to OpenAI GPT-4.1.
|
||||
|
||||
Returns:
|
||||
LLM: The appropriate model instance based on available API keys.
|
||||
|
||||
""" # noqa: D401
|
||||
if os.environ.get("ANTHROPIC_API_KEY"):
|
||||
return Anthropic_Claude_4()
|
||||
# Fall back to OpenAI if Anthropic not available
|
||||
if os.environ.get("AZURE_OPENAI_API_KEY") or os.environ.get("OPENAI_API_KEY"):
|
||||
return OpenAI_GPT_4_1()
|
||||
# Default to Claude (will fail gracefully with clear error from env_specific.py)
|
||||
return Anthropic_Claude_4()
|
||||
|
||||
|
||||
# Dynamically select models based on available API keys
|
||||
EXPLAIN_MODEL: LLM = _get_openai_model()
|
||||
PLAN_MODEL: LLM = _get_openai_model()
|
||||
EXECUTE_MODEL: LLM = _get_openai_model()
|
||||
OPTIMIZE_MODEL: LLM = _get_openai_model()
|
||||
RANKING_MODEL: LLM = _get_openai_model()
|
||||
|
||||
REFINEMENT_MODEL: LLM = _get_anthropic_model()
|
||||
EXPLANATIONS_MODEL: LLM = _get_anthropic_model()
|
||||
OPTIMIZATION_REVIEW_MODEL: LLM = _get_anthropic_model()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
|
|||
import sentry_sdk
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import validate_trace_id
|
||||
from aiservice.env_specific import create_claude_client, debug_log_sensitive_data
|
||||
from aiservice.env_specific import create_llm_client, debug_log_sensitive_data, llm_clients
|
||||
from aiservice.models.aimodels import EXPLANATIONS_MODEL, LLM, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
|
|
@ -213,9 +213,9 @@ async def explain_optimizations( # noqa: D417
|
|||
| ChatCompletionToolMessageParam
|
||||
| ChatCompletionFunctionMessageParam
|
||||
] = [system_message, user_message]
|
||||
async with create_claude_client() as claude_client:
|
||||
llm_client = llm_clients[explanations_model.model_type]
|
||||
try:
|
||||
output = await claude_client.with_options(max_retries=2).chat.completions.create(
|
||||
output = await llm_client.with_options(max_retries=2).chat.completions.create(
|
||||
model=explanations_model.name, messages=messages, n=1
|
||||
)
|
||||
await update_optimization_cost(trace_id=data.trace_id, cost=calculate_llm_cost(output, explanations_model))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from enum import Enum
|
|||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
import sentry_sdk
|
||||
from aiservice.env_specific import create_claude_client, debug_log_sensitive_data
|
||||
from aiservice.env_specific import create_llm_client, debug_log_sensitive_data, llm_clients
|
||||
from aiservice.models.aimodels import OPTIMIZATION_REVIEW_MODEL, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost, update_optimization_features_review
|
||||
from ninja import NinjaAPI, Schema
|
||||
|
|
@ -142,7 +142,9 @@ Output as a json markdown block with the key named as 'rating' and value being o
|
|||
|
||||
|
||||
async def get_optimization_review(
|
||||
request, data: OptimizationReviewSchema, optimization_review_model: LLM = OPTIMIZATION_REVIEW_MODEL
|
||||
request,
|
||||
data: OptimizationReviewSchema,
|
||||
optimization_review_model: LLM = OPTIMIZATION_REVIEW_MODEL, # noqa: ANN001
|
||||
) -> tuple[int, OptimizationReviewResponseSchema | OptimizationReviewErrorSchema]:
|
||||
"""Compute optimization review via Claude."""
|
||||
ph(request.user, "aiservice-optimization-review-called")
|
||||
|
|
@ -151,9 +153,9 @@ async def get_optimization_review(
|
|||
|
||||
debug_log_sensitive_data(f"{messages[0]}{messages[1]}")
|
||||
|
||||
async with create_claude_client() as claude_client:
|
||||
llm_client = llm_clients[optimization_review_model.model_type]
|
||||
# Call Claude API with retries
|
||||
response = await claude_client.with_options(max_retries=2).chat.completions.create(
|
||||
response = await llm_client.with_options(max_retries=2).chat.completions.create(
|
||||
model=optimization_review_model.name, messages=messages
|
||||
)
|
||||
# Calculate and update cost
|
||||
|
|
@ -197,7 +199,8 @@ async def get_optimization_review(
|
|||
},
|
||||
)
|
||||
async def optimization_review(
|
||||
request, data: OptimizationReviewSchema
|
||||
request,
|
||||
data: OptimizationReviewSchema, # noqa: ANN001
|
||||
) -> tuple[int, OptimizationReviewResponseSchema | OptimizationReviewErrorSchema]:
|
||||
response_code, output = await get_optimization_review(request, data)
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ from typing import TYPE_CHECKING
|
|||
|
||||
import libcst as cst
|
||||
import sentry_sdk
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import parse_python_version, should_hack_for_demo, validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable, llm_clients
|
||||
from aiservice.models.aimodels import OPTIMIZE_MODEL, calculate_llm_cost
|
||||
from authapp.user import get_user_by_id
|
||||
from log_features.log_event import log_optimization_event
|
||||
from log_features.log_features import log_features
|
||||
from ninja import NinjaAPI
|
||||
from ninja.errors import HttpError
|
||||
from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam
|
||||
from pydantic import ValidationError
|
||||
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import parse_python_version, should_hack_for_demo, validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable, openai_client
|
||||
from aiservice.models.aimodels import OPTIMIZE_MODEL, calculate_llm_cost
|
||||
from authapp.user import get_user_by_id
|
||||
from log_features.log_event import log_optimization_event
|
||||
from log_features.log_features import log_features
|
||||
from optimizer.context_utils.context_helpers import group_code
|
||||
from optimizer.context_utils.optimizer_context import (
|
||||
BaseOptimizerContext,
|
||||
|
|
@ -30,6 +30,7 @@ from optimizer.context_utils.optimizer_context import (
|
|||
from optimizer.models import OptimizeSchema # noqa: TC001
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiservice.models.aimodels import LLM
|
||||
from django.http import HttpRequest
|
||||
from openai.types.chat import (
|
||||
ChatCompletionAssistantMessageParam,
|
||||
|
|
@ -37,8 +38,6 @@ if TYPE_CHECKING:
|
|||
ChatCompletionToolMessageParam,
|
||||
)
|
||||
|
||||
from aiservice.models.aimodels import LLM
|
||||
|
||||
|
||||
optimizations_json = [
|
||||
{
|
||||
|
|
@ -138,8 +137,9 @@ async def optimize_python_code(
|
|||
| ChatCompletionToolMessageParam
|
||||
| ChatCompletionFunctionMessageParam
|
||||
] = [system_message, user_message]
|
||||
llm_client = llm_clients[optimize_model.model_type]
|
||||
try:
|
||||
output = await openai_client.with_options(max_retries=3).chat.completions.create(
|
||||
output = await llm_client.with_options(max_retries=3).chat.completions.create(
|
||||
model=optimize_model.name, messages=messages, n=n
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -5,34 +5,30 @@ from pathlib import Path
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
import sentry_sdk
|
||||
from ninja import NinjaAPI, Schema
|
||||
from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam
|
||||
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import parse_python_version, validate_trace_id
|
||||
from aiservice.env_specific import (
|
||||
debug_log_sensitive_data,
|
||||
debug_log_sensitive_data_from_callable,
|
||||
openai_client,
|
||||
)
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable, llm_clients
|
||||
from aiservice.models.aimodels import OPTIMIZE_MODEL, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
from ninja import NinjaAPI, Schema
|
||||
from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam
|
||||
|
||||
from optimizer.context_utils.optimizer_context import (
|
||||
BaseOptimizerContext,
|
||||
OptimizeErrorResponseSchema,
|
||||
OptimizeResponseItemSchema,
|
||||
OptimizeResponseSchema,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiservice.models.aimodels import LLM
|
||||
from openai.types.chat import (
|
||||
ChatCompletionAssistantMessageParam,
|
||||
ChatCompletionFunctionMessageParam,
|
||||
ChatCompletionToolMessageParam,
|
||||
)
|
||||
|
||||
from aiservice.models.aimodels import LLM
|
||||
from optimizer.context_utils.optimizer_context import OptimizeResponseItemSchema
|
||||
|
||||
|
||||
optimize_line_profiler_api = NinjaAPI(urls_namespace="optimize-line-profiler")
|
||||
|
|
@ -44,7 +40,7 @@ SYSTEM_PROMPT = (current_dir / "system_prompt.md").read_text()
|
|||
USER_PROMPT = (current_dir / "user_prompt.md").read_text()
|
||||
|
||||
|
||||
async def optimize_python_code_line_profiler(
|
||||
async def optimize_python_code_line_profiler( # noqa: D417
|
||||
user_id: str,
|
||||
trace_id: str,
|
||||
line_profiler_results: str,
|
||||
|
|
@ -52,7 +48,7 @@ async def optimize_python_code_line_profiler(
|
|||
dependency_code: str | None = None,
|
||||
n: int = 1,
|
||||
optimize_model: LLM = OPTIMIZE_MODEL,
|
||||
lsp_mode: bool = False,
|
||||
lsp_mode: bool = False, # noqa: FBT001, FBT002
|
||||
python_version: tuple[int, int, int] = (3, 12, 9),
|
||||
) -> list[OptimizeResponseItemSchema]:
|
||||
"""Optimize the given python code for performance using OpenAI's GPT-4o model.
|
||||
|
|
@ -92,8 +88,9 @@ async def optimize_python_code_line_profiler(
|
|||
] = [system_message, user_message]
|
||||
debug_log_sensitive_data(f"This was the user prompt\n {user_prompt}\n")
|
||||
# TODO: Verify if the context window length is within the model capability
|
||||
llm_client = llm_clients[optimize_model.model_type]
|
||||
try:
|
||||
output = await openai_client.with_options(max_retries=3).chat.completions.create(
|
||||
output = await llm_client.with_options(max_retries=3).chat.completions.create(
|
||||
model=optimize_model.name, messages=messages, n=n
|
||||
)
|
||||
await update_optimization_cost(trace_id=trace_id, cost=calculate_llm_cost(output, optimize_model))
|
||||
|
|
@ -140,12 +137,12 @@ class OptimizeSchemaLP(Schema):
|
|||
@optimize_line_profiler_api.post(
|
||||
"/", response={200: OptimizeResponseSchema, 400: OptimizeErrorResponseSchema, 500: OptimizeErrorResponseSchema}
|
||||
)
|
||||
async def optimize(request, data: OptimizeSchemaLP) -> tuple[int, OptimizeResponseSchema | OptimizeErrorResponseSchema]:
|
||||
async def optimize(request, data: OptimizeSchemaLP) -> tuple[int, OptimizeResponseSchema | OptimizeErrorResponseSchema]: # noqa: ANN001
|
||||
ph(request.user, "aiservice-optimize-called")
|
||||
ctx: BaseOptimizerContext = BaseOptimizerContext.get_dynamic_context(SYSTEM_PROMPT, USER_PROMPT, data.source_code)
|
||||
try:
|
||||
python_version: tuple[int, int, int] = parse_python_version(data.python_version)
|
||||
except:
|
||||
except: # noqa: E722
|
||||
return 400, OptimizeErrorResponseSchema(
|
||||
error="Invalid Python version, it should look like 3.x.x. We only support Python 3.9 and above."
|
||||
)
|
||||
|
|
@ -197,7 +194,7 @@ async def optimize(request, data: OptimizeSchemaLP) -> tuple[int, OptimizeRespon
|
|||
|
||||
response = OptimizeResponseSchema(optimizations=optimization_response_items)
|
||||
|
||||
def log_response():
|
||||
def log_response() -> None:
|
||||
debug_log_sensitive_data(f"Response:\n{response.json()}")
|
||||
for opt in response.optimizations:
|
||||
debug_log_sensitive_data(f"Optimized source:\n{opt.source_code}")
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import libcst as cst
|
|||
import sentry_sdk
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import validate_trace_id
|
||||
from aiservice.env_specific import create_claude_client, debug_log_sensitive_data
|
||||
from aiservice.env_specific import create_llm_client, debug_log_sensitive_data, llm_clients
|
||||
from aiservice.models.aimodels import REFINEMENT_MODEL, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
|
|
@ -227,9 +227,9 @@ async def refinement( # noqa: D417
|
|||
| ChatCompletionFunctionMessageParam
|
||||
] = [system_message, user_message]
|
||||
debug_log_sensitive_data(f"This was the user prompt\n {user_prompt}\n")
|
||||
async with create_claude_client() as claude_client:
|
||||
llm_client = llm_clients[optimize_model.model_type]
|
||||
try:
|
||||
output = await claude_client.with_options(max_retries=2).chat.completions.create(
|
||||
output = await llm_client.with_options(max_retries=2).chat.completions.create(
|
||||
model=optimize_model.name, messages=messages, n=1
|
||||
)
|
||||
llm_cost = calculate_llm_cost(output, optimize_model)
|
||||
|
|
@ -311,7 +311,8 @@ class Refinementschema(Schema):
|
|||
|
||||
@refinement_api.post("/", response={200: Refinementschema, 400: Refinementschema, 500: Refinementschema})
|
||||
async def refine(
|
||||
request, data: list[RefinementRequestSchema]
|
||||
request,
|
||||
data: list[RefinementRequestSchema], # noqa: ANN001
|
||||
) -> tuple[int, Refinementschema | OptimizeErrorResponseSchema]:
|
||||
ph(request.user, "aiservice-refinement-called")
|
||||
ctx_data_list = [
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
|
|||
import sentry_sdk
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, openai_client
|
||||
from aiservice.env_specific import create_llm_client, debug_log_sensitive_data, llm_clients
|
||||
from aiservice.models.aimodels import LLM, RANKING_MODEL, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
|
|
@ -109,12 +109,13 @@ async def rank_optimizations( # noqa: D417
|
|||
| ChatCompletionToolMessageParam
|
||||
| ChatCompletionFunctionMessageParam
|
||||
] = [system_message, user_message]
|
||||
llm_client = llm_clients[rank_model.model_type]
|
||||
try:
|
||||
output = await openai_client.with_options(max_retries=2).chat.completions.create(
|
||||
output = await llm_client.with_options(max_retries=2).chat.completions.create(
|
||||
model=rank_model.name, messages=messages, n=1
|
||||
)
|
||||
await update_optimization_cost(trace_id=data.trace_id, cost=calculate_llm_cost(output, rank_model))
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
debug_log_sensitive_data(f"Failed to generate new explanation, Error message: {e}")
|
||||
sentry_sdk.capture_exception(e)
|
||||
return RankErrorResponseSchema(error=str(e))
|
||||
|
|
@ -129,7 +130,7 @@ async def rank_optimizations( # noqa: D417
|
|||
try:
|
||||
explanation_match = re.search(explain_regex_pattern, output.choices[0].message.content)
|
||||
explanation = explanation_match.group(1)
|
||||
except:
|
||||
except: # noqa: E722
|
||||
# TODO add logging instead of print("No explanation found")
|
||||
explanation = ""
|
||||
# still doing stuff instead of returning coz ranking is important
|
||||
|
|
@ -141,10 +142,10 @@ async def rank_optimizations( # noqa: D417
|
|||
ranking_match = re.search(rank_regex_pattern, output.choices[0].message.content)
|
||||
# TODO better parsing, could be only comma separated, need to handle all edge cases
|
||||
ranking = list(map(int, ranking_match.group(1).strip().split(",")))
|
||||
except:
|
||||
except: # noqa: E722
|
||||
# TODO add logging instead of print("No ranking found")
|
||||
return RankErrorResponseSchema(error="No ranking found")
|
||||
if not sorted(ranking) == list(range(1, len(data.diffs) + 1)):
|
||||
if sorted(ranking) != list(range(1, len(data.diffs) + 1)):
|
||||
# TODO need to handle all edge cases
|
||||
# TODO add logging instead of print("Invalid ranking")
|
||||
return RankErrorResponseSchema(error="No ranking found")
|
||||
|
|
|
|||
|
|
@ -6,21 +6,20 @@ import asyncio
|
|||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import SupportsIndex
|
||||
from typing import TYPE_CHECKING, SupportsIndex
|
||||
|
||||
import sentry_sdk
|
||||
import stamina
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import parse_python_version, safe_isort, should_hack_for_demo, validate_trace_id
|
||||
from aiservice.env_specific import IS_PRODUCTION, create_llm_client, debug_log_sensitive_data, llm_clients
|
||||
from aiservice.models.aimodels import EXECUTE_MODEL, calculate_llm_cost
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
from ninja import NinjaAPI
|
||||
from ninja.errors import HttpError
|
||||
from openai import OpenAIError
|
||||
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import parse_python_version, safe_isort, should_hack_for_demo, validate_trace_id
|
||||
from aiservice.env_specific import IS_PRODUCTION, debug_log_sensitive_data, openai_client
|
||||
from aiservice.models.aimodels import EXECUTE_MODEL, LLM, calculate_llm_cost
|
||||
from authapp.auth import AuthBearer
|
||||
from log_features.log_event import update_optimization_cost
|
||||
from log_features.log_features import log_features
|
||||
from testgen.instrumentation.edit_generated_test import parse_module_to_cst, replace_definition_with_import
|
||||
from testgen.instrumentation.instrument_new_tests import instrument_test_source
|
||||
from testgen.models import (
|
||||
|
|
@ -34,6 +33,10 @@ from testgen.postprocessing.code_validator import has_test_functions, validate_t
|
|||
from testgen.postprocessing.postprocess_pipeline import postprocessing_testgen_pipeline
|
||||
from testgen.testgen_context import BaseTestGenContext, TestGenContextData
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiservice.models.aimodels import LLM
|
||||
from authapp.auth import AuthBearer
|
||||
|
||||
testgen_api = NinjaAPI(urls_namespace="testgen")
|
||||
|
||||
# Get the directory of the current file
|
||||
|
|
@ -111,7 +114,10 @@ To help unit test the function above, list diverse scenarios that the function s
|
|||
package_comment = ""
|
||||
# if unit_test_package == "pytest":
|
||||
# package_comment = "# below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator"
|
||||
execute_system_message = {"role": "system", "content": execute_system_prompt.format(function_name=ctx.data.qualified_name)}
|
||||
execute_system_message = {
|
||||
"role": "system",
|
||||
"content": execute_system_prompt.format(function_name=ctx.data.qualified_name),
|
||||
}
|
||||
|
||||
execute_messages = [execute_system_message, plan_user_message]
|
||||
|
||||
|
|
@ -196,7 +202,8 @@ async def generate_and_validate_test_code(
|
|||
user_id: str,
|
||||
posthog_event_suffix: str,
|
||||
) -> str:
|
||||
response = await openai_client.with_options(max_retries=2).chat.completions.create(
|
||||
llm_client = llm_clients[execute_model.model_type]
|
||||
response = await llm_client.with_options(max_retries=2).chat.completions.create(
|
||||
model=model.name, messages=messages, temperature=temperature
|
||||
)
|
||||
cost = calculate_llm_cost(response, execute_model) or 0.0
|
||||
|
|
|
|||
10
js/cf-api/Dockerfile
Normal file
10
js/cf-api/Dockerfile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
COPY /package*.json ./
|
||||
RUN npm ci --only=production
|
||||
COPY cf-api .
|
||||
RUN mkdir ../common
|
||||
COPY common ../common
|
||||
RUN npm run build
|
||||
EXPOSE 3001
|
||||
CMD ["node", "dist/index.js"]
|
||||
|
|
@ -61,11 +61,18 @@ const initializeApp = async () => {
|
|||
|
||||
// Export the actual App instance, initialized based on environment
|
||||
export const githubApp = await (async () => {
|
||||
if (process.env.NODE_ENV === "test") {
|
||||
// In test environment, return a minimal mock that won't fail
|
||||
// Check if GitHub App is configured
|
||||
const GH_APP_ID = process.env.GH_APP_ID
|
||||
|
||||
if (!GH_APP_ID || GH_APP_ID === "" || process.env.NODE_ENV === "test") {
|
||||
console.log("caution: GitHub App not configured (GH_APP_ID missing)")
|
||||
console.log("caution: PR creation and GitHub webhook features are disabled")
|
||||
console.log("caution: CLI and optimization features will continue to work")
|
||||
|
||||
// Return a minimal mock that won't fail
|
||||
return {
|
||||
octokit: {
|
||||
request: async () => ({ data: { name: "Test App" } }),
|
||||
request: async () => ({ data: { name: "GitHub App Disabled" } }),
|
||||
log: {
|
||||
debug: () => {},
|
||||
},
|
||||
|
|
@ -75,11 +82,14 @@ export const githubApp = await (async () => {
|
|||
onAny: () => {},
|
||||
onError: () => {},
|
||||
},
|
||||
getInstallationOctokit: async () => ({}),
|
||||
getInstallationOctokit: async () => {
|
||||
throw new Error("GitHub App not configured. Set GH_APP_ID to enable PR creation.")
|
||||
},
|
||||
} as any as App
|
||||
}
|
||||
|
||||
// In other environments, initialize normally
|
||||
console.log(`GitHub App ID ${GH_APP_ID} detected, initializing...`)
|
||||
const app = await initializeApp()
|
||||
|
||||
console.log(`Github App Initialized`)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import Stripe from "stripe"
|
||||
|
||||
if (!process.env.STRIPE_SECRET_KEY) {
|
||||
throw new Error("STRIPE_SECRET_KEY is not set in environment variables")
|
||||
console.warn("⚠️ STRIPE_SECRET_KEY not set, billing features will be disabled")
|
||||
}
|
||||
|
||||
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
|
||||
export const stripe = process.env.STRIPE_SECRET_KEY
|
||||
? new Stripe(process.env.STRIPE_SECRET_KEY, {
|
||||
apiVersion: "2025-08-27.basil",
|
||||
})
|
||||
: null
|
||||
|
|
|
|||
Loading…
Reference in a new issue