#!/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 <