1220 lines
29 KiB
Markdown
1220 lines
29 KiB
Markdown
# Deployment Guide - AI Study Assistant
|
|
|
|
> ⚠️ **ATUALIZADO**: Este documento foi corrigido para refletir a arquitetura REAL do projeto (Flutter + Firebase BaaS, sem backend Node.js).
|
|
>
|
|
> **O que mudou:**
|
|
> - ❌ Removido: Node.js dependencies, Cloud Functions, backend server setup
|
|
> - ✅ Atualizado: Flutter SDK ^3.11.5, Firebase BaaS only, Ollama LLM
|
|
|
|
## 🚀 DEPLOYMENT STRATEGY
|
|
|
|
---
|
|
|
|
## 📋 OVERVIEW
|
|
|
|
This guide covers the deployment process for the AI Study Assistant project. **Note:** This is a Flutter + Firebase BaaS (Backend-as-a-Service) architecture. There is no custom backend server - all business logic is in the Flutter app.
|
|
|
|
---
|
|
|
|
## 🏗️ DEPLOYMENT ARCHITECTURE
|
|
|
|
### Environment Structure:
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ DEVELOPMENT │
|
|
│ • Local development with Firebase emulators │
|
|
│ • Hot reload and fast iteration │
|
|
│ • Mock data and test environments │
|
|
│ • Feature branch testing │
|
|
└─────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ STAGING │
|
|
│ • Pre-production testing environment │
|
|
│ • Production-like Firebase project │
|
|
│ • Automated testing and validation │
|
|
│ • Performance and security testing │
|
|
└─────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ PRODUCTION │
|
|
│ • Live production environment │
|
|
│ • High availability and scalability │
|
|
│ • Real monitoring and alerting │
|
|
│ • User data and production services │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 ENVIRONMENT CONFIGURATION
|
|
|
|
### 1.1 Development Environment
|
|
|
|
#### Local Setup:
|
|
```bash
|
|
# Clone repository
|
|
git clone https://github.com/your-org/teachit.git
|
|
cd teachit
|
|
|
|
# Install Flutter dependencies
|
|
flutter pub get
|
|
|
|
# Note: No Node.js backend to install
|
|
# No Cloud Functions to set up
|
|
|
|
# Run Flutter app (Firebase services connect directly)
|
|
flutter run
|
|
```
|
|
|
|
#### Development Firebase Project:
|
|
- **Project ID**: `teachit-dev-12345`
|
|
- **Services**: Auth, Firestore, Storage, Analytics, Crashlytics
|
|
- **Security Rules**: Relaxed for development
|
|
- **Emulators**: Local Firestore, Auth, Storage (Functions not used)
|
|
|
|
#### Environment Variables:
|
|
```bash
|
|
# .env.development
|
|
FIREBASE_PROJECT_ID=teachit-dev-12345
|
|
FLUTTER_ENV=development
|
|
OLLAMA_BASE_URL=http://89.114.196.110:11434/api/chat
|
|
ENABLE_LOGGING=true
|
|
ENABLE_DEBUG=true
|
|
```
|
|
|
|
### 1.2 Staging Environment
|
|
|
|
#### Staging Firebase Project:
|
|
- **Project ID**: `teachit-staging-12345`
|
|
- **Services**: Production-like configuration
|
|
- **Security Rules**: Production rules
|
|
- **Testing**: Automated integration tests
|
|
|
|
#### Environment Variables:
|
|
```bash
|
|
# .env.staging
|
|
FIREBASE_PROJECT_ID=teachit-staging-12345
|
|
FLUTTER_ENV=staging
|
|
API_BASE_URL=https://teachit-staging.web.app
|
|
ENABLE_LOGGING=true
|
|
ENABLE_DEBUG=false
|
|
SENTRY_DSN=staging-sentry-dsn
|
|
```
|
|
|
|
### 1.3 Production Environment
|
|
|
|
#### Production Firebase Project:
|
|
- **Project ID**: `teachit-prod-12345`
|
|
- **Services**: Full production configuration
|
|
- **Security Rules**: Strict production rules
|
|
- **Monitoring**: Full monitoring and alerting
|
|
|
|
#### Environment Variables:
|
|
```bash
|
|
# .env.production
|
|
FIREBASE_PROJECT_ID=teachit-prod-12345
|
|
FLUTTER_ENV=production
|
|
API_BASE_URL=https://teachit.web.app
|
|
ENABLE_LOGGING=false
|
|
ENABLE_DEBUG=false
|
|
SENTRY_DSN=production-sentry-dsn
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 FLUTTER DEPLOYMENT
|
|
|
|
### 2.1 Web Deployment
|
|
|
|
#### Build Configuration:
|
|
```dart
|
|
// web/index.html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>AI Study Assistant</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="description" content="AI-powered educational assistant">
|
|
<link rel="icon" href="favicon.ico">
|
|
</head>
|
|
<body>
|
|
<script src="flutter.js" defer></script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
#### Build Commands:
|
|
```bash
|
|
# Build for web
|
|
flutter build web --release --web-renderer canvaskit --no-tree-shake-icons
|
|
|
|
# Build with custom configuration
|
|
flutter build web \
|
|
--release \
|
|
--dart-define=FLUTTER_WEB_USE_SKIA=true \
|
|
--dart-define=FLUTTER_WEB_CANVAS_KIT=true \
|
|
--no-tree-shake-icons \
|
|
--web-renderer canvaskit
|
|
```
|
|
|
|
#### Firebase Hosting Configuration:
|
|
```json
|
|
{
|
|
"hosting": {
|
|
"public": "build/web",
|
|
"ignore": [
|
|
"firebase.json",
|
|
"**/.*",
|
|
"**/node_modules/**"
|
|
],
|
|
"rewrites": [
|
|
{
|
|
"source": "**",
|
|
"destination": "/index.html"
|
|
}
|
|
],
|
|
"headers": [
|
|
{
|
|
"source": "**/*.@(js|css)",
|
|
"headers": [
|
|
{
|
|
"key": "Cache-Control",
|
|
"value": "max-age=31536000"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"source": "**",
|
|
"headers": [
|
|
{
|
|
"key": "X-Content-Type-Options",
|
|
"value": "nosniff"
|
|
},
|
|
{
|
|
"key": "X-Frame-Options",
|
|
"value": "DENY"
|
|
},
|
|
{
|
|
"key": "X-XSS-Protection",
|
|
"value": "1; mode=block"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Deployment Script:
|
|
```bash
|
|
#!/bin/bash
|
|
# deploy_web.sh
|
|
|
|
echo "Deploying Flutter Web App..."
|
|
|
|
# Build the app
|
|
echo "Building Flutter web app..."
|
|
flutter build web --release --no-tree-shake-icons
|
|
|
|
# Deploy to Firebase Hosting
|
|
echo "Deploying to Firebase Hosting..."
|
|
firebase deploy --only hosting:web
|
|
|
|
echo "Web deployment completed!"
|
|
```
|
|
|
|
### 2.2 Mobile Deployment
|
|
|
|
#### Android Deployment:
|
|
```bash
|
|
# Build APK
|
|
flutter build apk --release --dart-define=FLUTTER_ENV=production
|
|
|
|
# Build App Bundle (recommended for Play Store)
|
|
flutter build appbundle --release --dart-define=FLUTTER_ENV=production
|
|
|
|
# Deploy to Firebase App Distribution
|
|
firebase appdistribution:distribute \
|
|
--app 1:1234567890:android:abcdef \
|
|
--release-notes "Latest version with bug fixes" \
|
|
--testers "testers@company.com" \
|
|
build/app/outputs/flutter-release/app-release.apk
|
|
```
|
|
|
|
#### iOS Deployment:
|
|
```bash
|
|
# Build iOS app
|
|
flutter build ios --release --dart-define=FLUTTER_ENV=production
|
|
|
|
# Upload to TestFlight
|
|
cd ios
|
|
xcodebuild -workspace Runner.xcworkspace \
|
|
-scheme Runner \
|
|
-configuration Release \
|
|
-destination generic/platform=iOS \
|
|
-archivePath build/Runner.xcarchive \
|
|
archive
|
|
|
|
# Upload to App Store Connect
|
|
xcodebuild -exportArchive \
|
|
-archivePath build/Runner.xcarchive \
|
|
-exportPath build/ \
|
|
-exportOptionsPlist ExportOptions.plist
|
|
```
|
|
|
|
---
|
|
|
|
## ⚡ BACKEND DEPLOYMENT
|
|
|
|
### 3.1 Cloud Functions Deployment
|
|
|
|
#### Functions Configuration:
|
|
```typescript
|
|
// functions/src/config/environment.ts
|
|
export const config = {
|
|
environment: process.env.FIREBASE_CONFIG || 'development',
|
|
projectId: process.env.FIREBASE_PROJECT_ID,
|
|
|
|
// API Keys
|
|
openaiApiKey: process.env.OPENAI_API_KEY,
|
|
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
|
|
|
|
// Feature flags
|
|
enableAnalytics: process.env.ENABLE_ANALYTICS === 'true',
|
|
enableLogging: process.env.ENABLE_LOGGING === 'true',
|
|
|
|
// Rate limiting
|
|
rateLimits: {
|
|
apiCalls: parseInt(process.env.RATE_LIMIT_API_CALLS || '100'),
|
|
uploads: parseInt(process.env.RATE_LIMIT_UPLOADS || '10'),
|
|
llmCalls: parseInt(process.env.RATE_LIMIT_LLM_CALLS || '20'),
|
|
}
|
|
};
|
|
```
|
|
|
|
#### Deployment Commands:
|
|
```bash
|
|
# Deploy all functions
|
|
firebase deploy --only functions
|
|
|
|
# Deploy specific function
|
|
firebase deploy --only functions:askTutor
|
|
|
|
# Deploy with specific region
|
|
firebase deploy --only functions --region=us-central1
|
|
```
|
|
|
|
#### Environment Variables Setup:
|
|
```bash
|
|
# Set environment variables
|
|
firebase functions:config:set \
|
|
openai.api_key=your_openai_api_key \
|
|
anthropic.api_key=your_anthropic_api_key \
|
|
enable_analytics=true \
|
|
enable_logging=true \
|
|
rate_limit_api_calls=100
|
|
```
|
|
|
|
### 3.2 Database Deployment
|
|
|
|
#### Firestore Rules Deployment:
|
|
```bash
|
|
# Deploy security rules
|
|
firebase deploy --only firestore:rules
|
|
|
|
# Deploy indexes
|
|
firebase deploy --only firestore:indexes
|
|
```
|
|
|
|
#### Database Migration Script:
|
|
```typescript
|
|
// functions/scripts/migrate_database.ts
|
|
import * as admin from 'firebase-admin';
|
|
import { config } from '../src/config/environment';
|
|
|
|
export async function migrateDatabase() {
|
|
const db = admin.firestore();
|
|
|
|
// Create initial data structure
|
|
const schools = [
|
|
{
|
|
name: 'Demo School',
|
|
email: 'demo@teachit.app',
|
|
settings: {
|
|
curriculum: ['Mathematics', 'Science', 'English'],
|
|
language: 'en',
|
|
policies: {
|
|
allowExternalKnowledge: false,
|
|
fallbackMode: 'partial_with_hint',
|
|
minRetrievalConfidence: 0.6
|
|
}
|
|
},
|
|
subscription: {
|
|
plan: 'premium',
|
|
maxStudents: 1000,
|
|
maxTeachers: 50,
|
|
expiresAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000)
|
|
},
|
|
createdAt: new Date(),
|
|
isActive: true
|
|
}
|
|
];
|
|
|
|
// Create schools
|
|
for (const school of schools) {
|
|
await db.collection('schools').add(school);
|
|
console.log(`Created school: ${school.name}`);
|
|
}
|
|
|
|
console.log('Database migration completed');
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 CI/CD PIPELINE
|
|
|
|
### 4.1 GitHub Actions Configuration
|
|
|
|
#### Main Workflow:
|
|
```yaml
|
|
# .github/workflows/main.yml
|
|
name: Build and Deploy
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
env:
|
|
FLUTTER_VERSION: '3.41.0'
|
|
NODE_VERSION: '18'
|
|
|
|
jobs:
|
|
test:
|
|
name: Test
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v3
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v3
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Install Flutter dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Install Node dependencies
|
|
run: |
|
|
cd functions
|
|
npm install
|
|
|
|
- name: Run Flutter tests
|
|
run: flutter test --coverage
|
|
|
|
- name: Run Node tests
|
|
run: |
|
|
cd functions
|
|
npm test
|
|
|
|
- name: Upload coverage
|
|
uses: codecov/codecov-action@v3
|
|
with:
|
|
file: coverage/lcov.info
|
|
|
|
build-web:
|
|
name: Build Web
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v3
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Build web app
|
|
run: |
|
|
flutter build web --release --no-tree-shake-icons \
|
|
--dart-define=FLUTTER_ENV=production
|
|
|
|
- name: Deploy to staging
|
|
if: github.ref == 'refs/heads/develop'
|
|
run: |
|
|
firebase use teachit-staging-12345
|
|
firebase deploy --only hosting:staging
|
|
|
|
- name: Deploy to production
|
|
if: github.ref == 'refs/heads/main'
|
|
run: |
|
|
firebase use teachit-prod-12345
|
|
firebase deploy --only hosting:production
|
|
|
|
deploy-functions:
|
|
name: Deploy Functions
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v3
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v3
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
cd functions
|
|
npm install
|
|
|
|
- name: Deploy functions
|
|
run: |
|
|
firebase use teachit-prod-12345
|
|
firebase deploy --only functions
|
|
env:
|
|
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
|
|
deploy-mobile:
|
|
name: Deploy Mobile
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v3
|
|
|
|
- name: Setup Flutter
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: flutter pub get
|
|
|
|
- name: Build Android APK
|
|
run: |
|
|
flutter build apk --release \
|
|
--dart-define=FLUTTER_ENV=production
|
|
|
|
- name: Deploy to Firebase App Distribution
|
|
run: |
|
|
firebase appdistribution:distribute \
|
|
--app 1:1234567890:android:abcdef \
|
|
--release-notes "Latest version" \
|
|
--testers "testers@company.com" \
|
|
build/app/outputs/flutter-release/app-release.apk
|
|
env:
|
|
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
|
|
```
|
|
|
|
### 4.2 Branch Strategy
|
|
|
|
#### Git Flow:
|
|
```
|
|
main (production)
|
|
├── develop (staging)
|
|
├── feature/auth-enhancement
|
|
├── feature/rag-improvements
|
|
├── feature/ui-redesign
|
|
└── hotfix/critical-bug-fix
|
|
```
|
|
|
|
#### Deployment Rules:
|
|
- **main** → Production deployment
|
|
- **develop** → Staging deployment
|
|
- **feature/** → No deployment (testing only)
|
|
- **hotfix/** → Production deployment (urgent)
|
|
|
|
---
|
|
|
|
## 📊 MONITORING & LOGGING
|
|
|
|
### 5.1 Application Monitoring
|
|
|
|
#### Firebase Monitoring Setup:
|
|
```dart
|
|
// lib/core/services/monitoring_service.dart
|
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|
import 'package:firebase_performance/firebase_performance.dart';
|
|
|
|
class MonitoringService {
|
|
static Future<void> initialize() async {
|
|
// Analytics
|
|
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
|
|
|
|
// Crashlytics
|
|
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
|
|
|
// Performance
|
|
await FirebasePerformance.instance.setPerformanceCollectionEnabled(true);
|
|
}
|
|
|
|
static void logScreenView(String screenName) {
|
|
FirebaseAnalytics.instance.logScreenView(screenName: screenName);
|
|
}
|
|
|
|
static void logEvent(String name, {Map<String, Object>? parameters}) {
|
|
FirebaseAnalytics.instance.logEvent(name, parameters: parameters);
|
|
}
|
|
|
|
static void recordError(dynamic error, StackTrace? stackTrace) {
|
|
FirebaseCrashlytics.instance.recordError(error, stackTrace);
|
|
}
|
|
|
|
static void setUserIdentifier(String userId) {
|
|
FirebaseCrashlytics.instance.setUserIdentifier(userId);
|
|
}
|
|
|
|
static Trace startTrace(String traceName) {
|
|
return FirebasePerformance.instance.newTrace(traceName);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Custom Metrics:
|
|
```dart
|
|
// lib/core/services/metrics_service.dart
|
|
class MetricsService {
|
|
static void trackUserEngagement(String action, Map<String, dynamic> properties) {
|
|
MonitoringService.logEvent('user_engagement', parameters: {
|
|
'action': action,
|
|
...properties,
|
|
});
|
|
}
|
|
|
|
static void trackLearningProgress(String conceptId, double mastery) {
|
|
MonitoringService.logEvent('learning_progress', parameters: {
|
|
'concept_id': conceptId,
|
|
'mastery': mastery,
|
|
});
|
|
}
|
|
|
|
static void trackQuizPerformance(String quizId, double score, int timeSpent) {
|
|
MonitoringService.logEvent('quiz_performance', parameters: {
|
|
'quiz_id': quizId,
|
|
'score': score,
|
|
'time_spent': timeSpent,
|
|
});
|
|
}
|
|
|
|
static void trackAPIPerformance(String endpoint, int responseTime, bool success) {
|
|
MonitoringService.logEvent('api_performance', parameters: {
|
|
'endpoint': endpoint,
|
|
'response_time': responseTime,
|
|
'success': success,
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5.2 Backend Monitoring
|
|
|
|
#### Cloud Functions Monitoring:
|
|
```typescript
|
|
// functions/src/monitoring/middleware.ts
|
|
import * as functions from 'firebase-functions';
|
|
import * as admin from 'firebase-admin';
|
|
import { logger } from '../utils/logger';
|
|
|
|
export const monitoringMiddleware = functions.https.onRequest(async (req, res, next) => {
|
|
const startTime = Date.now();
|
|
const requestId = req.headers['x-request-id'] || generateRequestId();
|
|
|
|
// Add request ID to response headers
|
|
res.setHeader('x-request-id', requestId);
|
|
|
|
// Log request
|
|
logger.info('Request started', {
|
|
requestId,
|
|
method: req.method,
|
|
path: req.path,
|
|
userAgent: req.headers['user-agent'],
|
|
ip: req.ip,
|
|
});
|
|
|
|
try {
|
|
await next(req, res);
|
|
|
|
const responseTime = Date.now() - startTime;
|
|
|
|
// Log successful response
|
|
logger.info('Request completed', {
|
|
requestId,
|
|
statusCode: res.statusCode,
|
|
responseTime,
|
|
});
|
|
|
|
// Track performance
|
|
trackPerformance(req.path, responseTime, res.statusCode);
|
|
|
|
} catch (error) {
|
|
const responseTime = Date.now() - startTime;
|
|
|
|
// Log error
|
|
logger.error('Request failed', {
|
|
requestId,
|
|
error: error.message,
|
|
responseTime,
|
|
});
|
|
|
|
// Track error
|
|
trackError(req.path, error, responseTime);
|
|
|
|
res.status(500).json({
|
|
error: 'Internal server error',
|
|
requestId,
|
|
});
|
|
}
|
|
});
|
|
|
|
function generateRequestId(): string {
|
|
return Math.random().toString(36).substring(2, 15);
|
|
}
|
|
|
|
function trackPerformance(endpoint: string, responseTime: number, statusCode: number) {
|
|
// Send to monitoring service
|
|
admin.firestore().collection('performance').add({
|
|
endpoint,
|
|
responseTime,
|
|
statusCode,
|
|
timestamp: new Date(),
|
|
});
|
|
}
|
|
|
|
function trackError(endpoint: string, error: any, responseTime: number) {
|
|
// Send to error tracking
|
|
admin.firestore().collection('errors').add({
|
|
endpoint,
|
|
error: error.message,
|
|
stack: error.stack,
|
|
responseTime,
|
|
timestamp: new Date(),
|
|
});
|
|
}
|
|
```
|
|
|
|
### 5.3 Alerting Configuration
|
|
|
|
#### Alert Rules:
|
|
```yaml
|
|
# monitoring/alerts.yml
|
|
alerts:
|
|
- name: High Error Rate
|
|
condition: error_rate > 5%
|
|
duration: 5m
|
|
channels: [slack, email]
|
|
message: "Error rate is {{ error_rate }}% for the last 5 minutes"
|
|
|
|
- name: Slow Response Time
|
|
condition: avg_response_time > 3s
|
|
duration: 10m
|
|
channels: [slack]
|
|
message: "Average response time is {{ avg_response_time }}s"
|
|
|
|
- name: High Memory Usage
|
|
condition: memory_usage > 80%
|
|
duration: 15m
|
|
channels: [email]
|
|
message: "Memory usage is {{ memory_usage }}%"
|
|
|
|
- name: Database Connection Failed
|
|
condition: database_connection_failed
|
|
channels: [slack, email, sms]
|
|
message: "Database connection failed"
|
|
|
|
- name: LLM API Rate Limit
|
|
condition: llm_api_rate_limit_exceeded
|
|
channels: [slack]
|
|
message: "LLM API rate limit exceeded"
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 SECURITY DEPLOYMENT
|
|
|
|
### 6.1 Security Configuration
|
|
|
|
#### Environment Security:
|
|
```bash
|
|
# Secure environment variables
|
|
firebase functions:config:set \
|
|
openai.api_key=$OPENAI_API_KEY \
|
|
anthropic.api_key=$ANTHROPIC_API_KEY \
|
|
jwt_secret=$JWT_SECRET \
|
|
encryption_key=$ENCRYPTION_KEY
|
|
```
|
|
|
|
#### API Security:
|
|
```typescript
|
|
// functions/src/security/api_security.ts
|
|
import rateLimit from 'express-rate-limit';
|
|
import helmet from 'helmet';
|
|
import cors from 'cors';
|
|
|
|
export const securityMiddleware = [
|
|
helmet({
|
|
contentSecurityPolicy: {
|
|
directives: {
|
|
defaultSrc: ["'self'"],
|
|
scriptSrc: ["'self'", "'unsafe-inline'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
imgSrc: ["'self'", "data:", "https:"],
|
|
},
|
|
},
|
|
}),
|
|
cors({
|
|
origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
|
|
credentials: true,
|
|
}),
|
|
rateLimit({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 100, // limit each IP to 100 requests per windowMs
|
|
message: 'Too many requests from this IP',
|
|
}),
|
|
];
|
|
```
|
|
|
|
### 6.2 SSL/TLS Configuration
|
|
|
|
#### Firebase Hosting SSL:
|
|
```json
|
|
{
|
|
"hosting": {
|
|
"headers": [
|
|
{
|
|
"source": "**/*.@(js|css|png|jpg|jpeg|gif|svg)",
|
|
"headers": [
|
|
{
|
|
"key": "Strict-Transport-Security",
|
|
"value": "max-age=31536000; includeSubDomains"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 ROLLBACK PROCEDURES
|
|
|
|
### 7.1 Automated Rollback
|
|
|
|
#### Rollback Script:
|
|
```bash
|
|
#!/bin/bash
|
|
# rollback.sh
|
|
|
|
echo "Starting rollback procedure..."
|
|
|
|
# Get current version
|
|
CURRENT_VERSION=$(git rev-parse HEAD)
|
|
echo "Current version: $CURRENT_VERSION"
|
|
|
|
# Rollback to previous version
|
|
git checkout HEAD~1
|
|
|
|
# Deploy previous version
|
|
firebase deploy --only hosting,functions
|
|
|
|
# Verify deployment
|
|
if curl -f https://teachit.web.app/health; then
|
|
echo "Rollback successful"
|
|
else
|
|
echo "Rollback failed, manual intervention required"
|
|
exit 1
|
|
fi
|
|
|
|
# Notify team
|
|
curl -X POST "https://hooks.slack.com/your-webhook" \
|
|
-H 'Content-type: application/json' \
|
|
-d "{\"text\":\"Rollback to $CURRENT_VERSION completed\"}"
|
|
```
|
|
|
|
### 7.2 Manual Rollback
|
|
|
|
#### Manual Rollback Steps:
|
|
1. **Identify Problem Version**
|
|
```bash
|
|
git log --oneline -10
|
|
```
|
|
|
|
2. **Rollback Code**
|
|
```bash
|
|
git checkout <previous-stable-commit>
|
|
```
|
|
|
|
3. **Redeploy**
|
|
```bash
|
|
firebase deploy --only hosting,functions
|
|
```
|
|
|
|
4. **Verify**
|
|
```bash
|
|
curl -f https://teachit.web.app/health
|
|
```
|
|
|
|
5. **Communicate**
|
|
- Notify team of rollback
|
|
- Update status page
|
|
- Monitor for issues
|
|
|
|
---
|
|
|
|
## 📈 PERFORMANCE OPTIMIZATION
|
|
|
|
### 8.1 Web Performance
|
|
|
|
#### Build Optimization:
|
|
```bash
|
|
# Optimized web build
|
|
flutter build web --release \
|
|
--dart-define=FLUTTER_WEB_USE_SKIA=true \
|
|
--dart-define=FLUTTER_WEB_CANVAS_KIT=true \
|
|
--no-tree-shake-icons \
|
|
--web-renderer canvaskit \
|
|
--csp
|
|
```
|
|
|
|
#### Performance Monitoring:
|
|
```javascript
|
|
// web/js/performance.js
|
|
// Performance monitoring
|
|
const observer = new PerformanceObserver((list) => {
|
|
for (const entry of list.getEntries()) {
|
|
if (entry.entryType === 'navigation') {
|
|
console.log('Page load time:', entry.loadEventEnd - entry.loadEventStart);
|
|
}
|
|
}
|
|
});
|
|
|
|
observer.observe({ entryTypes: ['navigation', 'resource', 'paint'] });
|
|
```
|
|
|
|
### 8.2 Mobile Performance
|
|
|
|
#### Build Optimization:
|
|
```bash
|
|
# Optimized APK build
|
|
flutter build apk --release \
|
|
--shrink \
|
|
--obfuscate \
|
|
--dart-define=FLUTTER_ENV=production
|
|
```
|
|
|
|
#### Performance Profiling:
|
|
```dart
|
|
// lib/core/utils/performance_profiler.dart
|
|
class PerformanceProfiler {
|
|
static void profileWidget(String name, Widget Function() widgetBuilder) {
|
|
return ProfiledWidget(
|
|
name: name,
|
|
child: widgetBuilder(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class ProfiledWidget extends StatelessWidget {
|
|
final String name;
|
|
final Widget child;
|
|
|
|
const ProfiledWidget({required this.name, required this.child});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return PerformanceOverlay.all(
|
|
enabled: kDebugMode,
|
|
child: child,
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 DEPLOYMENT AUTOMATION
|
|
|
|
### 9.1 Deployment Scripts
|
|
|
|
#### Master Deployment Script:
|
|
```bash
|
|
#!/bin/bash
|
|
# deploy.sh
|
|
|
|
set -e
|
|
|
|
ENVIRONMENT=${1:-staging}
|
|
VERSION=${2:-latest}
|
|
|
|
echo "Deploying to $ENVIRONMENT environment..."
|
|
|
|
# Validate environment
|
|
if [[ "$ENVIRONMENT" != "staging" && "$ENVIRONMENT" != "production" ]]; then
|
|
echo "Invalid environment: $ENVIRONMENT"
|
|
exit 1
|
|
fi
|
|
|
|
# Set Firebase project
|
|
if [[ "$ENVIRONMENT" == "staging" ]]; then
|
|
firebase use teachit-staging-12345
|
|
else
|
|
firebase use teachit-prod-12345
|
|
fi
|
|
|
|
# Run tests
|
|
echo "Running tests..."
|
|
flutter test
|
|
cd functions && npm test
|
|
|
|
# Build Flutter web app
|
|
echo "Building Flutter web app..."
|
|
flutter build web --release --dart-define=FLUTTER_ENV=$ENVIRONMENT
|
|
|
|
# Deploy Firebase functions
|
|
echo "Deploying Firebase functions..."
|
|
firebase deploy --only functions
|
|
|
|
# Deploy web hosting
|
|
echo "Deploying web hosting..."
|
|
firebase deploy --only hosting
|
|
|
|
# Run smoke tests
|
|
echo "Running smoke tests..."
|
|
npm run smoke:test
|
|
|
|
# Notify team
|
|
curl -X POST "https://hooks.slack.com/your-webhook" \
|
|
-H 'Content-type: application/json' \
|
|
-d "{\"text\":\"Deployment to $ENVIRONMENT completed successfully\"}"
|
|
|
|
echo "Deployment to $ENVIRONMENT completed successfully!"
|
|
```
|
|
|
|
### 9.2 Health Check Script
|
|
|
|
#### Health Check Implementation:
|
|
```typescript
|
|
// functions/src/health/health_check.ts
|
|
export const healthCheck = functions.https.onRequest(async (req, res) => {
|
|
const health = {
|
|
status: 'healthy',
|
|
timestamp: new Date().toISOString(),
|
|
version: process.env.VERSION || 'unknown',
|
|
environment: process.env.FIREBASE_CONFIG || 'unknown',
|
|
services: {},
|
|
};
|
|
|
|
try {
|
|
// Check Firestore
|
|
const firestore = admin.firestore();
|
|
await firestore.collection('health').doc('check').get();
|
|
health.services.firestore = 'healthy';
|
|
} catch (error) {
|
|
health.services.firestore = 'unhealthy';
|
|
health.status = 'degraded';
|
|
}
|
|
|
|
try {
|
|
// Check Storage
|
|
const storage = admin.storage();
|
|
const bucket = storage.bucket();
|
|
await bucket.exists();
|
|
health.services.storage = 'healthy';
|
|
} catch (error) {
|
|
health.services.storage = 'unhealthy';
|
|
health.status = 'degraded';
|
|
}
|
|
|
|
// Check external services
|
|
if (process.env.OPENAI_API_KEY) {
|
|
try {
|
|
// Test OpenAI API
|
|
const response = await fetch('https://api.openai.com/v1/models', {
|
|
headers: {
|
|
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
|
|
},
|
|
});
|
|
|
|
if (response.ok) {
|
|
health.services.openai = 'healthy';
|
|
} else {
|
|
health.services.openai = 'unhealthy';
|
|
health.status = 'degraded';
|
|
}
|
|
} catch (error) {
|
|
health.services.openai = 'unhealthy';
|
|
health.status = 'degraded';
|
|
}
|
|
}
|
|
|
|
const statusCode = health.status === 'healthy' ? 200 : 503;
|
|
res.status(statusCode).json(health);
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 DEPLOYMENT CHECKLIST
|
|
|
|
### Pre-Deployment Checklist:
|
|
- [ ] All tests passing (unit, integration, E2E)
|
|
- [ ] Code coverage > 80%
|
|
- [ ] Security scan completed
|
|
- [ ] Performance benchmarks met
|
|
- [ ] Documentation updated
|
|
- [ ] Environment variables configured
|
|
- [ ] Backup procedures verified
|
|
- [ ] Rollback plan prepared
|
|
- [ ] Monitoring configured
|
|
- [ ] Team notified
|
|
|
|
### Post-Deployment Checklist:
|
|
- [ ] Health checks passing
|
|
- [ ] Smoke tests passing
|
|
- [ ] Monitoring alerts configured
|
|
- [ ] User acceptance testing
|
|
- [ ] Performance metrics collected
|
|
- [ ] Error tracking active
|
|
- [ ] Documentation updated
|
|
- [ ] Team debrief completed
|
|
|
|
### Production Deployment Checklist:
|
|
- [ ] Staging deployment successful
|
|
- [ ] All tests passing in staging
|
|
- [ ] Performance benchmarks met
|
|
- [ ] Security audit completed
|
|
- [ ] Backup procedures verified
|
|
- [ ] Rollback plan tested
|
|
- [ ] Team approval received
|
|
- [ ] Deployment window scheduled
|
|
- [ ] User communication prepared
|
|
|
|
---
|
|
|
|
## 🔧 TROUBLESHOOTING
|
|
|
|
### Common Deployment Issues:
|
|
|
|
#### 1. Build Failures
|
|
```bash
|
|
# Clean build cache
|
|
flutter clean
|
|
flutter pub get
|
|
|
|
# Check Flutter version
|
|
flutter --version
|
|
|
|
# Check dependencies
|
|
flutter pub deps
|
|
```
|
|
|
|
#### 2. Firebase Deployment Failures
|
|
```bash
|
|
# Check Firebase configuration
|
|
firebase projects:list
|
|
firebase use <project-id>
|
|
|
|
# Check authentication
|
|
firebase login
|
|
|
|
# Check permissions
|
|
firebase projects:list
|
|
```
|
|
|
|
#### 3. Performance Issues
|
|
```bash
|
|
# Profile Flutter app
|
|
flutter run --profile
|
|
|
|
# Check bundle size
|
|
flutter build web --analyze-size
|
|
|
|
# Monitor memory usage
|
|
flutter run --profile --trace-startup
|
|
```
|
|
|
|
#### 4. Database Issues
|
|
```bash
|
|
# Check Firestore rules
|
|
firebase deploy --only firestore:rules
|
|
|
|
# Check indexes
|
|
firebase deploy --only firestore:indexes
|
|
|
|
# Monitor database usage
|
|
firebase firestore:databases:list
|
|
```
|
|
|
|
---
|
|
|
|
## 📚 MAINTENANCE PROCEDURES
|
|
|
|
### Regular Maintenance Tasks:
|
|
1. **Daily**: Monitor system health and performance
|
|
2. **Weekly**: Review error logs and performance metrics
|
|
3. **Monthly**: Update dependencies and security patches
|
|
4. **Quarterly**: Perform security audits and penetration testing
|
|
5. **Annually**: Review architecture and plan improvements
|
|
|
|
### Backup Procedures:
|
|
```bash
|
|
# Backup Firestore data
|
|
firebase firestore:export --output-path=backup/firestore
|
|
|
|
# Backup Firebase Storage
|
|
gsutil -m rsync -r gs://teachit-content.appspot.com/ backup/storage
|
|
|
|
# Backup functions configuration
|
|
firebase functions:metadata > backup/functions-metadata.json
|
|
```
|
|
|
|
---
|
|
|
|
## 📞 SUPPORT PROCEDURES
|
|
|
|
### Incident Response:
|
|
1. **Detection**: Monitor alerts and user reports
|
|
2. **Assessment**: Evaluate impact and severity
|
|
3. **Response**: Implement fix or workaround
|
|
4. **Communication**: Notify users and stakeholders
|
|
5. **Recovery**: Restore normal operations
|
|
6. **Post-mortem**: Analyze and document incident
|
|
|
|
### Escalation Matrix:
|
|
- **Level 1**: Development team (minor issues)
|
|
- **Level 2**: DevOps team (infrastructure issues)
|
|
- **Level 3**: Management team (major incidents)
|
|
- **Level 4**: Crisis team (critical incidents)
|
|
|
|
---
|
|
|
|
*Last Updated: 2026-05-06*
|
|
*Version: 1.0.0*
|
|
*DevOps Lead: Deployment Team*
|