358 lines
10 KiB
Bash
358 lines
10 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
set -Eeuo pipefail
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# migrate-alliance-boreale-v2.sh
|
|||
|
|
#
|
|||
|
|
# Migration prudente vers une structure canonique du dépôt Alliance Boréale.
|
|||
|
|
#
|
|||
|
|
# Principes :
|
|||
|
|
# - DRY_RUN=1 par défaut
|
|||
|
|
# - ne supprime rien
|
|||
|
|
# - n'écrase rien silencieusement
|
|||
|
|
# - journalise tout
|
|||
|
|
# - évite les auto-déplacements de dossier
|
|||
|
|
#
|
|||
|
|
# Usage :
|
|||
|
|
# bash migrate-alliance-boreale-v2.sh
|
|||
|
|
# DRY_RUN=0 bash migrate-alliance-boreale-v2.sh
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
ROOT="${1:-.}"
|
|||
|
|
cd "$ROOT"
|
|||
|
|
|
|||
|
|
DRY_RUN="${DRY_RUN:-1}"
|
|||
|
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|||
|
|
LOG_DIR=".migration"
|
|||
|
|
LOG_FILE="${LOG_DIR}/migration-v2-${STAMP}.log"
|
|||
|
|
|
|||
|
|
mkdir -p "$LOG_DIR"
|
|||
|
|
|
|||
|
|
log() {
|
|||
|
|
echo "[$(date +%H:%M:%S)] $*" | tee -a "$LOG_FILE"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
run() {
|
|||
|
|
if [[ "$DRY_RUN" == "1" ]]; then
|
|||
|
|
log "DRY-RUN: $*"
|
|||
|
|
else
|
|||
|
|
log "RUN: $*"
|
|||
|
|
eval "$@" | tee -a "$LOG_FILE"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exists() {
|
|||
|
|
[[ -e "$1" ]]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ensure_dir() {
|
|||
|
|
local d="$1"
|
|||
|
|
[[ -d "$d" ]] || run "mkdir -p \"$d\""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
safe_mv() {
|
|||
|
|
local src="$1"
|
|||
|
|
local dst="$2"
|
|||
|
|
|
|||
|
|
if [[ ! -e "$src" ]]; then
|
|||
|
|
log "SKIP: source absente: $src"
|
|||
|
|
return 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [[ "$src" == "$dst" ]]; then
|
|||
|
|
log "SKIP: source et destination identiques: $src"
|
|||
|
|
return 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
ensure_dir "$(dirname "$dst")"
|
|||
|
|
|
|||
|
|
if [[ -e "$dst" ]]; then
|
|||
|
|
local backup="${dst}.pre-migration-${STAMP}"
|
|||
|
|
log "CONFLIT: destination existe: $dst"
|
|||
|
|
run "mv \"$dst\" \"$backup\""
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
run "mv \"$src\" \"$dst\""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
safe_mkdir_tree() {
|
|||
|
|
for d in "$@"; do
|
|||
|
|
ensure_dir "$d"
|
|||
|
|
done
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
move_if_exists() {
|
|||
|
|
local src="$1"
|
|||
|
|
local dst="$2"
|
|||
|
|
exists "$src" && safe_mv "$src" "$dst" || log "SKIP: absent: $src"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
quarantine_if_exists() {
|
|||
|
|
local src="$1"
|
|||
|
|
local bucket="$2"
|
|||
|
|
if exists "$src"; then
|
|||
|
|
ensure_dir "$bucket"
|
|||
|
|
safe_mv "$src" "$bucket/$(basename "$src")"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
create_readme_if_absent() {
|
|||
|
|
local path="$1"
|
|||
|
|
local content="$2"
|
|||
|
|
|
|||
|
|
if [[ ! -e "$path" ]]; then
|
|||
|
|
ensure_dir "$(dirname "$path")"
|
|||
|
|
if [[ "$DRY_RUN" == "1" ]]; then
|
|||
|
|
log "DRY-RUN: création de $path"
|
|||
|
|
else
|
|||
|
|
printf "%s\n" "$content" > "$path"
|
|||
|
|
log "RUN: création de $path"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log "Début migration v2"
|
|||
|
|
log "ROOT=$ROOT"
|
|||
|
|
log "DRY_RUN=$DRY_RUN"
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 1) Créer uniquement les branches structurelles sûres
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
log "Création de l’ossature cible"
|
|||
|
|
|
|||
|
|
safe_mkdir_tree \
|
|||
|
|
docs \
|
|||
|
|
infrastructure \
|
|||
|
|
operations \
|
|||
|
|
archives \
|
|||
|
|
tooling \
|
|||
|
|
security \
|
|||
|
|
docs/decisions \
|
|||
|
|
docs/diffusion \
|
|||
|
|
archives/pre-migration \
|
|||
|
|
archives/legacy-docs \
|
|||
|
|
archives/obsolete
|
|||
|
|
|
|||
|
|
# Répertoires feuilles qui ne reçoivent pas un mv de dossier entier existant
|
|||
|
|
safe_mkdir_tree \
|
|||
|
|
docs/decisions/adr \
|
|||
|
|
docs/rfc \
|
|||
|
|
docs/diffusion/conferences \
|
|||
|
|
docs/diffusion/site \
|
|||
|
|
docs/diffusion/visuels \
|
|||
|
|
docs/diffusion/recrutement \
|
|||
|
|
operations/runbooks \
|
|||
|
|
operations/evidence \
|
|||
|
|
operations/procedures \
|
|||
|
|
operations/checklists \
|
|||
|
|
infrastructure/opentofu \
|
|||
|
|
infrastructure/cloud-init \
|
|||
|
|
infrastructure/netbox \
|
|||
|
|
infrastructure/templates/proxmox
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 2) Déplacer les blocs racine évidents
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
log "Déplacement des blocs racine évidents"
|
|||
|
|
|
|||
|
|
move_if_exists "ansible" "infrastructure/ansible"
|
|||
|
|
move_if_exists "templates" "infrastructure/templates"
|
|||
|
|
move_if_exists "evidence" "operations/evidence"
|
|||
|
|
move_if_exists "configure" "tooling/configure"
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 3) Réorganiser docs/ par familles
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
if exists "docs"; then
|
|||
|
|
log "Réorganisation de docs/"
|
|||
|
|
|
|||
|
|
# Dossiers historiques -> familles cibles
|
|||
|
|
move_if_exists "docs/00-fondements" "docs/fondements"
|
|||
|
|
move_if_exists "docs/10-architecture" "docs/architecture"
|
|||
|
|
move_if_exists "docs/40-ecosystemes" "docs/ecosystemes"
|
|||
|
|
move_if_exists "docs/constitution" "docs/gouvernance"
|
|||
|
|
move_if_exists "docs/20-rag" "docs/corpus-a-integrer"
|
|||
|
|
move_if_exists "docs/vieustoq" "archives/legacy-docs/vieustoq"
|
|||
|
|
|
|||
|
|
# engineering / guides / opération
|
|||
|
|
move_if_exists "docs/engineering" "docs/guides-engineering"
|
|||
|
|
move_if_exists "docs/guides" "docs/guides"
|
|||
|
|
move_if_exists "docs/opération" "operations/procedures"
|
|||
|
|
|
|||
|
|
# pile opérateur -> recentrage
|
|||
|
|
move_if_exists "docs/pile opérateur/adr" "docs/decisions/adr"
|
|||
|
|
move_if_exists "docs/pile opérateur/pol" "docs/politiques"
|
|||
|
|
move_if_exists "docs/pile opérateur/runbooks" "operations/runbooks"
|
|||
|
|
move_if_exists "docs/pile opérateur/evidence" "operations/evidence/pile-operateur"
|
|||
|
|
move_if_exists "docs/pile opérateur/configs" "operations/procedures/pile-operateur-configs"
|
|||
|
|
|
|||
|
|
# Ce qui reste du dossier "pile opérateur" part en quarantaine s'il existe encore
|
|||
|
|
quarantine_if_exists "docs/pile opérateur/README.md" "archives/pre-migration/docs-pile-operateur"
|
|||
|
|
quarantine_if_exists "docs/pile opérateur" "archives/pre-migration"
|
|||
|
|
|
|||
|
|
# annexes -> corpus à intégrer
|
|||
|
|
move_if_exists "docs/50-annexes" "docs/corpus-a-integrer-annexes"
|
|||
|
|
|
|||
|
|
# assets / diffusion
|
|||
|
|
move_if_exists "docs/assets" "docs/diffusion/visuels/assets"
|
|||
|
|
|
|||
|
|
# fichiers de diffusion
|
|||
|
|
move_if_exists "docs/Alliance_Boreale_Conferences.pptx" "docs/diffusion/conferences/Alliance_Boreale_Conferences.pptx"
|
|||
|
|
move_if_exists "docs/Conference_01_Rideau_ou_Coffre_Fort.pptx" "docs/diffusion/conferences/Conference_01_Rideau_ou_Coffre_Fort.pptx"
|
|||
|
|
move_if_exists "docs/Conference_02_Colonisation_Numerique.pptx" "docs/diffusion/conferences/Conference_02_Colonisation_Numerique.pptx"
|
|||
|
|
move_if_exists "docs/2026-02-03 - Présentation d'Alliance Boréale - Rencontres Linux.odp" "docs/diffusion/conferences/2026-02-03-Rencontres-Linux.odp"
|
|||
|
|
move_if_exists "docs/alliance_boreale_site.html" "docs/diffusion/site/alliance_boreale_site.html"
|
|||
|
|
move_if_exists "docs/alliance_boreale_recrutement.docx" "docs/diffusion/recrutement/alliance_boreale_recrutement.docx"
|
|||
|
|
|
|||
|
|
# fichiers racine documentaires à classer proprement
|
|||
|
|
move_if_exists "docs/00_Etat_Depot_Vivant_v1.md" "docs/gouvernance/00_Etat_Depot_Vivant_v1.md"
|
|||
|
|
move_if_exists "docs/00_Glossaire_biomimetique_autopoietique_v3.md" "docs/modele-glossaire.md"
|
|||
|
|
move_if_exists "docs/00_Modele_8_couches_biomimetique_autopoietique_v3.md" "docs/modele-8-couches.md"
|
|||
|
|
move_if_exists "docs/00_Nomenclature_v4.md" "docs/nomenclature-v4.md"
|
|||
|
|
move_if_exists "docs/06 - Controles_Conformite_Label_Prestige_par_Couche_v1.0.md" "docs/politiques/06-Controles_Conformite_Label_Prestige_par_Couche_v1.0.md"
|
|||
|
|
|
|||
|
|
# divers à trier plus tard
|
|||
|
|
for f in \
|
|||
|
|
"docs/index.md" \
|
|||
|
|
"docs/linkedin_post.md" \
|
|||
|
|
"docs/TODO.md" \
|
|||
|
|
"docs/TRANSMISSION.md"
|
|||
|
|
do
|
|||
|
|
if exists "$f"; then
|
|||
|
|
move_if_exists "$f" "docs/corpus-a-integrer/$(basename "$f")"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 4) Corriger certaines branches créées implicitement
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
log "Consolidation des branches documentaires"
|
|||
|
|
|
|||
|
|
# Si gouvernance n'existe pas encore après déplacement depuis constitution
|
|||
|
|
ensure_dir "docs/gouvernance"
|
|||
|
|
ensure_dir "docs/corpus-a-integrer"
|
|||
|
|
ensure_dir "docs/politiques"
|
|||
|
|
|
|||
|
|
# Si les fichiers modèle ont été déplacés en racine docs, on leur donne une maison
|
|||
|
|
ensure_dir "docs/modele"
|
|||
|
|
move_if_exists "docs/modele-glossaire.md" "docs/modele/00_Glossaire_biomimetique_autopoietique_v3.md"
|
|||
|
|
move_if_exists "docs/modele-8-couches.md" "docs/modele/00_Modele_8_couches_biomimetique_autopoietique_v3.md"
|
|||
|
|
move_if_exists "docs/nomenclature-v4.md" "docs/modele/00_Nomenclature_v4.md"
|
|||
|
|
|
|||
|
|
# Si on a guides-engineering, le ranger sous guides
|
|||
|
|
if exists "docs/guides-engineering"; then
|
|||
|
|
ensure_dir "docs/guides"
|
|||
|
|
move_if_exists "docs/guides-engineering" "docs/guides/engineering"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Si corpus-a-integrer-annexes existe, le ranger sous corpus-a-integrer
|
|||
|
|
if exists "docs/corpus-a-integrer-annexes"; then
|
|||
|
|
ensure_dir "docs/corpus-a-integrer"
|
|||
|
|
move_if_exists "docs/corpus-a-integrer-annexes" "docs/corpus-a-integrer/annexes"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 5) Doubles probables -> quarantaine prudente
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
log "Mise en quarantaine des doublons probables"
|
|||
|
|
|
|||
|
|
ensure_dir "archives/pre-migration/duplicates"
|
|||
|
|
|
|||
|
|
for f in \
|
|||
|
|
"docs/fondements/00-manifeste.md" \
|
|||
|
|
"docs/fondements/00 - Manifeste.md" \
|
|||
|
|
"docs/corpus-a-integrer/03_Cadre_Conformite_Label_Prestige(1).md" \
|
|||
|
|
"docs/corpus-a-integrer/devis(2).md"
|
|||
|
|
do
|
|||
|
|
if exists "$f"; then
|
|||
|
|
move_if_exists "$f" "archives/pre-migration/duplicates/$(basename "$f")"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 6) README d’orientation
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
create_readme_if_absent "docs/README.md" \
|
|||
|
|
"# Documentation canonique
|
|||
|
|
|
|||
|
|
Ce dossier contient la documentation de référence de l'Alliance Boréale.
|
|||
|
|
|
|||
|
|
Branches principales :
|
|||
|
|
- fondements
|
|||
|
|
- modele
|
|||
|
|
- architecture
|
|||
|
|
- gouvernance
|
|||
|
|
- decisions
|
|||
|
|
- politiques
|
|||
|
|
- ecosystemes
|
|||
|
|
- guides
|
|||
|
|
- corpus-a-integrer
|
|||
|
|
- diffusion
|
|||
|
|
"
|
|||
|
|
|
|||
|
|
create_readme_if_absent "infrastructure/README.md" \
|
|||
|
|
"# Infrastructure
|
|||
|
|
|
|||
|
|
Contient l'implémentation opératoire :
|
|||
|
|
- ansible
|
|||
|
|
- opentofu
|
|||
|
|
- cloud-init
|
|||
|
|
- templates
|
|||
|
|
- netbox
|
|||
|
|
"
|
|||
|
|
|
|||
|
|
create_readme_if_absent "operations/README.md" \
|
|||
|
|
"# Operations
|
|||
|
|
|
|||
|
|
Contient :
|
|||
|
|
- runbooks
|
|||
|
|
- evidence
|
|||
|
|
- procedures
|
|||
|
|
- checklists
|
|||
|
|
"
|
|||
|
|
|
|||
|
|
create_readme_if_absent "archives/README.md" \
|
|||
|
|
"# Archives
|
|||
|
|
|
|||
|
|
Contient :
|
|||
|
|
- legacy
|
|||
|
|
- variantes remplacées
|
|||
|
|
- artefacts déplacés pendant migration
|
|||
|
|
"
|
|||
|
|
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
# 7) Rapport final
|
|||
|
|
# ----------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
log "Migration v2 terminée"
|
|||
|
|
log "Journal: $LOG_FILE"
|
|||
|
|
|
|||
|
|
cat <<EOF
|
|||
|
|
|
|||
|
|
Terminé.
|
|||
|
|
|
|||
|
|
Mode actuel :
|
|||
|
|
DRY_RUN=${DRY_RUN}
|
|||
|
|
|
|||
|
|
Commande conseillée d'abord :
|
|||
|
|
DRY_RUN=1 bash $(basename "$0")
|
|||
|
|
|
|||
|
|
Puis exécution réelle :
|
|||
|
|
DRY_RUN=0 bash $(basename "$0")
|
|||
|
|
|
|||
|
|
Ensuite :
|
|||
|
|
git status
|
|||
|
|
find docs infrastructure operations archives -maxdepth 2 -type d | sort
|
|||
|
|
|
|||
|
|
Zones à réviser manuellement :
|
|||
|
|
- docs/corpus-a-integrer/
|
|||
|
|
- archives/pre-migration/duplicates/
|
|||
|
|
- archives/legacy-docs/
|
|||
|
|
EOF
|