diff --git a/docs/technique/deploiement-wiki.md b/docs/technique/deploiement-wiki.md
index dd0e206..bd3d784 100644
--- a/docs/technique/deploiement-wiki.md
+++ b/docs/technique/deploiement-wiki.md
@@ -198,7 +198,20 @@ choses à savoir :
- **Seules les pages de la navigation sont annoncées.** Une page hors `nav` — typiquement
la redirection laissée derrière un article déplacé — n'apparaît jamais dans la liste.
- **Le hook n'échoue jamais.** Sans historique git, il n'écrit rien et le build continue ;
- l'accueil d'alpinux.org masque alors simplement sa section wiki.
+ l'accueil d'alpinux.org masque alors simplement sa section wiki. Ses messages sont pour
+ cela de niveau *info* et jamais *warning* : le déploiement construit avec `--strict`, où
+ un seul avertissement suffit à interrompre le build et donc la publication.
+
+!!! warning "Deux conditions côté serveur"
+ **Le clone doit avoir son historique.** Un clone `--depth 1` ne porte qu'un commit :
+ toutes les pages sembleraient modifiées le même jour. Le hook le détecte et le
+ signale dans le journal du build, sans rien casser.
+
+ **Le `.htaccess` du DocumentRoot est réécrit à chaque déploiement.** Le hook le
+ dépose dans le staging, que `rsync --delete` recopie intégralement : un `.htaccess`
+ qui aurait été posé à la main sur le serveur serait effacé au premier build. S'il
+ faut d'autres règles Apache, ajoutez-les dans le hook — c'est désormais lui qui fait
+ foi.
Le même hook dépose un `.htaccess` d'une ligne utile : il autorise les autres sous-domaines
à lire ce seul fichier JSON (`Access-Control-Allow-Origin`). Sans lui, le navigateur
diff --git a/hooks/derniers_articles.py b/hooks/derniers_articles.py
index b2c8547..7cf581d 100644
--- a/hooks/derniers_articles.py
+++ b/hooks/derniers_articles.py
@@ -11,6 +11,10 @@ le fait.
Le hook n'échoue jamais : sans git, ou en cas d'erreur, il n'écrit simplement rien et
le build continue (le site reste valide, la page d'accueil garde ses tuiles statiques).
+
+Ses messages sont volontairement de niveau *info* et jamais *warning* : le déploiement
+construit le site avec `--strict`, où le moindre avertissement interrompt le build. Un
+hook d'agrément ne doit pas pouvoir empêcher la publication du wiki.
"""
from __future__ import annotations
@@ -62,6 +66,14 @@ def _git(depot: Path, *args: str) -> str:
).stdout
+def _est_superficiel(depot: Path) -> bool:
+ """Un clone `--depth 1` n'a pas d'historique : toutes les dates seraient identiques."""
+ try:
+ return _git(depot, "rev-parse", "--is-shallow-repository").strip() == "true"
+ except (OSError, subprocess.SubprocessError):
+ return False
+
+
def _historique(depot: Path, dossier: str) -> tuple[dict, dict]:
"""Retourne (dernière modification, date de création) par chemin actuel.
@@ -115,9 +127,12 @@ def on_post_build(config):
try:
modifiees, creees = _historique(depot, dossier)
except (OSError, subprocess.SubprocessError) as erreur:
- log.warning("derniers-articles : historique git illisible (%s), fichier non écrit", erreur)
+ log.info("derniers-articles : historique git illisible (%s), fichier non écrit", erreur)
return
+ if _est_superficiel(depot):
+ log.info("derniers-articles : clone superficiel, les dates ne sont pas fiables")
+
limite = datetime.now(timezone.utc) - timedelta(days=JOURS_NOUVEAU)
articles = []
@@ -141,30 +156,34 @@ def on_post_build(config):
})
if not articles:
- log.warning("derniers-articles : aucune page datée, fichier non écrit")
+ log.info("derniers-articles : aucune page datée, fichier non écrit")
return
articles.sort(key=lambda a: a["date"], reverse=True)
articles = articles[:NB_MAX]
- (site_dir / FICHIER).write_text(
- json.dumps(
- {"genere": datetime.now(timezone.utc).isoformat(timespec="seconds"),
- "articles": articles},
- ensure_ascii=False, indent=2,
- ) + "\n",
- encoding="utf-8",
- )
+ try:
+ (site_dir / FICHIER).write_text(
+ json.dumps(
+ {"genere": datetime.now(timezone.utc).isoformat(timespec="seconds"),
+ "articles": articles},
+ ensure_ascii=False, indent=2,
+ ) + "\n",
+ encoding="utf-8",
+ )
- # La page d'accueil est sur un autre sous-domaine : sans cet en-tête, le
- # navigateur refuse de lui laisser lire le fichier.
- (site_dir / ".htaccess").write_text(
- "\n"
- f' \n'
- ' Header set Access-Control-Allow-Origin "*"\n'
- " \n"
- "\n",
- encoding="utf-8",
- )
+ # La page d'accueil est sur un autre sous-domaine : sans cet en-tête, le
+ # navigateur refuse de lui laisser lire le fichier.
+ (site_dir / ".htaccess").write_text(
+ "\n"
+ f' \n'
+ ' Header set Access-Control-Allow-Origin "*"\n'
+ " \n"
+ "\n",
+ encoding="utf-8",
+ )
+ except OSError as erreur:
+ log.info("derniers-articles : écriture impossible (%s), fichier non écrit", erreur)
+ return
log.info("derniers-articles : %d article(s) publié(s) dans %s", len(articles), FICHIER)