Outils de Développement et de Déploiement¶
Cette section documente les outils et utilitaires utilisés dans tous les projets Optim pour le développement, les tests et le déploiement.
Outils de Développement¶
Éditeurs de Code et IDEs¶
Visual Studio Code¶
Extensions Recommandées :
- ESLint - Linting JavaScript/TypeScript
- Prettier - Formatage de code
- GitLens - Capacités Git améliorées
- Thunder Client - Tests d'API
- Docker - Développement de conteneurs
- Kubernetes - Gestion des ressources K8s
Configuration :
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"typescript.preferences.importModuleSpecifier": "relative",
"git.enableSmartCommit": true,
"files.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/.git": true
}
}
IDEs JetBrains¶
- WebStorm - Développement JavaScript/TypeScript
- IntelliJ IDEA - Développement Java
- PyCharm - Développement Python
Contrôle de Version¶
Configuration Git¶
# Configuration Git globale
git config --global user.name "Votre Nom"
git config --global user.email "your.email@optim.com"
git config --global init.defaultBranch main
git config --global pull.rebase true
git config --global core.autocrlf input
# Useful aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
Git Hooks with Husky¶
{
"husky": {
"hooks": {
"pre-commit": "lint-staged && npm run test:unit",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-push": "npm run test:integration"
}
},
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,scss,md}": ["prettier --write"]
}
}
Package Managers¶
Node.js - npm/yarn¶
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"type-check": "tsc --noEmit"
},
"dependencies": {
"next": "^13.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/react": "^18.0.0",
"eslint": "^8.0.0",
"prettier": "^2.7.0",
"typescript": "^4.8.0"
}
}
Python - pip/poetry¶
# pyproject.toml
[tool.poetry]
name = "optim-api"
version = "1.0.0"
description = "Optim API Service"
[tool.poetry.dependencies]
python = "^3.9"
fastapi = "^0.95.0"
uvicorn = "^0.21.0"
sqlalchemy = "^2.0.0"
alembic = "^1.10.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.0.0"
pytest-asyncio = "^0.21.0"
black = "^23.0.0"
flake8 = "^6.0.0"
mypy = "^1.2.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Testing Tools¶
JavaScript/TypeScript Testing¶
Jest Configuration¶
// jest.config.js
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["<rootDir>/src", "<rootDir>/tests"],
testMatch: [
"**/__tests__/**/*.+(ts|tsx|js)",
"**/*.(test|spec).+(ts|tsx|js)",
],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
},
collectCoverageFrom: [
"src/**/*.{ts,tsx}",
"!src/**/*.d.ts",
"!src/types/**/*",
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
Testing Library Setup¶
// tests/setup.ts
import "@testing-library/jest-dom";
import { configure } from "@testing-library/react";
configure({ testIdAttribute: "data-testid" });
// Mock global objects
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
Python Testing¶
Pytest Configuration¶
# pytest.ini
[tool:pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
--strict-markers
--strict-config
--verbose
--cov=src
--cov-report=term-missing
--cov-report=html
--cov-fail-under=80
markers =
unit: Unit tests
integration: Integration tests
e2e: End-to-end tests
slow: Slow running tests
End-to-End Testing¶
Playwright Configuration¶
// playwright.config.ts
import { PlaywrightTestConfig } from "@playwright/test";
const config: PlaywrightTestConfig = {
testDir: "./e2e",
timeout: 30000,
retries: 2,
use: {
baseURL: "http://localhost:3000",
headless: true,
viewport: { width: 1280, height: 720 },
ignoreHTTPSErrors: true,
video: "retain-on-failure",
screenshot: "only-on-failure",
},
projects: [
{
name: "Chrome",
use: { ...devices["Desktop Chrome"] },
},
{
name: "Firefox",
use: { ...devices["Desktop Firefox"] },
},
{
name: "Safari",
use: { ...devices["Desktop Safari"] },
},
],
};
export default config;
Build Tools¶
Frontend Build Tools¶
Webpack Configuration¶
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].[contenthash].js",
clean: true,
},
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
}),
],
optimization: {
splitChunks: {
chunks: "all",
},
},
};
Vite Configuration¶
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { resolve } from "path";
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": resolve(__dirname, "src"),
},
},
build: {
outDir: "dist",
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
utils: ["lodash", "date-fns"],
},
},
},
},
server: {
port: 3000,
open: true,
},
});
Backend Build Tools¶
Docker Configuration¶
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["npm", "start"]
Multi-stage Docker Build¶
# Multi-stage Dockerfile
FROM node:18-alpine AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --frozen-lockfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=dependencies /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "dist/index.js"]
Deployment Tools¶
Container Orchestration¶
Docker Compose¶
# docker-compose.yml
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgres://user:pass@db:5432/optim
depends_on:
- db
- redis
volumes:
- ./src:/app/src
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: optim
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
Kubernetes Helm Charts¶
# helm/values.yaml
replicaCount: 3
image:
repository: optim/app
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: app.optim.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.optim.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Infrastructure as Code¶
Terraform Configuration¶
# terraform/main.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "optim-vpc"
cidr = "10.0.0.0/16"
azs = ["${var.aws_region}a", "${var.aws_region}b", "${var.aws_region}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
}
Monitoring and Debugging Tools¶
Application Monitoring¶
Prometheus Configuration¶
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alerts/*.yml"
scrape_configs:
- job_name: "optim-app"
static_configs:
- targets: ["localhost:3000"]
metrics_path: "/metrics"
scrape_interval: 5s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
Grafana Dashboard¶
{
"dashboard": {
"id": null,
"title": "Optim Application Dashboard",
"tags": ["optim"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{status}}"
}
]
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "5s"
}
}
Error Tracking¶
Sentry Configuration¶
// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
beforeSend(event) {
if (event.exception) {
const error = event.exception.values?.[0];
if (error?.value?.includes("Non-Error")) {
return null;
}
}
return event;
},
});
Service Uptime Monitoring¶
UptimeRobot¶
UptimeRobot est notre solution principale pour surveiller la disponibilité de nos services en production. Il surveille en continu nos applications web, API et services backend pour détecter les temps d'arrêt et les problèmes de performance.
Services Surveillés :
- Web App SAAS - Application frontend React
- Web API SAAS - API backend FastAPI
- Backoffice App - Interface d'administration
- Backoffice API - API de gestion interne
Fonctionnalités Principales :
- Surveillance 24/7 - Vérifications automatiques toutes les 5 minutes
- Notifications Instantanées - Alertes par email/SMS en cas de panne
- Statistiques Détaillées - Historique de disponibilité et temps de réponse
- Page de Status Public - Transparence pour les utilisateurs
Dashboard de Monitoring : 🔗 Status Page Optim
Configuration des Alertes :
# Configuration type pour UptimeRobot
monitors:
- name: "SAAS Web App"
url: "https://ref.web.optimbtp.fr"
type: "HTTP(s)"
interval: 300 # 5 minutes
- name: "SAAS API"
url: "https://api.ref.web.optimbtp.fr/docs"
type: "HTTP(s)"
interval: 300
- name: "Backoffice App"
url: "https://admin.web.optimbtp.fr/login"
type: "HTTP(s)"
interval: 300
- name: "Backoffice API"
url: "https://api.admin.web.optimbtp.fr/admin"
type: "HTTP(s)"
interval: 300
alert_contacts:
- type: "email"
value: "technique@optim-factory.fr"
Bonnes Pratiques :
- Endpoints de Health Check - Implémenter des endpoints
/healthdédiés - Seuils d'Alerte - Configurer des alertes après 2 échecs consécutifs
- Escalation - Alertes par email puis SMS si le problème persiste
- Maintenance Windows - Programmer les fenêtres de maintenance pour éviter les fausses alertes
Intégration avec les Autres Outils :
- Slack - Notifications dans le canal
#alerts - PagerDuty - Escalation pour les incidents critiques
- Grafana - Corrélation avec les métriques de performance
Code Quality Tools¶
Linting and Formatting¶
ESLint Configuration¶
// .eslintrc.js
module.exports = {
extends: [
"eslint:recommended",
"@typescript-eslint/recommended",
"next/core-web-vitals",
"prettier",
],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
rules: {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-function-return-type": "warn",
"prefer-const": "error",
"no-var": "error",
},
};
Prettier Configuration¶
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false
}
Security Scanning¶
GitHub Security Workflows¶
# .github/workflows/security.yml
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run npm audit
run: npm audit --audit-level moderate
- name: Run Snyk test
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
languages: javascript
Utility Scripts¶
Development Scripts¶
#!/bin/bash
# scripts/dev-setup.sh
echo "Setting up development environment..."
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Generate SSL certificates for local development
mkcert localhost 127.0.0.1 ::1
# Start database
docker-compose up -d db redis
# Run database migrations
npm run migrate
# Seed database
npm run seed
echo "Development environment ready."
echo "Run 'npm run dev' to start the application"
Deployment Scripts¶
#!/bin/bash
# scripts/deploy.sh
set -e
ENVIRONMENT=${1:-staging}
VERSION=${2:-latest}
echo "Deploying to $ENVIRONMENT with version $VERSION"
# Build and push Docker image
docker build -t optim/app:$VERSION .
docker push optim/app:$VERSION
# Deploy with Helm
helm upgrade --install optim-app ./helm/optim-app \
--set image.tag=$VERSION \
--namespace $ENVIRONMENT \
--wait
echo "Deployment complete!"
Resources and Documentation¶
Tool Documentation Links¶
- Docker Documentation
- Kubernetes Documentation
- Terraform Documentation
- Jest Documentation
- Playwright Documentation
Internal Tool Guides¶
For tool-specific questions or issues, consult the respective documentation or contact the DevOps team.