# Exemple de configuration Woodpecker CI pour le déploiement avec URLs dynamiques # Toute la logique de déploiement est intégrée directement dans ce fichier pipeline: # Étape de test (optionnel) test: image: node:20-alpine # Adaptez selon votre stack commands: - npm ci - npm run test - npm run lint # Étape de build build: image: docker:24-dind privileged: true environment: - DOCKER_HOST=tcp://docker:2375 commands: # Construire l'image Docker - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest # Déploiement sur la branche main/master deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=3000 # Adaptez selon votre application - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} # Secret Woodpecker - NPM_API_TOKEN=${NPM_API_TOKEN} # Secret Woodpecker commands: # Installer les dépendances nécessaires - apk add --no-cache curl jq # Nettoyer le nom de l'application (minuscules, pas de caractères spéciaux) - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') # Générer le sous-domaine basé sur la branche - | if [ "$CI_COMMIT_BRANCH" = "main" ] || [ "$CI_COMMIT_BRANCH" = "master" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" # Afficher les informations de déploiement - echo "🚀 Déploiement de ${APP_NAME_CLEAN}" - echo " Port: ${APP_PORT}" - echo " Branche: ${CI_COMMIT_BRANCH}" - echo " URL: https://${APP_URL}" # Vérifier que le réseau Docker existe - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true # Arrêter et supprimer l'ancien conteneur s'il existe - echo "📦 Arrêt de l'ancien conteneur..." - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true # Vérifier que l'image existe - docker image inspect "${APP_NAME_CLEAN}:latest" || (echo "❌ L'image ${APP_NAME_CLEAN}:latest n'existe pas" && exit 1) # Lancer le nouveau conteneur avec labels Consul - echo "🐳 Lancement du conteneur..." - | CONTAINER_ID=$(docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web,${CI_COMMIT_BRANCH}" \ --label "SERVICE_${APP_PORT}_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_${APP_PORT}_CHECK_HTTP=/" \ --label "SERVICE_${APP_PORT}_CHECK_INTERVAL=15s" \ -p "${APP_PORT}" \ "${APP_NAME_CLEAN}:latest") - echo "✅ Conteneur lancé: ${CONTAINER_ID}" # Attendre que le conteneur soit prêt - echo "⏳ Attente du démarrage du conteneur..." - sleep 3 # Récupérer l'IP du conteneur - APP_CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") - echo "📍 IP interne: ${APP_CONTAINER_IP}:${APP_PORT}" # Configurer Nginx Proxy Manager si les variables sont définies - | if [ -n "${NPM_API_URL}" ] && [ -n "${NPM_API_TOKEN}" ]; then echo "📝 Configuration du reverse proxy Nginx Proxy Manager..." # Vérifier si le proxy existe déjà EXISTING_PROXY=$(curl -s -H "Authorization: Bearer ${NPM_API_TOKEN}" \ "${NPM_API_URL}/api/nginx/proxy-hosts" 2>/dev/null | \ jq -r ".[] | select(.domain_names[] == \"${APP_URL}\") | .id" 2>/dev/null | head -1) PROXY_DATA=$(cat </dev/null) if echo "${RESPONSE}" | jq -e '.id' &> /dev/null; then echo "✅ Proxy mis à jour avec succès" else echo "⚠️ Échec de la mise à jour du proxy: ${RESPONSE}" fi else # Créer un nouveau proxy echo " Création d'un nouveau proxy..." RESPONSE=$(curl -s -X POST "${NPM_API_URL}/api/nginx/proxy-hosts" \ -H "Authorization: Bearer ${NPM_API_TOKEN}" \ -H "Content-Type: application/json" \ -d "${PROXY_DATA}" 2>/dev/null) if echo "${RESPONSE}" | jq -e '.id' &> /dev/null; then echo "✅ Proxy créé avec succès" else echo "⚠️ Échec de la création du proxy: ${RESPONSE}" echo " Configuration manuelle requise: ${APP_URL} -> ${APP_CONTAINER_IP}:${APP_PORT}" fi fi else echo "⚠️ NPM_API_URL ou NPM_API_TOKEN non définis" echo " Configuration manuelle du reverse proxy requise" echo " Domaine: ${APP_URL} -> ${APP_CONTAINER_IP}:${APP_PORT}" fi # Résumé du déploiement - echo "" - echo "═══════════════════════════════════════════════════════════" - echo "✅ Déploiement terminé avec succès" - echo "═══════════════════════════════════════════════════════════" - echo "Application: ${APP_NAME_CLEAN}" - echo "URL: https://${APP_URL}" - echo "IP interne: ${APP_CONTAINER_IP}:${APP_PORT}" - echo "Conteneur: ${CONTAINER_ID}" - echo "═══════════════════════════════════════════════════════════" when: branch: main status: success # Déploiement sur les branches de développement (staging) deploy-staging: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=3000 - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} - NPM_API_TOKEN=${NPM_API_TOKEN} commands: - apk add --no-cache curl jq # Nettoyer le nom de l'application - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') # Générer le sous-domaine avec le nom de la branche - BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') - SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - echo "🚀 Déploiement staging de ${APP_NAME_CLEAN} (branche: ${CI_COMMIT_BRANCH})" - echo " URL: https://${APP_URL}" # Vérifier le réseau - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true # Arrêter l'ancien conteneur - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true # Lancer le nouveau conteneur - | CONTAINER_ID=$(docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web,staging,${CI_COMMIT_BRANCH}" \ --label "SERVICE_${APP_PORT}_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_${APP_PORT}_CHECK_HTTP=/" \ --label "SERVICE_${APP_PORT}_CHECK_INTERVAL=15s" \ -p "${APP_PORT}" \ "${APP_NAME_CLEAN}:latest") - sleep 3 - APP_CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") # Configurer NPM (même logique que pour main) - | if [ -n "${NPM_API_URL}" ] && [ -n "${NPM_API_TOKEN}" ]; then EXISTING_PROXY=$(curl -s -H "Authorization: Bearer ${NPM_API_TOKEN}" \ "${NPM_API_URL}/api/nginx/proxy-hosts" 2>/dev/null | \ jq -r ".[] | select(.domain_names[] == \"${APP_URL}\") | .id" 2>/dev/null | head -1) PROXY_DATA=$(cat < /dev/null echo "✅ Proxy mis à jour" else curl -s -X POST "${NPM_API_URL}/api/nginx/proxy-hosts" \ -H "Authorization: Bearer ${NPM_API_TOKEN}" \ -H "Content-Type: application/json" \ -d "${PROXY_DATA}" > /dev/null echo "✅ Proxy créé" fi fi - echo "✅ Déployé sur https://${APP_URL}" when: branch: - develop - feature/* status: success