547 lines
18 KiB
Markdown
547 lines
18 KiB
Markdown
# RUNBOOK — Déploiement Blue/Green (NAS DS220+)
|
||
> Objectif : déployer une release **sans casser**, avec rollback immédiat.
|
||
|
||
## 0) Portée
|
||
Ce runbook décrit le déploiement de l’édition web Archicratie sur NAS (Synology), en mode blue/green :
|
||
- `web_blue` : upstream staging → `127.0.0.1:8081`
|
||
- `web_green` : upstream live → `127.0.0.1:8082`
|
||
- Edge Traefik publie :
|
||
- `staging.archicratie.trans-hands.synology.me` → 8081
|
||
- `archicratie.trans-hands.synology.me` → 8082
|
||
|
||
## 1) Pré-requis
|
||
- Accès shell NAS (user `archicratia`) + `sudo`
|
||
- Docker Compose Synology nécessite souvent :
|
||
- `sudo env DOCKER_API_VERSION=1.43 docker compose ...`
|
||
- Les fichiers edge Traefik sont dans :
|
||
- `/volume2/docker/edge/config/dynamic/`
|
||
|
||
## 2) Répertoires canon (NAS)
|
||
On considère ces chemins (adapter si besoin, mais rester cohérent) :
|
||
- Base : `/volume2/docker/archicratie-web`
|
||
- Releases : `/volume2/docker/archicratie-web/releases/YYYYMMDD-HHMMSS/app`
|
||
- Symlink actif : `/volume2/docker/archicratie-web/current` → pointe vers le `.../app` actif
|
||
|
||
## 3) Garde-fous (AVANT toute action)
|
||
### 3.1 Snapshot de l’état actuel
|
||
en bash :
|
||
|
||
cd /volume2/docker/archicratie-web
|
||
ls -la current || true
|
||
readlink current || true
|
||
|
||
### 3.2 Vérifier l’état live/staging upstream direct
|
||
|
||
curl -sSI http://127.0.0.1:8081/ | head -n 12
|
||
curl -sSI http://127.0.0.1:8082/ | head -n 12
|
||
|
||
### 3.3 Vérifier l’état edge (host routing)
|
||
|
||
curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \
|
||
| grep -iE 'HTTP/|location:|x-archi-router' | head -n 30
|
||
|
||
curl -sSI -H 'Host: archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \
|
||
| grep -iE 'HTTP/|location:|x-archi-router' | head -n 30
|
||
|
||
Si tu n’es pas authentifié, tu verras un 302 vers auth... : c’est normal.
|
||
|
||
## 4) Procédure de déploiement (release pack → nouvelle release)
|
||
### 4.1 Déposer le pack
|
||
|
||
Hypothèse : tu as un .tgz “release pack” (issu de release-pack.sh) dans incoming/ :
|
||
|
||
cd /volume2/docker/archicratie-web
|
||
ls -la incoming | tail -n 20
|
||
|
||
### 4.2 Créer un répertoire release
|
||
|
||
TS="$(date +%Y%m%d-%H%M%S)"
|
||
REL="/volume2/docker/archicratie-web/releases/$TS"
|
||
APP="$REL/app"
|
||
sudo mkdir -p "$APP"
|
||
|
||
### 4.3 Extraire le pack
|
||
|
||
PKG="/volume2/docker/archicratie-web/incoming/archicratie-web.tar.gz" # adapter au nom réel
|
||
sudo tar -xzf "$PKG" -C "$APP"
|
||
|
||
### 4.4 Sanity check (fichiers attendus)
|
||
|
||
sudo test -f "$APP/Dockerfile" && echo "OK Dockerfile"
|
||
sudo test -f "$APP/docker-compose.yml" && echo "OK compose"
|
||
sudo test -f "$APP/astro.config.mjs" && echo "OK astro config"
|
||
sudo test -f "$APP/src/layouts/EditionLayout.astro" && echo "OK layout"
|
||
sudo test -f "$APP/src/pages/archicrat-ia/index.astro" && echo "OK archicrat-ia index"
|
||
sudo test -f "$APP/docs/diagrams/archicratie-web-edition-global-verbatim-v2.svg" && echo "OK diagrams"
|
||
|
||
### 4.5 Permissions (crucial sur Synology)
|
||
|
||
But : archicratia:users doit pouvoir traverser le parent + lire le contenu.
|
||
|
||
sudo chown -R archicratia:users "$REL"
|
||
sudo chmod -R u+rwX,g+rX,o-rwx "$REL"
|
||
sudo chmod 750 "$REL" "$APP"
|
||
|
||
Vérifier :
|
||
|
||
ls -ld "$REL" "$APP"
|
||
ls -la "$APP" | head
|
||
|
||
## 5) Activation : basculer current vers la nouvelle release
|
||
### 5.1 Backup du current existant
|
||
|
||
cd /volume2/docker/archicratie-web
|
||
TS2="$(date +%F-%H%M%S)"
|
||
|
||
# on backup "current" (symlink ou dossier)
|
||
if [ -e current ] || [ -L current ]; then
|
||
sudo mv -f current "current.BAK.$TS2"
|
||
echo "✅ backup: current.BAK.$TS2"
|
||
fi
|
||
|
||
### 5.2 Recréer current (symlink propre)
|
||
|
||
sudo ln -s "$APP" current
|
||
|
||
ls -la current
|
||
readlink current
|
||
sudo test -f current/docker-compose.yml && echo "✅ OK: current/docker-compose.yml"
|
||
|
||
Si cd current échoue, c’est que current n’est pas un symlink correct OU que le parent n’est pas traversable (permissions).
|
||
|
||
## 6) Build & run : (re)construire web_blue/web_green
|
||
### 6.1 Vérifier la config compose
|
||
|
||
cd /volume2/docker/archicratie-web/current
|
||
sudo env DOCKER_API_VERSION=1.43 docker compose -f docker-compose.yml config \
|
||
| grep -nE 'services:|web_blue:|web_green:|context:|dockerfile:|PUBLIC_SITE|REQUIRE_PUBLIC_SITE' \
|
||
| sed -n '1,220p'
|
||
|
||
### 6.2 Build propre (recommandé si changement de code/config)
|
||
|
||
sudo env DOCKER_API_VERSION=1.43 docker compose build --no-cache web_blue web_green
|
||
|
||
### 6.3 Up (force recreate)
|
||
|
||
sudo env DOCKER_API_VERSION=1.43 docker compose up -d --force-recreate web_blue web_green
|
||
|
||
### 6.4 Vérifier upstream direct (8081/8082)
|
||
|
||
curl -sSI http://127.0.0.1:8081/ | head -n 12
|
||
curl -sSI http://127.0.0.1:8082/ | head -n 12
|
||
|
||
## 7) Tests de non-régression (MINIMAL CHECKLIST)
|
||
|
||
À exécuter systématiquement après up.
|
||
|
||
### 7.1 Upstreams directs
|
||
|
||
curl -sSI http://127.0.0.1:8081/ | head -n 12
|
||
curl -sSI http://127.0.0.1:8082/ | head -n 12
|
||
|
||
### 7.2 Canonical (anti “localhost en prod”)
|
||
|
||
curl -sS http://127.0.0.1:8081/ | grep -oE 'rel="canonical" href="[^"]+"' | head -n 1
|
||
curl -sS http://127.0.0.1:8082/ | grep -oE 'rel="canonical" href="[^"]+"' | head -n 1
|
||
|
||
Attendu :
|
||
|
||
blue (8081) → https://staging.archicratie.../
|
||
|
||
green (8082) → https://archicratie.../
|
||
|
||
### 7.3 Edge routing (Host header + diag)
|
||
|
||
curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \
|
||
| grep -iE 'HTTP/|location:|x-archi-router' | head -n 30
|
||
|
||
curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/_auth/whoami \
|
||
| grep -iE 'HTTP/|location:|x-archi-router' | head -n 30
|
||
|
||
### 7.4 Smoke UI (manuel)
|
||
|
||
Home : lien “Essai-thèse — ArchiCraT-IA” → /archicrat-ia/
|
||
|
||
TOC global : liens /archicrat-ia/* (pas de préfixe /archicratie/archicrat-ia/*)
|
||
|
||
Reading-follow/TOC local : scroll ok
|
||
|
||
## 8) Rollback (si un seul test est mauvais)
|
||
|
||
Objectif : revenir immédiatement à l’état précédent.
|
||
|
||
### 8.1 Repointer current sur l’ancien backup
|
||
|
||
cd /volume2/docker/archicratie-web
|
||
ls -la current.BAK.* | tail -n 5
|
||
|
||
# choisir le plus récent
|
||
OLD="current.BAK.YYYY-MM-DD-HHMMSS"
|
||
sudo rm -f current
|
||
sudo ln -s "$(readlink -f "$OLD")" current 2>/dev/null || sudo ln -s "$(readlink "$OLD")" current
|
||
|
||
ls -la current
|
||
readlink current
|
||
|
||
### 8.2 Rebuild + recreate
|
||
|
||
cd /volume2/docker/archicratie-web/current
|
||
sudo env DOCKER_API_VERSION=1.43 docker compose build --no-cache web_blue web_green
|
||
sudo env DOCKER_API_VERSION=1.43 docker compose up -d --force-recreate web_blue web_green
|
||
|
||
### 8.3 Re-tester la checklist (section 7)
|
||
|
||
Si rollback OK : investiguer en environnement isolé (staging upstream uniquement, ou release dans un autre current).
|
||
|
||
## 9) Notes opérationnelles
|
||
|
||
Ne jamais modifier dist/ “à la main” sur NAS.
|
||
|
||
Si un hotfix prod est indispensable : documenter et backporter via PR Gitea.
|
||
|
||
Le canonical dépend du build : PUBLIC_SITE doit être injecté (voir runbook ENV-PUBLIC_SITE).
|
||
|
||
## 10) CI Deploy (Gitea Actions) — Gate SKIP / HOTPATCH / FULL (merge-proof) + preuves
|
||
|
||
Cette section documente le comportement **canonique** du workflow :
|
||
- `.gitea/workflows/deploy-staging-live.yml`
|
||
|
||
Objectif : **zéro surprise**.
|
||
On ne veut plus “penser à force=1”.
|
||
Le gate doit décider automatiquement, y compris sur des **merge commits**.
|
||
|
||
### 10.1 — Principe (ce que fait réellement le gate)
|
||
|
||
Le job `deploy` calcule les fichiers modifiés entre :
|
||
- `BEFORE` = commit précédent (avant le push sur main)
|
||
- `AFTER` = commit actuel (après le push / merge sur main)
|
||
|
||
Puis il classe le déploiement dans un mode :
|
||
|
||
- **MODE=full**
|
||
- rebuild image + restart `archicratie-web-blue` (8081) + `archicratie-web-green` (8082)
|
||
- warmup endpoints (para-index, annotations-index, pagefind.js)
|
||
- vérification canonical staging + live
|
||
|
||
- **MODE=hotpatch**
|
||
- rebuild d’un `annotations-index.json` consolidé depuis `src/annotations/**`
|
||
- patch direct dans les conteneurs en cours d’exécution (blue+green)
|
||
- copie des médias modifiés `public/media/**` vers `/usr/share/nginx/html/media/**`
|
||
- smoke sur `/annotations-index.json` des deux ports
|
||
|
||
- **MODE=skip**
|
||
- pas de déploiement (on évite le bruit)
|
||
|
||
⚠️ Important : le mode “hotpatch” **ne rebuild pas** Astro.
|
||
Donc toute modification de contenu, routes, scripts, anchors, etc. doit déclencher **full**.
|
||
|
||
### 10.2 — Matrice de décision (règles officielles)
|
||
|
||
Le gate définit deux flags :
|
||
- `HAS_FULL=1` si changement “build-impacting”
|
||
- `HAS_HOTPATCH=1` si changement “annotations/media only”
|
||
|
||
Règle de priorité :
|
||
1) Si `HAS_FULL=1` → **MODE=full**
|
||
2) Sinon si `HAS_HOTPATCH=1` → **MODE=hotpatch**
|
||
3) Sinon → **MODE=skip**
|
||
|
||
#### 10.2.1 — Changements qui déclenchent FULL (build-impacting)
|
||
|
||
Exemples typiques (non exhaustif, mais on couvre le cœur) :
|
||
- `src/content/**` (contenu MD/MDX)
|
||
- `src/pages/**` (routes Astro)
|
||
- `src/anchors/**` (aliases d’ancres)
|
||
- `scripts/**` (tooling postbuild : injection, index, tests)
|
||
- `src/layouts/**`, `src/components/**`, `src/styles/**` (rendu et scripts inline)
|
||
- `astro.config.mjs`, `package.json`, `package-lock.json`
|
||
- `Dockerfile`, `docker-compose.yml`, `nginx.conf`
|
||
- `.gitea/workflows/**` (changement infra CI/CD)
|
||
|
||
=> On veut **full** pour garantir cohérence et éviter “site partiellement mis à jour”.
|
||
|
||
#### 10.2.2 — Changements qui déclenchent HOTPATCH (sans rebuild)
|
||
|
||
Uniquement :
|
||
- `src/annotations/**` (shards YAML)
|
||
- `public/media/**` (assets média)
|
||
|
||
=> On veut hotpatch pour vitesse et éviter rebuild NAS.
|
||
|
||
### 10.3 — “Merge-proof” : pourquoi on ne lit PAS seulement `git show $SHA`
|
||
|
||
Sur un merge commit, `git show --name-only $SHA` peut être trompeur selon le contexte.
|
||
La méthode robuste est :
|
||
- utiliser `event.json` (Gitea Actions) pour récupérer `before` et `after`
|
||
- calculer `git diff --name-only BEFORE AFTER`
|
||
|
||
C’est ce qui rend le gate **merge-proof**.
|
||
|
||
### 10.4 — Tests de preuve A/B (reproductibles)
|
||
|
||
Ces tests valident le gate sans ambiguïté.
|
||
But : vérifier que le mode choisi est EXACTEMENT celui attendu.
|
||
|
||
#### Test A — toucher `src/content/...` (FULL auto)
|
||
|
||
1) Créer une branche test
|
||
2) Modifier 1 fichier dans `src/content/` (ex : ajouter une ligne de commentaire non destructive)
|
||
3) PR → merge dans `main`
|
||
4) Vérifier dans `deploy-staging-live.yml` :
|
||
|
||
Attendus :
|
||
- `Gate flags: HAS_FULL=1 HAS_HOTPATCH=0`
|
||
- `✅ build-impacting change -> MODE=full (rebuild+restart)`
|
||
- Les étapes FULL (blue puis green) s’exécutent réellement
|
||
|
||
#### Test B — toucher `src/annotations/...` uniquement (HOTPATCH auto)
|
||
|
||
1) Créer une branche test
|
||
2) Modifier 1 fichier sous `src/annotations/**` (ex: un champ comment, ts, etc.)
|
||
3) PR → merge dans `main`
|
||
4) Vérifier dans `deploy-staging-live.yml` :
|
||
|
||
Attendus :
|
||
- `Gate flags: HAS_FULL=0 HAS_HOTPATCH=1`
|
||
- `✅ annotations/media change -> MODE=hotpatch`
|
||
- Les étapes FULL sont “skip” (durée 0s)
|
||
- L’étape HOTPATCH s’exécute réellement
|
||
|
||
### 10.5 — Preuve opérationnelle côté NAS (2 URLs + 2 commandes)
|
||
|
||
But : prouver que staging+live servent bien les endpoints essentiels (et que le déploiement n’a pas “fait semblant”).
|
||
|
||
#### 10.5.1 — Deux URLs à vérifier (staging et live)
|
||
|
||
- Staging (blue) : `http://127.0.0.1:8081/`
|
||
- Live (green) : `http://127.0.0.1:8082/`
|
||
|
||
#### 10.5.2 — Deux commandes minimales (zéro débat)
|
||
|
||
```bash
|
||
curl -fsSI http://127.0.0.1:8081/ | head -n 1
|
||
curl -fsSI http://127.0.0.1:8082/ | head -n 1
|
||
|
||
---
|
||
|
||
## 10) CI Deploy (Gitea Actions) — Gate SKIP / HOTPATCH / FULL (merge-proof) + preuves
|
||
|
||
Cette section documente le comportement **canonique** du workflow :
|
||
- `.gitea/workflows/deploy-staging-live.yml`
|
||
|
||
Objectif : **zéro surprise**.
|
||
On ne veut plus “penser à force=1”.
|
||
Le gate doit décider automatiquement, y compris sur des **merge commits**.
|
||
|
||
### 10.1 — Principe (ce que fait réellement le gate)
|
||
|
||
Le job `deploy` calcule les fichiers modifiés entre :
|
||
- `BEFORE` = commit précédent (avant le push sur main)
|
||
- `AFTER` = commit actuel (après le push / merge sur main)
|
||
|
||
Puis il classe le déploiement dans un mode :
|
||
|
||
- **MODE=full**
|
||
- rebuild image + restart `archicratie-web-blue` (8081) + `archicratie-web-green` (8082)
|
||
- warmup endpoints (para-index, annotations-index, pagefind.js)
|
||
- vérification canonical staging + live
|
||
|
||
- **MODE=hotpatch**
|
||
- rebuild d’un `annotations-index.json` consolidé depuis `src/annotations/**`
|
||
- patch direct dans les conteneurs en cours d’exécution (blue+green)
|
||
- copie des médias modifiés `public/media/**` vers `/usr/share/nginx/html/media/**`
|
||
- smoke sur `/annotations-index.json` des deux ports
|
||
|
||
- **MODE=skip**
|
||
- pas de déploiement (on évite le bruit)
|
||
|
||
⚠️ Important : le mode “hotpatch” **ne rebuild pas** Astro.
|
||
Donc toute modification de contenu, routes, scripts, anchors, etc. doit déclencher **full**.
|
||
|
||
### 10.2 — Matrice de décision (règles officielles)
|
||
|
||
Le gate définit deux flags :
|
||
- `HAS_FULL=1` si changement “build-impacting”
|
||
- `HAS_HOTPATCH=1` si changement “annotations/media only”
|
||
|
||
Règle de priorité :
|
||
1) Si `HAS_FULL=1` → **MODE=full**
|
||
2) Sinon si `HAS_HOTPATCH=1` → **MODE=hotpatch**
|
||
3) Sinon → **MODE=skip**
|
||
|
||
#### 10.2.1 — Changements qui déclenchent FULL (build-impacting)
|
||
|
||
Exemples typiques (non exhaustif, mais on couvre le cœur) :
|
||
- `src/content/**` (contenu MD/MDX)
|
||
- `src/pages/**` (routes Astro)
|
||
- `src/anchors/**` (aliases d’ancres)
|
||
- `scripts/**` (tooling postbuild : injection, index, tests)
|
||
- `src/layouts/**`, `src/components/**`, `src/styles/**` (rendu et scripts inline)
|
||
- `astro.config.mjs`, `package.json`, `package-lock.json`
|
||
- `Dockerfile`, `docker-compose.yml`, `nginx.conf`
|
||
- `.gitea/workflows/**` (changement infra CI/CD)
|
||
|
||
=> On veut **full** pour garantir cohérence et éviter “site partiellement mis à jour”.
|
||
|
||
#### 10.2.2 — Changements qui déclenchent HOTPATCH (sans rebuild)
|
||
|
||
Uniquement :
|
||
- `src/annotations/**` (shards YAML)
|
||
- `public/media/**` (assets média)
|
||
|
||
=> On veut hotpatch pour vitesse et éviter rebuild NAS.
|
||
|
||
### 10.3 — “Merge-proof” : pourquoi on ne lit PAS seulement `git show $SHA`
|
||
|
||
Sur un merge commit, `git show --name-only $SHA` peut être trompeur selon le contexte.
|
||
La méthode robuste est :
|
||
- utiliser `event.json` (Gitea Actions) pour récupérer `before` et `after`
|
||
- calculer `git diff --name-only BEFORE AFTER`
|
||
|
||
C’est ce qui rend le gate **merge-proof**.
|
||
|
||
### 10.4 — Tests de preuve A/B (reproductibles)
|
||
|
||
Ces tests valident le gate sans ambiguïté.
|
||
But : vérifier que le mode choisi est EXACTEMENT celui attendu.
|
||
|
||
#### Test A — toucher `src/content/...` (FULL auto)
|
||
|
||
1) Créer une branche test
|
||
2) Modifier 1 fichier dans `src/content/` (ex : ajouter une ligne de commentaire non destructive)
|
||
3) PR → merge dans `main`
|
||
4) Vérifier dans `deploy-staging-live.yml` :
|
||
|
||
Attendus :
|
||
- `Gate flags: HAS_FULL=1 HAS_HOTPATCH=0`
|
||
- `✅ build-impacting change -> MODE=full (rebuild+restart)`
|
||
- Les étapes FULL (blue puis green) s’exécutent réellement
|
||
|
||
#### Test B — toucher `src/annotations/...` uniquement (HOTPATCH auto)
|
||
|
||
1) Créer une branche test
|
||
2) Modifier 1 fichier sous `src/annotations/**` (ex: un champ comment, ts, etc.)
|
||
3) PR → merge dans `main`
|
||
4) Vérifier dans `deploy-staging-live.yml` :
|
||
|
||
Attendus :
|
||
- `Gate flags: HAS_FULL=0 HAS_HOTPATCH=1`
|
||
- `✅ annotations/media change -> MODE=hotpatch`
|
||
- Les étapes FULL sont “skip” (durée 0s)
|
||
- L’étape HOTPATCH s’exécute réellement
|
||
|
||
### 10.5 — Preuve opérationnelle côté NAS (2 URLs + 2 commandes)
|
||
|
||
But : prouver que staging+live servent bien les endpoints essentiels (et que le déploiement n’a pas “fait semblant”).
|
||
|
||
#### 10.5.1 — Deux URLs à vérifier (staging et live)
|
||
|
||
- Staging (blue) : `http://127.0.0.1:8081/`
|
||
- Live (green) : `http://127.0.0.1:8082/`
|
||
|
||
#### 10.5.2 — Deux commandes minimales (zéro débat)
|
||
|
||
en bash :
|
||
curl -fsSI http://127.0.0.1:8081/ | head -n 1
|
||
curl -fsSI http://127.0.0.1:8082/ | head -n 1
|
||
|
||
Attendu : HTTP/1.1 200 OK des deux côtés.
|
||
|
||
10.6 — Preuve “alias injection” (ancre ancienne → nouvelle) sur une page
|
||
|
||
Contexte : lorsqu’un paragraphe change (ex: ticket “Proposer” appliqué),
|
||
l’ID de paragraphe peut changer, mais on doit préserver les liens anciens via :
|
||
|
||
src/anchors/anchor-aliases.json
|
||
|
||
injection build-time dans dist (span .para-alias)
|
||
|
||
10.6.1 — Check rapide (staging + live)
|
||
|
||
Remplacer OLD/NEW par tes ids réels :
|
||
|
||
Attendu : HTTP/1.1 200 OK des deux côtés.
|
||
|
||
10.6 — Preuve “alias injection” (ancre ancienne → nouvelle) sur une page
|
||
|
||
Contexte : lorsqu’un paragraphe change (ex: ticket “Proposer” appliqué),
|
||
l’ID de paragraphe peut changer, mais on doit préserver les liens anciens via :
|
||
|
||
src/anchors/anchor-aliases.json
|
||
|
||
injection build-time dans dist (span .para-alias)
|
||
|
||
10.6.1 — Check rapide (staging + live)
|
||
|
||
Remplacer OLD/NEW par tes ids réels :
|
||
|
||
OLD="p-1-60c7ea48"
|
||
NEW="p-1-a21087b0"
|
||
|
||
for P in 8081 8082; do
|
||
echo "=== $P ==="
|
||
HTML="$(curl -fsS "http://127.0.0.1:${P}/archicrat-ia/chapitre-3/" | tr -d '\r')"
|
||
echo "OLD count: $(printf '%s' "$HTML" | grep -o "$OLD" | wc -l | tr -d ' ')"
|
||
echo "NEW count: $(printf '%s' "$HTML" | grep -o "$NEW" | wc -l | tr -d ' ')"
|
||
printf '%s\n' "$HTML" | grep -nE "$OLD|$NEW|class=\"para-alias\"" | head -n 40 || true
|
||
done
|
||
|
||
Attendu :
|
||
|
||
présence d’un alias : <span id="$OLD" class="para-alias"...>
|
||
|
||
présence du nouveau paragraphe : <p id="$NEW">...
|
||
|
||
10.6.2 — Check “lien ancien ne casse pas” (HTTP 200)
|
||
|
||
for P in 8081 8082; do
|
||
curl -fsSI "http://127.0.0.1:${P}/archicrat-ia/chapitre-3/#${OLD}" | head -n 1
|
||
done
|
||
|
||
Attendu : HTTP/1.1 200 OK et navigation fonctionnelle côté navigateur.
|
||
|
||
10.7 — Troubleshooting gate (symptômes typiques)
|
||
Symptom 1 : job bloqué “Set up job” très longtemps
|
||
|
||
Causes fréquentes :
|
||
|
||
runner indisponible / capacity saturée
|
||
|
||
runner ne récupère pas les tâches (fetch_timeout trop court + réseau instable)
|
||
|
||
erreur dans “Gate — decide …” qui casse bash (et donne l’impression d’un hang)
|
||
|
||
Commandes NAS (diagnostic rapide) :
|
||
|
||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}' | grep -E 'gitea-act-runner|registry|archicratie-web'
|
||
docker logs --since 30m --tail 400 gitea-act-runner | tail -n 200
|
||
Symptom 2 : conditional binary operator expected
|
||
|
||
Cause :
|
||
|
||
test bash du type [[ "$X" == "1" && "$Y" == "2" ]] mal formé
|
||
|
||
variable vide non quotée
|
||
|
||
usage d’un opérateur non supporté dans la shell effective
|
||
|
||
Fix :
|
||
|
||
set -euo pipefail
|
||
|
||
toujours quoter : [[ "${VAR:-}" == "..." ]]
|
||
|
||
logguer BEFORE/AFTER/FORCE et s’assurer qu’ils ne sont pas vides
|
||
|
||
Symptom 3 : le gate liste “trop de fichiers” alors qu’on a changé 1 seul fichier
|
||
|
||
Cause :
|
||
|
||
comparaison faite sur le mauvais range (ex: git show sur merge, ou mauvais parent)
|
||
Fix :
|
||
|
||
toujours utiliser git diff --name-only "$BEFORE" "$AFTER" (merge-proof)
|
||
|
||
confirmer dans le log : Gate ctx: BEFORE=... AFTER=...
|
||
|