Publier la liste des pages récemment mises à jour #8

Open
Cédric A5L wants to merge 2 commits from accueil-derniers-articles into main
2 changed files with 53 additions and 21 deletions
Showing only changes of commit ad1f459659 - Show all commits

View file

@ -198,7 +198,20 @@ choses à savoir :
- **Seules les pages de la navigation sont annoncées.** Une page hors `nav` — typiquement - **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. 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 ; - **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 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 à lire ce seul fichier JSON (`Access-Control-Allow-Origin`). Sans lui, le navigateur

View file

@ -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 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). 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 from __future__ import annotations
@ -62,6 +66,14 @@ def _git(depot: Path, *args: str) -> str:
).stdout ).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]: def _historique(depot: Path, dossier: str) -> tuple[dict, dict]:
"""Retourne (dernière modification, date de création) par chemin actuel. """Retourne (dernière modification, date de création) par chemin actuel.
@ -115,9 +127,12 @@ def on_post_build(config):
try: try:
modifiees, creees = _historique(depot, dossier) modifiees, creees = _historique(depot, dossier)
except (OSError, subprocess.SubprocessError) as erreur: 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 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) limite = datetime.now(timezone.utc) - timedelta(days=JOURS_NOUVEAU)
articles = [] articles = []
@ -141,30 +156,34 @@ def on_post_build(config):
}) })
if not articles: 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 return
articles.sort(key=lambda a: a["date"], reverse=True) articles.sort(key=lambda a: a["date"], reverse=True)
articles = articles[:NB_MAX] articles = articles[:NB_MAX]
(site_dir / FICHIER).write_text( try:
json.dumps( (site_dir / FICHIER).write_text(
{"genere": datetime.now(timezone.utc).isoformat(timespec="seconds"), json.dumps(
"articles": articles}, {"genere": datetime.now(timezone.utc).isoformat(timespec="seconds"),
ensure_ascii=False, indent=2, "articles": articles},
) + "\n", ensure_ascii=False, indent=2,
encoding="utf-8", ) + "\n",
) encoding="utf-8",
)
# La page d'accueil est sur un autre sous-domaine : sans cet en-tête, le # La page d'accueil est sur un autre sous-domaine : sans cet en-tête, le
# navigateur refuse de lui laisser lire le fichier. # navigateur refuse de lui laisser lire le fichier.
(site_dir / ".htaccess").write_text( (site_dir / ".htaccess").write_text(
"<IfModule mod_headers.c>\n" "<IfModule mod_headers.c>\n"
f' <Files "{FICHIER}">\n' f' <Files "{FICHIER}">\n'
' Header set Access-Control-Allow-Origin "*"\n' ' Header set Access-Control-Allow-Origin "*"\n'
" </Files>\n" " </Files>\n"
"</IfModule>\n", "</IfModule>\n",
encoding="utf-8", 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) log.info("derniers-articles : %d article(s) publié(s) dans %s", len(articles), FICHIER)