- Ajout step validate (docker compose config avec placeholder) - Remplacement export \$(cat .env.deploy | xargs) → --env-file .env.deploy - SERVICE_3000_TAGS : urlprefix-DOMAIN/ → urlprefix-DOMAIN/* (match tous les paths) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
118 lines
4.4 KiB
YAML
118 lines
4.4 KiB
YAML
when:
|
|
- branch:
|
|
- main
|
|
- stand-alone
|
|
event: push
|
|
|
|
steps:
|
|
|
|
# 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: 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
|
|
# 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)"
|
|
|
|
# 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:
|
|
- 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)
|
|
|
|
# --- 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
|