diff --git a/.gitignore b/.gitignore index 828fbf0..6d3df95 100644 --- a/.gitignore +++ b/.gitignore @@ -35,5 +35,7 @@ env/ .env scripts/deploy.sh deploy.sh +scripts/deploy.ps1 +deploy.ps1 .pytest_cache/ diff --git a/README.md b/README.md index 1048823..269c721 100644 --- a/README.md +++ b/README.md @@ -63,19 +63,26 @@ cd immersive-language-learning-with-live-api ### 2. Quick Install -Run the installation script to set up both backend (Python venv) and frontend (Node modules) dependencies: +Run the installation script to set up both backend (Python) and frontend (Node modules) dependencies: +**Linux / macOS:** ```bash ./scripts/install.sh ``` +**Windows (PowerShell):** +```powershell +.\scripts\install.ps1 +``` +If scripts are blocked by execution policy, run once: `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` + ### 3. Environment Config Create a `.env` file in the root directory: -```bash -cp .env.example .env -``` +**Linux / macOS:** `cp .env.example .env` + +**Windows (PowerShell):** `Copy-Item .env.example .env` Update `.env` with your Google Cloud details if necessary. @@ -85,10 +92,17 @@ Update `.env` with your Google Cloud details if necessary. Start both the backend server and frontend development server with a single command: +**Linux / macOS:** ```bash ./scripts/dev.sh ``` +**Windows (PowerShell):** +```powershell +.\scripts\dev.ps1 +``` +(Backend on port 8000, frontend on port 5173. Press Ctrl+C to stop both.) + This will: - Start the Python backend on port 8000. @@ -118,19 +132,13 @@ The fastest way to get Immergo running in production is using Google Cloud Run: [![Run on Google Cloud](https://deploy.cloud.run/button.svg)](https://deploy.cloud.run/?utm_source=github&utm_medium=unpaidsoc&utm_campaign=FY-Q1-global-cloud-ai-starter-apps&utm_content=immergo-app&utm_term=-) 2. **Follow the prompts** in the Google Cloud Shell to authorize and deploy. -### 🛠 Manual Deployment (via `deploy.sh`) - -If you prefer to deploy from your terminal, first create your own deployment script from the example: +### 🛠 Manual Deployment (via deploy script) -```bash -cp scripts/example.deploy.sh scripts/deploy.sh -``` +If you prefer to deploy from your terminal, first create your own deployment script from the example, edit it with your project details, then run it. -Edit `scripts/deploy.sh` with your project details, then run: +**Linux / macOS:** `cp scripts/example.deploy.sh scripts/deploy.sh` then edit `scripts/deploy.sh` and run `./scripts/deploy.sh` -```bash -./scripts/deploy.sh -``` +**Windows (PowerShell):** `Copy-Item scripts\example.deploy.ps1 scripts\deploy.ps1` then edit `scripts\deploy.ps1` and run `.\scripts\deploy.ps1` ### Advanced Configuration diff --git a/scripts/dev.ps1 b/scripts/dev.ps1 new file mode 100644 index 0000000..ec0a0ab --- /dev/null +++ b/scripts/dev.ps1 @@ -0,0 +1,61 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Set-Location (Join-Path (Split-Path -Parent $PSScriptRoot) "") +$env:DEV_MODE = "true" + +if (-not (Test-Path ".env")) { + if (Test-Path ".env.example") { + Write-Host "Warning: .env file not found. Copying from .env.example..." -ForegroundColor Yellow + Copy-Item ".env.example" ".env" + Write-Host "Please update .env with your configuration." + } else { + Write-Host "Warning: .env file not found and no .env.example exists." -ForegroundColor Yellow + } +} + +if (Test-Path "venv\Scripts\python.exe") { + $pythonExe = (Resolve-Path "venv\Scripts\python.exe").Path +} elseif (Get-Command python -ErrorAction SilentlyContinue) { + $pythonExe = "python" +} elseif (Get-Command py -ErrorAction SilentlyContinue) { + $pythonExe = (Get-Command py).Source +} else { + Write-Error "Python not found. Install Python 3.10+ or run .\scripts\install.ps1 first." +} + +# Resolve py to actual python for backend process (Start-Process needs executable path or command name) +$backendArgList = @("-m", "uvicorn", "server.main:app", "--host", "127.0.0.1", "--port", "8000", "--reload") +if ($pythonExe -match "py(\.exe)?$") { + $backendArgList = @("-3") + $backendArgList +} + +Write-Host "Starting development environment..." -ForegroundColor Cyan +Write-Host "Starting Backend (Uvicorn) on port 8000..." -ForegroundColor Cyan +$backendProcess = $null +try { + if ($pythonExe -match "py(\.exe)?$") { + $backendProcess = Start-Process -FilePath "py" -ArgumentList $backendArgList -NoNewWindow -PassThru + } else { + $backendProcess = Start-Process -FilePath $pythonExe -ArgumentList $backendArgList -NoNewWindow -PassThru + } + Start-Sleep -Seconds 2 + Write-Host "Starting Frontend (Vite)..." -ForegroundColor Cyan + npm run dev +} finally { + if ($backendProcess -and -not $backendProcess.HasExited) { + Write-Host "Stopping backend..." -ForegroundColor Yellow + Stop-Process -Id $backendProcess.Id -Force -ErrorAction SilentlyContinue + } +} diff --git a/scripts/example.deploy.ps1 b/scripts/example.deploy.ps1 new file mode 100644 index 0000000..3f005b4 --- /dev/null +++ b/scripts/example.deploy.ps1 @@ -0,0 +1,69 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Set-Location (Join-Path (Split-Path -Parent $PSScriptRoot) "") +$ErrorActionPreference = "Stop" + +# Configuration - replace these values with your own project configuration +$PROJECT_ID = "your-project-id" +$SERVICE_NAME = "immersive-language-learning" +$REGION = "us-central1" +$MODEL = "gemini-live-2.5-flash-native-audio" +$RECAPTCHA_SITE_KEY = "your-recaptcha-site-key" +$REDIS_URL = "redis://10.0.0.3:6379/0" +$SESSION_TIME_LIMIT = "180" +$GLOBAL_RATE_LIMIT = "100 per 5 minutes" +$PER_USER_RATE_LIMIT = "2 per minute" +$DATASET_ID = "your-dataset-id" +$TABLE_ID = "your-table-id" +$DEMO_NAME = "immersive-language-learning" +$DEV_MODE = "false" + +Write-Host "Building frontend..." -ForegroundColor Cyan +npm run build + +Write-Host "Deploying $SERVICE_NAME to Cloud Run..." -ForegroundColor Cyan +# NOTE: Ensure you have authenticated with gcloud: +# gcloud auth login +# gcloud config set project $PROJECT_ID + +$envVarPairs = @( + "PROJECT_ID=$PROJECT_ID", + "LOCATION=$REGION", + "MODEL=$MODEL", + "SESSION_TIME_LIMIT=$SESSION_TIME_LIMIT", + "APP_NAME=$SERVICE_NAME", + "GLOBAL_RATE_LIMIT=$GLOBAL_RATE_LIMIT", + "PER_USER_RATE_LIMIT=$PER_USER_RATE_LIMIT", + "RECAPTCHA_SITE_KEY=$RECAPTCHA_SITE_KEY", + "REDIS_URL=$REDIS_URL", + "DEV_MODE=$DEV_MODE", + "DATASET_ID=$DATASET_ID", + "TABLE_ID=$TABLE_ID", + "DEMO_NAME=$DEMO_NAME" +) +$envVarsStr = ($envVarPairs -join ",").ToString() + +# Omit --allow-unauthenticated for secure-by-default (service requires auth). Add it to allow public access. +gcloud run deploy $SERVICE_NAME ` + --source . ` + --region $REGION ` + --project $PROJECT_ID ` + --network default ` + --subnet default ` + --session-affinity ` + --clear-base-image ` + "--set-env-vars=$envVarsStr" + +Write-Host "Deployment command finished." -ForegroundColor Green diff --git a/scripts/install.ps1 b/scripts/install.ps1 new file mode 100644 index 0000000..b64acb9 --- /dev/null +++ b/scripts/install.ps1 @@ -0,0 +1,36 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Set-Location (Join-Path (Split-Path -Parent $PSScriptRoot) "") +$ErrorActionPreference = "Stop" + +Write-Host "Installing frontend dependencies..." -ForegroundColor Cyan +npm install + +Write-Host "Installing backend dependencies..." -ForegroundColor Cyan +$pythonExe = $null +if (Test-Path "venv\Scripts\python.exe") { + $pythonExe = (Resolve-Path "venv\Scripts\python.exe").Path +} elseif (Get-Command python -ErrorAction SilentlyContinue) { + $pythonExe = "python" +} elseif (Get-Command py -ErrorAction SilentlyContinue) { + $pythonExe = "py" +} +if (-not $pythonExe) { + Write-Error "Python not found. Install Python 3.10+ and ensure 'python' or 'py' is in PATH." +} +$pipArgs = @("-m", "pip", "install", "-r", "requirements.txt") +if ($pythonExe -eq "py") { & py -3 $pipArgs } else { & $pythonExe $pipArgs } + +Write-Host "Installation complete! You can now run .\scripts\dev.ps1 to start the app." -ForegroundColor Green