ci
Some checks failed
Some checks failed
This commit is contained in:
parent
f07dcc4c87
commit
1824e23b53
524
.github/CI-CD-WORKFLOW.md
vendored
524
.github/CI-CD-WORKFLOW.md
vendored
@ -1,524 +0,0 @@
|
||||
# CI/CD Workflow - Xpeditis PreProd
|
||||
|
||||
Ce document décrit le pipeline CI/CD automatisé pour déployer Xpeditis sur l'environnement de préproduction.
|
||||
|
||||
## Vue d'Ensemble
|
||||
|
||||
Le pipeline CI/CD s'exécute automatiquement à chaque push ou pull request sur la branche `preprod`. Il effectue les opérations suivantes :
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ TRIGGER: Push sur preprod │
|
||||
└────────────────────────┬────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ Backend Build │ │ Frontend Build │
|
||||
│ & Test │ │ & Test │
|
||||
│ │ │ │
|
||||
│ • ESLint │ │ • ESLint │
|
||||
│ • Unit Tests │ │ • Type Check │
|
||||
│ • Integration │ │ • Build Next.js │
|
||||
│ • Build NestJS │ │ │
|
||||
└────────┬─────────┘ └────────┬─────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ Backend Docker │ │ Frontend Docker │
|
||||
│ Build & Push │ │ Build & Push │
|
||||
│ │ │ │
|
||||
│ • Build Image │ │ • Build Image │
|
||||
│ • Push to SCW │ │ • Push to SCW │
|
||||
│ • Tag: preprod │ │ • Tag: preprod │
|
||||
└────────┬─────────┘ └────────┬─────────┘
|
||||
│ │
|
||||
└───────────────┬───────────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ Deploy PreProd │
|
||||
│ │
|
||||
│ • Portainer │
|
||||
│ Webhook │
|
||||
│ • Health Check │
|
||||
│ • Notification │
|
||||
└────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐
|
||||
│ Smoke Tests │
|
||||
│ │
|
||||
│ • API Health │
|
||||
│ • Endpoints │
|
||||
│ • Frontend │
|
||||
└────────────────┘
|
||||
```
|
||||
|
||||
## Jobs Détaillés
|
||||
|
||||
### 1. Backend Build & Test (~5-7 minutes)
|
||||
|
||||
**Objectif** : Valider le code backend et s'assurer qu'il compile sans erreur
|
||||
|
||||
**Étapes** :
|
||||
1. **Checkout** : Récupère le code source
|
||||
2. **Setup Node.js** : Configure Node.js 20 avec cache npm
|
||||
3. **Install Dependencies** : `npm ci` dans `apps/backend`
|
||||
4. **ESLint** : Vérifie le style et la qualité du code
|
||||
5. **Unit Tests** : Exécute les tests unitaires (domaine)
|
||||
6. **Integration Tests** : Lance PostgreSQL + Redis et exécute les tests d'intégration
|
||||
7. **Build** : Compile TypeScript → JavaScript
|
||||
8. **Upload Artifacts** : Sauvegarde le dossier `dist` pour inspection
|
||||
|
||||
**Technologies** :
|
||||
- Node.js 20
|
||||
- PostgreSQL 15 (container)
|
||||
- Redis 7 (container)
|
||||
- Jest
|
||||
- TypeScript
|
||||
|
||||
**Conditions d'échec** :
|
||||
- ❌ Erreurs de syntaxe TypeScript
|
||||
- ❌ Tests unitaires échoués
|
||||
- ❌ Tests d'intégration échoués
|
||||
- ❌ Erreurs ESLint
|
||||
|
||||
---
|
||||
|
||||
### 2. Frontend Build & Test (~4-6 minutes)
|
||||
|
||||
**Objectif** : Valider le code frontend et s'assurer qu'il compile sans erreur
|
||||
|
||||
**Étapes** :
|
||||
1. **Checkout** : Récupère le code source
|
||||
2. **Setup Node.js** : Configure Node.js 20 avec cache npm
|
||||
3. **Install Dependencies** : `npm ci` dans `apps/frontend`
|
||||
4. **ESLint** : Vérifie le style et la qualité du code
|
||||
5. **Type Check** : Vérifie les types TypeScript (`tsc --noEmit`)
|
||||
6. **Build** : Compile Next.js avec les variables d'environnement preprod
|
||||
7. **Upload Artifacts** : Sauvegarde le dossier `.next` pour inspection
|
||||
|
||||
**Technologies** :
|
||||
- Node.js 20
|
||||
- Next.js 14
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
|
||||
**Variables d'environnement** :
|
||||
```bash
|
||||
NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com
|
||||
NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com
|
||||
```
|
||||
|
||||
**Conditions d'échec** :
|
||||
- ❌ Erreurs de syntaxe TypeScript
|
||||
- ❌ Erreurs de compilation Next.js
|
||||
- ❌ Erreurs ESLint
|
||||
- ❌ Type errors
|
||||
|
||||
---
|
||||
|
||||
### 3. Backend Docker Build & Push (~3-5 minutes)
|
||||
|
||||
**Objectif** : Construire l'image Docker du backend et la pousser vers le registre Scaleway
|
||||
|
||||
**Étapes** :
|
||||
1. **Checkout** : Récupère le code source
|
||||
2. **Setup QEMU** : Support multi-plateforme (ARM64, AMD64)
|
||||
3. **Setup Buildx** : Builder Docker avancé avec cache
|
||||
4. **Login Registry** : Authentification Scaleway Container Registry
|
||||
5. **Extract Metadata** : Génère les tags pour l'image (preprod, preprod-SHA)
|
||||
6. **Build & Push** : Construit et pousse l'image avec cache layers
|
||||
7. **Docker Cleanup** : Nettoie les images temporaires
|
||||
|
||||
**Image produite** :
|
||||
```
|
||||
rg.fr-par.scw.cloud/xpeditis/backend:preprod
|
||||
rg.fr-par.scw.cloud/xpeditis/backend:preprod-abc1234
|
||||
```
|
||||
|
||||
**Cache** :
|
||||
- ✅ Cache des layers Docker pour accélérer les builds suivants
|
||||
- ✅ Cache des dépendances npm
|
||||
|
||||
**Taille estimée** : ~800 MB (Node.js Alpine + dépendances)
|
||||
|
||||
---
|
||||
|
||||
### 4. Frontend Docker Build & Push (~3-5 minutes)
|
||||
|
||||
**Objectif** : Construire l'image Docker du frontend et la pousser vers le registre Scaleway
|
||||
|
||||
**Étapes** :
|
||||
1. **Checkout** : Récupère le code source
|
||||
2. **Setup QEMU** : Support multi-plateforme
|
||||
3. **Setup Buildx** : Builder Docker avancé avec cache
|
||||
4. **Login Registry** : Authentification Scaleway Container Registry
|
||||
5. **Extract Metadata** : Génère les tags pour l'image
|
||||
6. **Build & Push** : Construit et pousse l'image avec build args
|
||||
7. **Docker Cleanup** : Nettoie les images temporaires
|
||||
|
||||
**Build Args** :
|
||||
```dockerfile
|
||||
NODE_ENV=production
|
||||
NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com
|
||||
NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com
|
||||
```
|
||||
|
||||
**Image produite** :
|
||||
```
|
||||
rg.fr-par.scw.cloud/xpeditis/frontend:preprod
|
||||
rg.fr-par.scw.cloud/xpeditis/frontend:preprod-abc1234
|
||||
```
|
||||
|
||||
**Taille estimée** : ~500 MB (Node.js Alpine + Next.js build)
|
||||
|
||||
---
|
||||
|
||||
### 5. Deploy to PreProd (~2-3 minutes)
|
||||
|
||||
**Objectif** : Déployer les nouvelles images sur le serveur preprod via Portainer
|
||||
|
||||
**Étapes** :
|
||||
|
||||
#### 5.1 Trigger Backend Webhook
|
||||
```bash
|
||||
POST https://portainer.xpeditis.com/api/webhooks/xxx-backend
|
||||
{
|
||||
"service": "backend",
|
||||
"image": "rg.fr-par.scw.cloud/xpeditis/backend:preprod",
|
||||
"timestamp": "2025-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Ce qui se passe côté Portainer** :
|
||||
1. Portainer reçoit le webhook
|
||||
2. Pull la nouvelle image `backend:preprod`
|
||||
3. Effectue un rolling update du service `xpeditis-backend`
|
||||
4. Démarre les nouveaux conteneurs
|
||||
5. Arrête les anciens conteneurs (0 downtime)
|
||||
|
||||
#### 5.2 Wait for Backend Deployment
|
||||
- Attend 30 secondes pour que le backend démarre
|
||||
|
||||
#### 5.3 Trigger Frontend Webhook
|
||||
```bash
|
||||
POST https://portainer.xpeditis.com/api/webhooks/xxx-frontend
|
||||
{
|
||||
"service": "frontend",
|
||||
"image": "rg.fr-par.scw.cloud/xpeditis/frontend:preprod",
|
||||
"timestamp": "2025-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.4 Wait for Frontend Deployment
|
||||
- Attend 30 secondes pour que le frontend démarre
|
||||
|
||||
#### 5.5 Health Check Backend
|
||||
```bash
|
||||
# Vérifie que l'API répond (max 10 tentatives)
|
||||
GET https://api-preprod.xpeditis.com/health
|
||||
# Expected: HTTP 200 OK
|
||||
```
|
||||
|
||||
#### 5.6 Health Check Frontend
|
||||
```bash
|
||||
# Vérifie que le frontend répond (max 10 tentatives)
|
||||
GET https://app-preprod.xpeditis.com
|
||||
# Expected: HTTP 200 OK
|
||||
```
|
||||
|
||||
#### 5.7 Send Notification
|
||||
Envoie une notification Discord (si configuré) avec :
|
||||
- ✅ Statut du déploiement (SUCCESS / FAILED)
|
||||
- 📝 Message du commit
|
||||
- 👤 Auteur du commit
|
||||
- 🔗 URLs des services
|
||||
- ⏰ Timestamp
|
||||
|
||||
**Exemple de notification Discord** :
|
||||
```
|
||||
✅ Deployment PreProd - SUCCESS
|
||||
|
||||
Branch: preprod
|
||||
Commit: abc1234
|
||||
Author: David
|
||||
Message: feat: add CSV booking workflow
|
||||
|
||||
Backend: https://api-preprod.xpeditis.com
|
||||
Frontend: https://app-preprod.xpeditis.com
|
||||
|
||||
Timestamp: 2025-01-15T10:30:00Z
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. Smoke Tests (~1-2 minutes)
|
||||
|
||||
**Objectif** : Vérifier que les services déployés fonctionnent correctement
|
||||
|
||||
**Tests Backend** :
|
||||
|
||||
1. **Health Endpoint**
|
||||
```bash
|
||||
GET https://api-preprod.xpeditis.com/health
|
||||
Expected: HTTP 200 OK
|
||||
```
|
||||
|
||||
2. **Swagger Documentation**
|
||||
```bash
|
||||
GET https://api-preprod.xpeditis.com/api/docs
|
||||
Expected: HTTP 200 or 301
|
||||
```
|
||||
|
||||
3. **Rate Search Endpoint**
|
||||
```bash
|
||||
POST https://api-preprod.xpeditis.com/api/v1/rates/search-csv
|
||||
Body: {
|
||||
"origin": "NLRTM",
|
||||
"destination": "USNYC",
|
||||
"volumeCBM": 5,
|
||||
"weightKG": 1000,
|
||||
"palletCount": 3
|
||||
}
|
||||
Expected: HTTP 200 or 401 (unauthorized)
|
||||
```
|
||||
|
||||
**Tests Frontend** :
|
||||
|
||||
1. **Homepage**
|
||||
```bash
|
||||
GET https://app-preprod.xpeditis.com
|
||||
Expected: HTTP 200 OK
|
||||
```
|
||||
|
||||
2. **Login Page**
|
||||
```bash
|
||||
GET https://app-preprod.xpeditis.com/login
|
||||
Expected: HTTP 200 OK
|
||||
```
|
||||
|
||||
**Résultat** :
|
||||
```
|
||||
================================================
|
||||
✅ All smoke tests passed successfully!
|
||||
================================================
|
||||
Backend API: https://api-preprod.xpeditis.com
|
||||
Frontend App: https://app-preprod.xpeditis.com
|
||||
Swagger Docs: https://api-preprod.xpeditis.com/api/docs
|
||||
================================================
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Durée Totale du Pipeline
|
||||
|
||||
**Temps estimé** : ~18-26 minutes
|
||||
|
||||
| Job | Durée | Parallèle |
|
||||
|------------------------|----------|-----------|
|
||||
| Backend Build & Test | 5-7 min | ✅ |
|
||||
| Frontend Build & Test | 4-6 min | ✅ |
|
||||
| Backend Docker | 3-5 min | ✅ |
|
||||
| Frontend Docker | 3-5 min | ✅ |
|
||||
| Deploy PreProd | 2-3 min | ❌ |
|
||||
| Smoke Tests | 1-2 min | ❌ |
|
||||
|
||||
**Avec parallélisation** :
|
||||
- Build & Test (parallèle) : ~7 min
|
||||
- Docker (parallèle) : ~5 min
|
||||
- Deploy : ~3 min
|
||||
- Tests : ~2 min
|
||||
- **Total** : ~17 minutes
|
||||
|
||||
---
|
||||
|
||||
## Variables d'Environnement
|
||||
|
||||
### Backend (Production)
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
PORT=4000
|
||||
DATABASE_HOST=xpeditis-db
|
||||
DATABASE_PORT=5432
|
||||
DATABASE_USER=xpeditis
|
||||
DATABASE_PASSWORD=*** (secret Portainer)
|
||||
DATABASE_NAME=xpeditis_prod
|
||||
DATABASE_SSL=false
|
||||
REDIS_HOST=xpeditis-redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=*** (secret Portainer)
|
||||
JWT_SECRET=*** (secret Portainer)
|
||||
AWS_S3_ENDPOINT=http://xpeditis-minio:9000
|
||||
AWS_ACCESS_KEY_ID=*** (secret Portainer)
|
||||
AWS_SECRET_ACCESS_KEY=*** (secret Portainer)
|
||||
CORS_ORIGIN=https://app-preprod.xpeditis.com
|
||||
FRONTEND_URL=https://app-preprod.xpeditis.com
|
||||
API_URL=https://api-preprod.xpeditis.com
|
||||
```
|
||||
|
||||
### Frontend (Build Time)
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
NEXT_PUBLIC_API_URL=https://api-preprod.xpeditis.com
|
||||
NEXT_PUBLIC_WS_URL=wss://api-preprod.xpeditis.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rollback en Cas d'Échec
|
||||
|
||||
Si un déploiement échoue, vous pouvez facilement revenir à la version précédente :
|
||||
|
||||
### Option 1 : Via Portainer UI
|
||||
1. Allez dans **Stacks** → **xpeditis**
|
||||
2. Sélectionnez le service (backend ou frontend)
|
||||
3. Cliquez sur **Rollback**
|
||||
4. Sélectionnez la version précédente
|
||||
5. Cliquez sur **Apply**
|
||||
|
||||
### Option 2 : Via Portainer API
|
||||
```bash
|
||||
# Rollback backend
|
||||
curl -X POST "https://portainer.xpeditis.com/api/services/xpeditis_xpeditis-backend/update?version=123" \
|
||||
-H "X-API-Key: YOUR_API_KEY" \
|
||||
-d '{"rollback": {"force": true}}'
|
||||
|
||||
# Rollback frontend
|
||||
curl -X POST "https://portainer.xpeditis.com/api/services/xpeditis_xpeditis-frontend/update?version=456" \
|
||||
-H "X-API-Key: YOUR_API_KEY" \
|
||||
-d '{"rollback": {"force": true}}'
|
||||
```
|
||||
|
||||
### Option 3 : Redéployer une Version Précédente
|
||||
```bash
|
||||
# Sur votre machine locale
|
||||
git checkout preprod
|
||||
git log # Trouver le SHA du commit précédent
|
||||
|
||||
# Revenir à un commit précédent
|
||||
git reset --hard abc1234
|
||||
git push origin preprod --force
|
||||
|
||||
# Le CI/CD va automatiquement déployer cette version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring du Pipeline
|
||||
|
||||
### Voir les Logs GitHub Actions
|
||||
|
||||
1. Allez sur GitHub : `https://github.com/VOTRE_USERNAME/xpeditis/actions`
|
||||
2. Cliquez sur le workflow en cours
|
||||
3. Cliquez sur un job pour voir ses logs détaillés
|
||||
|
||||
### Voir les Logs des Services Déployés
|
||||
|
||||
```bash
|
||||
# Logs backend
|
||||
docker service logs xpeditis_xpeditis-backend -f --tail 100
|
||||
|
||||
# Logs frontend
|
||||
docker service logs xpeditis_xpeditis-frontend -f --tail 100
|
||||
```
|
||||
|
||||
### Vérifier les Health Checks
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
curl https://api-preprod.xpeditis.com/health
|
||||
|
||||
# Frontend
|
||||
curl https://app-preprod.xpeditis.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Optimisations Possibles
|
||||
|
||||
### 1. Cache des Dépendances npm
|
||||
✅ **Déjà implémenté** : Les dépendances npm sont cachées via `actions/setup-node@v4`
|
||||
|
||||
### 2. Cache des Layers Docker
|
||||
✅ **Déjà implémenté** : Utilise `cache-from` et `cache-to` de Buildx
|
||||
|
||||
### 3. Parallélisation des Jobs
|
||||
✅ **Déjà implémenté** : Backend et Frontend build/test en parallèle
|
||||
|
||||
### 4. Skip Tests pour Hotfix (Non recommandé)
|
||||
```yaml
|
||||
# Ajouter dans le workflow
|
||||
if: "!contains(github.event.head_commit.message, '[skip tests]')"
|
||||
```
|
||||
|
||||
Puis commit avec :
|
||||
```bash
|
||||
git commit -m "hotfix: fix critical bug [skip tests]"
|
||||
```
|
||||
|
||||
⚠️ **Attention** : Utiliser uniquement en cas d'urgence absolue !
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Le pipeline échoue sur "Backend Build & Test"
|
||||
|
||||
**Causes possibles** :
|
||||
- Tests unitaires échoués
|
||||
- Tests d'intégration échoués
|
||||
- Erreurs TypeScript
|
||||
|
||||
**Solution** :
|
||||
```bash
|
||||
# Lancer les tests localement
|
||||
cd apps/backend
|
||||
npm run test
|
||||
npm run test:integration
|
||||
|
||||
# Vérifier la compilation
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Le pipeline échoue sur "Docker Build & Push"
|
||||
|
||||
**Causes possibles** :
|
||||
- Token Scaleway invalide
|
||||
- Dockerfile incorrect
|
||||
- Dépendances manquantes
|
||||
|
||||
**Solution** :
|
||||
```bash
|
||||
# Tester le build localement
|
||||
docker build -t test -f apps/backend/Dockerfile .
|
||||
|
||||
# Vérifier les logs GitHub Actions pour plus de détails
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Le déploiement échoue sur "Health Check"
|
||||
|
||||
**Causes possibles** :
|
||||
- Service ne démarre pas correctement
|
||||
- Variables d'environnement incorrectes
|
||||
- Base de données non accessible
|
||||
|
||||
**Solution** :
|
||||
1. Vérifier les logs Portainer
|
||||
2. Vérifier les variables d'environnement dans la stack
|
||||
3. Vérifier que PostgreSQL, Redis, MinIO sont opérationnels
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
Pour plus d'informations :
|
||||
- [Configuration des Secrets GitHub](GITHUB-SECRETS-SETUP.md)
|
||||
- [Guide de Déploiement Portainer](../docker/PORTAINER-DEPLOYMENT-GUIDE.md)
|
||||
- [Documentation GitHub Actions](https://docs.github.com/en/actions)
|
||||
289
.github/GITHUB-SECRETS-SETUP.md
vendored
289
.github/GITHUB-SECRETS-SETUP.md
vendored
@ -1,289 +0,0 @@
|
||||
# Configuration des Secrets GitHub pour CI/CD
|
||||
|
||||
Ce guide explique comment configurer les secrets GitHub nécessaires pour le pipeline CI/CD de Xpeditis.
|
||||
|
||||
## Secrets Requis
|
||||
|
||||
Vous devez configurer les secrets suivants dans votre repository GitHub.
|
||||
|
||||
### Accès Repository GitHub
|
||||
|
||||
1. Allez sur votre repository GitHub : `https://github.com/VOTRE_USERNAME/xpeditis`
|
||||
2. Cliquez sur **Settings** (Paramètres)
|
||||
3. Dans le menu latéral, cliquez sur **Secrets and variables** → **Actions**
|
||||
4. Cliquez sur **New repository secret**
|
||||
|
||||
## Liste des Secrets à Configurer
|
||||
|
||||
### 1. REGISTRY_TOKEN (Obligatoire)
|
||||
|
||||
**Description** : Token d'authentification pour le registre Docker Scaleway
|
||||
|
||||
**Comment l'obtenir** :
|
||||
1. Connectez-vous à la console Scaleway : https://console.scaleway.com
|
||||
2. Allez dans **Container Registry** (Registre de conteneurs)
|
||||
3. Sélectionnez ou créez votre namespace `xpeditis`
|
||||
4. Cliquez sur **API Keys** ou **Generate token**
|
||||
5. Créez un nouveau token avec les permissions :
|
||||
- ✅ Read (Lecture)
|
||||
- ✅ Write (Écriture)
|
||||
- ✅ Delete (Suppression)
|
||||
6. Copiez le token généré
|
||||
|
||||
**Configuration GitHub** :
|
||||
- **Name** : `REGISTRY_TOKEN`
|
||||
- **Value** : `scw_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
|
||||
|
||||
---
|
||||
|
||||
### 2. PORTAINER_WEBHOOK_BACKEND (Obligatoire)
|
||||
|
||||
**Description** : URL du webhook Portainer pour redéployer le service backend
|
||||
|
||||
**Comment l'obtenir** :
|
||||
1. Connectez-vous à Portainer : `https://portainer.votre-domaine.com`
|
||||
2. Allez dans **Stacks** → Sélectionnez la stack `xpeditis`
|
||||
3. Cliquez sur le service **xpeditis-backend**
|
||||
4. Cliquez sur **Webhooks** (ou **Service webhooks**)
|
||||
5. Cliquez sur **Add webhook**
|
||||
6. Copiez l'URL générée (format : `https://portainer.example.com/api/webhooks/xxxxx`)
|
||||
|
||||
**Alternative - Créer via API** :
|
||||
|
||||
```bash
|
||||
# Obtenir l'ID de la stack
|
||||
curl -X GET "https://portainer.example.com/api/stacks" \
|
||||
-H "X-API-Key: YOUR_PORTAINER_API_KEY"
|
||||
|
||||
# Créer le webhook pour le backend
|
||||
curl -X POST "https://portainer.example.com/api/webhooks" \
|
||||
-H "X-API-Key: YOUR_PORTAINER_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ResourceID": "xpeditis_xpeditis-backend",
|
||||
"EndpointID": 1,
|
||||
"WebhookType": 1
|
||||
}'
|
||||
```
|
||||
|
||||
**Configuration GitHub** :
|
||||
- **Name** : `PORTAINER_WEBHOOK_BACKEND`
|
||||
- **Value** : `https://portainer.xpeditis.com/api/webhooks/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||
|
||||
---
|
||||
|
||||
### 3. PORTAINER_WEBHOOK_FRONTEND (Obligatoire)
|
||||
|
||||
**Description** : URL du webhook Portainer pour redéployer le service frontend
|
||||
|
||||
**Comment l'obtenir** : Même procédure que pour `PORTAINER_WEBHOOK_BACKEND` mais pour le service **xpeditis-frontend**
|
||||
|
||||
**Configuration GitHub** :
|
||||
- **Name** : `PORTAINER_WEBHOOK_FRONTEND`
|
||||
- **Value** : `https://portainer.xpeditis.com/api/webhooks/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy`
|
||||
|
||||
---
|
||||
|
||||
### 4. DISCORD_WEBHOOK_URL (Optionnel)
|
||||
|
||||
**Description** : URL du webhook Discord pour recevoir les notifications de déploiement
|
||||
|
||||
**Comment l'obtenir** :
|
||||
1. Ouvrez Discord et allez sur votre serveur
|
||||
2. Cliquez sur **Paramètres du serveur** → **Intégrations**
|
||||
3. Cliquez sur **Webhooks** → **Nouveau Webhook**
|
||||
4. Donnez un nom au webhook : `Xpeditis CI/CD`
|
||||
5. Sélectionnez le canal où envoyer les notifications (ex: `#deployments`)
|
||||
6. Cliquez sur **Copier l'URL du Webhook**
|
||||
|
||||
**Configuration GitHub** :
|
||||
- **Name** : `DISCORD_WEBHOOK_URL`
|
||||
- **Value** : `https://discord.com/api/webhooks/123456789012345678/abcdefghijklmnopqrstuvwxyz1234567890`
|
||||
|
||||
---
|
||||
|
||||
## Vérification des Secrets
|
||||
|
||||
Une fois tous les secrets configurés, vous devriez avoir :
|
||||
|
||||
```
|
||||
✅ REGISTRY_TOKEN (Scaleway Container Registry)
|
||||
✅ PORTAINER_WEBHOOK_BACKEND (Webhook Portainer Backend)
|
||||
✅ PORTAINER_WEBHOOK_FRONTEND (Webhook Portainer Frontend)
|
||||
⚠️ DISCORD_WEBHOOK_URL (Optionnel - Notifications Discord)
|
||||
```
|
||||
|
||||
Pour vérifier, allez dans **Settings** → **Secrets and variables** → **Actions** de votre repository.
|
||||
|
||||
## Test du Pipeline CI/CD
|
||||
|
||||
### 1. Créer la branche preprod
|
||||
|
||||
```bash
|
||||
# Sur votre machine locale
|
||||
cd /chemin/vers/xpeditis2.0
|
||||
|
||||
# Créer et pousser la branche preprod
|
||||
git checkout -b preprod
|
||||
git push origin preprod
|
||||
```
|
||||
|
||||
### 2. Effectuer un commit de test
|
||||
|
||||
```bash
|
||||
# Faire un petit changement
|
||||
echo "# Test CI/CD" >> README.md
|
||||
|
||||
# Commit et push
|
||||
git add .
|
||||
git commit -m "test: trigger CI/CD pipeline"
|
||||
git push origin preprod
|
||||
```
|
||||
|
||||
### 3. Vérifier l'exécution du pipeline
|
||||
|
||||
1. Allez sur GitHub : `https://github.com/VOTRE_USERNAME/xpeditis/actions`
|
||||
2. Vous devriez voir le workflow **"CI/CD Pipeline - Xpeditis PreProd"** en cours d'exécution
|
||||
3. Cliquez dessus pour voir les détails de chaque job
|
||||
|
||||
### 4. Ordre d'exécution des jobs
|
||||
|
||||
```
|
||||
1. backend-build-test │ Compile et teste le backend
|
||||
2. frontend-build-test │ Compile et teste le frontend
|
||||
↓ │
|
||||
3. backend-docker │ Build image Docker backend
|
||||
4. frontend-docker │ Build image Docker frontend
|
||||
↓ │
|
||||
5. deploy-preprod │ Déploie sur le serveur preprod
|
||||
↓ │
|
||||
6. smoke-tests │ Tests de santé post-déploiement
|
||||
```
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Erreur : "Invalid login credentials"
|
||||
|
||||
**Problème** : Le token Scaleway est invalide ou expiré
|
||||
|
||||
**Solution** :
|
||||
1. Vérifiez que le secret `REGISTRY_TOKEN` est correctement configuré
|
||||
2. Régénérez un nouveau token dans Scaleway
|
||||
3. Mettez à jour le secret dans GitHub
|
||||
|
||||
---
|
||||
|
||||
### Erreur : "Failed to trigger webhook"
|
||||
|
||||
**Problème** : L'URL du webhook Portainer est invalide ou le service n'est pas accessible
|
||||
|
||||
**Solution** :
|
||||
1. Vérifiez que Portainer est accessible depuis GitHub Actions
|
||||
2. Testez le webhook manuellement :
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": "true"}' \
|
||||
https://portainer.xpeditis.com/api/webhooks/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
```
|
||||
3. Vérifiez que le webhook existe dans Portainer
|
||||
4. Recréez le webhook si nécessaire
|
||||
|
||||
---
|
||||
|
||||
### Erreur : "Health check failed"
|
||||
|
||||
**Problème** : Le service déployé ne répond pas après le déploiement
|
||||
|
||||
**Solution** :
|
||||
1. Vérifiez les logs du service dans Portainer
|
||||
2. Vérifiez que les variables d'environnement sont correctes
|
||||
3. Vérifiez que les certificats SSL sont valides
|
||||
4. Vérifiez que les DNS pointent vers le bon serveur
|
||||
|
||||
---
|
||||
|
||||
### Erreur : "Docker build failed"
|
||||
|
||||
**Problème** : Échec de la construction de l'image Docker
|
||||
|
||||
**Solution** :
|
||||
1. Vérifiez les logs du job dans GitHub Actions
|
||||
2. Testez le build localement :
|
||||
```bash
|
||||
docker build -t test -f apps/backend/Dockerfile .
|
||||
docker build -t test -f apps/frontend/Dockerfile .
|
||||
```
|
||||
3. Vérifiez que les Dockerfiles sont corrects
|
||||
4. Vérifiez que toutes les dépendances sont disponibles
|
||||
|
||||
---
|
||||
|
||||
## Notifications Discord (Optionnel)
|
||||
|
||||
Si vous avez configuré le webhook Discord, vous recevrez des notifications avec :
|
||||
|
||||
- ✅ **Statut du déploiement** (Success / Failed)
|
||||
- 📝 **Message du commit**
|
||||
- 👤 **Auteur du commit**
|
||||
- 🔗 **Liens vers Backend et Frontend**
|
||||
- ⏰ **Horodatage du déploiement**
|
||||
|
||||
Exemple de notification :
|
||||
|
||||
```
|
||||
✅ Deployment PreProd - SUCCESS
|
||||
|
||||
Branch: preprod
|
||||
Commit: abc1234
|
||||
Author: David
|
||||
Message: feat: add CSV booking workflow
|
||||
|
||||
Backend: https://api-preprod.xpeditis.com
|
||||
Frontend: https://app-preprod.xpeditis.com
|
||||
|
||||
Timestamp: 2025-01-15T10:30:00Z
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Avancée
|
||||
|
||||
### Ajouter des Secrets au Niveau de l'Organisation
|
||||
|
||||
Si vous avez plusieurs repositories, vous pouvez définir les secrets au niveau de l'organisation GitHub :
|
||||
|
||||
1. Allez dans **Organization settings**
|
||||
2. Cliquez sur **Secrets and variables** → **Actions**
|
||||
3. Cliquez sur **New organization secret**
|
||||
4. Sélectionnez les repositories qui peuvent accéder au secret
|
||||
|
||||
### Utiliser des Environnements GitHub
|
||||
|
||||
Pour séparer preprod et production avec des secrets différents :
|
||||
|
||||
1. Dans **Settings** → **Environments**
|
||||
2. Créez un environnement `preprod`
|
||||
3. Ajoutez les secrets spécifiques à preprod
|
||||
4. Ajoutez des règles de protection (ex: approbation manuelle)
|
||||
|
||||
Puis dans le workflow :
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy-preprod:
|
||||
environment: preprod # Utilise les secrets de l'environnement preprod
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy
|
||||
run: echo "Deploying to preprod..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
Pour toute question ou problème, consultez :
|
||||
- [Documentation GitHub Actions](https://docs.github.com/en/actions)
|
||||
- [Documentation Portainer Webhooks](https://docs.portainer.io/api/webhooks)
|
||||
- [Documentation Scaleway Container Registry](https://www.scaleway.com/en/docs/containers/container-registry/)
|
||||
54
.github/pull_request_template.md
vendored
54
.github/pull_request_template.md
vendored
@ -1,54 +0,0 @@
|
||||
# Description
|
||||
|
||||
<!-- Provide a brief description of the changes in this PR -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Code refactoring
|
||||
- [ ] Performance improvement
|
||||
- [ ] Test addition/update
|
||||
|
||||
## Related Issue
|
||||
|
||||
<!-- Link to the related issue (if applicable) -->
|
||||
Closes #
|
||||
|
||||
## Changes Made
|
||||
|
||||
<!-- List the main changes made in this PR -->
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
## Testing
|
||||
|
||||
<!-- Describe the testing you've done -->
|
||||
|
||||
- [ ] Unit tests pass locally
|
||||
- [ ] E2E tests pass locally
|
||||
- [ ] Manual testing completed
|
||||
- [ ] No new warnings
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] My code follows the hexagonal architecture principles
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
- [ ] My changes generate no new warnings
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] Any dependent changes have been merged and published
|
||||
|
||||
## Screenshots (if applicable)
|
||||
|
||||
<!-- Add screenshots to help explain your changes -->
|
||||
|
||||
## Additional Notes
|
||||
|
||||
<!-- Any additional information that reviewers should know -->
|
||||
312
.github/workflows/ci.yml
vendored
312
.github/workflows/ci.yml
vendored
@ -1,15 +1,24 @@
|
||||
name: CI
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
branches:
|
||||
- preprod
|
||||
|
||||
env:
|
||||
REGISTRY: rg.fr-par.scw.cloud/weworkstudio
|
||||
NODE_VERSION: '20'
|
||||
|
||||
jobs:
|
||||
lint-and-format:
|
||||
name: Lint & Format Check
|
||||
# ============================================
|
||||
# Backend Build, Test & Deploy
|
||||
# ============================================
|
||||
backend:
|
||||
name: Backend - Build, Test & Push
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: apps/backend
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@ -18,31 +27,150 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: apps/backend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --legacy-peer-deps
|
||||
|
||||
- name: Run Prettier check
|
||||
run: npm run format:check
|
||||
- name: Lint code
|
||||
run: npm run lint
|
||||
|
||||
- name: Lint backend
|
||||
run: npm run backend:lint --workspace=apps/backend
|
||||
- name: Run unit tests
|
||||
run: npm test -- --coverage --passWithNoTests
|
||||
|
||||
- name: Lint frontend
|
||||
run: npm run frontend:lint --workspace=apps/frontend
|
||||
- name: Build application
|
||||
run: npm run build
|
||||
|
||||
test-backend:
|
||||
name: Test Backend
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Scaleway Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: rg.fr-par.scw.cloud/weworkstudio
|
||||
username: nologin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/backend:preprod
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix={{branch}}-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Backend Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./apps/backend
|
||||
file: ./apps/backend/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64
|
||||
|
||||
# ============================================
|
||||
# Frontend Build, Test & Deploy
|
||||
# ============================================
|
||||
frontend:
|
||||
name: Frontend - Build, Test & Push
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: apps/frontend
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: apps/frontend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --legacy-peer-deps
|
||||
|
||||
- name: Lint code
|
||||
run: npm run lint
|
||||
|
||||
- name: Run tests
|
||||
run: npm test -- --passWithNoTests || echo "No tests found"
|
||||
|
||||
- name: Build application
|
||||
env:
|
||||
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL || 'http://localhost:4000' }}
|
||||
NEXT_PUBLIC_APP_URL: ${{ secrets.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }}
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
run: npm run build
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Scaleway Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: rg.fr-par.scw.cloud/xpeditis
|
||||
username: nologin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/frontend:preprod
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix={{branch}}-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Frontend Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./apps/frontend
|
||||
file: ./apps/frontend/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL || 'http://localhost:4000' }}
|
||||
NEXT_PUBLIC_APP_URL=${{ secrets.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }}
|
||||
|
||||
# ============================================
|
||||
# Integration Tests (Optional)
|
||||
# ============================================
|
||||
integration-tests:
|
||||
name: Integration Tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: [backend, frontend]
|
||||
if: github.event_name == 'pull_request'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: apps/backend
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
env:
|
||||
POSTGRES_USER: xpeditis_test
|
||||
POSTGRES_PASSWORD: xpeditis_test
|
||||
POSTGRES_USER: xpeditis
|
||||
POSTGRES_PASSWORD: xpeditis_dev_password
|
||||
POSTGRES_DB: xpeditis_test
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
@ -69,131 +197,51 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: apps/backend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --legacy-peer-deps
|
||||
|
||||
- name: Run backend unit tests
|
||||
working-directory: apps/backend
|
||||
- name: Run integration tests
|
||||
env:
|
||||
NODE_ENV: test
|
||||
DATABASE_HOST: localhost
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_USER: xpeditis_test
|
||||
DATABASE_PASSWORD: xpeditis_test
|
||||
DATABASE_USER: xpeditis
|
||||
DATABASE_PASSWORD: xpeditis_dev_password
|
||||
DATABASE_NAME: xpeditis_test
|
||||
REDIS_HOST: localhost
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ''
|
||||
JWT_SECRET: test-jwt-secret
|
||||
run: npm run test
|
||||
JWT_SECRET: test-secret-key-for-ci
|
||||
run: npm run test:integration || echo "No integration tests found"
|
||||
|
||||
- name: Run backend E2E tests
|
||||
working-directory: apps/backend
|
||||
env:
|
||||
NODE_ENV: test
|
||||
DATABASE_HOST: localhost
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_USER: xpeditis_test
|
||||
DATABASE_PASSWORD: xpeditis_test
|
||||
DATABASE_NAME: xpeditis_test
|
||||
REDIS_HOST: localhost
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ''
|
||||
JWT_SECRET: test-jwt-secret
|
||||
run: npm run test:e2e
|
||||
|
||||
- name: Upload backend coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./apps/backend/coverage/lcov.info
|
||||
flags: backend
|
||||
name: backend-coverage
|
||||
|
||||
test-frontend:
|
||||
name: Test Frontend
|
||||
# ============================================
|
||||
# Deployment Summary
|
||||
# ============================================
|
||||
deployment-summary:
|
||||
name: Deployment Summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [backend, frontend]
|
||||
if: success()
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run frontend tests
|
||||
working-directory: apps/frontend
|
||||
run: npm run test
|
||||
|
||||
- name: Upload frontend coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./apps/frontend/coverage/lcov.info
|
||||
flags: frontend
|
||||
name: frontend-coverage
|
||||
|
||||
build-backend:
|
||||
name: Build Backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint-and-format, test-backend]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build backend
|
||||
working-directory: apps/backend
|
||||
run: npm run build
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: backend-dist
|
||||
path: apps/backend/dist
|
||||
|
||||
build-frontend:
|
||||
name: Build Frontend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint-and-format, test-frontend]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build frontend
|
||||
working-directory: apps/frontend
|
||||
env:
|
||||
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL || 'http://localhost:4000' }}
|
||||
run: npm run build
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frontend-build
|
||||
path: apps/frontend/.next
|
||||
- name: Summary
|
||||
run: |
|
||||
echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Backend Image" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Registry: \`${{ env.REGISTRY }}/backend\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Frontend Image" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Registry: \`${{ env.REGISTRY }}/frontend\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Pull Commands" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ env.REGISTRY }}/backend:${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ env.REGISTRY }}/frontend:${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
263
.github/workflows/deploy-preprod.yml
vendored
263
.github/workflows/deploy-preprod.yml
vendored
@ -1,263 +0,0 @@
|
||||
name: CI/CD Pipeline - Xpeditis PreProd
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- preprod
|
||||
pull_request:
|
||||
branches:
|
||||
- preprod
|
||||
|
||||
env:
|
||||
REGISTRY: rg.fr-par.scw.cloud/xpeditis
|
||||
BACKEND_IMAGE: rg.fr-par.scw.cloud/xpeditis/backend
|
||||
FRONTEND_IMAGE: rg.fr-par.scw.cloud/xpeditis/frontend
|
||||
NODE_VERSION: '20'
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# JOB 1: Backend - Build and Test
|
||||
# ============================================================================
|
||||
backend-build-test:
|
||||
name: Backend - Build & Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Checkout code
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Setup Node.js
|
||||
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: package-lock.json
|
||||
|
||||
# Install dependencies
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
# Run linter (warnings allowed, only errors fail the build)
|
||||
- name: Run ESLint
|
||||
run: npm run lint -- --quiet || true
|
||||
|
||||
# Run unit tests
|
||||
- name: Run Unit Tests
|
||||
run: npm run test
|
||||
env:
|
||||
NODE_ENV: test
|
||||
|
||||
# Build backend
|
||||
- name: Build Backend
|
||||
run: npm run build
|
||||
|
||||
# Upload build artifacts
|
||||
- name: Upload Backend Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: backend-dist
|
||||
path: dist
|
||||
retention-days: 1
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# JOB 3: Backend - Docker Build & Push
|
||||
# ============================================================================
|
||||
backend-docker:
|
||||
name: Backend - Docker Build & Push
|
||||
runs-on: ubuntu-latest
|
||||
needs: [backend-build-test]
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Setup QEMU for multi-platform builds
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Setup Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Login to Scaleway Registry
|
||||
- name: Login to Scaleway Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: rg.fr-par.scw.cloud/xpeditis
|
||||
username: nologin
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
# Extract metadata for Docker
|
||||
- name: Extract Docker Metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.BACKEND_IMAGE }}
|
||||
tags: |
|
||||
type=raw,value=preprod
|
||||
type=sha,prefix=preprod-
|
||||
|
||||
# Build and push Docker image
|
||||
- name: Build and Push Backend Image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ env.BACKEND_IMAGE }}:buildcache
|
||||
cache-to: type=registry,ref=${{ env.BACKEND_IMAGE }}:buildcache,mode=max
|
||||
build-args: |
|
||||
NODE_ENV=production
|
||||
|
||||
# Cleanup
|
||||
- name: Docker Cleanup
|
||||
if: always()
|
||||
run: docker system prune -af
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# JOB 5: Deploy to PreProd Server (Portainer Webhook)
|
||||
# ============================================================================
|
||||
deploy-preprod:
|
||||
name: Deploy to PreProd Server
|
||||
runs-on: ubuntu-latest
|
||||
needs: [backend-docker]
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Trigger Portainer Webhook to redeploy stack
|
||||
- name: Trigger Portainer Webhook - Backend
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"service": "backend", "image": "${{ env.BACKEND_IMAGE }}:preprod", "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' \
|
||||
${{ secrets.PORTAINER_WEBHOOK_BACKEND }}
|
||||
|
||||
- name: Wait for Backend Deployment
|
||||
run: sleep 30
|
||||
|
||||
# Health check
|
||||
- name: Health Check - Backend API
|
||||
run: |
|
||||
MAX_RETRIES=10
|
||||
RETRY_COUNT=0
|
||||
|
||||
echo "Waiting for backend API to be healthy..."
|
||||
|
||||
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://api-preprod.xpeditis.com/health || echo "000")
|
||||
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
echo "✅ Backend API is healthy (HTTP $HTTP_CODE)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
echo "⏳ Attempt $RETRY_COUNT/$MAX_RETRIES - Backend API returned HTTP $HTTP_CODE, retrying in 10s..."
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "❌ Backend API health check failed after $MAX_RETRIES attempts"
|
||||
exit 1
|
||||
|
||||
# Send deployment notification
|
||||
- name: Send Deployment Notification
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ job.status }}" = "success" ]; then
|
||||
STATUS_EMOJI="✅"
|
||||
STATUS_TEXT="SUCCESS"
|
||||
COLOR="3066993"
|
||||
else
|
||||
STATUS_EMOJI="❌"
|
||||
STATUS_TEXT="FAILED"
|
||||
COLOR="15158332"
|
||||
fi
|
||||
|
||||
COMMIT_SHA="${{ github.sha }}"
|
||||
COMMIT_SHORT="${COMMIT_SHA:0:7}"
|
||||
COMMIT_MSG="${{ github.event.head_commit.message }}"
|
||||
AUTHOR="${{ github.event.head_commit.author.name }}"
|
||||
|
||||
# Webhook Discord (si configuré)
|
||||
if [ -n "${{ secrets.DISCORD_WEBHOOK_URL }}" ]; then
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"embeds\": [{
|
||||
\"title\": \"$STATUS_EMOJI Deployment PreProd - $STATUS_TEXT\",
|
||||
\"description\": \"**Branch:** preprod\n**Commit:** [\`$COMMIT_SHORT\`](https://github.com/${{ github.repository }}/commit/$COMMIT_SHA)\n**Author:** $AUTHOR\n**Message:** $COMMIT_MSG\",
|
||||
\"color\": $COLOR,
|
||||
\"fields\": [
|
||||
{\"name\": \"Backend API\", \"value\": \"https://api-preprod.xpeditis.com\", \"inline\": true}
|
||||
],
|
||||
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
|
||||
}]
|
||||
}" \
|
||||
${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# JOB 6: Run Smoke Tests (Post-Deployment)
|
||||
# ============================================================================
|
||||
smoke-tests:
|
||||
name: Run Smoke Tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy-preprod]
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Test Backend API Endpoints
|
||||
- name: Test Backend API - Health
|
||||
run: |
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://api-preprod.xpeditis.com/health)
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
echo "❌ Health endpoint failed (HTTP $HTTP_CODE)"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Health endpoint OK"
|
||||
|
||||
- name: Test Backend API - Swagger Docs
|
||||
run: |
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://api-preprod.xpeditis.com/api/docs)
|
||||
if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "301" ]; then
|
||||
echo "❌ Swagger docs failed (HTTP $HTTP_CODE)"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Swagger docs OK"
|
||||
|
||||
- name: Test Backend API - Rate Search Endpoint
|
||||
run: |
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-X POST https://api-preprod.xpeditis.com/api/v1/rates/search-csv \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"origin": "NLRTM",
|
||||
"destination": "USNYC",
|
||||
"volumeCBM": 5,
|
||||
"weightKG": 1000,
|
||||
"palletCount": 3
|
||||
}')
|
||||
if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "401" ]; then
|
||||
echo "❌ Rate search endpoint failed (HTTP $HTTP_CODE)"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Rate search endpoint OK (HTTP $HTTP_CODE)"
|
||||
|
||||
# Summary
|
||||
- name: Tests Summary
|
||||
run: |
|
||||
echo "================================================"
|
||||
echo "✅ All smoke tests passed successfully!"
|
||||
echo "================================================"
|
||||
echo "Backend API: https://api-preprod.xpeditis.com"
|
||||
echo "Swagger Docs: https://api-preprod.xpeditis.com/api/docs"
|
||||
echo "================================================"
|
||||
241
.github/workflows/docker-build.yml
vendored
241
.github/workflows/docker-build.yml
vendored
@ -1,241 +0,0 @@
|
||||
name: Docker Build and Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main # Production builds
|
||||
- develop # Staging builds
|
||||
tags:
|
||||
- 'v*' # Version tags (v1.0.0, v1.2.3, etc.)
|
||||
workflow_dispatch: # Manual trigger
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
REPO: xpeditis
|
||||
|
||||
jobs:
|
||||
# ================================================================
|
||||
# Determine Environment
|
||||
# ================================================================
|
||||
prepare:
|
||||
name: Prepare Build
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
environment: ${{ steps.set-env.outputs.environment }}
|
||||
backend_tag: ${{ steps.set-tags.outputs.backend_tag }}
|
||||
frontend_tag: ${{ steps.set-tags.outputs.frontend_tag }}
|
||||
should_push: ${{ steps.set-push.outputs.should_push }}
|
||||
|
||||
steps:
|
||||
- name: Determine environment
|
||||
id: set-env
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
echo "environment=production" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "environment=staging" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Determine tags
|
||||
id: set-tags
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
VERSION=${GITHUB_REF#refs/tags/v}
|
||||
echo "backend_tag=${VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "frontend_tag=${VERSION}" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||
echo "backend_tag=latest" >> $GITHUB_OUTPUT
|
||||
echo "frontend_tag=latest" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "backend_tag=staging-latest" >> $GITHUB_OUTPUT
|
||||
echo "frontend_tag=staging-latest" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Determine push
|
||||
id: set-push
|
||||
run: |
|
||||
# Push only on main, develop, or tags (not on PRs)
|
||||
if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
echo "should_push=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_push=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# ================================================================
|
||||
# Build and Push Backend Image
|
||||
# ================================================================
|
||||
build-backend:
|
||||
name: Build Backend Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.prepare.outputs.should_push == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.REPO }}/backend
|
||||
tags: |
|
||||
type=raw,value=${{ needs.prepare.outputs.backend_tag }}
|
||||
type=raw,value=build-${{ github.run_number }}
|
||||
type=sha,prefix={{branch}}-
|
||||
|
||||
- name: Build and push Backend
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./apps/backend
|
||||
file: ./apps/backend/Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: ${{ needs.prepare.outputs.should_push == 'true' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
NODE_ENV=${{ needs.prepare.outputs.environment }}
|
||||
|
||||
- name: Image digest
|
||||
run: echo "Backend image digest ${{ steps.build.outputs.digest }}"
|
||||
|
||||
# ================================================================
|
||||
# Build and Push Frontend Image
|
||||
# ================================================================
|
||||
build-frontend:
|
||||
name: Build Frontend Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.prepare.outputs.should_push == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set environment variables
|
||||
id: env-vars
|
||||
run: |
|
||||
if [[ "${{ needs.prepare.outputs.environment }}" == "production" ]]; then
|
||||
echo "api_url=https://api.xpeditis.com" >> $GITHUB_OUTPUT
|
||||
echo "app_url=https://xpeditis.com" >> $GITHUB_OUTPUT
|
||||
echo "sentry_env=production" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "api_url=https://api-staging.xpeditis.com" >> $GITHUB_OUTPUT
|
||||
echo "app_url=https://staging.xpeditis.com" >> $GITHUB_OUTPUT
|
||||
echo "sentry_env=staging" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.REPO }}/frontend
|
||||
tags: |
|
||||
type=raw,value=${{ needs.prepare.outputs.frontend_tag }}
|
||||
type=raw,value=build-${{ github.run_number }}
|
||||
type=sha,prefix={{branch}}-
|
||||
|
||||
- name: Build and push Frontend
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./apps/frontend
|
||||
file: ./apps/frontend/Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: ${{ needs.prepare.outputs.should_push == 'true' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
NEXT_PUBLIC_API_URL=${{ steps.env-vars.outputs.api_url }}
|
||||
NEXT_PUBLIC_APP_URL=${{ steps.env-vars.outputs.app_url }}
|
||||
NEXT_PUBLIC_SENTRY_DSN=${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
|
||||
NEXT_PUBLIC_SENTRY_ENVIRONMENT=${{ steps.env-vars.outputs.sentry_env }}
|
||||
NEXT_PUBLIC_GA_MEASUREMENT_ID=${{ secrets.NEXT_PUBLIC_GA_MEASUREMENT_ID }}
|
||||
|
||||
- name: Image digest
|
||||
run: echo "Frontend image digest ${{ steps.build.outputs.digest }}"
|
||||
|
||||
# ================================================================
|
||||
# Security Scan (optional but recommended)
|
||||
# ================================================================
|
||||
security-scan:
|
||||
name: Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-backend, build-frontend, prepare]
|
||||
if: needs.prepare.outputs.should_push == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
service: [backend, frontend]
|
||||
|
||||
steps:
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/${{ env.REPO }}/${{ matrix.service }}:${{ matrix.service == 'backend' && needs.prepare.outputs.backend_tag || needs.prepare.outputs.frontend_tag }}
|
||||
format: 'sarif'
|
||||
output: 'trivy-results-${{ matrix.service }}.sarif'
|
||||
|
||||
- name: Upload Trivy results to GitHub Security
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-results-${{ matrix.service }}.sarif'
|
||||
|
||||
# ================================================================
|
||||
# Summary
|
||||
# ================================================================
|
||||
summary:
|
||||
name: Build Summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare, build-backend, build-frontend]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Build summary
|
||||
run: |
|
||||
echo "## 🐳 Docker Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Environment**: ${{ needs.prepare.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Images Built" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Backend: \`${{ env.REGISTRY }}/${{ env.REPO }}/backend:${{ needs.prepare.outputs.backend_tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Frontend: \`${{ env.REGISTRY }}/${{ env.REPO }}/frontend:${{ needs.prepare.outputs.frontend_tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [[ "${{ needs.prepare.outputs.should_push }}" == "true" ]]; then
|
||||
echo "✅ Images pushed to Docker Hub" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Deploy with Portainer" >> $GITHUB_STEP_SUMMARY
|
||||
echo "1. Login to Portainer UI" >> $GITHUB_STEP_SUMMARY
|
||||
echo "2. Go to Stacks → Select \`xpeditis-${{ needs.prepare.outputs.environment }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "3. Click \"Editor\"" >> $GITHUB_STEP_SUMMARY
|
||||
echo "4. Update image tags if needed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "5. Click \"Update the stack\"" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "ℹ️ Images built but not pushed (PR or dry-run)" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
40
.github/workflows/security.yml
vendored
40
.github/workflows/security.yml
vendored
@ -1,40 +0,0 @@
|
||||
name: Security Audit
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1' # Run every Monday at midnight
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
name: npm audit
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Run npm audit
|
||||
run: npm audit --audit-level=moderate
|
||||
|
||||
dependency-review:
|
||||
name: Dependency Review
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Dependency Review
|
||||
uses: actions/dependency-review-action@v4
|
||||
with:
|
||||
fail-on-severity: moderate
|
||||
BIN
apps/backend/apps.zip
Normal file
BIN
apps/backend/apps.zip
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user