Compare commits
25
Commits
801fbd359d
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86f87955cf | ||
|
|
7a9d45fb0c | ||
|
|
58d8a8d7fb | ||
|
|
96c690dd79 | ||
|
|
ccbcf5c6be | ||
|
|
645d07fdfc | ||
|
|
e1cffb8fc8 | ||
|
|
3daef9b567 | ||
|
|
d987b9e46c | ||
|
|
c5a4ae9498 | ||
|
|
3354f3ee70 | ||
|
|
dae97f15ba | ||
|
|
37611dc79f | ||
|
|
ab63a8a913 | ||
|
|
a4186ab4d3 | ||
|
|
1231947e2b | ||
|
|
7450ea07ab | ||
|
|
22d8f5aea1 | ||
|
|
e70bf08fe9 | ||
|
|
748d86e71c | ||
|
|
75611d147c | ||
|
|
e6de9836fc | ||
|
|
c198368c19 | ||
|
|
390c547920 | ||
|
|
2d390b553d |
@@ -120,34 +120,75 @@ jobs:
|
||||
DB_SERVER_HOST: ${{ secrets.PROD_DB_HOST }}
|
||||
DB_SERVER_USER: ${{ secrets.PROD_DB_SSH_USER }}
|
||||
REMOTE_PORT: ${{ secrets.REMOTE_PORT }}
|
||||
PROD_DB_SSH_KEY: ${{ secrets.PROD_DB_SSH_KEY }}
|
||||
SSH_KEY_PATH_SECRET: ${{ secrets.SSH_KEY_PATH }}
|
||||
SSH_KEY_SECRET: ${{ secrets.SSH_KEY }}
|
||||
run: |
|
||||
TARGET_HOST="${DB_SERVER_HOST:-10.8.0.3}"
|
||||
TARGET_USER="${DB_SERVER_USER:-root}"
|
||||
PORT="${REMOTE_PORT:-22}"
|
||||
DEST_DIR="/opt/as-talange"
|
||||
RAW_KEY="${PROD_DB_SSH_KEY:-${SSH_KEY_PATH_SECRET:-${SSH_KEY_SECRET}}}"
|
||||
|
||||
if [ -n "${RAW_KEY}" ] && [ -f "${RAW_KEY}" ]; then
|
||||
RAW_KEY=$(cat "${RAW_KEY}")
|
||||
fi
|
||||
|
||||
if [ -z "${RAW_KEY}" ]; then
|
||||
if [ -f /root/.ssh/gitea_ci_key ]; then
|
||||
RAW_KEY=$(cat /root/.ssh/gitea_ci_key)
|
||||
elif [ -f /home/ucef/.ssh/gitea_ci_key ]; then
|
||||
RAW_KEY=$(cat /home/ucef/.ssh/gitea_ci_key)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${RAW_KEY}" ]; then
|
||||
echo "========================================================================="
|
||||
echo "ERREUR : Le secret PROD_DB_SSH_KEY est totalement vide dans Gitea !"
|
||||
echo "========================================================================="
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KEY_B64=$(printf "%s" "${RAW_KEY}" | tr -d '\r' | base64 | tr -d '\r\n')
|
||||
SCRIPT_B64=$(base64 scripts/backup_db.sh | tr -d '\r\n')
|
||||
[ -f .env ] && ENV_B64=$(base64 .env | tr -d '\r\n') || ENV_B64=""
|
||||
|
||||
docker run --rm --net=host \
|
||||
-v "$(pwd):/workspace" -w /workspace \
|
||||
-v "${HOME}/.ssh:/root/.ssh:ro" \
|
||||
-e TARGET_HOST="${TARGET_HOST}" \
|
||||
-e TARGET_USER="${TARGET_USER}" \
|
||||
-e PORT="${PORT}" \
|
||||
-e DEST_DIR="${DEST_DIR}" \
|
||||
-e KEY_B64="${KEY_B64}" \
|
||||
-e SCRIPT_B64="${SCRIPT_B64}" \
|
||||
-e ENV_B64="${ENV_B64}" \
|
||||
alpine:latest sh -c '
|
||||
apk add --no-cache openssh-client rsync && \
|
||||
KEY_ARG="" && \
|
||||
if [ -f /root/.ssh/gitea_ci_key ]; then \
|
||||
KEY_ARG="-i /root/.ssh/gitea_ci_key -o IdentitiesOnly=yes" ; \
|
||||
elif [ -f /root/.ssh/id_ed25519 ]; then \
|
||||
KEY_ARG="-i /root/.ssh/id_ed25519 -o IdentitiesOnly=yes" ; \
|
||||
elif [ -f /root/.ssh/id_rsa ]; then \
|
||||
KEY_ARG="-i /root/.ssh/id_rsa -o IdentitiesOnly=yes" ; \
|
||||
apk add --no-cache openssh-client rsync coreutils && \
|
||||
(echo "$KEY_B64" | base64 -d 2>/dev/null || echo "$KEY_B64" | base64 --decode) > /tmp/raw_key && \
|
||||
HEADER=$(grep "BEGIN" /tmp/raw_key) && \
|
||||
FOOTER=$(grep "END" /tmp/raw_key) && \
|
||||
BODY=$(grep -v "BEGIN" /tmp/raw_key | grep -v "END" | tr -d " \r\n") && \
|
||||
printf "%s\n" "$HEADER" > /tmp/working_key && \
|
||||
printf "%s\n" "$BODY" | fold -w 64 >> /tmp/working_key && \
|
||||
printf "%s\n" "$FOOTER" >> /tmp/working_key && \
|
||||
echo "" >> /tmp/working_key && \
|
||||
chmod 600 /tmp/working_key && \
|
||||
(echo "$SCRIPT_B64" | base64 -d 2>/dev/null || echo "$SCRIPT_B64" | base64 --decode) > /tmp/backup_db.sh && \
|
||||
if [ -n "$ENV_B64" ]; then \
|
||||
(echo "$ENV_B64" | base64 -d 2>/dev/null || echo "$ENV_B64" | base64 --decode) > /tmp/.env ; \
|
||||
else \
|
||||
touch /tmp/.env ; \
|
||||
fi && \
|
||||
SSH_CMD="ssh -p ${PORT} ${KEY_ARG} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=15" && \
|
||||
echo "Deploying backup script and .env to DB Server (${TARGET_USER}@${TARGET_HOST}:${DEST_DIR})..." && \
|
||||
echo "=== 🔍 DIAGNOSTIC DETAILS ===" && \
|
||||
echo "Target Host: ${TARGET_USER}@${TARGET_HOST} (Port: ${PORT})" && \
|
||||
echo "Destination Directory: ${DEST_DIR}" && \
|
||||
echo "=== 🔑 KEY FINGERPRINT ===" && \
|
||||
ssh-keygen -l -f /tmp/working_key && \
|
||||
SSH_CMD="ssh -p ${PORT} -i /tmp/working_key -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=15" && \
|
||||
echo "=== 🚀 EXECUTING REMOTE COMMAND ===" && \
|
||||
$SSH_CMD "${TARGET_USER}@${TARGET_HOST}" "mkdir -p ${DEST_DIR}/scripts" && \
|
||||
rsync -avz -e "$SSH_CMD" scripts/backup_db.sh "${TARGET_USER}@${TARGET_HOST}:${DEST_DIR}/scripts/" && \
|
||||
rsync -avz -e "$SSH_CMD" .env "${TARGET_USER}@${TARGET_HOST}:${DEST_DIR}/.env" && \
|
||||
echo "=== 📦 RSYNC TRANSFER SCRIPT & ENV ===" && \
|
||||
rsync -avz -e "$SSH_CMD" /tmp/backup_db.sh "${TARGET_USER}@${TARGET_HOST}:${DEST_DIR}/scripts/backup_db.sh" && \
|
||||
rsync -avz -e "$SSH_CMD" /tmp/.env "${TARGET_USER}@${TARGET_HOST}:${DEST_DIR}/.env" && \
|
||||
$SSH_CMD "${TARGET_USER}@${TARGET_HOST}" "chmod +x ${DEST_DIR}/scripts/backup_db.sh" && \
|
||||
echo "Backup script and .env deployed successfully to ${DEST_DIR} on DB Server!"
|
||||
echo "SUCCESS: Backup script and .env deployed successfully to ${DEST_DIR} on DB Server!"
|
||||
'
|
||||
|
||||
+96
-6
@@ -31,6 +31,14 @@ DB_HOST="${POSTGRES_HOST:-localhost}"
|
||||
DB_PORT="${POSTGRES_PORT:-5432}"
|
||||
CONTAINER_NAME="${DOCKER_CONTAINER_NAME:-astalange_db}"
|
||||
|
||||
# Variables UAT
|
||||
ENABLE_UAT_RESTORE="${ENABLE_UAT_RESTORE:-true}"
|
||||
UAT_DB_HOST="${UAT_DB_HOST:-10.8.0.2}"
|
||||
UAT_DB_PORT="${UAT_DB_PORT:-5433}"
|
||||
UAT_DB_NAME="${UAT_DB_NAME:-astalange}"
|
||||
UAT_DB_USER="${UAT_DB_USER:-myuser}"
|
||||
UAT_DB_PASSWORD="${UAT_DB_PASSWORD:-mypassword}"
|
||||
|
||||
# Configuration du transfert distant vers le VPS (optionnel)
|
||||
ENABLE_REMOTE_COPY="${ENABLE_REMOTE_COPY:-false}"
|
||||
REMOTE_HOST="${REMOTE_HOST:-}"
|
||||
@@ -80,24 +88,106 @@ if [ "$STATUS" = "SUCCESS" ]; then
|
||||
# Vérification si le conteneur Docker est actif
|
||||
if command -v docker >/dev/null 2>&1 && docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
||||
log "Mode détection: Conteneur Docker '${CONTAINER_NAME}' trouvé. Utilisation de pg_dump via docker exec."
|
||||
docker exec -e PGPASSWORD="${DB_PASSWORD}" "${CONTAINER_NAME}" pg_dump -U "${DB_USER}" -d "${DB_NAME}" | gzip > "$DUMP_PATH" 2>> "$LOG_FILE"
|
||||
docker exec -e PGPASSWORD="${DB_PASSWORD}" "${CONTAINER_NAME}" pg_dump --no-owner --no-privileges -U "${DB_USER}" -d "${DB_NAME}" | gzip > "$DUMP_PATH" 2>> "$LOG_FILE"
|
||||
DUMP_EXIT_CODE=${PIPESTATUS[0]}
|
||||
else
|
||||
log "Mode détection: Exécution directe de pg_dump (hôte local)."
|
||||
PGPASSWORD="${DB_PASSWORD}" pg_dump -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" | gzip > "$DUMP_PATH" 2>> "$LOG_FILE"
|
||||
PGPASSWORD="${DB_PASSWORD}" pg_dump --no-owner --no-privileges -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" | gzip > "$DUMP_PATH" 2>> "$LOG_FILE"
|
||||
DUMP_EXIT_CODE=${PIPESTATUS[0]}
|
||||
fi
|
||||
|
||||
if [ ${DUMP_EXIT_CODE} -eq 0 ] && [ -s "$DUMP_PATH" ]; then
|
||||
DUMP_SIZE=$(du -h "$DUMP_PATH" | cut -f1)
|
||||
log "✅ Dump généré avec succès ! Taille du fichier : ${DUMP_SIZE}"
|
||||
else
|
||||
if [ ${DUMP_EXIT_CODE} -eq 0 ] || [ ${DUMP_EXIT_CODE} -eq 141 ]; then
|
||||
if [ -s "$DUMP_PATH" ]; then
|
||||
DUMP_SIZE=$(du -h "$DUMP_PATH" | cut -f1)
|
||||
log "✅ Dump généré avec succès ! Taille du fichier : ${DUMP_SIZE}"
|
||||
DUMP_EXIT_CODE=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${DUMP_EXIT_CODE} -ne 0 ]; then
|
||||
log "❌ ERREUR lors de l'extraction de la base de données (code de sortie: ${DUMP_EXIT_CODE})."
|
||||
STATUS="FAILURE"
|
||||
rm -f "$DUMP_PATH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2b. Restauration et Anonymisation vers la BDD UAT (10.8.0.2)
|
||||
if [ "$STATUS" = "SUCCESS" ] && [ "$ENABLE_UAT_RESTORE" = "true" ]; then
|
||||
log "Démarrage de la restauration et l'anonymisation sur UAT (${UAT_DB_USER}@${UAT_DB_HOST}:${UAT_DB_PORT}/${UAT_DB_NAME})..."
|
||||
|
||||
CLEAN_SCHEMA_SQL="
|
||||
DO \$\$ DECLARE r RECORD; BEGIN FOR r IN (SELECT oid FROM pg_largeobject_metadata) LOOP PERFORM lo_unlink(r.oid); END LOOP; EXCEPTION WHEN OTHERS THEN NULL; END \$\$;
|
||||
DROP SCHEMA IF EXISTS public CASCADE;
|
||||
CREATE SCHEMA public;
|
||||
GRANT ALL ON SCHEMA public TO ${UAT_DB_USER};
|
||||
GRANT ALL ON SCHEMA public TO public;
|
||||
"
|
||||
|
||||
ANONYMIZE_SQL="
|
||||
UPDATE adherent SET
|
||||
nom = 'Nom_Adherent_' || id,
|
||||
prenom = 'Prenom_Adherent_' || id,
|
||||
email = 'adherent' || id || '@test.local',
|
||||
telephone = '06' || LPAD((id)::text, 8, '0'),
|
||||
lieu_naissance_ville = 'Ville_' || id,
|
||||
representant_legal = CASE
|
||||
WHEN representant_legal IS NOT NULL AND TRIM(representant_legal) <> ''
|
||||
THEN 'Representant_' || id
|
||||
ELSE representant_legal
|
||||
END;
|
||||
|
||||
UPDATE pre_inscription SET
|
||||
nom = 'Nom_PreInscr_' || id,
|
||||
prenom = 'Prenom_PreInscr_' || id,
|
||||
email = 'preinscr' || id || '@test.local',
|
||||
telephone = '06' || LPAD((id)::text, 8, '0'),
|
||||
lieu_naissance_ville = 'Ville_' || id,
|
||||
representant_legal = CASE
|
||||
WHEN representant_legal IS NOT NULL AND TRIM(representant_legal) <> ''
|
||||
THEN 'Representant_PreInscr_' || id
|
||||
ELSE representant_legal
|
||||
END;
|
||||
|
||||
UPDATE educateur SET
|
||||
nom = 'Nom_Educ_' || id,
|
||||
prenom = 'Prenom_Educ_' || id,
|
||||
email = 'educ' || id || '@test.local',
|
||||
telephone = '06' || LPAD((id)::text, 8, '0');
|
||||
"
|
||||
|
||||
RESTORE_SUCCESS=false
|
||||
|
||||
if command -v psql >/dev/null 2>&1; then
|
||||
log "Réinitialisation du schéma public sur UAT..."
|
||||
PGPASSWORD="${UAT_DB_PASSWORD}" psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" -c "$CLEAN_SCHEMA_SQL" >> "$LOG_FILE" 2>&1
|
||||
|
||||
log "Restauration du dump Prod vers UAT..."
|
||||
if gunzip -c "$DUMP_PATH" | PGPASSWORD="${UAT_DB_PASSWORD}" psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" >> "$LOG_FILE" 2>&1; then
|
||||
log "Exécution des requêtes d'anonymisation sur UAT..."
|
||||
if PGPASSWORD="${UAT_DB_PASSWORD}" psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" -c "$ANONYMIZE_SQL" >> "$LOG_FILE" 2>&1; then
|
||||
RESTORE_SUCCESS=true
|
||||
fi
|
||||
fi
|
||||
elif command -v docker >/dev/null 2>&1; then
|
||||
log "Réinitialisation du schéma public sur UAT via Docker..."
|
||||
docker run --rm --net=host -e PGPASSWORD="${UAT_DB_PASSWORD}" postgres:15-alpine psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" -c "$CLEAN_SCHEMA_SQL" >> "$LOG_FILE" 2>&1
|
||||
|
||||
log "Restauration du dump Prod vers UAT via Docker..."
|
||||
if gunzip -c "$DUMP_PATH" | docker run --rm -i --net=host -e PGPASSWORD="${UAT_DB_PASSWORD}" postgres:15-alpine psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" >> "$LOG_FILE" 2>&1; then
|
||||
log "Exécution des requêtes d'anonymisation sur UAT via Docker..."
|
||||
if docker run --rm --net=host -e PGPASSWORD="${UAT_DB_PASSWORD}" postgres:15-alpine psql -h "${UAT_DB_HOST}" -p "${UAT_DB_PORT}" -U "${UAT_DB_USER}" -d "${UAT_DB_NAME}" -c "$ANONYMIZE_SQL" >> "$LOG_FILE" 2>&1; then
|
||||
RESTORE_SUCCESS=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$RESTORE_SUCCESS" = "true" ]; then
|
||||
log "✅ Restauration et anonymisation UAT réussies avec succès !"
|
||||
else
|
||||
log "⚠️ AVERTISSEMENT: Impossible d'effectuer la restauration/anonymisation UAT."
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3. Transfert sécurisé RSYNC / SCP vers le serveur VPS (Optionnel)
|
||||
if [ "$STATUS" = "SUCCESS" ] && [ "$ENABLE_REMOTE_COPY" = "true" ] && [ -n "$REMOTE_HOST" ]; then
|
||||
log "Transfert du dump vers le serveur VPS distant (${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BACKUP_DIR})..."
|
||||
|
||||
Reference in New Issue
Block a user