Skip to content

Refactor weather and theme functionality into dedicated tools #95

Refactor weather and theme functionality into dedicated tools

Refactor weather and theme functionality into dedicated tools #95

Workflow file for this run

name: CI/CD Workflow
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
PROJECT_ID: ohzbghitbjryfpmucgju
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
# Frontend environment variables (for CI testing only - localhost values)
# Production deployments use secrets via Vercel CLI
VITE_SUPABASE_URL: http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY: sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH
# Supabase edge function secrets
DEFAULT_AGENT_MODEL: openai/gpt-4.1
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
HF_TOKEN: ${{ secrets.HF_TOKEN }}
jobs:
# Preview deployment for pull requests and feature branches
preview:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
export PATH="$HOME/.cargo/bin:$PATH"
uv --version
- name: Install dependencies
run: npm ci
- name: Sync Python dependencies
run: |
uv sync
env:
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SUPABASE_ANON_KEY: ${{ env.VITE_SUPABASE_ANON_KEY }}
SUPABASE_URL: ${{ env.VITE_SUPABASE_URL }}
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Setup Supabase CLI
uses: supabase/setup-cli@v1
with:
version: latest
- name: Create Supabase config for CI
run: |
echo "Creating Supabase config for CI environment..."
cat > supabase/config.toml << EOF
project_id = "ohzbghitbjryfpmucgju"
[edge_runtime]
enabled = true
[edge_runtime.secrets]
DEFAULT_AGENT_MODEL = "$DEFAULT_AGENT_MODEL"
OPENAI_API_KEY = "$OPENAI_API_KEY"
OLLAMA_API_KEY = "$OLLAMA_API_KEY"
HF_TOKEN = "$HF_TOKEN"
[auth]
enabled = true
site_url = "http://localhost:8080"
additional_redirect_urls = ["http://localhost:8080", "http://127.0.0.1:8080", "http://localhost:5173", "http://127.0.0.1:5173", "http://127.0.0.1:3000", "https://127.0.0.1:3000"]
jwt_expiry = 3600
enable_refresh_token_rotation = true
refresh_token_reuse_interval = 10
enable_signup = true
enable_anonymous_sign_ins = true
[functions.agents]
enabled = true
verify_jwt = true
import_map = "./functions/agents/deno.json"
entrypoint = "./functions/agents/index.ts"
[functions.openai-polyfill]
enabled = true
verify_jwt = true
import_map = "./functions/openai-polyfill/deno.json"
entrypoint = "./functions/openai-polyfill/index.ts"
[functions.threads]
enabled = true
verify_jwt = true
import_map = "./functions/threads/deno.json"
entrypoint = "./functions/threads/index.ts"
EOF
- name: Start Supabase local development
run: |
echo "Starting Supabase local development environment..."
supabase start
env:
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
- name: Wait for Supabase to be ready
run: |
echo "Waiting for Supabase services to be ready..."
# Give Supabase time to start up
sleep 30
# Check if Supabase is responding
for i in {1..20}; do
if curl -f http://127.0.0.1:54321/rest/v1/ > /dev/null 2>&1; then
echo "Supabase is ready!"
break
fi
echo "Attempt $i/20: Waiting for Supabase..."
sleep 5
done
# Final check
if ! curl -f http://127.0.0.1:54321/rest/v1/ > /dev/null 2>&1; then
echo "Supabase failed to start properly"
exit 1
fi
- name: Start Python backend server
run: |
# Start Python backend in background and save PID for cleanup
OLLAMA_API_KEY="$OLLAMA_API_KEY" \
OPENAI_API_KEY="$OPENAI_API_KEY" \
SUPABASE_ANON_KEY="$SUPABASE_ANON_KEY" \
SUPABASE_URL="$SUPABASE_URL" \
npm run dev:api &
PYTHON_API_PID=$!
echo "PYTHON_API_PID=$PYTHON_API_PID" >> $GITHUB_ENV
# Wait for the Python backend to be ready
for i in {1..30}; do
if curl -f http://127.0.0.1:8000/health > /dev/null 2>&1 || curl -f http://127.0.0.1:8000/docs > /dev/null 2>&1; then
echo "Python backend server is ready!"
break
fi
echo "Attempt $i/30: Waiting for Python backend server..."
sleep 2
done
# Final check
if ! curl -f http://127.0.0.1:8000/docs > /dev/null 2>&1; then
echo "Python backend server failed to start properly"
kill $PYTHON_API_PID 2>/dev/null || true
exit 1
fi
env:
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SUPABASE_ANON_KEY: ${{ env.VITE_SUPABASE_ANON_KEY }}
SUPABASE_URL: ${{ env.VITE_SUPABASE_URL }}
- name: Start frontend development server
run: |
# Start server in background and save PID for cleanup
npm run dev &
SERVER_PID=$!
echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
# Wait for the server to be ready
for i in {1..30}; do
if curl -f http://localhost:8080 > /dev/null 2>&1; then
echo "Frontend server is ready!"
break
fi
echo "Attempt $i/30: Waiting for frontend server..."
sleep 2
done
# Final check
if ! curl -f http://localhost:8080 > /dev/null 2>&1; then
echo "Frontend server failed to start properly"
kill $SERVER_PID 2>/dev/null || true
exit 1
fi
- name: Run E2E tests (headed)
run: |
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24 -ac' \
npm run test
- name: Stop frontend development server
if: always()
run: |
if [ ! -z "$SERVER_PID" ]; then
echo "Stopping frontend development server (PID: $SERVER_PID)..."
kill $SERVER_PID 2>/dev/null || true
fi
- name: Stop Python backend server
if: always()
run: |
if [ ! -z "$PYTHON_API_PID" ]; then
echo "Stopping Python backend server (PID: $PYTHON_API_PID)..."
kill $PYTHON_API_PID 2>/dev/null || true
fi
- name: Stop Supabase local development
if: always()
run: |
echo "Stopping Supabase local development environment..."
supabase stop || true
- name: Link to Supabase project
run: supabase link --project-ref $PROJECT_ID
- name: Create Supabase preview branch
run: |
echo "Creating Supabase preview branch for PR #${{ github.event.number }}"
supabase branches create pr-${{ github.event.number }}
- name: Deploy to Supabase preview branch
run: |
echo "Deploying to Supabase preview branch..."
supabase db push --linked --yes --include-all
supabase functions deploy --project-ref $PROJECT_ID --yes
- name: Build application (test build)
run: npm run build
# Note: This build uses localhost values for CI testing
# Vercel will rebuild with production values during deployment
- name: Install Vercel CLI
run: npm install -g vercel
- name: Link Vercel Project
run: |
vercel link --yes --token ${{ secrets.VERCEL_TOKEN }} \
--scope ${{ secrets.VERCEL_ORG_ID }} \
--project ${{ secrets.VERCEL_PROJECT_ID }}
continue-on-error: true
- name: Set Vercel Environment Variables (Preview)
run: |
# Set environment variables for preview deployments
# Remove existing variables first (ignore errors if they don't exist), then add new ones
vercel env rm VITE_SUPABASE_URL preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm VITE_SUPABASE_ANON_KEY preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm VITE_PYTHON_BACKEND_URL preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm DEFAULT_AGENT_MODEL preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm OPENAI_API_KEY preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm OLLAMA_API_KEY preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm HF_TOKEN preview --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
# Add environment variables
echo "${{ secrets.VITE_SUPABASE_URL }}" | vercel env add VITE_SUPABASE_URL preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.VITE_SUPABASE_ANON_KEY }}" | vercel env add VITE_SUPABASE_ANON_KEY preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.VITE_PYTHON_BACKEND_URL }}" | vercel env add VITE_PYTHON_BACKEND_URL preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.DEFAULT_AGENT_MODEL }}" | vercel env add DEFAULT_AGENT_MODEL preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.OPENAI_API_KEY }}" | vercel env add OPENAI_API_KEY preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.OLLAMA_API_KEY }}" | vercel env add OLLAMA_API_KEY preview --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.HF_TOKEN }}" | vercel env add HF_TOKEN preview --token ${{ secrets.VERCEL_TOKEN }}
continue-on-error: true
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Deploy to Vercel Preview
run: |
vercel --yes --token ${{ secrets.VERCEL_TOKEN }} \
--scope ${{ secrets.VERCEL_ORG_ID }}
# Production deployment for main branch
production:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
export PATH="$HOME/.cargo/bin:$PATH"
uv --version
- name: Install dependencies
run: npm ci
- name: Sync Python dependencies
run: |
uv sync
env:
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SUPABASE_ANON_KEY: ${{ env.VITE_SUPABASE_ANON_KEY }}
SUPABASE_URL: ${{ env.VITE_SUPABASE_URL }}
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Setup Supabase CLI
uses: supabase/setup-cli@v1
with:
version: latest
- name: Create Supabase config for CI
run: |
echo "Creating Supabase config for CI environment..."
cat > supabase/config.toml << EOF
project_id = "ohzbghitbjryfpmucgju"
[edge_runtime]
enabled = true
[edge_runtime.secrets]
DEFAULT_AGENT_MODEL = "$DEFAULT_AGENT_MODEL"
OPENAI_API_KEY = "$OPENAI_API_KEY"
OLLAMA_API_KEY = "$OLLAMA_API_KEY"
HF_TOKEN = "$HF_TOKEN"
[auth]
enabled = true
site_url = "http://localhost:8080"
additional_redirect_urls = ["http://localhost:8080", "http://127.0.0.1:8080", "http://localhost:5173", "http://127.0.0.1:5173", "http://127.0.0.1:3000", "https://127.0.0.1:3000"]
jwt_expiry = 3600
enable_refresh_token_rotation = true
refresh_token_reuse_interval = 10
enable_signup = true
enable_anonymous_sign_ins = true
[functions.agents]
enabled = true
verify_jwt = true
import_map = "./functions/agents/deno.json"
entrypoint = "./functions/agents/index.ts"
[functions.openai-polyfill]
enabled = true
verify_jwt = true
import_map = "./functions/openai-polyfill/deno.json"
entrypoint = "./functions/openai-polyfill/index.ts"
EOF
- name: Start Supabase local development
run: |
echo "Starting Supabase local development environment..."
supabase start
env:
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
- name: Wait for Supabase to be ready
run: |
echo "Waiting for Supabase services to be ready..."
# Give Supabase time to start up
sleep 30
# Check if Supabase is responding
for i in {1..20}; do
if curl -f http://127.0.0.1:54321/rest/v1/ > /dev/null 2>&1; then
echo "Supabase is ready!"
break
fi
echo "Attempt $i/20: Waiting for Supabase..."
sleep 5
done
# Final check
if ! curl -f http://127.0.0.1:54321/rest/v1/ > /dev/null 2>&1; then
echo "Supabase failed to start properly"
exit 1
fi
- name: Start Python backend server
run: |
# Start Python backend in background and save PID for cleanup
OLLAMA_API_KEY="$OLLAMA_API_KEY" \
OPENAI_API_KEY="$OPENAI_API_KEY" \
SUPABASE_ANON_KEY="$SUPABASE_ANON_KEY" \
SUPABASE_URL="$SUPABASE_URL" \
npm run dev:api &
PYTHON_API_PID=$!
echo "PYTHON_API_PID=$PYTHON_API_PID" >> $GITHUB_ENV
# Wait for the Python backend to be ready
for i in {1..30}; do
if curl -f http://127.0.0.1:8000/health > /dev/null 2>&1 || curl -f http://127.0.0.1:8000/docs > /dev/null 2>&1; then
echo "Python backend server is ready!"
break
fi
echo "Attempt $i/30: Waiting for Python backend server..."
sleep 2
done
# Final check
if ! curl -f http://127.0.0.1:8000/docs > /dev/null 2>&1; then
echo "Python backend server failed to start properly"
kill $PYTHON_API_PID 2>/dev/null || true
exit 1
fi
env:
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SUPABASE_ANON_KEY: ${{ env.VITE_SUPABASE_ANON_KEY }}
SUPABASE_URL: ${{ env.VITE_SUPABASE_URL }}
- name: Start frontend development server
run: |
# Start server in background and save PID for cleanup
npm run dev &
SERVER_PID=$!
echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
# Wait for the server to be ready
for i in {1..30}; do
if curl -f http://localhost:8080 > /dev/null 2>&1; then
echo "Frontend server is ready!"
break
fi
echo "Attempt $i/30: Waiting for frontend server..."
sleep 2
done
# Final check
if ! curl -f http://localhost:8080 > /dev/null 2>&1; then
echo "Frontend server failed to start properly"
kill $SERVER_PID 2>/dev/null || true
exit 1
fi
- name: Run E2E tests (headed)
run: |
xvfb-run --auto-servernum --server-args='-screen 0 1280x960x24 -ac' \
npm run test
- name: Stop frontend development server
if: always()
run: |
if [ ! -z "$SERVER_PID" ]; then
echo "Stopping frontend development server (PID: $SERVER_PID)..."
kill $SERVER_PID 2>/dev/null || true
fi
- name: Stop Python backend server
if: always()
run: |
if [ ! -z "$PYTHON_API_PID" ]; then
echo "Stopping Python backend server (PID: $PYTHON_API_PID)..."
kill $PYTHON_API_PID 2>/dev/null || true
fi
- name: Stop Supabase local development
if: always()
run: |
echo "Stopping Supabase local development environment..."
supabase stop || true
- name: Run linting
run: npm run lint
- name: Link to Supabase project
run: supabase link --project-ref $PROJECT_ID
- name: Check migration status
run: |
echo "Checking current migration status..."
supabase migration list
- name: Run database migrations
run: |
echo "Applying migrations to production..."
supabase db push --linked --yes --include-all
- name: Verify migrations were applied
run: |
echo "Final migration status:"
supabase migration list
- name: Deploy Supabase functions
run: supabase functions deploy --project-ref $PROJECT_ID --yes
- name: Build application (test build)
run: npm run build
# Note: This build uses localhost values for CI testing
# Vercel will rebuild with production values during deployment
- name: Install Vercel CLI
run: npm install -g vercel
- name: Link Vercel Project
run: |
vercel link --yes --token ${{ secrets.VERCEL_TOKEN }} \
--scope ${{ secrets.VERCEL_ORG_ID }} \
--project ${{ secrets.VERCEL_PROJECT_ID }}
continue-on-error: true
- name: Set Vercel Environment Variables (Production)
run: |
# Set environment variables for production deployments
# Remove existing variables first (ignore errors if they don't exist), then add new ones
vercel env rm VITE_SUPABASE_URL production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm VITE_SUPABASE_ANON_KEY production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm VITE_PYTHON_BACKEND_URL production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm DEFAULT_AGENT_MODEL production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm OPENAI_API_KEY production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm OLLAMA_API_KEY production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
vercel env rm HF_TOKEN production --token ${{ secrets.VERCEL_TOKEN }} --yes 2>/dev/null || true
# Add environment variables
echo "${{ secrets.VITE_SUPABASE_URL }}" | vercel env add VITE_SUPABASE_URL production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.VITE_SUPABASE_ANON_KEY }}" | vercel env add VITE_SUPABASE_ANON_KEY production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.VITE_PYTHON_BACKEND_URL }}" | vercel env add VITE_PYTHON_BACKEND_URL production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.DEFAULT_AGENT_MODEL }}" | vercel env add DEFAULT_AGENT_MODEL production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.OPENAI_API_KEY }}" | vercel env add OPENAI_API_KEY production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.OLLAMA_API_KEY }}" | vercel env add OLLAMA_API_KEY production --token ${{ secrets.VERCEL_TOKEN }}
echo "${{ secrets.HF_TOKEN }}" | vercel env add HF_TOKEN production --token ${{ secrets.VERCEL_TOKEN }}
continue-on-error: true
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
- name: Deploy to Vercel Production
run: |
vercel --yes --token ${{ secrets.VERCEL_TOKEN }} \
--scope ${{ secrets.VERCEL_ORG_ID }} \
--prod
# Cleanup preview branches when PR is closed
cleanup:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Setup Supabase CLI
uses: supabase/setup-cli@v1
with:
version: latest
- name: Link to Supabase project
run: supabase link --project-ref $PROJECT_ID
- name: Delete Supabase preview branch
run: |
echo "Deleting Supabase preview branch for PR #${{ github.event.number }}"
supabase branches delete pr-${{ github.event.number }} --yes
continue-on-error: true