Compare commits
18 Commits
stand-alon
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fb80ef59f | ||
|
|
53ceb29bbe | ||
|
|
7862bb11b7 | ||
|
|
42b3d28505 | ||
|
|
658be24b7c | ||
|
|
a2fbbe5d44 | ||
|
|
e1447aca28 | ||
|
|
4755b392a3 | ||
|
|
445a540d54 | ||
|
|
1dd4b4d1d1 | ||
|
|
7bb7484ec8 | ||
|
|
940834d993 | ||
|
|
fa0aa808ac | ||
|
|
002764ea9a | ||
|
|
b4d7f7e10f | ||
|
|
029fbe5d26 | ||
|
|
fe16d01be7 | ||
|
|
7c4204c689 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -31,4 +31,4 @@ public/strategie-inline.html
|
||||
# Docs
|
||||
docs/
|
||||
docs-sbom/
|
||||
docs-syoul/
|
||||
docs-syoul/
|
||||
|
||||
367
.woodpecker.yml
367
.woodpecker.yml
@@ -1,245 +1,158 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build-and-deploy
|
||||
|
||||
# Ce pipeline Woodpecker CI automatise le build et le déploiement de l'application statique
|
||||
# Il se déclenche automatiquement sur chaque push vers les branches main ou stand-alone
|
||||
when:
|
||||
- branch:
|
||||
- main
|
||||
- stand-alone
|
||||
event: push
|
||||
|
||||
steps:
|
||||
# ============================================
|
||||
# ÉTAPE 1: BUILD DE L'APPLICATION STATIQUE
|
||||
# ============================================
|
||||
# Cette étape construit l'application Next.js et génère les fichiers statiques HTML/CSS/JS
|
||||
|
||||
# Etape 0 : Validation syntaxique du docker-compose
|
||||
# Les vars CI (CI_REPO_OWNER, CI_COMMIT_BRANCH) sont injectees automatiquement par Woodpecker
|
||||
- name: validate
|
||||
image: docker:27-cli
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
RADAR_DOMAIN: validate.example.com
|
||||
commands:
|
||||
- |
|
||||
export COMPOSE_PROJECT_NAME=$(printf '%s-%s-%s' "$CI_REPO_OWNER" "$CI_REPO_NAME" "$CI_COMMIT_BRANCH" | tr 'A-Z/' 'a-z-')
|
||||
docker compose -f docker-compose.business.yml config --quiet
|
||||
- echo "docker-compose.business.yml valide"
|
||||
|
||||
# Etape 1 : Build de l'application statique
|
||||
- name: build
|
||||
# Image Docker utilisée : Node.js 20 sur Alpine Linux (légère et rapide)
|
||||
image: node:20-alpine
|
||||
|
||||
# Variables d'environnement nécessaires pour le build
|
||||
environment:
|
||||
NODE_ENV: production # Mode production (optimisations activées)
|
||||
HUSKY: 0 # Désactive Husky (git hooks) pour éviter les erreurs
|
||||
HUSKY_SKIP_INSTALL: 1 # Skip l'installation de Husky
|
||||
|
||||
# Commandes exécutées dans l'ordre
|
||||
NODE_ENV: production
|
||||
HUSKY: 0
|
||||
HUSKY_SKIP_INSTALL: 1
|
||||
commands:
|
||||
# Installation des dépendances système nécessaires
|
||||
# - git : pour cloner/récupérer des dépendances si nécessaire
|
||||
# - python3 : requis pour les scripts de patch (patch_document.py, add_team_link.py)
|
||||
- apk add --no-cache git python3
|
||||
|
||||
# Installation des dépendances Node.js de la racine du projet
|
||||
# npm ci : Clean Install (supprime node_modules et réinstalle depuis package-lock.json)
|
||||
# --legacy-peer-deps : Ignore les conflits de dépendances peer (compatibilité)
|
||||
- npm ci --legacy-peer-deps
|
||||
|
||||
# Installation des dépendances de radar-app/ (le framework Next.js vendu)
|
||||
# On se déplace dans le dossier radar-app pour installer ses dépendances
|
||||
- cd radar-app
|
||||
|
||||
# Installation des dépendances de radar-app (y compris devDependencies)
|
||||
# --include=dev : Inclut les dépendances de développement (tsx, eslint, etc.)
|
||||
- npm ci --legacy-peer-deps --include=dev
|
||||
|
||||
# Build des icônes SVG en composants React TypeScript
|
||||
# Ce script génère les composants Icons depuis les fichiers SVG dans src/icons/
|
||||
- npm run build:icons
|
||||
|
||||
# Retour à la racine du projet
|
||||
- cd ..
|
||||
|
||||
# Génération des données de visualisation équipe
|
||||
# Ce script lit les profils dans docs/data/team/*.md et les technologies
|
||||
# Il génère public/team-visualization-data.json utilisé par la page /team
|
||||
- cd radar-app && npm ci --legacy-peer-deps --include=dev && npm run build:icons && cd ..
|
||||
- node scripts/generate-team-visualization-data.js
|
||||
|
||||
# Build de l'application complète
|
||||
# Ce script (build-radar.js) :
|
||||
# 1. Copie config-business.json vers radar-app/data/config.json
|
||||
# 2. Copie radar-business/2025-01-15/ vers radar-app/data/radar/2025-01-15/
|
||||
# 3. Copie public/* vers radar-app/public/
|
||||
# 4. Applique les patches (team page, _document, Navigation)
|
||||
# 5. Lance npm run build:data puis npm run build dans radar-app/
|
||||
# 6. Copie radar-app/out/ vers build/ à la racine
|
||||
- npm run build
|
||||
|
||||
# Vérification que le build a réussi
|
||||
# Affiche les 10 premiers fichiers du dossier build/ pour vérifier la génération
|
||||
- ls -la build/ | head -10
|
||||
|
||||
# Volumes temporaires pour accélérer les builds suivants
|
||||
# Ces volumes persistent les node_modules entre les étapes pour éviter de réinstaller
|
||||
volumes:
|
||||
- name: node_modules_root
|
||||
path: /app/node_modules
|
||||
- name: node_modules_radar_app
|
||||
path: /app/radar-app/node_modules
|
||||
|
||||
# ============================================
|
||||
# ÉTAPE 2: DÉPLOIEMENT VIA RSYNC (OPTIONNEL)
|
||||
# ============================================
|
||||
# Cette étape synchronise les fichiers statiques vers un serveur web distant
|
||||
# Utile si vous avez un serveur Nginx/Apache qui sert des fichiers statiques
|
||||
- name: deploy-rsync
|
||||
# Image Alpine (légère) avec rsync et SSH
|
||||
image: alpine:latest
|
||||
|
||||
# Variables d'environnement récupérées depuis les secrets Woodpecker
|
||||
# Etape 2a : Ecriture du .env depuis les secrets
|
||||
# NOTE: from_secret et volumes: incompatibles dans le meme step (bug Woodpecker next)
|
||||
- name: write-env
|
||||
image: alpine:3.20
|
||||
environment:
|
||||
DEPLOY_HOST:
|
||||
from_secret: deploy_host # Exemple: techradar.example.com
|
||||
DEPLOY_USER:
|
||||
from_secret: deploy_user # Exemple: deploy
|
||||
DEPLOY_PATH:
|
||||
from_secret: deploy_path # Exemple: /var/www/techradar
|
||||
DEPLOY_KEY:
|
||||
from_secret: deploy_key # Clé privée SSH complète
|
||||
|
||||
RADAR_DOMAIN:
|
||||
from_secret: radar_domain
|
||||
commands:
|
||||
# Installation des outils nécessaires
|
||||
- apk add --no-cache openssh-client rsync
|
||||
|
||||
# Création du dossier .ssh pour les clés SSH
|
||||
- mkdir -p ~/.ssh
|
||||
|
||||
# Écriture de la clé privée SSH dans le fichier id_rsa
|
||||
# $$ est échappé pour éviter l'interpolation par le shell
|
||||
- echo "$$DEPLOY_KEY" > ~/.ssh/id_rsa
|
||||
|
||||
# Protection de la clé privée (lecture/écriture uniquement pour le propriétaire)
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
# Ajout de la clé publique du serveur dans known_hosts
|
||||
# Évite la vérification manuelle lors de la première connexion
|
||||
- ssh-keyscan -H $$DEPLOY_HOST >> ~/.ssh/known_hosts || true
|
||||
|
||||
# Synchronisation des fichiers
|
||||
# rsync -avz : Archive mode, Verbose, Compression
|
||||
# --delete : Supprime les fichiers sur le serveur qui n'existent plus localement
|
||||
# build/ : Source (dossier build généré à l'étape précédente)
|
||||
# $$DEPLOY_USER@$$DEPLOY_HOST:$$DEPLOY_PATH/ : Destination (serveur distant)
|
||||
- rsync -avz --delete build/ $$DEPLOY_USER@$$DEPLOY_HOST:$$DEPLOY_PATH/
|
||||
|
||||
# Message de confirmation
|
||||
- echo "✅ Déploiement terminé sur $$DEPLOY_HOST:$$DEPLOY_PATH"
|
||||
|
||||
# Conditions de déclenchement
|
||||
# Cette étape ne s'exécute que si :
|
||||
when:
|
||||
branch:
|
||||
- main # Sur la branche main
|
||||
- stand-alone # Ou sur la branche stand-alone
|
||||
event:
|
||||
- push # Et uniquement sur un événement push (pas sur les PR)
|
||||
- env | grep -E "^(RADAR_DOMAIN)=" > .env.deploy
|
||||
# COMPOSE_PROJECT_NAME : convention user-project-branch, genere depuis les vars CI
|
||||
- OWNER=$(echo "$CI_REPO_OWNER" | tr 'A-Z' 'a-z') && REPO=$(echo "$CI_REPO_NAME" | tr 'A-Z' 'a-z') && BRANCH=$(echo "$CI_COMMIT_BRANCH" | tr 'A-Z/' 'a-z-') && echo "COMPOSE_PROJECT_NAME=$OWNER-$REPO-$BRANCH" >> .env.deploy
|
||||
- echo "Fichier .env.deploy cree ($(wc -c < .env.deploy) octets)"
|
||||
|
||||
# ============================================
|
||||
# ÉTAPE 3: DÉPLOIEMENT DOCKER (RECOMMANDÉ)
|
||||
# ============================================
|
||||
# Cette étape build et déploie l'application via Docker
|
||||
# Plus simple et reproductible que rsync
|
||||
- name: deploy-docker
|
||||
# Image Docker officielle avec docker-compose
|
||||
image: docker:latest
|
||||
|
||||
# Configuration Docker
|
||||
environment:
|
||||
DOCKER_HOST: unix:///var/run/docker.sock # Socket Docker du serveur Woodpecker
|
||||
|
||||
commands:
|
||||
# Installation de docker-compose
|
||||
- apk add --no-cache docker-compose
|
||||
|
||||
# Build de l'image Docker sans cache
|
||||
# --no-cache : Force un rebuild complet (garantit que tout est à jour)
|
||||
# docker-compose.business.yml : Fichier de configuration Docker Compose
|
||||
- docker compose -f docker-compose.business.yml build --no-cache
|
||||
|
||||
# Démarrage du conteneur en mode détaché
|
||||
# -d : Détaché (en arrière-plan)
|
||||
# up : Crée et démarre les conteneurs
|
||||
- docker compose -f docker-compose.business.yml up -d
|
||||
|
||||
# Vérification que le conteneur tourne
|
||||
# Affiche les conteneurs contenant "laplank-radar" ou un message si non trouvé
|
||||
- docker ps | grep laplank-radar || echo "Conteneur non trouvé"
|
||||
|
||||
# Volume pour accéder au socket Docker du serveur
|
||||
# Nécessaire pour que le conteneur puisse utiliser Docker
|
||||
# Etape 2b : Deploiement sur sonic via Docker socket
|
||||
# NOTE: from_secret et volumes: incompatibles — pas de secrets ici
|
||||
- name: deploy
|
||||
image: docker:27-cli
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
|
||||
# Conditions de déclenchement (identique à deploy-rsync)
|
||||
when:
|
||||
branch:
|
||||
- main
|
||||
- stand-alone
|
||||
event:
|
||||
- push
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- docker compose --env-file .env.deploy -f docker-compose.business.yml build --no-cache
|
||||
- docker compose --env-file .env.deploy -f docker-compose.business.yml up -d --remove-orphans
|
||||
- docker compose --env-file .env.deploy -f docker-compose.business.yml ps
|
||||
- |
|
||||
DOMAIN=$(grep '^RADAR_DOMAIN=' .env.deploy | cut -d= -f2)
|
||||
|
||||
# ============================================
|
||||
# ÉTAPE 4: NOTIFICATION TELEGRAM
|
||||
# ============================================
|
||||
# Cette étape envoie une notification Telegram à la fin du pipeline
|
||||
# Utile pour être informé immédiatement du résultat du build
|
||||
- name: notify
|
||||
# Plugin Drone/Woodpecker pour Telegram
|
||||
# Compatible avec Woodpecker (fork de Drone)
|
||||
image: appleboy/drone-telegram
|
||||
|
||||
# Configuration du plugin Telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: telegram_token # Token du bot Telegram
|
||||
to:
|
||||
from_secret: telegram_chat_id_ajr # ID du chat Telegram (destinataire)
|
||||
format: markdown # Format du message (Markdown supporté)
|
||||
|
||||
# Message personnalisé avec template Woodpecker
|
||||
# {{#success build.status}} : Condition si le build a réussi
|
||||
# {{repo.name}} : Nom du dépôt Git
|
||||
# {{commit.branch}} : Branche du commit
|
||||
# {{commit.message}} : Message du commit
|
||||
# {{commit.author}} : Auteur du commit
|
||||
# {{build.link}} : Lien vers le build dans Woodpecker
|
||||
message: >
|
||||
{{#success build.status}}
|
||||
✅ Build réussi pour `{{repo.name}}` sur la branche `{{commit.branch}}`
|
||||
📝 Commit: `{{commit.message}}`
|
||||
👤 Auteur: {{commit.author}}
|
||||
🔗 {{ build.link }}
|
||||
{{else}}
|
||||
❌ Build échoué pour `{{repo.name}}` sur la branche `{{commit.branch}}`
|
||||
📝 Commit: `{{commit.message}}`
|
||||
👤 Auteur: {{commit.author}}
|
||||
🔗 {{ build.link }}
|
||||
{{/success}}
|
||||
|
||||
# Conditions de déclenchement
|
||||
# S'exécute toujours, que le build réussisse ou échoue
|
||||
when:
|
||||
status:
|
||||
- success # Si le build réussit
|
||||
- failure # Si le build échoue
|
||||
# --- Certificat TLS (acme.sh via sonic-acme-1) ---
|
||||
# acme.sh est idempotent : skip si cert valide, renouvelle si proche expiration
|
||||
# exit 0 = emis/renouvele, exit 2 = skip (domaine inchange), autres = erreur
|
||||
ACME_EXIT=0
|
||||
docker exec sonic-acme-1 /app/acme.sh \
|
||||
--home /etc/acme.sh \
|
||||
--issue -d "$DOMAIN" \
|
||||
--webroot /usr/share/nginx/html \
|
||||
--server letsencrypt \
|
||||
--accountemail support+acme@asycn.io || ACME_EXIT=$?
|
||||
if [ "$ACME_EXIT" -ne 0 ] && [ "$ACME_EXIT" -ne 2 ]; then
|
||||
echo "ERREUR: acme.sh a echoue (exit $ACME_EXIT)"
|
||||
exit 1
|
||||
fi
|
||||
docker exec sonic-acme-1 cp /etc/acme.sh/$DOMAIN/fullchain.cer /host/certs/$DOMAIN-cert.pem
|
||||
docker exec sonic-acme-1 cp /etc/acme.sh/$DOMAIN/$DOMAIN.key /host/certs/$DOMAIN-key.pem
|
||||
echo "Cert TLS: /host/certs/$DOMAIN-cert.pem OK (acme exit $ACME_EXIT)"
|
||||
|
||||
# ============================================
|
||||
# VOLUMES TEMPORAIRES
|
||||
# ============================================
|
||||
# Ces volumes sont créés temporairement pour chaque pipeline
|
||||
# Ils permettent de partager des données entre les étapes
|
||||
volumes:
|
||||
# Volume pour les node_modules de la racine
|
||||
# Persiste entre les étapes pour éviter de réinstaller
|
||||
- name: node_modules_root
|
||||
temp: {} # Volume temporaire (supprimé à la fin du pipeline)
|
||||
|
||||
# Volume pour les node_modules de radar-app
|
||||
# Persiste entre les étapes pour éviter de réinstaller
|
||||
- name: node_modules_radar_app
|
||||
temp: {}
|
||||
|
||||
# Volume pour accéder au socket Docker du serveur
|
||||
# Nécessaire pour que les conteneurs puissent utiliser Docker
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock # Chemin du socket Docker sur le serveur
|
||||
# Etape 3a : Generation SBOM (Syft) — inventaire des dependances npm du workspace
|
||||
# Scan du repertoire source (pas de docker socket = pas de bug volumes/CI-vars)
|
||||
- name: sbom-generate
|
||||
image: alpine:3.20
|
||||
commands:
|
||||
- apk add --no-cache curl
|
||||
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin latest
|
||||
- mkdir -p .reports
|
||||
- syft dir:. --exclude './build' --exclude './radar-app/.next' --exclude './radar-app/out' -o cyclonedx-json --file .reports/sbom-radar.cyclonedx.json
|
||||
- echo "SBOM genere $(wc -c < .reports/sbom-radar.cyclonedx.json) octets"
|
||||
|
||||
# Etape 3b : Scan CVE (Trivy) depuis le SBOM Syft
|
||||
# Cache /home/syoul/trivy-cache evite ~200Mo de telechargement des DB CVE a chaque build
|
||||
# Prerequis sur sonic : mkdir -p /home/syoul/trivy-cache
|
||||
- name: sbom-scan
|
||||
image: aquasec/trivy:latest
|
||||
volumes:
|
||||
- /home/syoul/trivy-cache:/root/.cache/trivy
|
||||
commands:
|
||||
- trivy sbom --format json --output .reports/trivy-radar.json .reports/sbom-radar.cyclonedx.json
|
||||
- echo "Scan CVE termine"
|
||||
|
||||
# Etape 3c : Publication SBOM vers Dependency-Track (dtrack.syoul.fr)
|
||||
# NOTE: from_secret et volumes: incompatibles — pas de volumes ici
|
||||
- name: sbom-publish
|
||||
image: alpine/curl:latest
|
||||
environment:
|
||||
DTRACK_TOKEN:
|
||||
from_secret: dependency_track_token
|
||||
commands:
|
||||
- |
|
||||
VERSION=$(date +%Y-%m-%d)-$(echo "$CI_COMMIT_SHA" | cut -c1-8)
|
||||
HTTP=$(curl -s -o /tmp/dtrack-response.txt -w "%{http_code}" -X POST "https://dtrack.syoul.fr/api/v1/bom" \
|
||||
-H "X-Api-Key: $DTRACK_TOKEN" \
|
||||
-F "autoCreate=true" \
|
||||
-F "projectName=techradardev-app" \
|
||||
-F "projectVersion=$VERSION" \
|
||||
-F "bom=@.reports/sbom-radar.cyclonedx.json")
|
||||
echo "HTTP $HTTP : $(cat /tmp/dtrack-response.txt)"
|
||||
[ "$HTTP" -ge 200 ] && [ "$HTTP" -lt 300 ] || exit 1
|
||||
|
||||
# Etape 4 : Healthcheck post-deploiement
|
||||
- name: healthcheck
|
||||
image: alpine:3.20
|
||||
commands:
|
||||
- apk add --no-cache --quiet curl
|
||||
- |
|
||||
DOMAIN=$(grep '^RADAR_DOMAIN=' .env.deploy | cut -d= -f2)
|
||||
if [ -z "$DOMAIN" ]; then
|
||||
echo "ERREUR: RADAR_DOMAIN non defini dans .env.deploy"
|
||||
exit 1
|
||||
fi
|
||||
TARGET="https://$DOMAIN"
|
||||
echo "Healthcheck sur $TARGET (max 100s)..."
|
||||
MAX=20
|
||||
i=0
|
||||
until [ $i -ge $MAX ]; do
|
||||
CODE=$(curl -sSo /dev/null -w "%{http_code}" "$TARGET" 2>/dev/null)
|
||||
echo "Tentative $((i+1))/$MAX - HTTP $CODE"
|
||||
if [ "$CODE" = "200" ] || [ "$CODE" = "301" ] || [ "$CODE" = "302" ]; then
|
||||
echo "Radar repond sur $TARGET"
|
||||
exit 0
|
||||
fi
|
||||
i=$((i+1))
|
||||
sleep 5
|
||||
done
|
||||
echo "ERREUR: Radar ne repond pas apres 100 secondes"
|
||||
exit 1
|
||||
|
||||
# Notification en cas d'echec
|
||||
- name: notify-failure
|
||||
image: alpine:3.20
|
||||
commands:
|
||||
- 'echo "ECHEC pipeline #$CI_BUILD_NUMBER sur commit $CI_COMMIT_SHA"'
|
||||
- 'echo "Branche: $CI_COMMIT_BRANCH"'
|
||||
when:
|
||||
- status: failure
|
||||
|
||||
55
Readme.md
55
Readme.md
@@ -124,27 +124,27 @@ Accès à trois pages de stratégie depuis le header :
|
||||
|
||||
```
|
||||
TechradarDev/
|
||||
├── radar-app/ # Framework Next.js vendu (stand-alone)
|
||||
│ ├── src/ # Code source Next.js
|
||||
│ ├── data/ # Données du radar
|
||||
│ └── package.json # Next.js 16.1.6, React 19
|
||||
├── radar-business/ # Contenu du radar business
|
||||
│ ├── 2025-01-15/ # Release actuelle (38 technologies)
|
||||
│ └── config-business.json # Configuration du radar
|
||||
├── docs/
|
||||
│ ├── data/
|
||||
│ │ └── team/ # Profils des 12 membres
|
||||
│ └── app/ # Documentation technique
|
||||
├── radar-business/ # ✏️ SOURCE DE VÉRITÉ — éditer ici
|
||||
│ ├── 2025-01-15/ # Fichiers .md des technologies (38 blips)
|
||||
│ ├── config-business.json # Configuration du radar (quadrants, rings)
|
||||
│ └── FORMAT-BLIP.md # Format des métadonnées
|
||||
├── data/ # ✏️ Données de build versionnées
|
||||
│ └── team/ # Profils des 12 membres (*.md)
|
||||
├── radar-app/ # ⚙️ Framework Next.js (ne pas éditer)
|
||||
│ ├── src/ # Code source Next.js
|
||||
│ └── data/ # Copie générée au build (ne pas éditer)
|
||||
├── radar/ # ⚠️ Dossier temporaire (généré par serve-business.sh)
|
||||
│ └── ... # Ne jamais éditer ici — écrasé à chaque lancement
|
||||
├── scripts/
|
||||
│ ├── build-radar.js # Script de build stand-alone
|
||||
│ ├── serve-radar.js # Script de serve
|
||||
│ ├── generate-team-visualization-data.js # Génération données équipe
|
||||
│ ├── generate-team-visualization-data.js
|
||||
│ └── ...
|
||||
├── public/ # Fichiers statiques
|
||||
│ ├── team-block-script.js # Script page équipe
|
||||
│ └── team-visualization-data.json # Données visualisations
|
||||
├── Dockerfile.business # Dockerfile pour déploiement
|
||||
└── docker-compose.business.yml # Configuration Docker Compose
|
||||
│ ├── team-block-script.js
|
||||
│ └── team-visualization-data.json # Généré par generate-team-visualization-data.js
|
||||
├── Dockerfile.business
|
||||
└── docker-compose.business.yml
|
||||
```
|
||||
|
||||
## 🛠️ Scripts disponibles
|
||||
@@ -158,6 +158,15 @@ TechradarDev/
|
||||
| `npm run extract-tech` | Extraction des technologies depuis la doc |
|
||||
| `npm run analyze-business` | Analyse des métriques business |
|
||||
|
||||
## ✏️ Où éditer le contenu
|
||||
|
||||
| Quoi | Dossier |
|
||||
|---|---|
|
||||
| Ajouter / modifier une technologie | `radar-business/2025-01-15/` |
|
||||
| Ajouter / modifier un membre d'équipe | `data/team/` |
|
||||
|
||||
> ⚠️ Ne jamais éditer dans `radar/` (temporaire, écrasé au lancement) ni dans `radar-app/data/` (copie générée au build).
|
||||
|
||||
## 📝 Content Guidelines
|
||||
|
||||
### Tags disponibles
|
||||
@@ -191,20 +200,14 @@ Voir `radar-business/FORMAT-BLIP.md` pour le format complet des métadonnées bu
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
La documentation complète est disponible dans le dossier `docs/` :
|
||||
La documentation technique est disponible dans `docs/app/` (non versionnée, locale uniquement) :
|
||||
|
||||
- [Architecture](./docs/app/architecture.md) - Architecture technique du projet
|
||||
- [Configuration](./docs/app/configuration.md) - Configuration du radar
|
||||
- [Développement](./docs/app/developpement.md) - Guide de développement
|
||||
- [Déploiement](./docs/app/deploiement.md) - Guide de déploiement
|
||||
- [Contribution](./docs/app/contribution.md) - Guide de contribution
|
||||
- [Guide Radar Business](./docs/app/guide-radar-business.md) - Guide spécifique au radar business
|
||||
- [Guide Page Équipe](./docs/app/guide-page-equipe.md) - Documentation de la page équipe
|
||||
- [Migration Next.js 16](./docs/app/migration-nextjs-16.md) - Notes de migration
|
||||
- Architecture, Configuration, Développement, Déploiement
|
||||
- Guide Radar Business, Guide Page Équipe, Migration Next.js 16
|
||||
|
||||
## 🔄 État du projet
|
||||
|
||||
- **Branche actuelle** : `stand-alone`
|
||||
- **Branche principale** : `main`
|
||||
- **Version** : 4.3.0
|
||||
- **Statut** : Projet stand-alone, indépendant du package externe `aoe_technology_radar`
|
||||
- **Framework** : Code vendu dans `radar-app/` (basé sur aoe_technology_radar)
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
version: '3.8'
|
||||
# Convention de nommage : user-project-branch (ex: ajr-techradardev-main)
|
||||
# Permet plusieurs instances en parallele (prod/test) sans collision
|
||||
name: ${COMPOSE_PROJECT_NAME:-ajr-techradardev-main}
|
||||
|
||||
services:
|
||||
radar-business:
|
||||
container_name: laplank-radar-technolologique
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-ajr-techradardev-main}-app
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.business
|
||||
pull: true # Force le pull de l'image de base pour éviter le cache
|
||||
pull: true
|
||||
args:
|
||||
BUILD_DATE: "${BUILD_DATE:-$(date +%s)}"
|
||||
BUILD_VERSION: "${BUILD_VERSION:-dev}"
|
||||
CACHE_BUST: "${CACHE_BUST:-$(date +%s%N)}" # Nanosecondes pour garantir l'unicité et forcer l'invalidation
|
||||
# Note: no_cache n'est pas supporté dans docker-compose
|
||||
# Pour forcer le rebuild sans cache dans Portainer, utilisez l'option "Rebuild" avec "No cache" dans l'interface
|
||||
# Si vous utilisez une image pré-bâtie, décommentez image et commentez build
|
||||
# image: votre-registre/laplank-radar-business:latest
|
||||
CACHE_BUST: "${CACHE_BUST:-$(date +%s%N)}"
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3006:3000" # Mappe le port 3006 de l'hôte vers le port 3000 du conteneur
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
# Optionnel : Persistance des logs si nécessaire
|
||||
# volumes:
|
||||
# - ./logs:/app/logs
|
||||
labels:
|
||||
# Registrator lit l'IP du conteneur depuis le reseau "sonic" (-useIpFromNetwork sonic)
|
||||
# et enregistre le service dans Consul avec le tag urlprefix- -> Fabio route vers ce service
|
||||
- SERVICE_3000_NAME=${COMPOSE_PROJECT_NAME:-ajr-techradardev-main}-app-3000
|
||||
- SERVICE_3000_TAGS=urlprefix-${RADAR_DOMAIN}/*
|
||||
- SERVICE_3000_CHECK_TCP=true
|
||||
# sonic-acme-1 (acme-companion) emet le cert TLS et le copie dans /host/certs/
|
||||
# Fabio le detecte automatiquement par SNI pour HTTPS
|
||||
- LETSENCRYPT_HOST=${RADAR_DOMAIN}
|
||||
networks:
|
||||
- sonic
|
||||
|
||||
networks:
|
||||
sonic:
|
||||
# Reseau externe existant sur le serveur (partage avec Registrator/Consul/Fabio)
|
||||
external: true
|
||||
|
||||
1129
package-lock.json
generated
1129
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
1414
radar-app/package-lock.json
generated
1414
radar-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,7 @@
|
||||
"marked": "^15.0.7",
|
||||
"marked-highlight": "^2.2.1",
|
||||
"next": "16.1.6",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-nested": "^7.0.2",
|
||||
"postcss-preset-env": "^10.1.5",
|
||||
"prettier": "^3.5.3",
|
||||
|
||||
@@ -358,7 +358,7 @@ ${metrics.emergingTechnologies.filter(t => t.differentiation === 'high').length
|
||||
// Main
|
||||
function main() {
|
||||
const radarDir = path.join(__dirname, '../radar-business/2025-01-15');
|
||||
const outputFile = path.join(__dirname, '../docs/data/analyse-strategique.md');
|
||||
const outputFile = path.join(__dirname, '../data/analyse-strategique.md');
|
||||
|
||||
if (!fs.existsSync(radarDir)) {
|
||||
console.error(`Répertoire non trouvé: ${radarDir}`);
|
||||
|
||||
@@ -164,7 +164,7 @@ try {
|
||||
// Modifier Navigation.tsx
|
||||
const patchNavScript = path.join(CWD, 'docker', 'add_team_link.sh');
|
||||
if (fs.existsSync(patchNavScript)) {
|
||||
execSync(`bash ${patchNavScript}`, {
|
||||
execSync(`sh ${patchNavScript}`, {
|
||||
cwd: CWD,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ const path = require('path');
|
||||
|
||||
// Charger les compétences de l'équipe depuis les fichiers individuels
|
||||
function loadTeamSkills() {
|
||||
const teamDir = path.join(__dirname, '../docs/data/team');
|
||||
const teamDir = path.join(__dirname, '../data/team');
|
||||
const teamSkills = {};
|
||||
|
||||
if (!fs.existsSync(teamDir)) {
|
||||
@@ -291,7 +291,7 @@ function parseTechnologiesFile(filePath) {
|
||||
|
||||
// Main
|
||||
function main() {
|
||||
const techFile = path.join(__dirname, '../docs/data/technologies-duniter.md');
|
||||
const techFile = path.join(__dirname, '../data/technologies-duniter.md');
|
||||
const outputDir = path.join(__dirname, '../radar-business/2025-01-15');
|
||||
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
|
||||
@@ -145,7 +145,7 @@ function loadTechnologies() {
|
||||
|
||||
// Charger les membres de l'équipe (avec profils complets)
|
||||
function loadTeamMembers() {
|
||||
const teamDir = path.join(__dirname, '../docs/data/team');
|
||||
const teamDir = path.join(__dirname, '../data/team');
|
||||
const members = [];
|
||||
|
||||
if (!fs.existsSync(teamDir)) {
|
||||
|
||||
Reference in New Issue
Block a user