Compare commits
8 Commits
bot/propos
...
docs-and-o
| Author | SHA1 | Date | |
|---|---|---|---|
| 3086f333ed | |||
| c1c3c19d13 | |||
| ddcd0acd4d | |||
| 9bc4eeb3e7 | |||
| 7a9a5319ac | |||
| 7d75de5c9f | |||
| 69c91cb661 | |||
| a1bfbf4405 |
@@ -297,6 +297,19 @@ jobs:
|
|||||||
docker image tag archicratie-web:blue "archicratie-web:blue.BAK.${TS}" || true
|
docker image tag archicratie-web:blue "archicratie-web:blue.BAK.${TS}" || true
|
||||||
docker image tag archicratie-web:green "archicratie-web:green.BAK.${TS}" || true
|
docker image tag archicratie-web:green "archicratie-web:green.BAK.${TS}" || true
|
||||||
|
|
||||||
|
BUILD_TIME_RAW="$(TZ=Europe/Paris date '+%Y-%m-%dT%H:%M:%S%z')"
|
||||||
|
BUILD_TIME="${BUILD_TIME_RAW:0:${#BUILD_TIME_RAW}-2}:${BUILD_TIME_RAW:${#BUILD_TIME_RAW}-2}"
|
||||||
|
|
||||||
|
PUBLIC_OPS_ENV=staging \
|
||||||
|
PUBLIC_OPS_UPSTREAM=web_blue \
|
||||||
|
PUBLIC_BUILD_SHA="${AFTER}" \
|
||||||
|
PUBLIC_BUILD_TIME="${BUILD_TIME}" \
|
||||||
|
node scripts/write-ops-health.mjs
|
||||||
|
|
||||||
|
test -f public/__ops/health.json
|
||||||
|
echo "=== public/__ops/health.json (blue/staging) ==="
|
||||||
|
cat public/__ops/health.json
|
||||||
|
|
||||||
docker compose -p "$PROJ" -f docker-compose.yml build web_blue
|
docker compose -p "$PROJ" -f docker-compose.yml build web_blue
|
||||||
docker rm -f archicratie-web-blue || true
|
docker rm -f archicratie-web-blue || true
|
||||||
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_blue
|
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_blue
|
||||||
@@ -306,6 +319,11 @@ jobs:
|
|||||||
wait_url "http://127.0.0.1:8081/annotations-index.json" "blue annotations-index"
|
wait_url "http://127.0.0.1:8081/annotations-index.json" "blue annotations-index"
|
||||||
wait_url "http://127.0.0.1:8081/pagefind/pagefind.js" "blue pagefind.js"
|
wait_url "http://127.0.0.1:8081/pagefind/pagefind.js" "blue pagefind.js"
|
||||||
|
|
||||||
|
wait_url "http://127.0.0.1:8081/__ops/health.json" "blue ops health"
|
||||||
|
|
||||||
|
curl -fsS --max-time 6 "http://127.0.0.1:8081/__ops/health.json" \
|
||||||
|
| python3 -c 'import sys, json; j=json.load(sys.stdin); print("env=", j.get("env")); print("upstream=", j.get("upstream")); print("buildSha=", j.get("buildSha")); print("builtAt=", j.get("builtAt"))'
|
||||||
|
|
||||||
CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8081/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)"
|
CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8081/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)"
|
||||||
echo "canonical(blue)=$CANON"
|
echo "canonical(blue)=$CANON"
|
||||||
echo "$CANON" | grep -q 'https://staging\.archicratie\.trans-hands\.synology\.me/' || {
|
echo "$CANON" | grep -q 'https://staging\.archicratie\.trans-hands\.synology\.me/' || {
|
||||||
@@ -353,6 +371,19 @@ jobs:
|
|||||||
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_green || true
|
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_green || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUILD_TIME_RAW="$(TZ=Europe/Paris date '+%Y-%m-%dT%H:%M:%S%z')"
|
||||||
|
BUILD_TIME="${BUILD_TIME_RAW:0:${#BUILD_TIME_RAW}-2}:${BUILD_TIME_RAW:${#BUILD_TIME_RAW}-2}"
|
||||||
|
|
||||||
|
PUBLIC_OPS_ENV=prod \
|
||||||
|
PUBLIC_OPS_UPSTREAM=web_green \
|
||||||
|
PUBLIC_BUILD_SHA="${AFTER}" \
|
||||||
|
PUBLIC_BUILD_TIME="${BUILD_TIME}" \
|
||||||
|
node scripts/write-ops-health.mjs
|
||||||
|
|
||||||
|
test -f public/__ops/health.json
|
||||||
|
echo "=== public/__ops/health.json (green/prod) ==="
|
||||||
|
cat public/__ops/health.json
|
||||||
|
|
||||||
# build/restart green
|
# build/restart green
|
||||||
if ! docker compose -p "$PROJ" -f docker-compose.yml build web_green; then
|
if ! docker compose -p "$PROJ" -f docker-compose.yml build web_green; then
|
||||||
echo "❌ build green failed"; rollback; exit 4
|
echo "❌ build green failed"; rollback; exit 4
|
||||||
@@ -366,6 +397,11 @@ jobs:
|
|||||||
if ! wait_url "http://127.0.0.1:8082/annotations-index.json" "green annotations-index"; then rollback; exit 4; fi
|
if ! wait_url "http://127.0.0.1:8082/annotations-index.json" "green annotations-index"; then rollback; exit 4; fi
|
||||||
if ! wait_url "http://127.0.0.1:8082/pagefind/pagefind.js" "green pagefind.js"; then rollback; exit 4; fi
|
if ! wait_url "http://127.0.0.1:8082/pagefind/pagefind.js" "green pagefind.js"; then rollback; exit 4; fi
|
||||||
|
|
||||||
|
if ! wait_url "http://127.0.0.1:8082/__ops/health.json" "green ops health"; then rollback; exit 4; fi
|
||||||
|
|
||||||
|
curl -fsS --max-time 6 "http://127.0.0.1:8082/__ops/health.json" \
|
||||||
|
| python3 -c 'import sys, json; j=json.load(sys.stdin); print("env=", j.get("env")); print("upstream=", j.get("upstream")); print("buildSha=", j.get("buildSha")); print("builtAt=", j.get("builtAt"))'
|
||||||
|
|
||||||
CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8082/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)"
|
CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8082/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)"
|
||||||
echo "canonical(green)=$CANON"
|
echo "canonical(green)=$CANON"
|
||||||
echo "$CANON" | grep -q 'https://archicratie\.trans-hands\.synology\.me/' || {
|
echo "$CANON" | grep -q 'https://archicratie\.trans-hands\.synology\.me/' || {
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -30,4 +30,5 @@ public/favicon_io.zip
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# local temp workspace
|
# local temp workspace
|
||||||
.tmp/
|
.tmp/
|
||||||
|
public/__ops/health.json
|
||||||
|
|||||||
1393
docs/OPS-LOCALHOST-AUTO-SYNC.md
Normal file
1393
docs/OPS-LOCALHOST-AUTO-SYNC.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,51 +1,147 @@
|
|||||||
# START-HERE — Archicratie / Édition Web (v2)
|
# START-HERE — Archicratie / Édition Web (v3)
|
||||||
> Onboarding + exploitation “nickel chrome” (DEV → Gitea → CI → Release → Blue/Green → Edge/SSO)
|
> Onboarding + exploitation “nickel chrome” (DEV → Gitea → CI → Release → Blue/Green → Edge/SSO → localhost auto-sync)
|
||||||
|
|
||||||
## 0) TL;DR (la règle d’or)
|
## 0) TL;DR (la règle d’or)
|
||||||
- **Gitea = source canonique**.
|
|
||||||
- **main est protégé** : toute modification passe par **branche → PR → CI → merge**.
|
- **Gitea = source canonique**.
|
||||||
- **Le NAS n’est pas la source** : si un hotfix est fait sur NAS, on **backporte** via PR immédiatement.
|
- **`main` est protégée** : toute modification passe par **branche → PR → CI → merge**.
|
||||||
- **Le site est statique Astro** : la prod sert du HTML (nginx), l’accès est contrôlé au niveau reverse-proxy (Traefik + Authelia).
|
- **Le NAS n’est pas la source** : si un hotfix est fait sur NAS, il doit être **backporté immédiatement** via PR.
|
||||||
|
- **Le site est statique Astro** : la prod sert du HTML via nginx ; l’accès est contrôlé au niveau reverse-proxy (Traefik + Authelia).
|
||||||
|
- **Le localhost automatique n’est pas le repo de dev** : il tourne depuis un **worktree dédié**, synchronisé sur `origin/main`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1) Architecture mentale (ultra simple)
|
## 1) Architecture mentale (ultra simple)
|
||||||
- **DEV (Mac Studio)** : édition + tests + commit + push
|
|
||||||
- **Gitea** : dépôt canon + PR + CI (CI.yaml)
|
- **DEV canonique (Mac Studio)** : édition, dev, tests, commits, pushes
|
||||||
- **NAS (DS220+)** : déploiement “blue/green”
|
- **Gitea** : dépôt canonique, PR, CI, workflows éditoriaux
|
||||||
- `web_blue` (staging upstream) → `127.0.0.1:8081`
|
- **NAS (DS220+)** : déploiement blue/green
|
||||||
- `web_green` (live upstream) → `127.0.0.1:8082`
|
- `web_blue` → staging upstream → `127.0.0.1:8081`
|
||||||
- **Edge (Traefik)** : route les hosts
|
- `web_green` → live upstream → `127.0.0.1:8082`
|
||||||
|
- **Edge (Traefik)** : routage des hosts
|
||||||
- `staging.archicratie...` → 8081
|
- `staging.archicratie...` → 8081
|
||||||
- `archicratie...` → 8082
|
- `archicratie...` → 8082
|
||||||
- **Authelia** devant, via middleware `chain-auth@file`
|
- **Authelia** devant, via middleware `chain-auth@file`
|
||||||
|
- **Localhost auto-sync**
|
||||||
|
- un **repo canonique de développement**
|
||||||
|
- un **worktree localhost miroir de `origin/main`**
|
||||||
|
- un **agent de sync**
|
||||||
|
- un **agent Astro**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2) Répertoires & conventions (repo)
|
## 2) Répertoires & conventions (repo)
|
||||||
|
|
||||||
### 2.1 Contenu canon (édition)
|
### 2.1 Contenu canon (édition)
|
||||||
- `src/content/**` : contenu MD / MDX canon (Astro content collections)
|
|
||||||
- `src/pages/**` : routes Astro (index, [...slug], etc.)
|
- `src/content/**` : contenu MD / MDX canon
|
||||||
- `src/components/**` : composants UI (SiteNav, TOC, SidePanel, etc.)
|
- `src/pages/**` : routes Astro
|
||||||
- `src/layouts/**` : layouts (EditionLayout, SiteLayout)
|
- `src/components/**` : composants UI
|
||||||
|
- `src/layouts/**` : layouts
|
||||||
- `src/styles/**` : CSS global
|
- `src/styles/**` : CSS global
|
||||||
|
|
||||||
### 2.2 Annotations (pré-Édition “tickets”)
|
### 2.2 Annotations (pré-Édition “tickets”)
|
||||||
|
|
||||||
- `src/annotations/<workKey>/<slug>.yml`
|
- `src/annotations/<workKey>/<slug>.yml`
|
||||||
- Exemple : `src/annotations/archicrat-ia/prologue.yml`
|
- Exemple :
|
||||||
- Objectif : stocker “Références / Médias / Commentaires” par page et par paragraphe (`p-...`).
|
`src/annotations/archicrat-ia/prologue.yml`
|
||||||
|
|
||||||
|
Objectif :
|
||||||
|
stocker “Références / Médias / Commentaires” par page et par paragraphe (`p-...`).
|
||||||
|
|
||||||
### 2.3 Scripts (tooling / build)
|
### 2.3 Scripts (tooling / build)
|
||||||
- `scripts/inject-anchor-aliases.mjs` : injection aliases dans dist
|
|
||||||
- `scripts/dedupe-ids-dist.mjs` : retire IDs dupliqués dans dist
|
- `scripts/inject-anchor-aliases.mjs` : injection aliases dans `dist`
|
||||||
- `scripts/build-para-index.mjs` : index paragraphes (postbuild / predev)
|
- `scripts/dedupe-ids-dist.mjs` : retrait IDs dupliqués
|
||||||
- `scripts/build-annotations-index.mjs` : index annotations (postbuild / predev)
|
- `scripts/build-para-index.mjs` : index paragraphes
|
||||||
- `scripts/check-anchors.mjs` : contrat stabilité d’ancres (CI)
|
- `scripts/build-annotations-index.mjs` : index annotations
|
||||||
|
- `scripts/check-anchors.mjs` : contrat stabilité d’ancres
|
||||||
- `scripts/check-annotations*.mjs` : sanity YAML + médias
|
- `scripts/check-annotations*.mjs` : sanity YAML + médias
|
||||||
|
|
||||||
> Important : les scripts sont **partie intégrante** de la stabilité (IDs/ancres/indexation).
|
> Important : ces scripts ne sont pas accessoires.
|
||||||
> On évite “la magie” : tout est scripté + vérifié.
|
> Ils font partie du contrat de stabilité éditoriale.
|
||||||
|
|
||||||
## 3) Workflow Git “pro” (main protégé)
|
---
|
||||||
### 3.1 Cycle standard (toute modif)
|
|
||||||
en bash :
|
|
||||||
|
|
||||||
|
## 3) Les trois espaces à ne jamais confondre
|
||||||
|
|
||||||
|
### 3.1 Repo canonique de développement
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Volumes/FunIA/dev/archicratie-edition/site
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
|
||||||
|
- développement normal
|
||||||
|
- branches de travail
|
||||||
|
- nouvelles fonctionnalités
|
||||||
|
- corrections manuelles
|
||||||
|
- commits
|
||||||
|
- pushes
|
||||||
|
- PR
|
||||||
|
|
||||||
|
### 3.2 Worktree localhost miroir de `main`
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Users/s-funia/ops-local/archicratie/localhost-worktree
|
||||||
|
```
|
||||||
|
|
||||||
|
Branche attendue :
|
||||||
|
|
||||||
|
```text
|
||||||
|
localhost-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
|
||||||
|
- exécuter le localhost automatique
|
||||||
|
- refléter `origin/main`
|
||||||
|
- ne jamais servir d’espace de développement
|
||||||
|
|
||||||
|
### 3.3 Ops local hors repo
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Users/s-funia/ops-local/archicratie
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
|
||||||
|
- scripts d’exploitation
|
||||||
|
- état
|
||||||
|
- logs
|
||||||
|
- automatisation `launchd`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4) Pourquoi cette séparation existe
|
||||||
|
|
||||||
|
Il ne faut pas utiliser le repo canonique de développement comme serveur localhost permanent.
|
||||||
|
|
||||||
|
Sinon on mélange :
|
||||||
|
|
||||||
|
- travail en cours
|
||||||
|
- commits non poussés
|
||||||
|
- essais temporaires
|
||||||
|
- état réellement publié sur `main`
|
||||||
|
|
||||||
|
Le résultat devient ambigu.
|
||||||
|
|
||||||
|
La séparation retenue est donc :
|
||||||
|
|
||||||
|
- **repo canonique** = espace de développement
|
||||||
|
- **worktree localhost** = miroir exécutable de `origin/main`
|
||||||
|
- **ops local** = scripts et automatisation
|
||||||
|
|
||||||
|
C’est cette séparation qui rend le système lisible, robuste et opérable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5) Workflow Git “pro” (main protégée)
|
||||||
|
|
||||||
|
### 5.1 Cycle standard (toute modif)
|
||||||
|
|
||||||
|
```bash
|
||||||
git checkout main
|
git checkout main
|
||||||
git pull --ff-only
|
git pull --ff-only
|
||||||
|
|
||||||
@@ -60,37 +156,48 @@ npm run test:anchors
|
|||||||
git add -A
|
git add -A
|
||||||
git commit -m "xxx: description claire"
|
git commit -m "xxx: description claire"
|
||||||
git push -u origin "$BR"
|
git push -u origin "$BR"
|
||||||
|
```
|
||||||
|
|
||||||
### 3.2 PR vers main
|
### 5.2 PR vers `main`
|
||||||
|
|
||||||
Ouvrir PR dans Gitea
|
- ouvrir une PR dans Gitea
|
||||||
|
- attendre une CI verte
|
||||||
|
- merger
|
||||||
|
- laisser les workflows faire le reste
|
||||||
|
|
||||||
CI doit être verte
|
### 5.3 Cas spécial : hotfix prod (NAS)
|
||||||
|
|
||||||
Merge PR → main
|
On peut faire un hotfix d’urgence côté NAS si nécessaire.
|
||||||
|
|
||||||
### 3.3 Cas spécial : hotfix prod (NAS)
|
Mais l’état final doit toujours revenir dans Gitea :
|
||||||
|
|
||||||
On peut faire un hotfix “urgence” en prod/staging si nécessaire…
|
- branche
|
||||||
|
- PR
|
||||||
|
- CI
|
||||||
|
- merge
|
||||||
|
|
||||||
MAIS : l’état final doit revenir dans Gitea : branche → PR → CI → merge.
|
---
|
||||||
|
|
||||||
## 4) Déploiement (NAS) — principe
|
## 6) Déploiement (NAS) — principe
|
||||||
### 4.1 Release pack
|
|
||||||
|
|
||||||
On génère un pack “reproductible” (source + config + scripts) puis on déploie.
|
### 6.1 Release pack
|
||||||
|
|
||||||
### 4.2 Blue/Green
|
On génère un pack reproductible, puis on déploie.
|
||||||
|
|
||||||
web_blue = staging upstream (8081)
|
### 6.2 Blue/Green
|
||||||
|
|
||||||
web_green = live upstream (8082)
|
- `web_blue` = staging (`8081`)
|
||||||
|
- `web_green` = live (`8082`)
|
||||||
|
|
||||||
Edge Traefik sélectionne quel host pointe vers quel upstream.
|
Le reverse-proxy choisit l’upstream selon le host demandé.
|
||||||
|
|
||||||
## 5) Check-list “≤ 10 commandes” (happy path complet)
|
---
|
||||||
### 5.1 DEV (Mac)
|
|
||||||
|
|
||||||
|
## 7) Happy path complet
|
||||||
|
|
||||||
|
### 7.1 DEV (Mac)
|
||||||
|
|
||||||
|
```bash
|
||||||
git checkout main && git pull --ff-only
|
git checkout main && git pull --ff-only
|
||||||
git checkout -b chore/my-change-$(date +%Y%m%d)
|
git checkout -b chore/my-change-$(date +%Y%m%d)
|
||||||
|
|
||||||
@@ -99,55 +206,258 @@ rm -rf .astro node_modules/.vite dist
|
|||||||
npm run build
|
npm run build
|
||||||
npm run test:anchors
|
npm run test:anchors
|
||||||
npm run dev
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
### 5.2 Push + PR
|
### 7.2 Push + PR
|
||||||
|
|
||||||
|
```bash
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "chore: my change"
|
git commit -m "chore: my change"
|
||||||
git push -u origin chore/my-change-YYYYMMDD
|
git push -u origin chore/my-change-YYYYMMDD
|
||||||
# ouvrir PR dans Gitea
|
```
|
||||||
|
|
||||||
### 5.3 Déploiement NAS (résumé)
|
Puis ouvrir la PR dans Gitea.
|
||||||
|
|
||||||
Voir docs/runbooks/DEPLOY-BLUE-GREEN.md.
|
### 7.3 Déploiement NAS
|
||||||
|
|
||||||
## 6) Problèmes “classiques” + diagnostic rapide
|
Voir :
|
||||||
### 6.1 “Le staging ne ressemble pas au local”
|
|
||||||
|
|
||||||
# Comparer upstream direct 8081 vs 8082 :
|
```text
|
||||||
|
docs/runbooks/DEPLOY-BLUE-GREEN.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8) Localhost auto-sync — ce qu’il faut retenir
|
||||||
|
|
||||||
|
Le localhost automatique sert à voir **la vérité de `main`**, pas à développer du neuf.
|
||||||
|
|
||||||
|
### 8.1 Scripts principaux
|
||||||
|
|
||||||
|
#### Script de sync
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/ops-local/archicratie/auto-sync-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Rôle :
|
||||||
|
|
||||||
|
- fetch `origin/main`
|
||||||
|
- réaligner le worktree localhost
|
||||||
|
- lancer `npm ci` si besoin
|
||||||
|
- redéclencher l’agent Astro si nécessaire
|
||||||
|
|
||||||
|
#### Script Astro
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/ops-local/archicratie/run-astro-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Rôle :
|
||||||
|
|
||||||
|
- lancer `astro dev`
|
||||||
|
- depuis le bon worktree
|
||||||
|
- avec le bon runtime Node
|
||||||
|
- sur `127.0.0.1:4321`
|
||||||
|
|
||||||
|
> Oui : ce script est nécessaire.
|
||||||
|
> Il isole proprement le lancement du serveur Astro dans un contexte `launchd` stable.
|
||||||
|
|
||||||
|
### 8.2 LaunchAgents
|
||||||
|
|
||||||
|
#### Agent sync
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/Library/LaunchAgents/me.archicratie.localhost-sync.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Agent Astro
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/Library/LaunchAgents/me.archicratie.localhost-astro.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 Document de référence
|
||||||
|
|
||||||
|
Pour tout le détail d’exploitation du localhost automatique, lire :
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/OPS-LOCALHOST-AUTO-SYNC.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9) Règle d’or : il y a deux usages locaux distincts
|
||||||
|
|
||||||
|
### 9.1 Voir ce qui est réellement sur `main`
|
||||||
|
|
||||||
|
Utiliser :
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://127.0.0.1:4321
|
||||||
|
```
|
||||||
|
|
||||||
|
Ce localhost doit être considéré comme :
|
||||||
|
|
||||||
|
**un miroir local exécutable de `origin/main`**
|
||||||
|
|
||||||
|
### 9.2 Développer / tester une nouvelle fonctionnalité
|
||||||
|
|
||||||
|
Utiliser le repo canonique :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Volumes/FunIA/dev/archicratie-edition/site
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Donc :
|
||||||
|
|
||||||
|
- **localhost auto-sync** = vérité de `main`
|
||||||
|
- **localhost de dev manuel** = expérimentation en cours
|
||||||
|
|
||||||
|
Il ne faut pas les confondre.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10) Ce qu’il ne faut pas faire
|
||||||
|
|
||||||
|
### 10.1 Ne pas développer dans le worktree localhost
|
||||||
|
|
||||||
|
Le worktree localhost est piloté automatiquement.
|
||||||
|
|
||||||
|
Il peut être :
|
||||||
|
|
||||||
|
- réaligné
|
||||||
|
- nettoyé
|
||||||
|
- redémarré
|
||||||
|
|
||||||
|
Donc :
|
||||||
|
|
||||||
|
- pas de commits dedans
|
||||||
|
- pas de dev feature dedans
|
||||||
|
- pas d’expérimentation de fond dedans
|
||||||
|
|
||||||
|
### 10.2 Ne pas utiliser le repo canonique comme miroir auto-sync
|
||||||
|
|
||||||
|
Sinon on mélange :
|
||||||
|
|
||||||
|
- espace de dev
|
||||||
|
- état publié
|
||||||
|
- serveur local permanent
|
||||||
|
|
||||||
|
### 10.3 Ne pas remettre les scripts ops sur un volume externe
|
||||||
|
|
||||||
|
Les scripts d’ops doivent rester sous `HOME`.
|
||||||
|
|
||||||
|
Le fait de les mettre sous `/Volumes/...` a déjà provoqué des erreurs du type :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Operation not permitted
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.4 Ne pas supprimer `run-astro-localhost.sh`
|
||||||
|
|
||||||
|
Ce script fait partie de l’architecture actuelle.
|
||||||
|
Le supprimer reviendrait à réintroduire le flou entre sync Git et exécution d’Astro.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11) Commandes de contrôle essentielles
|
||||||
|
|
||||||
|
### 11.1 État global
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.2 État Git
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD
|
||||||
|
git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main
|
||||||
|
git -C ~/ops-local/archicratie/localhost-worktree branch --show-current
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.3 État LaunchAgents
|
||||||
|
|
||||||
|
```bash
|
||||||
|
launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p'
|
||||||
|
launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.4 État logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log
|
||||||
|
tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log
|
||||||
|
tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log
|
||||||
|
tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.5 État serveur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
lsof -nP -iTCP:4321 -sTCP:LISTEN
|
||||||
|
PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)"
|
||||||
|
ps -p "$PID" -o pid=,command=
|
||||||
|
lsof -a -p "$PID" -d cwd
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.6 Vérification contenu
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12) Problèmes classiques + diagnostic
|
||||||
|
|
||||||
|
### 12.1 “Le staging ne ressemble pas au local”
|
||||||
|
|
||||||
|
Comparer les upstream directs :
|
||||||
|
|
||||||
|
```bash
|
||||||
curl -sS http://127.0.0.1:8081/ | head -n 2
|
curl -sS http://127.0.0.1:8081/ | head -n 2
|
||||||
curl -sS http://127.0.0.1:8082/ | head -n 2
|
curl -sS http://127.0.0.1:8082/ | head -n 2
|
||||||
|
```
|
||||||
|
|
||||||
# Vérifier quel routeur edge répond (header diag) :
|
Vérifier le routeur edge :
|
||||||
|
|
||||||
|
```bash
|
||||||
curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \
|
curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \
|
||||||
| grep -iE 'HTTP/|location:|x-archi-router'
|
| grep -iE 'HTTP/|location:|x-archi-router'
|
||||||
|
```
|
||||||
|
|
||||||
# Lire docs/runbooks/EDGE-TRAEFIK.md.
|
Voir :
|
||||||
|
|
||||||
### 6.2 Canonical incorrect (localhost en prod)
|
```text
|
||||||
|
docs/runbooks/EDGE-TRAEFIK.md
|
||||||
|
```
|
||||||
|
|
||||||
Cause racine : site dans Astro = PUBLIC_SITE non injecté au build.
|
### 12.2 Canonical incorrect
|
||||||
|
|
||||||
Fix canonique : voir docs/runbooks/ENV-PUBLIC_SITE.md.
|
Cause probable : `PUBLIC_SITE` mal injecté au build.
|
||||||
|
|
||||||
Test :
|
Test :
|
||||||
|
|
||||||
|
```bash
|
||||||
curl -sS http://127.0.0.1:8082/ | grep -oE 'rel="canonical" href="[^"]+"' | head -1
|
curl -sS http://127.0.0.1:8082/ | grep -oE 'rel="canonical" href="[^"]+"' | head -1
|
||||||
|
```
|
||||||
|
|
||||||
### 6.3 Contrat “anchors” en échec après migration d’URL
|
Voir :
|
||||||
|
|
||||||
Quand on déplace des routes (ex: /archicratie/archicrat-ia/* → /archicrat-ia/*), le test d’ancres peut échouer même si les IDs n’ont pas changé, car les pages ont changé de chemin.
|
```text
|
||||||
|
docs/runbooks/ENV-PUBLIC_SITE.md
|
||||||
|
```
|
||||||
|
|
||||||
# Procédure safe :
|
### 12.3 Contrat anchors en échec après migration d’URL
|
||||||
|
|
||||||
Backup baseline :
|
Procédure safe :
|
||||||
|
|
||||||
|
```bash
|
||||||
cp -a tests/anchors-baseline.json /tmp/anchors-baseline.json.bak.$(date +%F-%H%M%S)
|
cp -a tests/anchors-baseline.json /tmp/anchors-baseline.json.bak.$(date +%F-%H%M%S)
|
||||||
|
|
||||||
Mettre à jour les clés (chemins) sans toucher aux IDs :
|
|
||||||
|
|
||||||
node - <<'NODE'
|
node - <<'NODE'
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
const p='tests/anchors-baseline.json';
|
const p='tests/anchors-baseline.json';
|
||||||
@@ -161,16 +471,213 @@ fs.writeFileSync(p, JSON.stringify(out,null,2)+'\n');
|
|||||||
console.log('updated keys:', Object.keys(j).length, '->', Object.keys(out).length);
|
console.log('updated keys:', Object.keys(j).length, '->', Object.keys(out).length);
|
||||||
NODE
|
NODE
|
||||||
|
|
||||||
Re-run :
|
|
||||||
|
|
||||||
npm run test:anchors
|
npm run test:anchors
|
||||||
|
```
|
||||||
|
|
||||||
## 7) Ce que l’étape 9 doit faire (orientation)
|
### 12.4 “Le localhost auto-sync ne montre pas les dernières modifs”
|
||||||
|
|
||||||
Stabiliser le pipeline “tickets → YAML annotations”
|
Commande réflexe :
|
||||||
|
|
||||||
Formaliser la spec YAML + merge + anti-doublon (voir docs/EDITORIAL-ANNOTATIONS-SPEC.md)
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
Durcir l’onboarding (ce START-HERE + runbooks)
|
Puis :
|
||||||
|
|
||||||
Éviter les régressions par tests (anchors / annotations / smoke)
|
```bash
|
||||||
|
git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD
|
||||||
|
git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main
|
||||||
|
```
|
||||||
|
|
||||||
|
Si les SHA diffèrent :
|
||||||
|
- le sync n’a pas tourné
|
||||||
|
- ou l’agent sync a un problème
|
||||||
|
|
||||||
|
### 12.5 “Le SHA est bon mais le contenu web est faux”
|
||||||
|
|
||||||
|
Vérifier quel Astro écoute réellement :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
lsof -nP -iTCP:4321 -sTCP:LISTEN
|
||||||
|
PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)"
|
||||||
|
ps -p "$PID" -o pid=,command=
|
||||||
|
lsof -a -p "$PID" -d cwd
|
||||||
|
```
|
||||||
|
|
||||||
|
Attendu :
|
||||||
|
- commande contenant `astro dev`
|
||||||
|
- cwd = `~/ops-local/archicratie/localhost-worktree`
|
||||||
|
|
||||||
|
### 12.6 Erreur `EBADENGINE`
|
||||||
|
|
||||||
|
Cause probable :
|
||||||
|
- Node 23 utilisé au lieu de Node 22
|
||||||
|
|
||||||
|
Résolution :
|
||||||
|
- forcer `node@22` dans les scripts et les LaunchAgents
|
||||||
|
|
||||||
|
### 12.7 Erreur `Operation not permitted`
|
||||||
|
|
||||||
|
Cause probable :
|
||||||
|
- scripts d’ops placés sous `/Volumes/...`
|
||||||
|
|
||||||
|
Résolution :
|
||||||
|
- garder les scripts sous :
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/ops-local/archicratie
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12.8 Erreur `EPERM` sur `astro.mjs`
|
||||||
|
|
||||||
|
Cause probable :
|
||||||
|
- ancien worktree sur volume externe
|
||||||
|
- ancien chemin résiduel
|
||||||
|
- Astro lancé depuis un mauvais emplacement
|
||||||
|
|
||||||
|
Résolution :
|
||||||
|
- worktree localhost sous :
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/ops-local/archicratie/localhost-worktree
|
||||||
|
```
|
||||||
|
|
||||||
|
- scripts cohérents avec ce chemin
|
||||||
|
- réinstallation propre via :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/install-localhost-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13) Redémarrage machine
|
||||||
|
|
||||||
|
Après reboot, le comportement attendu est :
|
||||||
|
|
||||||
|
1. le LaunchAgent sync se recharge
|
||||||
|
2. le LaunchAgent Astro se recharge
|
||||||
|
3. le worktree localhost est réaligné
|
||||||
|
4. Astro redémarre sur `127.0.0.1:4321`
|
||||||
|
|
||||||
|
### Vérification rapide après reboot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Si nécessaire :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/install-localhost-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14) Procédure de secours manuelle
|
||||||
|
|
||||||
|
### Forcer un sync
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/auto-sync-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Réinstaller proprement le dispositif local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/install-localhost-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Diagnostic complet
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15) Décision d’exploitation finale
|
||||||
|
|
||||||
|
La politique retenue est la suivante :
|
||||||
|
|
||||||
|
- **repo canonique** = espace de développement
|
||||||
|
- **worktree localhost** = miroir automatique de `main`
|
||||||
|
- **ops sous HOME** = scripts, logs, automation
|
||||||
|
- **LaunchAgent sync** = réalignement Git
|
||||||
|
- **LaunchAgent Astro** = exécution stable du serveur local
|
||||||
|
- **Astro local** = lancé uniquement depuis le worktree localhost
|
||||||
|
|
||||||
|
Cette séparation rend le dispositif plus :
|
||||||
|
|
||||||
|
- lisible
|
||||||
|
- robuste
|
||||||
|
- opérable
|
||||||
|
- antifragile
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16) Résumé opératoire
|
||||||
|
|
||||||
|
### Pour voir la vérité de `main`
|
||||||
|
|
||||||
|
Ouvrir :
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://127.0.0.1:4321
|
||||||
|
```
|
||||||
|
|
||||||
|
Le serveur doit provenir de :
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Users/s-funia/ops-local/archicratie/localhost-worktree
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pour développer
|
||||||
|
|
||||||
|
Travailler dans :
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Volumes/FunIA/dev/archicratie-edition/site
|
||||||
|
```
|
||||||
|
|
||||||
|
avec les commandes habituelles.
|
||||||
|
|
||||||
|
### Pour réparer vite
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
~/ops-local/archicratie/auto-sync-localhost.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 17) Mémoire courte
|
||||||
|
|
||||||
|
Si un jour plus rien n’est clair, repartir de ces commandes :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/ops-local/archicratie/doctor-localhost.sh
|
||||||
|
git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD
|
||||||
|
git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main
|
||||||
|
lsof -nP -iTCP:4321 -sTCP:LISTEN
|
||||||
|
```
|
||||||
|
|
||||||
|
Puis lire :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log
|
||||||
|
tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 18) Statut actuel visé
|
||||||
|
|
||||||
|
Quand tout fonctionne correctement :
|
||||||
|
|
||||||
|
- le worktree localhost pointe sur le même SHA que `origin/main`
|
||||||
|
- `astro dev` écoute sur `127.0.0.1:4321`
|
||||||
|
- son cwd est `~/ops-local/archicratie/localhost-worktree`
|
||||||
|
- le contenu servi correspond au contenu mergé sur `main`
|
||||||
|
|
||||||
|
C’est l’état de référence à préserver.
|
||||||
20
scripts/write-ops-health.mjs
Normal file
20
scripts/write-ops-health.mjs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const root = process.cwd();
|
||||||
|
const outDir = path.join(root, "public", "__ops");
|
||||||
|
const outFile = path.join(outDir, "health.json");
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
service: "archicratie-site",
|
||||||
|
env: process.env.PUBLIC_OPS_ENV || "unknown",
|
||||||
|
upstream: process.env.PUBLIC_OPS_UPSTREAM || "unknown",
|
||||||
|
buildSha: process.env.PUBLIC_BUILD_SHA || "unknown",
|
||||||
|
builtAt: process.env.PUBLIC_BUILD_TIME || new Date().toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.mkdirSync(outDir, { recursive: true });
|
||||||
|
fs.writeFileSync(outFile, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
||||||
|
|
||||||
|
console.log(`✅ ops health written: ${outFile}`);
|
||||||
|
console.log(payload);
|
||||||
Reference in New Issue
Block a user