Compare commits
19 Commits
prod-snaps
...
docs/norma
| Author | SHA1 | Date | |
|---|---|---|---|
| 80c047369f | |||
| d7c158a0fc | |||
| 30f0ef4164 | |||
| d2963673c9 | |||
| d59e10dfc6 | |||
| 214f930e56 | |||
| 9e903607bb | |||
| 8b7cfdfd48 | |||
| c12b6015ab | |||
| f7f6b8f770 | |||
| ae8ec42349 | |||
| 2f296f4fe4 | |||
| ccaa8029fb | |||
| 770dad30fb | |||
| 0d79d1aa78 | |||
| a1d9638e28 | |||
| ff013a746f | |||
| 46eca41879 | |||
|
|
7f871ca46f |
3
.env
3
.env
@@ -1,3 +0,0 @@
|
||||
PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me
|
||||
PUBLIC_GITEA_OWNER=archicratia
|
||||
PUBLIC_GITEA_REPO=archicratie-web
|
||||
@@ -1,4 +0,0 @@
|
||||
PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me
|
||||
PUBLIC_GITEA_OWNER=Archicratia
|
||||
PUBLIC_GITEA_REPO=archicratie-edition
|
||||
PUBLIC_SITE=https://archicratie.trans-hands.synology.me
|
||||
@@ -1,5 +0,0 @@
|
||||
FORGE_API=http://192.168.1.20:3000
|
||||
FORGE_BASE=https://gitea.archicratie.trans-hands.synology.me
|
||||
FORGE_TOKEN=aW73wpfJ4MiN2!3UU69qL*vWF9$9V7f@2
|
||||
PUBLIC_GITEA_OWNER=Archicratia
|
||||
PUBLIC_GITEA_REPO=archicratie-edition
|
||||
@@ -1,6 +0,0 @@
|
||||
PUBLIC_SITE=https://archicratie.trans-hands.synology.me
|
||||
PUBLIC_RELEASE=0.1.0
|
||||
|
||||
PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me
|
||||
PUBLIC_GITEA_OWNER=Archicratia
|
||||
PUBLIC_GITEA_REPO=archicratie-edition
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,6 +1,23 @@
|
||||
# --- secrets / env ---
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# --- local backups ---
|
||||
*.bak
|
||||
*.bak.*
|
||||
Dockerfile.bak.*
|
||||
*.swp
|
||||
*~
|
||||
node_modules/
|
||||
dist/
|
||||
.astro/
|
||||
/_release_out/
|
||||
|
||||
# --- macOS ---
|
||||
.DS_Store
|
||||
._*
|
||||
|
||||
# local backups
|
||||
Dockerfile.bak.*
|
||||
public/favicon_io.zip
|
||||
|
||||
@@ -10,7 +10,7 @@ ENV npm_config_update_notifier=false \
|
||||
npm_config_progress=false
|
||||
|
||||
# (Optionnel mais propre) git + certificats
|
||||
RUN --network=host apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true update \
|
||||
RUN apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true update \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -36,4 +36,6 @@ RUN npm run build
|
||||
FROM nginx:1.27-alpine AS runtime
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/dist/ /usr/share/nginx/html/
|
||||
RUN find /usr/share/nginx/html -type d -exec chmod 755 {} \; \
|
||||
&& find /usr/share/nginx/html -type f -exec chmod 644 {} \;
|
||||
EXPOSE 80
|
||||
|
||||
65
docs/CONFIG-ENV.md
Normal file
65
docs/CONFIG-ENV.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# CONFIG-ENV — variables, priorités, injection build
|
||||
|
||||
## 0) Ce que la prod doit garantir
|
||||
Le bouton “Proposer” doit ouvrir :
|
||||
- `PUBLIC_GITEA_BASE` (domaine Gitea)
|
||||
- `PUBLIC_GITEA_OWNER=Archicratia`
|
||||
- `PUBLIC_GITEA_REPO=archicratie-edition`
|
||||
|
||||
Si un seul de ces 3 paramètres est faux → on obtient :
|
||||
- 404 / redirect login inattendu
|
||||
- ou un repo/owner incorrect
|
||||
|
||||
## 1) Variables utilisées (publique, côté build Astro)
|
||||
|
||||
- `PUBLIC_GITEA_BASE`
|
||||
- `PUBLIC_GITEA_OWNER`
|
||||
- `PUBLIC_GITEA_REPO`
|
||||
|
||||
Elles sont consommées via `import.meta.env.PUBLIC_*` dans `EditionLayout.astro`.
|
||||
|
||||
## 2) Où elles vivent (en pratique)
|
||||
Sur NAS, vous avez vu des divergences entre :
|
||||
- `.env`
|
||||
- `.env.local`
|
||||
- `.env.production`
|
||||
|
||||
Règle :
|
||||
- **prod build docker** doit être piloté par **`.env`** (ou `.env.production` si vous standardisez ainsi),
|
||||
- mais on évite que `.env.local` “corrige en douce” un `.env` faux.
|
||||
|
||||
## 3) Vérification rapide (NAS)
|
||||
en sh
|
||||
for f in .env .env.local .env.production .env.production.local; do
|
||||
[ -f "$f" ] && echo "---- $f" && grep -nE '^PUBLIC_GITEA_(BASE|OWNER|REPO)=' "$f" || true
|
||||
done
|
||||
|
||||
## 4) Injection Docker (ce qui doit être vrai)
|
||||
|
||||
Le build passe bien les build-args :
|
||||
|
||||
--build-arg PUBLIC_GITEA_BASE=...
|
||||
|
||||
--build-arg PUBLIC_GITEA_OWNER=...
|
||||
|
||||
--build-arg PUBLIC_GITEA_REPO=...
|
||||
|
||||
et le Dockerfile expose via ENV pour Astro build.
|
||||
|
||||
## 5) Contrôle “résultat dans le HTML”
|
||||
|
||||
Après build, vérifier que la page contient le bon chemin /issues/new vers le bon owner/repo :
|
||||
|
||||
curl -fsS http://127.0.0.1:8082/archicratie/archicrat-ia/chapitre-4/ > /tmp/page.html
|
||||
grep -nE 'issues/new|archicratie-edition|Archicratia' /tmp/page.html | head -n 40
|
||||
|
||||
## 6) Secrets (à ne pas committer)
|
||||
|
||||
GITEA_TOKEN : jamais dans le repo.
|
||||
|
||||
Le token peut être utilisé ponctuellement pour push non-interactif, mais doit rester dans l’environnement local/CI.
|
||||
|
||||
## 7) Docker BuildKit / API (si besoin)
|
||||
|
||||
Si BuildKit/buildx est instable sur la machine, vous avez déjà un protocole “fonctionnel”.
|
||||
Ne documenter ici que le “standard validé” (voir DEPLOY_PROD).
|
||||
@@ -1,18 +1,29 @@
|
||||
# Déploiement production (Synology DS220+ / DSM 7.3) — Astro → Nginx statique
|
||||
|
||||
Dernière mise à jour : 2026-01-29
|
||||
> ✅ **CANONIQUE** — Procédure de référence “prod DS220+ / DSM 7.3”.
|
||||
|
||||
Ce document décrit la mise en place stable sur NAS :
|
||||
> Toute modif de déploiement doit être faite **ici**, via PR sur Gitea/main (pas d’édition à la main en prod).
|
||||
|
||||
> Périmètre : build Docker (Node→Nginx), blue/green 8081/8082, Reverse Proxy DSM, smoke, rollback.
|
||||
|
||||
> Dépendances critiques : variables PUBLIC_GITEA_* (sinon “Proposer” part en 404/login loop).
|
||||
|
||||
> Voir aussi : OPS-REFERENCE.md (index), OPS_COCKPIT.md (checklist), TROUBLESHOOTING.md (incidents).
|
||||
|
||||
Dernière mise à jour : 2026-02-01
|
||||
|
||||
Ce document décrit une mise en place stable sur NAS :
|
||||
- build Astro dans une image (Node)
|
||||
- runtime Nginx statique
|
||||
- bascule blue/green via Reverse Proxy DSM
|
||||
- tests fonctionnels (dont “Proposer” → Gitea)
|
||||
|
||||
---
|
||||
|
||||
## 1) Arborescence recommandée
|
||||
|
||||
Dossier racine :
|
||||
- `/volume2/docker/archicratie-web/current`
|
||||
Dossier racine “courant” :
|
||||
- `/volume2/docker/archicratie-web/current` (symlink vers la release active)
|
||||
|
||||
Contenu attendu :
|
||||
- `Dockerfile`
|
||||
@@ -20,6 +31,10 @@ Contenu attendu :
|
||||
- `nginx.conf`
|
||||
- `.env`
|
||||
- le code du site (package.json, src/, scripts/, etc.)
|
||||
- `ops/` (scripts de smoke, etc.)
|
||||
|
||||
Releases :
|
||||
- `/volume2/docker/archicratie-web/releases/<YYYYmmdd-HHMMSS>/app`
|
||||
|
||||
---
|
||||
|
||||
@@ -28,6 +43,7 @@ Contenu attendu :
|
||||
- DSM 7.3 avec accès SSH (admin)
|
||||
- Docker / Container Manager installé
|
||||
- Reverse Proxy DSM configuré (Portail des applications)
|
||||
- Sortie Internet OK depuis le NAS (résolution DNS + accès registry)
|
||||
|
||||
---
|
||||
|
||||
@@ -42,12 +58,12 @@ Les ports 8081/8082 :
|
||||
|
||||
---
|
||||
|
||||
## 4) Variables Gitea (Proposer)
|
||||
## 4) Variables Gitea (FEATURE “Proposer”)
|
||||
|
||||
Le site injecte des variables “publiques” au build :
|
||||
|
||||
- `PUBLIC_GITEA_BASE` (URL gitea)
|
||||
- `PUBLIC_GITEA_OWNER` (casse sensible)
|
||||
- `PUBLIC_GITEA_OWNER` (**casse sensible**)
|
||||
- `PUBLIC_GITEA_REPO`
|
||||
|
||||
Exemple dans `.env` :
|
||||
@@ -55,49 +71,210 @@ PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me
|
||||
PUBLIC_GITEA_OWNER=Archicratia
|
||||
PUBLIC_GITEA_REPO=archicratie-edition
|
||||
|
||||
### 4.1 Piège validé : mauvais owner/repo ⇒ 404/redirect
|
||||
Symptômes typiques :
|
||||
- nouvel onglet “Proposer” ouvre `/archicratia/archicratie-web/...` (mauvais)
|
||||
- Gitea renvoie 404 “page inexistante ou non autorisé”
|
||||
- ou 303 `/user/login` (si non loggé)
|
||||
|
||||
Contrôle rapide :
|
||||
en sh
|
||||
for f in .env .env.local .env.production .env.production.local; do
|
||||
[ -f "$f" ] && echo "---- $f" && grep -nE '^PUBLIC_GITEA_(BASE|OWNER|REPO)=' "$f" || true
|
||||
done
|
||||
|
||||
## 5) Reverse Proxy DSM (le point clé)
|
||||
|
||||
DSM 7.3 :
|
||||
### DSM 7.3 :
|
||||
Panneau de configuration → Portail des applications → Proxy inversé
|
||||
|
||||
# Règle pour le site :
|
||||
Règle pour le site :
|
||||
|
||||
Source : HTTPS / archicratie.trans-hands.synology.me / port 443
|
||||
|
||||
Destination : HTTP / 127.0.0.1 / port 8081 (BLUE) ou 8082 (GREEN)
|
||||
|
||||
# Certificat :
|
||||
Certificat :
|
||||
|
||||
Sécurité → Certificat : associer le bon certificat au nom de domaine.
|
||||
|
||||
## 6) Notes DS220+ “spécificités”
|
||||
### 6.1 Build réseau (DNS/apt/npm)
|
||||
### 6.1 Build réseau (DNS/apt/npm) : mode robuste
|
||||
|
||||
Sur DSM, il arrive que apt-get ou des résolutions DNS échouent pendant docker build.
|
||||
Solution : build avec réseau host (déjà prévu dans compose) :
|
||||
Sur DSM, il arrive que apt-get/npm aient des soucis réseau pendant docker build.
|
||||
Mesures robustes validées :
|
||||
|
||||
build: network: host
|
||||
build en --network host
|
||||
|
||||
Et activer BuildKit :
|
||||
export DOCKER_BUILDKIT=1
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
||||
apt-get avec retries + ForceIPv4
|
||||
|
||||
### 6.2 Artefacts Mac (PaxHeader / ._ / DS_Store)
|
||||
Exemple (dans Dockerfile) :
|
||||
|
||||
Si tu transfères une archive depuis macOS, tu peux embarquer des dossiers/fichiers parasites.
|
||||
Conséquence possible : Astro “voit” un faux contenu (ex: PaxHeader/...mdx) → erreurs de schema.
|
||||
apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true ...
|
||||
|
||||
Remède : .dockerignore robuste (voir anchors.md section “Artefacts Mac”).
|
||||
### 6.2 BuildKit / buildx / API Docker (DSM)
|
||||
|
||||
## 7) Cycle blue/green (résumé)
|
||||
Certains environnements DSM peuvent :
|
||||
|
||||
Tu rebuild le slot inactif (ex: GREEN)
|
||||
exiger BuildKit pour --network=host au build
|
||||
|
||||
Tu valides en local (curl/smoke/health)
|
||||
avoir des incompatibilités d’API (client/daemon)
|
||||
|
||||
Tu bascules DSM vers ce port
|
||||
Standard “chez nous” :
|
||||
|
||||
Rollback immédiat : tu repasses DSM sur l’autre port
|
||||
activer BuildKit au build
|
||||
|
||||
Pour l’opérationnel minute par minute, voir OPS_COCKPIT.md.
|
||||
utiliser DOCKER_API_VERSION="$API" si requis sur la machine
|
||||
|
||||
Remarque : la valeur de $API est celle validée localement sur le NAS.
|
||||
|
||||
### 6.3 Artefacts Mac (PaxHeader / ._ / DS_Store)
|
||||
|
||||
Si tu transfères une archive depuis macOS, tu peux embarquer des fichiers parasites.
|
||||
Conséquence possible : Astro “voit” un faux contenu → erreurs de schema.
|
||||
|
||||
Remède :
|
||||
|
||||
.dockerignore robuste (voir docs anchors / ops)
|
||||
|
||||
éviter les copies “tar” non nettoyées
|
||||
|
||||
## 7) Cycle blue/green (procédure protocolaire)
|
||||
### 7.1 Identifier quel slot est actuellement “en prod”
|
||||
|
||||
Comparer l’ETag/Last-Modified public avec 8081/8082 :
|
||||
curl -kI https://archicratie.trans-hands.synology.me/ | egrep -i 'etag:|last-modified:|server:'
|
||||
curl -fsSI http://127.0.0.1:8081/ | egrep -i 'etag:|last-modified:'
|
||||
curl -fsSI http://127.0.0.1:8082/ | egrep -i 'etag:|last-modified:'
|
||||
|
||||
Le port qui “match” est le slot actif.
|
||||
|
||||
### 7.2 Déployer sur le slot inactif (ex: GREEN 8082)
|
||||
|
||||
# Se placer sur le checkout courant :
|
||||
cd /volume2/docker/archicratie-web/current || exit 1
|
||||
|
||||
# Charger .env dans le shell (pour les build-args) :
|
||||
set -a
|
||||
. ./.env
|
||||
set +a
|
||||
|
||||
# Rebuild image (exemple green) :
|
||||
sudo env DOCKER_BUILDKIT=1 DOCKER_API_VERSION="$API" docker build --no-cache --network host \
|
||||
--build-arg PUBLIC_GITEA_BASE="$PUBLIC_GITEA_BASE" \
|
||||
--build-arg PUBLIC_GITEA_OWNER="$PUBLIC_GITEA_OWNER" \
|
||||
--build-arg PUBLIC_GITEA_REPO="$PUBLIC_GITEA_REPO" \
|
||||
-t archicratie-web:green \
|
||||
-f Dockerfile .
|
||||
|
||||
# Recreate conteneur (important) :
|
||||
sudo docker compose up -d --force-recreate --no-build web_green
|
||||
|
||||
# Smoke local :
|
||||
/volume2/docker/archicratie-web/ops/smoke.sh 8082
|
||||
|
||||
# Sanity check (fichiers clés) :
|
||||
curl -fsSI http://127.0.0.1:8082/ | head -n 20
|
||||
curl -fsSI http://127.0.0.1:8082/favicon.ico | head -n 20
|
||||
curl -fsSI http://127.0.0.1:8082/favicon.svg | head -n 20
|
||||
|
||||
# Contrôle “Proposer” (validation fonctionnelle)
|
||||
|
||||
Ouvrir une page chapitre sur le domaine public (ou sur le slot direct si tu testes en local)
|
||||
|
||||
Clic Proposer → choix 1 → choix 2
|
||||
|
||||
Attendus :
|
||||
|
||||
un seul onglet
|
||||
|
||||
URL sur .../Archicratia/archicratie-edition/issues/new?...
|
||||
|
||||
formulaire visible (si loggé sur Gitea)
|
||||
|
||||
issue créée et CI/runner OK (si configuré)
|
||||
|
||||
### 7.3 Bascule DSM
|
||||
|
||||
Dans DSM Reverse Proxy :
|
||||
|
||||
destination 8081 ↔ 8082 (BLUE ↔ GREEN)
|
||||
|
||||
### 7.4 Rollback (immédiat)
|
||||
|
||||
repointer DSM sur l’ancien port (1 clic)
|
||||
|
||||
analyser ensuite le slot inactif
|
||||
|
||||
## 8) Favicon (et faux positifs navigateur)
|
||||
### 8.1 Symptom: Firefox affiche un 504 sur /favicon.ico
|
||||
|
||||
Cause fréquemment observée : cache navigateur (Firefox).
|
||||
Diagnose :
|
||||
|
||||
curl -kI https://.../favicon.ico renvoie 200
|
||||
|
||||
mais la console navigateur montre encore une erreur
|
||||
Fix :
|
||||
|
||||
désactiver le cache dans l’onglet Réseau, puis reload
|
||||
|
||||
ou vider le cache site
|
||||
|
||||
### 8.2 Permissions fichiers (si 403)
|
||||
|
||||
Si /favicon.svg renvoie 403 :
|
||||
|
||||
vérifier droits dans l’image nginx
|
||||
|
||||
standard : fichiers 644, répertoires 755 (validé via RUN find ... chmod)
|
||||
|
||||
## 9) Exploitation : log driver “db” et erreur “database is locked”
|
||||
|
||||
# Erreur observée :
|
||||
|
||||
failed to initialize logging driver : database is locked
|
||||
|
||||
# Contexte validé :
|
||||
|
||||
docker info → Logging Driver: db
|
||||
|
||||
# Remède validé :
|
||||
|
||||
redémarrer Container Manager (centre de paquets DSM)
|
||||
|
||||
# vérifier l’espace disque (df -h) et /tmp
|
||||
|
||||
Commandes :
|
||||
sudo docker info 2>/dev/null | egrep -i 'Logging Driver|Docker Root Dir|Server Version' || true
|
||||
df -h
|
||||
df -i
|
||||
|
||||
## 10) Références
|
||||
|
||||
Pour l’opérationnel minute par minute + tableau de bord : OPS_COCKPIT.md
|
||||
|
||||
Pour la synchro Mac/Gitea/NAS : OPS-SYNC-TRIPLE-SOURCE.md
|
||||
|
||||
Pour le workflow branches/PR/tags : WORKFLOW-GIT.md
|
||||
|
||||
Pour l’ENV : CONFIG-ENV.md
|
||||
|
||||
Pour les pannes connues : TROUBLESHOOTING.md
|
||||
|
||||
## Depuis quelle machine tu fais ça ?
|
||||
|
||||
- **Édition des docs** : **Mac Studio** (éditeur confortable, git propre)
|
||||
- **Commit/push** : **Mac Studio** (idéal), NAS seulement en “urgence”
|
||||
- **Déploiement** : **NAS** (évidemment)
|
||||
- **Gitea docker** : juste l’UI/Actions, pas nécessaire pour écrire les fichiers.
|
||||
|
||||
---
|
||||
|
||||
## Et maintenant (ordre propre)
|
||||
|
||||
1) Sur Mac : crée/complète ce doc (ci-dessus) + les autres docs.
|
||||
2) Commit “docs: ops runbooks (2026-02-01)” sur `main`.
|
||||
3) Push → CI verte.
|
||||
4) Sur NAS : `reset --hard origin/main` (via alpine/git si besoin).
|
||||
5) Rebuild/deploy **uniquement si** tu as touché Dockerfile/nginx/src/public (pas si docs only).
|
||||
|
||||
103
docs/FEATURE-PROPOSER.md
Normal file
103
docs/FEATURE-PROPOSER.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# FEATURE — “Proposer” (édition par paragraphe → issue Gitea)
|
||||
|
||||
Dernière mise à jour : 2026-02-01
|
||||
|
||||
Cette feature permet à un lecteur de proposer une correction/amélioration d’un paragraphe, en générant une issue pré-remplie dans Gitea.
|
||||
|
||||
---
|
||||
|
||||
## 0) Objectif fonctionnel
|
||||
Depuis une page chapitre :
|
||||
1) clic sur **Proposer** sur un paragraphe
|
||||
2) choix #1 (type)
|
||||
3) choix #2 (state/catégorie selon UI)
|
||||
4) ouverture d’un seul onglet vers Gitea : `/issues/new?...`
|
||||
5) issue pré-remplie avec :
|
||||
- chemin / URL / ancre
|
||||
- texte actuel (citation)
|
||||
- champs “Proposition / Justification”
|
||||
6) l’utilisateur valide, et le runner/CI traite.
|
||||
|
||||
---
|
||||
|
||||
## 1) Dépendances de configuration (critique)
|
||||
|
||||
Le lien Gitea est construit à partir de variables publiques injectées au build Astro :
|
||||
|
||||
- `PUBLIC_GITEA_BASE` (ex: `https://gitea.archicratie.trans-hands.synology.me`)
|
||||
- `PUBLIC_GITEA_OWNER` (**casse sensible**, ex: `Archicratia`)
|
||||
- `PUBLIC_GITEA_REPO` (ex: `archicratie-edition`)
|
||||
|
||||
### Symptômes si mauvais
|
||||
- mauvais repo → 404
|
||||
- redirect login inattendu
|
||||
- création d’issues impossible
|
||||
|
||||
---
|
||||
|
||||
## 2) Contrat “une seule ouverture d’onglet”
|
||||
Le flow ne doit jamais ouvrir deux onglets.
|
||||
|
||||
### Contrat
|
||||
- pas de `window.open(...)`
|
||||
- un seul `a.target="_blank"` (ou équivalent) déclenché
|
||||
- sur click : handler doit neutraliser les propagations parasites
|
||||
|
||||
### Vérification (NAS)
|
||||
en sh :
|
||||
curl -fsS http://127.0.0.1:8082/archicratie/archicrat-ia/chapitre-4/ > /tmp/page.html
|
||||
grep -n "window.open" /tmp/page.html | head
|
||||
|
||||
Doit retourner 0 ligne.
|
||||
|
||||
## 3) Diagnostic “trace ouverture onglet” (navigateur)
|
||||
|
||||
Dans la console, tu peux surcharger temporairement les mécanismes d’ouverture pour tracer :
|
||||
|
||||
si un window.open survient,
|
||||
|
||||
ou si un a.click target _blank est appelé.
|
||||
|
||||
But : prouver qu’il n’y a qu’un seul événement d’ouverture.
|
||||
|
||||
## 4) URL attendue (forme)
|
||||
|
||||
L’onglet doit ressembler à :
|
||||
|
||||
{PUBLIC_GITEA_BASE}/{OWNER}/{REPO}/issues/new?title=...&body=...
|
||||
|
||||
Important : owner et repo doivent être exactement ceux du repo canonique.
|
||||
|
||||
## 5) Pré-requis d’accès
|
||||
|
||||
L’utilisateur doit être loggé sur Gitea pour accéder à /issues/new
|
||||
|
||||
Si non loggé : redirect vers /user/login (comportement normal)
|
||||
|
||||
## 6) Tests fonctionnels (checklist)
|
||||
|
||||
Ouvrir une page chapitre (ex chapitre 4)
|
||||
|
||||
Clic Proposer (sur un paragraphe)
|
||||
|
||||
Choix 1 puis choix 2
|
||||
|
||||
Vérifier :
|
||||
|
||||
1 seul onglet
|
||||
|
||||
URL du repo correct
|
||||
|
||||
formulaire new issue visible
|
||||
|
||||
title/body pré-remplis (chemin + ancre + texte actuel)
|
||||
|
||||
Créer l’issue → vérifier le traitement CI/runner
|
||||
|
||||
## 7) Pannes typiques + causes
|
||||
|
||||
404 sur issue/new : PUBLIC_GITEA_OWNER/REPO faux (souvent casse)
|
||||
|
||||
2 onglets : double handler (bubbling + ouverture multiple)
|
||||
|
||||
pas de favicon : cache ou absence dans public/ → rebuild
|
||||
@@ -1,6 +1,16 @@
|
||||
OPS — Déploiement Archicratie Web Edition (Mac Studio → DS220+)
|
||||
# OPS — Déploiement Archicratie Web Edition (Mac Studio → DS220+)
|
||||
Objectif : déployer une nouvelle version du site sur le NAS (DS220+) sans jamais casser la prod, en utilisant un schéma blue/green piloté par DSM Reverse Proxy, avec une procédure robuste même quand docker compose build est instable sur le NAS.
|
||||
|
||||
> 🟧 **LEGACY / HISTORIQUE** — Ce document n’est plus la source de vérité.
|
||||
|
||||
> Référence actuelle : docs/DEPLOY_PROD_SYNOLOGY_DS220.md (canonique).
|
||||
|
||||
> Statut : gelé (on n’édite plus que pour ajouter un lien vers le canonique, si nécessaire).
|
||||
|
||||
> Raison : doublon → risque de divergence → risque d’erreur en prod.
|
||||
|
||||
> Si tu lis ceci pour déployer : stop → ouvre le canonique.
|
||||
|
||||
## 0) Repères essentiels
|
||||
Noms & domaines
|
||||
• Site public (prod) : https://archicratie.trans-hands.synology.me
|
||||
|
||||
30
docs/OPS-REFERENCE.md
Normal file
30
docs/OPS-REFERENCE.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# OPS-REFERENCE — Archicratie Édition
|
||||
|
||||
Document “pivot” : liens, invariants, conventions, commandes réflexes.
|
||||
|
||||
## 0) Invariants (à ne pas casser)
|
||||
|
||||
- **Source de vérité Git** : `origin/main` sur :contentReference[oaicite:0]{index=0}.
|
||||
- **Prod** : conteneur `archicratie-web-*` (nginx) derrière reverse proxy DSM.
|
||||
- **Config “Proposer”** : dépend de `PUBLIC_GITEA_BASE`, `PUBLIC_GITEA_OWNER`, `PUBLIC_GITEA_REPO` injectés au build.
|
||||
- **Branches** : `main` = travail ; `master` = legacy/compat (alignée mais protégée).
|
||||
- **NAS** : shell sans `git` → usage standard : `alpine/git` en conteneur.
|
||||
|
||||
## 1) Repères (chemins & objets)
|
||||
|
||||
### NAS (DS220+)
|
||||
- Checkout/release courant : `/volume2/docker/archicratie-web/current` (symlink vers releases/*/app)
|
||||
- Releases : `/volume2/docker/archicratie-web/releases/<timestamp>/app`
|
||||
- Conteneur green (exemple) : `archicratie-web-green` → `127.0.0.1:8082->80`
|
||||
- Conteneur blue (exemple) : `archicratie-web-blue` → `127.0.0.1:8081->80`
|
||||
- Smoke : `/volume2/docker/archicratie-web/ops/smoke.sh <port>`
|
||||
|
||||
### Mac Studio
|
||||
- Repo de travail : `site/` (ou équivalent)
|
||||
- Git natif : OK (branches, PR, tags, etc.)
|
||||
|
||||
## 2) Commandes réflexes (diagnostic)
|
||||
|
||||
### “Quelle version sert le domaine public ?”
|
||||
```sh
|
||||
curl -kI https://archicratie.trans-hands.synology.me/ | egrep -i 'etag:|last-modified:|server:'
|
||||
79
docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md
Normal file
79
docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# OPS Runbook — Archicratie Web (NAS Synology DS220 + Gitea)
|
||||
|
||||
> 🟦 **ALIAS (résumé)** — Runbook 1-page pour opérer vite sans se tromper.
|
||||
|
||||
> La procédure détaillée **canonique** est : docs/DEPLOY_PROD_SYNOLOGY_DS220.md.
|
||||
|
||||
> Source Git : Gitea/main ; déploiement = rebuild depuis main ; pas de hotfix non versionné.
|
||||
|
||||
> Déploiement : build sur slot inactif → smoke → bascule DSM → rollback si besoin.
|
||||
|
||||
> Incidents connus : voir docs/TROUBLESHOOTING.md.
|
||||
|
||||
## 0. Objectif
|
||||
Ce document décrit la procédure **exacte** pour :
|
||||
- maintenir un état cohérent entre **Local (Mac Studio)**, **Gitea**, **NAS (prod)** ;
|
||||
- déployer proprement une release Docker (build, smoke, bascule) ;
|
||||
- éviter les régressions (branches protégées, CI bloquante, rollback).
|
||||
|
||||
## 1. Invariants (à ne jamais violer)
|
||||
1) **La branche `main` sur Gitea = vérité canonique.**
|
||||
2) La prod NAS doit être **rebuild** depuis `main` (pas de modifications “à la main” non versionnées).
|
||||
3) Les variables `PUBLIC_GITEA_*` doivent pointer vers **le bon owner/repo** (sinon 404 / login loop).
|
||||
4) En solo : PR requise OK, mais **0 approval** (sinon blocage). CI doit rester bloquante.
|
||||
5) Interdiction : token/secret commité dans le repo.
|
||||
|
||||
## 2. Topologie (NAS)
|
||||
- Arborescence :
|
||||
- `/volume2/docker/archicratie-web/releases/<timestamp>/app`
|
||||
- `/volume2/docker/archicratie-web/current` (symlink vers release active)
|
||||
- Services :
|
||||
- `web_green` → port local typique `127.0.0.1:8082` (smoke)
|
||||
- (optionnel) `web_blue` → `127.0.0.1:8081` (ancienne)
|
||||
- Script :
|
||||
- `/volume2/docker/archicratie-web/ops/smoke.sh <port>`
|
||||
|
||||
## 3. Standard Git (Gitea)
|
||||
### 3.1 Branches
|
||||
- `main` : branche de travail et de déploiement (par défaut)
|
||||
- `master` : branche legacy (archivée / conservée pour compat si nécessaire)
|
||||
- Stratégie : `master` est soit supprimée, soit alignée sur `main`, mais **pas** utilisée comme axe actif.
|
||||
|
||||
### 3.2 Protection branches (solo recommandé)
|
||||
- `main` :
|
||||
- ✅ Exiger PR (Require pull request)
|
||||
- ✅ 0 approval (solo)
|
||||
- ✅ Bloquer merge si CI KO (Prevent merge if checks fail)
|
||||
- ✅ Désactiver force-push
|
||||
- (optionnel) désactiver push direct (selon UI Gitea)
|
||||
- `master` :
|
||||
- ✅ Interdire push direct
|
||||
- ✅ Désactiver force-push
|
||||
- ✅ Mention “legacy” (si UI le permet)
|
||||
|
||||
## 4. Variables d’environnement (cause n°1 des 404)
|
||||
### 4.1 Variables publiques injectées au build
|
||||
- `PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me`
|
||||
- `PUBLIC_GITEA_OWNER=Archicratia`
|
||||
- `PUBLIC_GITEA_REPO=archicratie-edition`
|
||||
|
||||
### 4.2 Règle d’or
|
||||
- Le site génère des liens `.../<OWNER>/<REPO>/issues/new?...`
|
||||
- Si OWNER/REPO est faux (ex: `archicratia/archicratie-web`) :
|
||||
- `/issues` peut marcher
|
||||
- MAIS `/issues/new` finit en 404 / redirect login / droits
|
||||
- => corriger `.env` et rebuild
|
||||
|
||||
## 5. Déploiement NAS (procédure protocolaire)
|
||||
### 5.1 Pré-check
|
||||
Sur NAS :
|
||||
- Vérifier qu’on est bien dans `/volume2/docker/archicratie-web/current`
|
||||
- Charger `.env` (pour build args)
|
||||
|
||||
Commandes :
|
||||
```sh
|
||||
cd /volume2/docker/archicratie-web/current || exit 1
|
||||
set -a
|
||||
. ./.env
|
||||
set +a
|
||||
grep -nE '^PUBLIC_GITEA_(BASE|OWNER|REPO)=' .env
|
||||
122
docs/OPS-SYNC-TRIPLE-SOURCE.md
Normal file
122
docs/OPS-SYNC-TRIPLE-SOURCE.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# OPS-SYNC-TRIPLE-SOURCE — Mac Studio / Gitea / NAS (prod)
|
||||
|
||||
Dernière mise à jour : 2026-02-01
|
||||
|
||||
Ce document décrit la synchronisation **sans ambiguïté** entre :
|
||||
- **Local (Mac Studio)** : édition / écriture / préparation PR
|
||||
- **Gitea** : **vérité canonique** (branche `main`)
|
||||
- **NAS Synology DS220+** : déploiement (blue/green) à partir de `main`
|
||||
|
||||
---
|
||||
|
||||
## 0) Invariants (à ne jamais violer)
|
||||
|
||||
1) **Gitea `main` = source de vérité.**
|
||||
2) Le NAS ne doit pas “inventer” du code : pas d’édition manuelle non versionnée en prod (sauf hotfix temporaire immédiatement reporté dans une PR).
|
||||
3) Le bouton “Proposer” dépend de `PUBLIC_GITEA_*` : une valeur fausse → 404 / redirect login / mauvais repo.
|
||||
4) Les secrets (tokens) **ne doivent jamais** entrer dans le repo : `.env*` ignorés, token injecté uniquement via variable d’environnement locale/CI.
|
||||
|
||||
---
|
||||
|
||||
## 1) Topologie réelle (ce que nous avons)
|
||||
|
||||
### 1.1 Local (Mac Studio)
|
||||
- Dev et documentation.
|
||||
- Git complet.
|
||||
- On fait : branches, commits, push, PR, merge.
|
||||
|
||||
### 1.2 Gitea
|
||||
- Repo canonique : `Archicratia/archicratie-edition`.
|
||||
- `main` = défaut + protégée.
|
||||
- Toute modif arrive via PR.
|
||||
|
||||
### 1.3 NAS (prod)
|
||||
- Chemin canonique :
|
||||
- `/volume2/docker/archicratie-web/releases/<timestamp>/app`
|
||||
- `/volume2/docker/archicratie-web/current` → symlink vers la release active
|
||||
- Blue/Green :
|
||||
- `web_blue` sur `127.0.0.1:8081`
|
||||
- `web_green` sur `127.0.0.1:8082`
|
||||
- Reverse proxy DSM : bascule 8081 ↔ 8082.
|
||||
|
||||
---
|
||||
|
||||
## 2) Règle d’or : qui écrit quoi, où ?
|
||||
|
||||
### 2.1 Toute écriture “source” se fait sur Mac Studio
|
||||
- Code Astro
|
||||
- Scripts
|
||||
- Docs `docs/*.md`
|
||||
- `.gitignore`
|
||||
|
||||
### 2.2 Gitea ne reçoit que via PR
|
||||
- Push sur branche feature/docs
|
||||
- PR → CI → merge
|
||||
|
||||
### 2.3 NAS ne fait que :
|
||||
- `git reset --hard origin/main` (alignement)
|
||||
- build image + restart slot blue/green
|
||||
- smoke test
|
||||
- bascule reverse proxy DSM
|
||||
|
||||
---
|
||||
|
||||
## 3) Procédure standard (la seule à utiliser)
|
||||
|
||||
### Étape A — Mac Studio → Gitea (PR)
|
||||
1) `git checkout -b feat/...` ou `docs/...`
|
||||
2) commits propres et atomiques
|
||||
3) `git push -u origin <branch>`
|
||||
4) PR dans Gitea → CI OK → merge dans `main`
|
||||
|
||||
### Étape B — NAS : aligner `current` sur `origin/main`
|
||||
Sur NAS, git n’est pas forcément installé : on utilise un conteneur git.
|
||||
en sh :
|
||||
|
||||
APP="/volume2/docker/archicratie-web/current"
|
||||
U_ID="$(id -u)"; G_ID="$(id -g)"
|
||||
|
||||
sudo docker run --rm --network host \
|
||||
-u "$U_ID:$G_ID" -e HOME=/tmp \
|
||||
-v "$APP":/repo -w /repo \
|
||||
--entrypoint sh alpine/git -lc '
|
||||
set -eu
|
||||
git config --global --add safe.directory /repo
|
||||
git config http.sslVerify false
|
||||
|
||||
git fetch origin --prune
|
||||
git checkout -B main
|
||||
git reset --hard origin/main
|
||||
git status -sb
|
||||
'
|
||||
|
||||
### Étape C — NAS : rebuild du slot inactif + smoke + bascule
|
||||
|
||||
Rebuild de l’image (slot inactif recommandé).
|
||||
|
||||
docker compose up -d --force-recreate --no-build web_green (ou blue)
|
||||
|
||||
smoke test via script ou curl
|
||||
|
||||
bascule DSM vers le port du slot actif
|
||||
|
||||
## 4) Checkpoints rapides (sanity)
|
||||
### 4.1 Vérifier que NAS = origin/main
|
||||
|
||||
git rev-parse --short HEAD sur NAS (via alpine/git)
|
||||
|
||||
doit égaler origin/main.
|
||||
|
||||
### 4.2 Vérifier “Proposer” (points minimum)
|
||||
|
||||
PUBLIC_GITEA_OWNER=Archicratia (casse sensible)
|
||||
|
||||
PUBLIC_GITEA_REPO=archicratie-edition
|
||||
|
||||
Flow : Proposer → choix 1 → choix 2 → onglet Gitea /issues/new?... OK
|
||||
|
||||
## 5) Rollback
|
||||
|
||||
DSM reverse proxy : repasser sur l’autre port (8081/8082).
|
||||
|
||||
En cas de code cassé : réaligner NAS sur origin/main précédent (tag/release) ou repointer /current vers une release précédente.
|
||||
213
docs/TROUBLESHOOTING.md
Normal file
213
docs/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# TROUBLESHOOTING — Archicratie Web / NAS / Gitea
|
||||
|
||||
Dernière mise à jour : 2026-02-01
|
||||
|
||||
Ce document liste les symptômes rencontrés et les remèdes **concrets**.
|
||||
|
||||
---
|
||||
|
||||
## 0) Réflexe unique
|
||||
Toujours isoler : **Local**, **Gitea**, **NAS**, **Navigateur**.
|
||||
|
||||
- Si ça marche sur `127.0.0.1:8082` mais pas sur le domaine → proxy/cache.
|
||||
- Si ça marche après login Gitea mais pas via “Proposer” → variables `PUBLIC_GITEA_*`.
|
||||
- Si push refusé → branch protection (normal).
|
||||
|
||||
---
|
||||
|
||||
## 1) “Proposer” ouvre Gitea mais retourne 404 / non autorisé
|
||||
|
||||
### Symptôme
|
||||
Nouvel onglet :
|
||||
- 404 Not Found / “n’existe pas ou pas autorisé”
|
||||
- ou redirect `/user/login`
|
||||
|
||||
### Cause la plus fréquente
|
||||
URL pointe vers **mauvais owner/repo** (casse sensible) :
|
||||
- `archicratia/archicratie-web` au lieu de `Archicratia/archicratie-edition`
|
||||
|
||||
### Diagnostic
|
||||
Sur NAS (ou dans le HTML généré), vérifier l’URL ouverte :
|
||||
- doit contenir : `/Archicratia/archicratie-edition/issues/new`
|
||||
|
||||
### Fix
|
||||
Dans `.env` de build prod (NAS) :
|
||||
- `PUBLIC_GITEA_OWNER=Archicratia`
|
||||
- `PUBLIC_GITEA_REPO=archicratie-edition`
|
||||
Puis rebuild + restart du container + smoke.
|
||||
|
||||
---
|
||||
|
||||
## 2) Double onglet à la validation du flow “Proposer”
|
||||
|
||||
### Symptôme
|
||||
Deux onglets s’ouvrent au moment de valider (après choix 1 / choix 2).
|
||||
|
||||
### Causes possibles
|
||||
- handler JS déclenché deux fois (bubbling)
|
||||
- présence d’un `window.open` + `a.click()` simultanément
|
||||
- bouton “Proposer” est un `<a target=_blank>` et un autre handler ouvre aussi.
|
||||
|
||||
### Diagnostic rapide (devtools navigateur)
|
||||
Chercher `window.open` dans la page générée :
|
||||
- la commande doit retourner 0 lignes.
|
||||
|
||||
Sur NAS :
|
||||
en sh :
|
||||
|
||||
curl -fsS http://127.0.0.1:8082/archicratie/archicrat-ia/chapitre-4/ > /tmp/page.html
|
||||
grep -n "window.open" /tmp/page.html | head
|
||||
|
||||
Fix
|
||||
|
||||
garder un seul mécanisme d’ouverture
|
||||
|
||||
sur click : preventDefault() + stopImmediatePropagation()
|
||||
|
||||
## 3) Favicon 504 / erreurs console sur favicon
|
||||
# Symptôme
|
||||
|
||||
Console navigateur : GET /favicon.ico 504
|
||||
|
||||
# Cause fréquente
|
||||
|
||||
Cache du navigateur (ancienne erreur conservée).
|
||||
|
||||
# Diagnostic
|
||||
|
||||
Comparer :
|
||||
|
||||
curl -I http://127.0.0.1:8082/favicon.ico
|
||||
|
||||
curl -kI https://<domaine>/favicon.ico
|
||||
|
||||
Si curl = 200 et navigateur = 504 → cache.
|
||||
|
||||
# Fix
|
||||
|
||||
Désactiver cache dans l’onglet Réseau (devtools)
|
||||
|
||||
hard refresh
|
||||
|
||||
vérifier droits fichiers dans dist/
|
||||
|
||||
## 4) Sur NAS : git: command not found
|
||||
# Symptôme
|
||||
|
||||
git fetch impossible sur le NAS.
|
||||
|
||||
# Cause
|
||||
|
||||
Git non installé sur DSM shell.
|
||||
|
||||
# Fix standard (recommandé)
|
||||
|
||||
Utiliser un conteneur git :
|
||||
|
||||
APP="/volume2/docker/archicratie-web/current"
|
||||
U_ID="$(id -u)"; G_ID="$(id -g)"
|
||||
|
||||
sudo docker run --rm --network host \
|
||||
-u "$U_ID:$G_ID" -e HOME=/tmp \
|
||||
-v "$APP":/repo -w /repo \
|
||||
--entrypoint sh alpine/git -lc '
|
||||
set -eu
|
||||
git config --global --add safe.directory /repo
|
||||
git config http.sslVerify false
|
||||
git fetch origin --prune
|
||||
git status -sb
|
||||
'
|
||||
|
||||
## 5) Git : “dubious ownership in repository”
|
||||
# Symptôme
|
||||
|
||||
fatal: detected dubious ownership
|
||||
|
||||
# Fix
|
||||
|
||||
Dans le conteneur git (ou machine locale) :
|
||||
git config --global --add safe.directory /repo
|
||||
|
||||
## 6) Git : non-fast-forward au push
|
||||
# Symptôme
|
||||
|
||||
rejected (non-fast-forward)
|
||||
|
||||
# Cause
|
||||
|
||||
Ta branche locale est en retard vs remote.
|
||||
|
||||
# Fix
|
||||
|
||||
En général :
|
||||
|
||||
on fait une PR depuis une branche
|
||||
|
||||
ou on rebase/merge origin/main avant push
|
||||
|
||||
Sur une branche de travail :
|
||||
git fetch origin
|
||||
git rebase origin/main
|
||||
# ou
|
||||
git merge origin/main
|
||||
|
||||
## 7) Gitea : “Not allowed to push to protected branch main”
|
||||
# Symptôme
|
||||
|
||||
pre-receive hook declined
|
||||
|
||||
# Cause
|
||||
|
||||
Protection de branche (normal/attendu).
|
||||
|
||||
# Fix
|
||||
|
||||
Push sur une branche
|
||||
|
||||
Ouvrir PR
|
||||
|
||||
Merger via UI Gitea
|
||||
|
||||
## 8) Docker build : BuildKit / buildx / API version
|
||||
# Symptômes typiques
|
||||
|
||||
the --network option requires BuildKit
|
||||
|
||||
BuildKit is enabled but the buildx component is missing
|
||||
|
||||
client version ... too new. Maximum supported API version ...
|
||||
|
||||
# Fix “robuste” (principe)
|
||||
|
||||
installer buildx si nécessaire
|
||||
|
||||
si DSM/docker API ancienne : définir DOCKER_API_VERSION=<compatible> (selon ton environnement)
|
||||
|
||||
garder le build en --network host si nécessaire
|
||||
|
||||
## 9) Container Manager / Docker : “database is locked” (logging driver db)
|
||||
# Symptôme
|
||||
|
||||
failed to initialize logging driver : database is locked
|
||||
|
||||
# Cause
|
||||
|
||||
Le driver de logs Docker est db (Synology) et sa DB est verrouillée.
|
||||
|
||||
# Fix rapide
|
||||
|
||||
Redémarrer “Container Manager” depuis le centre de paquets DSM.
|
||||
|
||||
Vérifier que le conteneur redémarre ensuite.
|
||||
|
||||
## 10) Checklist “tout marche”
|
||||
|
||||
curl -I http://127.0.0.1:8082/ => 200
|
||||
|
||||
curl -kI https://<domaine>/ => 200
|
||||
|
||||
PUBLIC_GITEA_* corrects
|
||||
|
||||
“Proposer” : 1 onglet, pas de 404, issue pré-remplie
|
||||
|
||||
CI passe sur PR merge
|
||||
71
docs/WORKFLOW-GIT.md
Normal file
71
docs/WORKFLOW-GIT.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# WORKFLOW-GIT — branches, PR, tags (standard “main”)
|
||||
|
||||
## 0) Objectif
|
||||
- Tout le monde (toi compris) suit un protocole unique.
|
||||
- Zéro ambigüité entre “ce qui tourne” et “ce qui est versionné”.
|
||||
|
||||
## 1) Branches : politique
|
||||
|
||||
### main (branche de travail)
|
||||
- Branche par défaut du repo.
|
||||
- Tout changement passe idéalement par PR (même si tu es seul).
|
||||
|
||||
### master (legacy/compat)
|
||||
- Doit rester alignée sur main (si vous gardez master).
|
||||
- Protégée contre push accidentel (pas de force-push, pas de push direct).
|
||||
- N’est **pas** un axe de travail.
|
||||
|
||||
### branches de feature
|
||||
Conventions recommandées :
|
||||
- `fix/<sujet>` : correctif
|
||||
- `feat/<sujet>` : nouvelle fonction
|
||||
- `ops/<sujet>` : infra, déploiement, scripts, docs ops
|
||||
|
||||
## 2) PR (même si tu es seul)
|
||||
- Créer une PR → vérifier CI (Actions) → merge.
|
||||
- Règle : “Prevent merge if checks fail” activée (bonne pratique).
|
||||
- Approvals : 0 (si tu es seul).
|
||||
|
||||
## 3) Tags
|
||||
- Tags d’archives : `archive-master-<YYYYmmdd-HHMMSS>` (déjà fait).
|
||||
- Snapshots prod : `prod-snapshot-<YYYYmmdd-HHMMSS>` si besoin.
|
||||
|
||||
## 4) Commandes standard (Mac)
|
||||
|
||||
### Se mettre parfaitement à jour
|
||||
en sh :
|
||||
git checkout main
|
||||
git fetch origin --prune --tags
|
||||
git reset --hard origin/main
|
||||
git clean -fd # optionnel : supprime untracked
|
||||
|
||||
### Publier un changement
|
||||
git checkout -b fix/<slug>
|
||||
# edits...
|
||||
git add -A
|
||||
git commit -m "fix: <message>"
|
||||
git push -u origin HEAD
|
||||
# PR via UI, merge
|
||||
|
||||
## 5) Remote case-sensitive (piège déjà rencontré)
|
||||
|
||||
Le repo peut exister avec Owner en casse différente (ex: Archicratia vs archicratia).
|
||||
Standard : remote doit être :
|
||||
|
||||
https://.../Archicratia/archicratie-edition.git
|
||||
|
||||
Vérifier :
|
||||
git remote -v
|
||||
|
||||
## 6) NAS : pas de git natif
|
||||
|
||||
Sur NAS, on n’installe pas forcément git dans le shell.
|
||||
Standard : utiliser alpine/git en conteneur (cf. OPS-SYNC-TRIPLE-SOURCE).
|
||||
|
||||
## 7) Interdits (pour éviter l’enfer)
|
||||
|
||||
Éditer des fichiers du repo via FileStation “pour aller vite” (sauf hotfix d’urgence, puis backport immédiat Git).
|
||||
|
||||
Pousser sur master (sauf opération contrôlée d’alignement).
|
||||
|
||||
Force-push sur main.
|
||||
12
nginx.conf
12
nginx.conf
@@ -9,6 +9,18 @@ server {
|
||||
add_header X-Frame-Options SAMEORIGIN always;
|
||||
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||
|
||||
location = /favicon.ico {
|
||||
try_files /favicon.ico =404;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location = /favicon.svg {
|
||||
try_files /favicon.svg =404;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Assets statiques (cache long)
|
||||
location ~* \.(?:css|js|mjs|json|png|jpg|jpeg|gif|svg|webp|ico|woff2?|ttf|eot|wasm)$ {
|
||||
try_files $uri =404;
|
||||
|
||||
6
public/about.txt
Executable file
6
public/about.txt
Executable file
@@ -0,0 +1,6 @@
|
||||
This favicon was generated using the following font:
|
||||
|
||||
- Font Title: Leckerli One
|
||||
- Font Author: undefined
|
||||
- Font Source: https://fonts.gstatic.com/s/leckerlione/v21/V8mCoQH8VCsNttEnxnGQ-1itLZxcBtItFw.ttf
|
||||
- Font License: undefined)
|
||||
BIN
public/android-chrome-192x192.png
Executable file
BIN
public/android-chrome-192x192.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
BIN
public/android-chrome-512x512.png
Executable file
BIN
public/android-chrome-512x512.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
public/apple-touch-icon.png
Executable file
BIN
public/apple-touch-icon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
public/favicon-16x16.png
Executable file
BIN
public/favicon-16x16.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 558 B |
BIN
public/favicon-32x32.png
Executable file
BIN
public/favicon-32x32.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/favicon.ico
Executable file
BIN
public/favicon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1
public/site.webmanifest
Executable file
1
public/site.webmanifest
Executable file
@@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
@@ -160,15 +160,8 @@
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ Ouvre EN NOUVEL ONGLET sans jamais remplacer l’onglet courant
|
||||
// ✅ Ouvre EN NOUVEL ONGLET : stratégie unique (anchor click) => jamais 2 onglets
|
||||
const openInNewTab = (url) => {
|
||||
// 1) tente window.open
|
||||
try {
|
||||
const w = window.open(url, "_blank", "noopener,noreferrer");
|
||||
if (w) return true;
|
||||
} catch {}
|
||||
|
||||
// 2) fallback "anchor click" (souvent mieux toléré)
|
||||
try {
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
@@ -181,7 +174,7 @@
|
||||
return true;
|
||||
} catch {}
|
||||
|
||||
// 3) dernier recours: on ne quitte PAS la page
|
||||
// dernier recours
|
||||
window.prompt("Popup bloquée. Copiez ce lien pour ouvrir le ticket :", url);
|
||||
return false;
|
||||
};
|
||||
@@ -200,7 +193,7 @@
|
||||
if (!a) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
const rawUrl = a.dataset.url || a.getAttribute("href") || "";
|
||||
if (!rawUrl || rawUrl === "#") return;
|
||||
@@ -210,10 +203,8 @@
|
||||
try {
|
||||
const u = new URL(rawUrl);
|
||||
|
||||
// Option B.1 : copie presse-papier du texte complet (si dispo)
|
||||
if (full) {
|
||||
try { await navigator.clipboard.writeText(full); } catch {}
|
||||
// Option B.2 : upgrade du body (si l'URL reste raisonnable)
|
||||
tryUpgradeBodyWithFull(u, full);
|
||||
}
|
||||
|
||||
@@ -221,7 +212,7 @@
|
||||
} catch {
|
||||
openInNewTab(rawUrl);
|
||||
}
|
||||
});
|
||||
}, { capture: true });
|
||||
|
||||
// Step 1: type
|
||||
dlg.addEventListener("click", (e) => {
|
||||
|
||||
@@ -497,27 +497,17 @@ const GITEA_REPO = import.meta.env.PUBLIC_GITEA_REPO ?? "";
|
||||
const excerpt = raw.length > 420 ? (raw.slice(0, 420) + "…") : raw;
|
||||
|
||||
const issueUrl = buildIssueURL(p.id, raw, excerpt);
|
||||
|
||||
// Lien fallback (si JS casse totalement)
|
||||
propose.href = issueUrl;
|
||||
|
||||
// 🔥 indispensables pour réactiver ProposeModal (les 2 filtres)
|
||||
// ✅ Marqueurs pour ProposeModal (interception 2 étapes)
|
||||
propose.dataset.propose = "1";
|
||||
propose.dataset.url = issueUrl;
|
||||
|
||||
// optionnel mais top : permet à ProposeModal de copier le texte complet
|
||||
propose.dataset.full = raw;
|
||||
|
||||
// ✅ CRUCIAL : permet à ProposeModal d’intercepter le clic (2 étapes)
|
||||
propose.setAttribute("data-propose", "1");
|
||||
propose.setAttribute("data-url", issueUrl);
|
||||
|
||||
// ✅ Bonus : ProposeModal peut copier/upgrade avec le texte complet si dispo
|
||||
// (tu peux commenter si tu veux éviter de stocker le texte en attribut)
|
||||
propose.setAttribute("data-full", raw);
|
||||
|
||||
// ✅ Fallback si JS casse : on ouvre quand même le lien (idéalement en nouvel onglet)
|
||||
propose.href = issueUrl;
|
||||
propose.target = "_blank";
|
||||
propose.rel = "noopener noreferrer";
|
||||
// ❌ PAS de target=_blank ici
|
||||
// ❌ PAS de rel noopener ici
|
||||
|
||||
row.appendChild(propose);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user