Initial local backup snapshot
This commit is contained in:
commit
acd9e14ba5
367 changed files with 118038 additions and 0 deletions
179
scripts/deploy-vps.sh
Executable file
179
scripts/deploy-vps.sh
Executable file
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
SSH_KEY_DEFAULT="${HOME}/.ssh/vps_ovh_cd035e9a_ed25519"
|
||||
SSH_USER_DEFAULT="ubuntu"
|
||||
SSH_HOST_DEFAULT="142.44.210.180"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./scripts/deploy-vps.sh <prod|preprod> [--skip-check] [--skip-build]
|
||||
|
||||
Examples:
|
||||
./scripts/deploy-vps.sh preprod
|
||||
./scripts/deploy-vps.sh prod
|
||||
|
||||
Behavior:
|
||||
- synchronise les sources utiles vers le VPS
|
||||
- exécute le check TypeScript local (sauf --skip-check)
|
||||
- exécute le build local (sauf --skip-build)
|
||||
- reconstruit et redémarre l'application distante
|
||||
- utilise explicitement le bon fichier d'environnement par cible
|
||||
EOF
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TARGET="${1:-}"
|
||||
if [[ -z "${TARGET}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift || true
|
||||
|
||||
RUN_CHECK=1
|
||||
RUN_BUILD=1
|
||||
USE_MAINTENANCE_FLAG="${USE_MAINTENANCE_FLAG:-0}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--skip-check)
|
||||
RUN_CHECK=0
|
||||
;;
|
||||
--skip-build)
|
||||
RUN_BUILD=0
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Option inconnue: $1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
case "${TARGET}" in
|
||||
prod)
|
||||
REMOTE_DIR="/home/${SSH_USER_DEFAULT}/portail-associations"
|
||||
REMOTE_DEPLOY_CMD='cd /home/ubuntu/portail-associations && docker compose --env-file .env up -d --build app'
|
||||
POST_CHECK_URL='https://www.portail-association973.com'
|
||||
;;
|
||||
preprod)
|
||||
REMOTE_DIR="/home/${SSH_USER_DEFAULT}/portail-associations-preprod"
|
||||
REMOTE_DEPLOY_CMD='cd /home/ubuntu/portail-associations-preprod/deployments/preprod && docker compose --env-file .env up -d --build app'
|
||||
POST_CHECK_URL='https://preprod.portail-association973.com'
|
||||
;;
|
||||
*)
|
||||
echo "Cible invalide: ${TARGET}" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
SSH_KEY="${SSH_KEY:-${SSH_KEY_DEFAULT}}"
|
||||
SSH_USER="${SSH_USER:-${SSH_USER_DEFAULT}}"
|
||||
SSH_HOST="${SSH_HOST:-${SSH_HOST_DEFAULT}}"
|
||||
SSH_TARGET="${SSH_USER}@${SSH_HOST}"
|
||||
SSH_CMD=(ssh -i "${SSH_KEY}" -o BatchMode=yes -o ConnectTimeout=10 "${SSH_TARGET}")
|
||||
RSYNC_SSH="ssh -i ${SSH_KEY} -o BatchMode=yes -o ConnectTimeout=10"
|
||||
POST_CHECK_HEALTH_URL="${POST_CHECK_URL}/health/ready"
|
||||
|
||||
SYNC_ITEMS=(
|
||||
"${ROOT_DIR}/client"
|
||||
"${ROOT_DIR}/server"
|
||||
"${ROOT_DIR}/shared"
|
||||
"${ROOT_DIR}/drizzle"
|
||||
"${ROOT_DIR}/docs"
|
||||
"${ROOT_DIR}/deployments"
|
||||
"${ROOT_DIR}/scripts"
|
||||
"${ROOT_DIR}/patches"
|
||||
"${ROOT_DIR}/package.json"
|
||||
"${ROOT_DIR}/pnpm-lock.yaml"
|
||||
"${ROOT_DIR}/Dockerfile"
|
||||
"${ROOT_DIR}/docker-compose.yml"
|
||||
"${ROOT_DIR}/vite.config.ts"
|
||||
"${ROOT_DIR}/tsconfig.json"
|
||||
"${ROOT_DIR}/components.json"
|
||||
"${ROOT_DIR}/drizzle.config.ts"
|
||||
"${ROOT_DIR}/MAIL_PROVIDERS.md"
|
||||
)
|
||||
|
||||
echo "==> Vérification SSH (${SSH_TARGET})"
|
||||
"${SSH_CMD[@]}" 'echo SSH_OK >/dev/null'
|
||||
|
||||
remote_maintenance() {
|
||||
local mode="$1"
|
||||
"${SSH_CMD[@]}" "cd ${REMOTE_DIR} && MAINTENANCE_FLAG_PATH=${REMOTE_DIR}/uploads/system/maintenance.flag ./scripts/maintenance-flag.sh ${mode}"
|
||||
}
|
||||
|
||||
wait_for_http_200() {
|
||||
local url="$1"
|
||||
local label="$2"
|
||||
local max_attempts="${3:-20}"
|
||||
local delay_seconds="${4:-3}"
|
||||
local attempt=1
|
||||
while [[ "${attempt}" -le "${max_attempts}" ]]; do
|
||||
local code
|
||||
code="$(curl -k -s -o /dev/null -w "%{http_code}" -m 20 "${url}" || true)"
|
||||
echo " - ${label} tentative ${attempt}/${max_attempts} -> ${code}"
|
||||
if [[ "${code}" == "200" ]]; then
|
||||
return 0
|
||||
fi
|
||||
sleep "${delay_seconds}"
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if [[ "${RUN_CHECK}" -eq 1 ]]; then
|
||||
echo "==> TypeScript check local"
|
||||
(cd "${ROOT_DIR}" && corepack pnpm check)
|
||||
fi
|
||||
|
||||
if [[ "${RUN_BUILD}" -eq 1 ]]; then
|
||||
echo "==> Build local"
|
||||
(cd "${ROOT_DIR}" && corepack pnpm build)
|
||||
fi
|
||||
|
||||
echo "==> Synchronisation des sources vers ${REMOTE_DIR}"
|
||||
rsync -az --delete \
|
||||
--exclude '.git/' \
|
||||
--exclude 'node_modules/' \
|
||||
--exclude 'dist/' \
|
||||
--exclude 'uploads/' \
|
||||
--exclude '.env' \
|
||||
-e "${RSYNC_SSH}" \
|
||||
"${SYNC_ITEMS[@]}" \
|
||||
"${SSH_TARGET}:${REMOTE_DIR}/"
|
||||
|
||||
if [[ "${USE_MAINTENANCE_FLAG}" == "1" ]]; then
|
||||
echo "==> Activation du mode maintenance"
|
||||
remote_maintenance on
|
||||
fi
|
||||
|
||||
echo "==> Déploiement ${TARGET}"
|
||||
"${SSH_CMD[@]}" "${REMOTE_DEPLOY_CMD}"
|
||||
|
||||
echo "==> Attente de disponibilité applicative (${POST_CHECK_HEALTH_URL})"
|
||||
wait_for_http_200 "${POST_CHECK_HEALTH_URL}" "health" 25 3
|
||||
|
||||
if [[ "${USE_MAINTENANCE_FLAG}" == "1" ]]; then
|
||||
echo "==> Désactivation du mode maintenance"
|
||||
remote_maintenance off
|
||||
fi
|
||||
|
||||
echo "==> Contrôle HTTP ${POST_CHECK_URL}"
|
||||
wait_for_http_200 "${POST_CHECK_URL}" "home" 10 2
|
||||
curl -I -k -m 20 "${POST_CHECK_HEALTH_URL}"
|
||||
|
||||
echo "==> Déploiement ${TARGET} terminé"
|
||||
Loading…
Add table
Add a link
Reference in a new issue