Files
TechradarDev/.woodpecker.yml
syoul fa0aa808ac feat: intégration Fabio/Consul/Registrator + TLS acme.sh
docker-compose.business.yml:
- Suppression version: obsolete et ports: (Fabio gère le routing)
- Ajout labels SERVICE_3000_* pour Registrator/Consul/Fabio
- Ajout LETSENCRYPT_HOST pour sonic-acme-1
- Ajout réseau sonic (externe, partagé avec la stack)

.woodpecker.yml:
- Ajout write-env (RADAR_DOMAIN depuis secret, séparé car from_secret + volumes incompatibles)
- Ajout TLS acme.sh dans deploy (idempotent, exit 2 = skip)
- Healthcheck sur https://RADAR_DOMAIN (100s max)

Secret Woodpecker à créer : radar_domain

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:29:39 +01:00

104 lines
3.6 KiB
YAML

when:
- branch:
- main
- stand-alone
event: push
steps:
# Etape 1 : Build de l'application statique
# Les vars CI (CI_REPO_OWNER, CI_COMMIT_BRANCH) sont injectees automatiquement par Woodpecker
- name: build
image: node:20-alpine
environment:
NODE_ENV: production
HUSKY: 0
HUSKY_SKIP_INSTALL: 1
commands:
- apk add --no-cache git python3
- npm ci --legacy-peer-deps
- cd radar-app && npm ci --legacy-peer-deps --include=dev && npm run build:icons && cd ..
- node scripts/generate-team-visualization-data.js
- npm run build
- ls -la build/ | head -10
# 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:
RADAR_DOMAIN:
from_secret: radar_domain
commands:
- env | grep -E "^(RADAR_DOMAIN)=" > .env.deploy
- echo "Fichier .env.deploy cree ($(wc -c < .env.deploy) octets)"
# 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:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- export $(cat .env.deploy | xargs)
- docker compose -f docker-compose.business.yml build --no-cache
- docker compose -f docker-compose.business.yml up -d --remove-orphans
- docker compose -f docker-compose.business.yml ps
- |
DOMAIN=$(grep '^RADAR_DOMAIN=' .env.deploy | cut -d= -f2)
# --- 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)"
# Etape 3 : 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