Some checks failed
E2E Tests / e2e (push) Has been cancelled
Build & Push Images / build (brain) (push) Successful in 1m5s
Build & Push Images / build (core) (push) Successful in 1m42s
Build & Push Images / build (web) (push) Successful in 1m38s
Build & Push Images / build-switcher (push) Successful in 1m48s
124 lines
4.9 KiB
Bash
124 lines
4.9 KiB
Bash
#!/bin/bash
|
|
# switch.sh — execute le switch de canal pour LoreMind.
|
|
#
|
|
# Usage interne (appele par watch.sh) :
|
|
# ./switch.sh stable
|
|
# ./switch.sh beta
|
|
#
|
|
# Ce que ca fait, dans l'ordre :
|
|
# 1. Valide l'argument (stable|beta uniquement, rien d'autre — defense
|
|
# contre command injection si le Core etait compromis)
|
|
# 2. Sed la ligne IMAGE_NAMESPACE= du .env du host pour basculer le prefixe
|
|
# 3. docker compose pull (recupere les nouvelles images du canal cible)
|
|
# 4. docker compose up -d (recree core/brain/web avec les nouvelles images)
|
|
#
|
|
# Le switcher LUI-MEME n'est PAS dans IMAGE_NAMESPACE — il survit au switch
|
|
# sans interruption (cf. docker-compose.yml).
|
|
|
|
set -euo pipefail
|
|
|
|
CHANNEL="${1:-}"
|
|
|
|
# --- Validation stricte -----------------------------------------------------
|
|
# Aucune autre valeur acceptee. Pas d'echappement, pas de slash, rien.
|
|
# C'est le filet de securite si le JSON depose dans /data/command.json
|
|
# contenait un payload exotique (Core compromis = on ne laisse PAS
|
|
# executer du code arbitraire sur l'hote).
|
|
case "${CHANNEL}" in
|
|
stable|beta) ;;
|
|
*)
|
|
echo "Channel invalide: '${CHANNEL}' (attendu: stable|beta)" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
# --- Configuration ---------------------------------------------------------
|
|
# Repertoire monte depuis l'hote contenant docker-compose.yml + .env
|
|
COMPOSE_DIR="${COMPOSE_DIR:-/compose}"
|
|
ENV_FILE="${COMPOSE_DIR}/.env"
|
|
|
|
if [[ ! -f "${ENV_FILE}" ]]; then
|
|
echo "Fichier .env introuvable dans ${COMPOSE_DIR}" >&2
|
|
exit 3
|
|
fi
|
|
if [[ ! -f "${COMPOSE_DIR}/docker-compose.yml" ]]; then
|
|
echo "docker-compose.yml introuvable dans ${COMPOSE_DIR}" >&2
|
|
exit 3
|
|
fi
|
|
|
|
# --- Detection du nom de projet compose ------------------------------------
|
|
# Pour eviter que le switcher cree un projet PARALLELE (cas ou COMPOSE_PROJECT_NAME
|
|
# ne correspond pas au nom du projet sous lequel les containers tournent),
|
|
# on lit le label compose du container core en cours d'execution.
|
|
# Ce label est ecrit par docker compose au moment du `up -d` initial — c'est
|
|
# la source de verite.
|
|
PROJECT_NAME=$(docker inspect loremind-core \
|
|
--format '{{ index .Config.Labels "com.docker.compose.project" }}' \
|
|
2>/dev/null || echo "")
|
|
if [[ -z "${PROJECT_NAME}" ]]; then
|
|
# Fallback : env var ou defaut. Ne devrait pas arriver en prod
|
|
# (loremind-core tourne forcement quand l'UI declenche un switch).
|
|
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-loremind}"
|
|
echo "Warning: nom de projet auto-detecte impossible, fallback sur '${PROJECT_NAME}'" >&2
|
|
fi
|
|
export COMPOSE_PROJECT_NAME="${PROJECT_NAME}"
|
|
echo "→ Projet compose cible: ${PROJECT_NAME}"
|
|
|
|
# --- Mapping canal -> (namespace, tag) -------------------------------------
|
|
# Le slash final du namespace est important : concatene avec le suffixe image
|
|
# (core/brain/web) dans le docker-compose.yml.
|
|
# Cote tag : le workflow CI pousse :latest pour le canal stable, :beta pour
|
|
# le canal beta. Le switcher doit donc forcer ces deux variables ensemble.
|
|
case "${CHANNEL}" in
|
|
stable)
|
|
NAMESPACE="igmlcreation/loremind-"
|
|
TAG="latest"
|
|
;;
|
|
beta)
|
|
NAMESPACE="igmlcreation/loremind-beta-"
|
|
TAG="beta"
|
|
;;
|
|
esac
|
|
|
|
# Helper : met a jour (ou ajoute) une variable key=value dans le .env.
|
|
update_env_var() {
|
|
local key="$1"
|
|
local value="$2"
|
|
if grep -q "^${key}=" "${ENV_FILE}"; then
|
|
# Sur Alpine, sed -i sans backup. Le pattern '/' dans la valeur impose
|
|
# un delimiter alternatif (|).
|
|
sed -i "s|^${key}=.*|${key}=${value}|" "${ENV_FILE}"
|
|
else
|
|
# Ligne absente → on l'ajoute en fin de fichier la premiere fois.
|
|
{
|
|
echo ""
|
|
echo "# Ajoute automatiquement par le switcher de canal LoreMind."
|
|
echo "${key}=${value}"
|
|
} >> "${ENV_FILE}"
|
|
fi
|
|
}
|
|
|
|
# --- Etape 1 : sed le .env -------------------------------------------------
|
|
echo "→ Mise a jour de IMAGE_NAMESPACE + TAG dans .env (canal: ${CHANNEL})"
|
|
update_env_var "IMAGE_NAMESPACE" "${NAMESPACE}"
|
|
update_env_var "TAG" "${TAG}"
|
|
|
|
# --- Etape 2 : docker compose pull -----------------------------------------
|
|
echo "→ Pull des nouvelles images (${NAMESPACE}*)"
|
|
# --no-deps inutile ici : pull n'a pas de notion de deps.
|
|
# --policy missing eviterait de re-puller si deja la, mais on VEUT puller
|
|
# pour avoir la derniere version disponible — c'est le but du switch.
|
|
cd "${COMPOSE_DIR}"
|
|
docker compose pull core brain web
|
|
|
|
# --- Etape 3 : recreate les containers avec les nouvelles images -----------
|
|
# On cible explicitement core/brain/web — pas le switcher (qui s'auto-tuerait
|
|
# au milieu de la commande), pas postgres/minio (pas de changement d'image).
|
|
# --no-deps : ne pas re-recreer postgres/minio comme effet de bord.
|
|
echo "→ Recreation des containers avec les nouvelles images"
|
|
docker compose up -d --no-deps core brain web
|
|
|
|
echo ""
|
|
echo "Switch vers le canal ${CHANNEL} termine avec succes."
|
|
echo "Containers core/brain/web recrees avec ${NAMESPACE}*:${TAG}."
|