claude-code-templates 1.14.13 → 1.14.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +7 -7
  2. package/package.json +1 -2
  3. package/src/health-check.js +310 -0
  4. package/src/index.js +1 -1
  5. package/templates/common/.claude/commands/git-workflow.md +0 -239
  6. package/templates/common/.claude/commands/project-setup.md +0 -316
  7. package/templates/common/.mcp.json +0 -41
  8. package/templates/common/CLAUDE.md +0 -109
  9. package/templates/common/README.md +0 -96
  10. package/templates/go/.mcp.json +0 -78
  11. package/templates/go/README.md +0 -25
  12. package/templates/javascript-typescript/.claude/commands/api-endpoint.md +0 -51
  13. package/templates/javascript-typescript/.claude/commands/debug.md +0 -52
  14. package/templates/javascript-typescript/.claude/commands/lint.md +0 -48
  15. package/templates/javascript-typescript/.claude/commands/npm-scripts.md +0 -48
  16. package/templates/javascript-typescript/.claude/commands/refactor.md +0 -55
  17. package/templates/javascript-typescript/.claude/commands/test.md +0 -61
  18. package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +0 -51
  19. package/templates/javascript-typescript/.claude/settings.json +0 -142
  20. package/templates/javascript-typescript/.mcp.json +0 -80
  21. package/templates/javascript-typescript/CLAUDE.md +0 -185
  22. package/templates/javascript-typescript/README.md +0 -259
  23. package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +0 -63
  24. package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +0 -62
  25. package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +0 -46
  26. package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +0 -56
  27. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +0 -61
  28. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +0 -57
  29. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +0 -102
  30. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +0 -29
  31. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +0 -44
  32. package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +0 -45
  33. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +0 -81
  34. package/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +0 -530
  35. package/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +0 -295
  36. package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +0 -46
  37. package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +0 -51
  38. package/templates/python/.claude/commands/lint.md +0 -111
  39. package/templates/python/.claude/commands/test.md +0 -73
  40. package/templates/python/.claude/settings.json +0 -153
  41. package/templates/python/.mcp.json +0 -78
  42. package/templates/python/CLAUDE.md +0 -276
  43. package/templates/python/examples/django-app/.claude/commands/admin.md +0 -264
  44. package/templates/python/examples/django-app/.claude/commands/django-model.md +0 -124
  45. package/templates/python/examples/django-app/.claude/commands/views.md +0 -222
  46. package/templates/python/examples/django-app/CLAUDE.md +0 -313
  47. package/templates/python/examples/fastapi-app/.claude/commands/api-endpoints.md +0 -513
  48. package/templates/python/examples/fastapi-app/.claude/commands/auth.md +0 -775
  49. package/templates/python/examples/fastapi-app/.claude/commands/database.md +0 -657
  50. package/templates/python/examples/fastapi-app/.claude/commands/deployment.md +0 -160
  51. package/templates/python/examples/fastapi-app/.claude/commands/testing.md +0 -927
  52. package/templates/python/examples/fastapi-app/CLAUDE.md +0 -229
  53. package/templates/python/examples/flask-app/.claude/commands/app-factory.md +0 -384
  54. package/templates/python/examples/flask-app/.claude/commands/blueprint.md +0 -243
  55. package/templates/python/examples/flask-app/.claude/commands/database.md +0 -410
  56. package/templates/python/examples/flask-app/.claude/commands/deployment.md +0 -620
  57. package/templates/python/examples/flask-app/.claude/commands/flask-route.md +0 -217
  58. package/templates/python/examples/flask-app/.claude/commands/testing.md +0 -559
  59. package/templates/python/examples/flask-app/CLAUDE.md +0 -391
  60. package/templates/ruby/.claude/commands/model.md +0 -360
  61. package/templates/ruby/.claude/commands/test.md +0 -480
  62. package/templates/ruby/.claude/settings.json +0 -146
  63. package/templates/ruby/.mcp.json +0 -83
  64. package/templates/ruby/CLAUDE.md +0 -284
  65. package/templates/ruby/examples/rails-app/.claude/commands/authentication.md +0 -490
  66. package/templates/ruby/examples/rails-app/CLAUDE.md +0 -376
  67. package/templates/rust/.mcp.json +0 -78
  68. package/templates/rust/README.md +0 -26
@@ -1,620 +0,0 @@
1
- # Flask Deployment Configuration
2
-
3
- Complete production deployment setup for Flask applications.
4
-
5
- ## Usage
6
-
7
- ```bash
8
- # Build Docker image
9
- docker build -t myapp .
10
-
11
- # Run with Docker Compose
12
- docker-compose up -d
13
-
14
- # Deploy to cloud
15
- gunicorn --bind 0.0.0.0:8000 app:app
16
- ```
17
-
18
- ## Production Configuration
19
-
20
- ```python
21
- # config.py
22
- import os
23
- from urllib.parse import quote_plus
24
-
25
- class ProductionConfig:
26
- """Production configuration."""
27
-
28
- # Security
29
- SECRET_KEY = os.environ.get('SECRET_KEY')
30
- DEBUG = False
31
- TESTING = False
32
-
33
- # Database
34
- SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
35
- f"postgresql://{os.environ.get('DB_USER')}:{quote_plus(os.environ.get('DB_PASSWORD'))}@" \
36
- f"{os.environ.get('DB_HOST')}:{os.environ.get('DB_PORT', '5432')}/{os.environ.get('DB_NAME')}"
37
- SQLALCHEMY_TRACK_MODIFICATIONS = False
38
- SQLALCHEMY_ENGINE_OPTIONS = {
39
- 'pool_size': 10,
40
- 'max_overflow': 20,
41
- 'pool_recycle': 3600,
42
- 'pool_pre_ping': True
43
- }
44
-
45
- # Security Headers
46
- SECURITY_HEADERS = {
47
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
48
- 'X-Content-Type-Options': 'nosniff',
49
- 'X-Frame-Options': 'DENY',
50
- 'X-XSS-Protection': '1; mode=block',
51
- 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
52
- }
53
-
54
- # Session
55
- SESSION_COOKIE_SECURE = True
56
- SESSION_COOKIE_HTTPONLY = True
57
- SESSION_COOKIE_SAMESITE = 'Lax'
58
- PERMANENT_SESSION_LIFETIME = 3600 # 1 hour
59
-
60
- # Cache
61
- CACHE_TYPE = 'redis'
62
- CACHE_REDIS_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379/0')
63
- CACHE_DEFAULT_TIMEOUT = 300
64
-
65
- # Rate Limiting
66
- RATELIMIT_STORAGE_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379/1')
67
- RATELIMIT_DEFAULT = '100/hour'
68
-
69
- # Logging
70
- LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')
71
- LOG_FILE = os.environ.get('LOG_FILE', '/var/log/app/app.log')
72
-
73
- # File Upload
74
- MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB
75
- UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', '/var/uploads')
76
-
77
- # Email
78
- MAIL_SERVER = os.environ.get('MAIL_SERVER')
79
- MAIL_PORT = int(os.environ.get('MAIL_PORT', 587))
80
- MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'true').lower() in ['true', 'on', '1']
81
- MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
82
- MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
83
- MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER')
84
- ```
85
-
86
- ## WSGI Configuration
87
-
88
- ```python
89
- # wsgi.py
90
- import os
91
- from app import create_app
92
-
93
- # Get environment
94
- config_name = os.environ.get('FLASK_ENV', 'production')
95
- app = create_app(config_name)
96
-
97
- if __name__ == "__main__":
98
- app.run()
99
- ```
100
-
101
- ## Gunicorn Configuration
102
-
103
- ```python
104
- # gunicorn.conf.py
105
- import multiprocessing
106
- import os
107
-
108
- # Server socket
109
- bind = f"0.0.0.0:{os.environ.get('PORT', 8000)}"
110
- backlog = 2048
111
-
112
- # Worker processes
113
- workers = multiprocessing.cpu_count() * 2 + 1
114
- worker_class = 'sync'
115
- worker_connections = 1000
116
- timeout = 30
117
- keepalive = 60
118
- max_requests = 1000
119
- max_requests_jitter = 100
120
-
121
- # Security
122
- limit_request_line = 4094
123
- limit_request_fields = 100
124
- limit_request_field_size = 8190
125
-
126
- # Logging
127
- accesslog = '-'
128
- errorlog = '-'
129
- loglevel = os.environ.get('LOG_LEVEL', 'info').lower()
130
- access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'
131
-
132
- # Process naming
133
- proc_name = 'flask_app'
134
-
135
- # Server mechanics
136
- daemon = False
137
- pidfile = '/tmp/gunicorn.pid'
138
- user = os.environ.get('USER', 'www-data')
139
- group = os.environ.get('GROUP', 'www-data')
140
- tmp_upload_dir = None
141
-
142
- # SSL
143
- keyfile = os.environ.get('SSL_KEYFILE')
144
- certfile = os.environ.get('SSL_CERTFILE')
145
- ```
146
-
147
- ## Docker Configuration
148
-
149
- ```dockerfile
150
- # Dockerfile
151
- FROM python:3.11-slim
152
-
153
- # Set environment variables
154
- ENV PYTHONDONTWRITEBYTECODE=1 \
155
- PYTHONUNBUFFERED=1 \
156
- PIP_NO_CACHE_DIR=1 \
157
- PIP_DISABLE_PIP_VERSION_CHECK=1
158
-
159
- # Install system dependencies
160
- RUN apt-get update && apt-get install -y \
161
- build-essential \
162
- libpq-dev \
163
- curl \
164
- && rm -rf /var/lib/apt/lists/*
165
-
166
- # Create app user
167
- RUN groupadd -r appuser && useradd -r -g appuser appuser
168
-
169
- # Set work directory
170
- WORKDIR /app
171
-
172
- # Install Python dependencies
173
- COPY requirements/production.txt ./requirements.txt
174
- RUN pip install --no-cache-dir -r requirements.txt
175
-
176
- # Copy application code
177
- COPY . .
178
-
179
- # Create necessary directories
180
- RUN mkdir -p /var/log/app /var/uploads && \
181
- chown -R appuser:appuser /app /var/log/app /var/uploads
182
-
183
- # Switch to non-root user
184
- USER appuser
185
-
186
- # Expose port
187
- EXPOSE 8000
188
-
189
- # Health check
190
- HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
191
- CMD curl -f http://localhost:8000/health || exit 1
192
-
193
- # Run application
194
- CMD ["gunicorn", "--config", "gunicorn.conf.py", "wsgi:app"]
195
- ```
196
-
197
- ## Docker Compose
198
-
199
- ```yaml
200
- # docker-compose.yml
201
- version: '3.8'
202
-
203
- services:
204
- web:
205
- build: .
206
- ports:
207
- - "8000:8000"
208
- environment:
209
- - FLASK_ENV=production
210
- - DATABASE_URL=postgresql://postgres:password@db:5432/myapp
211
- - REDIS_URL=redis://redis:6379/0
212
- - SECRET_KEY=${SECRET_KEY}
213
- depends_on:
214
- - db
215
- - redis
216
- volumes:
217
- - uploads:/var/uploads
218
- - logs:/var/log/app
219
- restart: unless-stopped
220
- healthcheck:
221
- test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
222
- interval: 30s
223
- timeout: 10s
224
- retries: 3
225
-
226
- db:
227
- image: postgres:15
228
- environment:
229
- - POSTGRES_DB=myapp
230
- - POSTGRES_USER=postgres
231
- - POSTGRES_PASSWORD=password
232
- volumes:
233
- - postgres_data:/var/lib/postgresql/data
234
- restart: unless-stopped
235
- healthcheck:
236
- test: ["CMD-SHELL", "pg_isready -U postgres"]
237
- interval: 30s
238
- timeout: 10s
239
- retries: 3
240
-
241
- redis:
242
- image: redis:7-alpine
243
- command: redis-server --appendonly yes
244
- volumes:
245
- - redis_data:/data
246
- restart: unless-stopped
247
- healthcheck:
248
- test: ["CMD", "redis-cli", "ping"]
249
- interval: 30s
250
- timeout: 10s
251
- retries: 3
252
-
253
- nginx:
254
- image: nginx:alpine
255
- ports:
256
- - "80:80"
257
- - "443:443"
258
- volumes:
259
- - ./nginx.conf:/etc/nginx/nginx.conf:ro
260
- - ./ssl:/etc/nginx/ssl:ro
261
- - uploads:/var/uploads:ro
262
- depends_on:
263
- - web
264
- restart: unless-stopped
265
-
266
- volumes:
267
- postgres_data:
268
- redis_data:
269
- uploads:
270
- logs:
271
- ```
272
-
273
- ## Nginx Configuration
274
-
275
- ```nginx
276
- # nginx.conf
277
- events {
278
- worker_connections 1024;
279
- }
280
-
281
- http {
282
- upstream app {
283
- server web:8000;
284
- }
285
-
286
- # Rate limiting
287
- limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
288
- limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
289
-
290
- # SSL configuration
291
- ssl_protocols TLSv1.2 TLSv1.3;
292
- ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
293
- ssl_prefer_server_ciphers off;
294
-
295
- # Security headers
296
- add_header X-Frame-Options DENY;
297
- add_header X-Content-Type-Options nosniff;
298
- add_header X-XSS-Protection "1; mode=block";
299
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
300
-
301
- server {
302
- listen 80;
303
- server_name example.com www.example.com;
304
- return 301 https://$server_name$request_uri;
305
- }
306
-
307
- server {
308
- listen 443 ssl http2;
309
- server_name example.com www.example.com;
310
-
311
- ssl_certificate /etc/nginx/ssl/cert.pem;
312
- ssl_certificate_key /etc/nginx/ssl/key.pem;
313
-
314
- # File upload size
315
- client_max_body_size 16M;
316
-
317
- # Static files
318
- location /static/ {
319
- alias /var/uploads/static/;
320
- expires 1y;
321
- add_header Cache-Control "public, immutable";
322
- }
323
-
324
- location /uploads/ {
325
- alias /var/uploads/;
326
- expires 1h;
327
- }
328
-
329
- # API rate limiting
330
- location /api/ {
331
- limit_req zone=api burst=20 nodelay;
332
- proxy_pass http://app;
333
- proxy_set_header Host $host;
334
- proxy_set_header X-Real-IP $remote_addr;
335
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
336
- proxy_set_header X-Forwarded-Proto $scheme;
337
- }
338
-
339
- # Login rate limiting
340
- location /auth/login {
341
- limit_req zone=login burst=5 nodelay;
342
- proxy_pass http://app;
343
- proxy_set_header Host $host;
344
- proxy_set_header X-Real-IP $remote_addr;
345
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
346
- proxy_set_header X-Forwarded-Proto $scheme;
347
- }
348
-
349
- # Main application
350
- location / {
351
- proxy_pass http://app;
352
- proxy_set_header Host $host;
353
- proxy_set_header X-Real-IP $remote_addr;
354
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
355
- proxy_set_header X-Forwarded-Proto $scheme;
356
-
357
- # Timeout settings
358
- proxy_connect_timeout 60s;
359
- proxy_send_timeout 60s;
360
- proxy_read_timeout 60s;
361
- }
362
- }
363
- }
364
- ```
365
-
366
- ## Environment Variables
367
-
368
- ```bash
369
- # .env.production
370
- # Application
371
- FLASK_ENV=production
372
- SECRET_KEY=your-super-secret-key-here
373
-
374
- # Database
375
- DATABASE_URL=postgresql://user:password@localhost:5432/myapp
376
- DB_HOST=localhost
377
- DB_PORT=5432
378
- DB_NAME=myapp
379
- DB_USER=user
380
- DB_PASSWORD=password
381
-
382
- # Redis
383
- REDIS_URL=redis://localhost:6379/0
384
-
385
- # Email
386
- MAIL_SERVER=smtp.gmail.com
387
- MAIL_PORT=587
388
- MAIL_USE_TLS=true
389
- MAIL_USERNAME=your-email@gmail.com
390
- MAIL_PASSWORD=your-app-password
391
- MAIL_DEFAULT_SENDER=your-email@gmail.com
392
-
393
- # Logging
394
- LOG_LEVEL=INFO
395
- LOG_FILE=/var/log/app/app.log
396
-
397
- # File Upload
398
- UPLOAD_FOLDER=/var/uploads
399
-
400
- # SSL (if using)
401
- SSL_KEYFILE=/path/to/private.key
402
- SSL_CERTFILE=/path/to/certificate.crt
403
- ```
404
-
405
- ## Health Check Endpoint
406
-
407
- ```python
408
- # app/health.py
409
- from flask import Blueprint, jsonify
410
- from app.extensions import db
411
- from sqlalchemy import text
412
- import redis
413
- import os
414
-
415
- health_bp = Blueprint('health', __name__)
416
-
417
- @health_bp.route('/health')
418
- def health_check():
419
- """Application health check."""
420
- checks = {
421
- 'status': 'healthy',
422
- 'database': check_database(),
423
- 'redis': check_redis(),
424
- 'disk_space': check_disk_space()
425
- }
426
-
427
- # Determine overall status
428
- if all(check['status'] == 'ok' for check in checks.values() if isinstance(check, dict)):
429
- status_code = 200
430
- else:
431
- status_code = 503
432
- checks['status'] = 'unhealthy'
433
-
434
- return jsonify(checks), status_code
435
-
436
- def check_database():
437
- """Check database connectivity."""
438
- try:
439
- db.session.execute(text('SELECT 1'))
440
- return {'status': 'ok', 'message': 'Database connection successful'}
441
- except Exception as e:
442
- return {'status': 'error', 'message': str(e)}
443
-
444
- def check_redis():
445
- """Check Redis connectivity."""
446
- try:
447
- redis_url = os.environ.get('REDIS_URL', 'redis://localhost:6379/0')
448
- r = redis.from_url(redis_url)
449
- r.ping()
450
- return {'status': 'ok', 'message': 'Redis connection successful'}
451
- except Exception as e:
452
- return {'status': 'error', 'message': str(e)}
453
-
454
- def check_disk_space():
455
- """Check available disk space."""
456
- try:
457
- import shutil
458
- total, used, free = shutil.disk_usage('/')
459
- free_percent = (free / total) * 100
460
-
461
- if free_percent > 10:
462
- status = 'ok'
463
- elif free_percent > 5:
464
- status = 'warning'
465
- else:
466
- status = 'critical'
467
-
468
- return {
469
- 'status': status,
470
- 'free_space_percent': round(free_percent, 2),
471
- 'free_space_gb': round(free / (1024**3), 2)
472
- }
473
- except Exception as e:
474
- return {'status': 'error', 'message': str(e)}
475
- ```
476
-
477
- ## Monitoring and Logging
478
-
479
- ```python
480
- # app/logging.py
481
- import logging
482
- import logging.handlers
483
- import os
484
- from flask import request, g
485
- import time
486
-
487
- def setup_logging(app):
488
- """Setup application logging."""
489
- if not app.debug and not app.testing:
490
- # File logging
491
- if app.config.get('LOG_FILE'):
492
- file_handler = logging.handlers.RotatingFileHandler(
493
- app.config['LOG_FILE'],
494
- maxBytes=10240000, # 10MB
495
- backupCount=10
496
- )
497
- file_handler.setFormatter(logging.Formatter(
498
- '%(asctime)s %(levelname)s: %(message)s '
499
- '[in %(pathname)s:%(lineno)d]'
500
- ))
501
- file_handler.setLevel(getattr(logging, app.config.get('LOG_LEVEL', 'INFO')))
502
- app.logger.addHandler(file_handler)
503
-
504
- # Console logging
505
- if not app.logger.handlers:
506
- stream_handler = logging.StreamHandler()
507
- stream_handler.setFormatter(logging.Formatter(
508
- '%(asctime)s %(levelname)s: %(message)s'
509
- ))
510
- stream_handler.setLevel(logging.INFO)
511
- app.logger.addHandler(stream_handler)
512
-
513
- app.logger.setLevel(logging.INFO)
514
- app.logger.info('Application startup')
515
-
516
- # Request timing middleware
517
- @app.before_request
518
- def before_request():
519
- g.start_time = time.time()
520
-
521
- @app.after_request
522
- def after_request(response):
523
- if hasattr(g, 'start_time'):
524
- duration = time.time() - g.start_time
525
- app.logger.info(
526
- f'{request.method} {request.path} - '
527
- f'{response.status_code} - {duration:.3f}s'
528
- )
529
- return response
530
- ```
531
-
532
- ## Database Backup Script
533
-
534
- ```bash
535
- #!/bin/bash
536
- # backup.sh
537
-
538
- set -e
539
-
540
- # Configuration
541
- BACKUP_DIR="/var/backups/db"
542
- DATABASE_URL="$DATABASE_URL"
543
- DATE=$(date +%Y%m%d_%H%M%S)
544
- BACKUP_FILE="$BACKUP_DIR/backup_$DATE.sql"
545
- RETENTION_DAYS=7
546
-
547
- # Create backup directory
548
- mkdir -p "$BACKUP_DIR"
549
-
550
- # Create backup
551
- echo "Creating database backup..."
552
- pg_dump "$DATABASE_URL" > "$BACKUP_FILE"
553
-
554
- # Compress backup
555
- gzip "$BACKUP_FILE"
556
-
557
- # Remove old backups
558
- echo "Cleaning up old backups..."
559
- find "$BACKUP_DIR" -name "backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete
560
-
561
- echo "Backup completed: $BACKUP_FILE.gz"
562
- ```
563
-
564
- ## Deployment Scripts
565
-
566
- ```bash
567
- #!/bin/bash
568
- # deploy.sh
569
-
570
- set -e
571
-
572
- echo "Starting deployment..."
573
-
574
- # Pull latest code
575
- git pull origin main
576
-
577
- # Build new Docker image
578
- docker-compose build web
579
-
580
- # Run database migrations
581
- docker-compose run --rm web flask db upgrade
582
-
583
- # Update services
584
- docker-compose up -d
585
-
586
- # Health check
587
- echo "Waiting for application to be ready..."
588
- sleep 10
589
-
590
- if curl -f http://localhost:8000/health; then
591
- echo "Deployment successful!"
592
- else
593
- echo "Deployment failed - health check failed"
594
- exit 1
595
- fi
596
- ```
597
-
598
- ## Monitoring with Prometheus
599
-
600
- ```python
601
- # app/metrics.py
602
- from prometheus_flask_exporter import PrometheusMetrics
603
- from flask import request
604
- import time
605
-
606
- def setup_metrics(app):
607
- """Setup Prometheus metrics."""
608
- metrics = PrometheusMetrics(app)
609
-
610
- # Custom metrics
611
- metrics.info('app_info', 'Application info', version='1.0.0')
612
-
613
- # Database connection pool metrics
614
- @metrics.gauge('db_pool_size', 'Database connection pool size')
615
- def db_pool_size():
616
- from app.extensions import db
617
- return db.engine.pool.size()
618
-
619
- return metrics
620
- ```