Aller au contenu

Publication et versions

Dans Menestrel, sauvegarder et publier sont deux gestes séparés. Tout ce qui est tapé dans l’admin est sauvegardé en continu, mais rien ne sort tant que personne n’a cliqué sur « Publier ». Cette page suit une modification de bout en bout : le brouillon, les statuts par langue, le snapshot, le build chez l’hébergeur, et le retour arrière.

Chaque entrée a un brouillon de travail, séparé des versions publiées. L’admin le sauvegarde tout seul : 2 secondes après la dernière frappe, et au plus tard toutes les 15 secondes en frappe continue. Ferme l’onglet, rouvre l’entrée sur un autre appareil : le brouillon est là.

Le brouillon est mutable, écrasé en place. L’historique, lui, est fait de versions immuables, consolidées aux moments qui comptent : à la publication, quand l’auteur change, et au plus une fois toutes les dix minutes en saisie continue. Une session de saisie d’une heure ne produit donc pas des centaines de versions, et « qui a écrit quoi » reste attribué au bon auteur.

Une entrée multilingue ne se publie pas en bloc. Chaque langue porte son propre statut :

  • brouillon : jamais publiée dans cette langue ;
  • publiée : la version en ligne est à jour ;
  • à retraduire : publiée, mais la langue par défaut a changé depuis. Le site continue de servir la traduction telle quelle ; l’admin signale seulement qu’elle est en retard.

Le bouton Publier suit ce découpage : « Publier : fr », « Publier : en » ou « Publier toutes les langues ». La validation aussi : un champ requis vide en anglais bloque la publication de l’anglais, pas celle du français, et le dialog liste ce qui manque, champ par champ.

Deux gestes, même mécanique :

  • depuis l’éditeur : « Publier » sur l’entrée ouverte, avec le choix des langues ;
  • depuis l’écran Publication : un bouton contextuel regroupe tout ce qui attend (« Publier 3 modifications »). La validation reste par entrée et par langue : les couples en erreur se décochent avec le détail du champ fautif, et tu re-soumets sans eux.

Publier n’écrase rien : les versions d’une entrée sont en append-only. Publier insère une nouvelle version publiée, l’historique complet reste consultable.

Chaque publication produit un snapshot : un fichier JSON par collection et par langue (valeurs aplaties, fallbacks de langue appliqués, images résolues en URLs CDN), plus un manifest qui porte le schéma et la liste des fichiers. Le tout est poussé sur le CDN et ne bouge plus jamais : en base, un trigger SQL interdit toute mise à jour d’un snapshot. Une seule chose est mutable, le pointeur latest.json, qui désigne le snapshot en ligne.

Ce choix porte le reste du système :

  • le build ne dépend jamais de l’API : le loader lit les fichiers du snapshot sur le CDN. Application éteinte, un astro build passe encore ;
  • revenir en arrière est trivial : re-pointer latest.json suffit, aucun contenu à recalculer ;
  • l’historique est fidèle : chaque publication a son snapshot, on sait exactement ce qui était en ligne à quelle heure.

Un client qui corrige quatre fiches en trois minutes ne doit pas déclencher quatre builds. Chaque projet a une fenêtre de regroupement, 90 secondes par défaut, réglable dans les réglages du projet. Elle absorbe les rafales sans jamais retarder le geste isolé :

  • fenêtre calme : la première publication déclenche le build immédiatement. Corriger un tarif pendant un appel téléphonique reste un aller-retour de moins de trois minutes ;
  • rafale : les publications suivantes dans la fenêtre sont regroupées en un seul build, celui du dernier snapshot. Les builds en file des snapshots dépassés passent « Annulé » : jamais de build pour un contenu déjà obsolète.

Pendant une rafale, l’admin affiche « Publication groupée dans 42 s… » avec un bouton « Publier maintenant » qui force l’envoi sans attendre la fin de la fenêtre.

S’ajoute un quota de déclenchements par heure et par projet, selon le plan (4 en Libre, 12 en Site, 30 en Studio et Sur mesure). Au-delà, les publications sont regroupées d’office, jamais rejetées : l’admin affiche « Vos modifications sont regroupées automatiquement » avec l’heure de mise en ligne.

Le build part vers chaque hébergeur connecté au projet : Vercel, Netlify, Cloudflare ou GitHub Actions. Chaque déploiement suit une machine à états honnête :

État Affiché Sens
queued En file le build attend son déclenchement
triggered Déclenché l’hébergeur a accepté le déclenchement
building En construction le build tourne chez l’hébergeur
live En ligne le site sert le nouveau contenu
failed Échec le build a échoué, diagnostic à l’appui
cancelled Annulé dépassé par une publication plus récente

Le déclenchement est tenté jusqu’à trois fois, avec backoff, avant de déclarer l’échec. Le suivi interroge ensuite l’API de l’hébergeur, si un token de suivi (facultatif) est configuré sur la cible. Sans token, Menestrel reste honnête : le déploiement affiche « Déclenché à 14 h 31 » et s’arrête là, jamais de faux « En ligne ».

Deux règles d’affichage :

  • l’éditeur voit le vocabulaire éditeur : « Publication en cours… », puis « En ligne à 14 h 32 ». Jamais build, deploy, hook ni pipeline ;
  • les échecs vont à l’agence, jamais au client final : email et indicateur dans l’admin, avec un diagnostic lisible. Après trois échecs consécutifs, l’hébergeur passe « En pause » (on arrête de le marteler) ; un bouton « Reprendre » le réactive une fois la configuration corrigée.

Chaque snapshot de l’historique se restaure : choisis la version (« Revenir à la version d’hier 18 h 04 »), confirme. Menestrel re-pointe latest.json sur ce snapshot et redéclenche les hébergeurs : le site rebuild avec le contenu exact de ce moment-là, servi tel qu’il avait été construit.

Le retour arrière est un geste d’urgence : il part immédiatement, sans fenêtre de regroupement, et ne compte pas dans le quota horaire de publications.

L’historique de snapshots est conservé selon le plan : 7 jours en Libre, 90 jours en Site, 1 an en Studio et Sur mesure. Deux snapshots ne sont jamais purgés, quel que soit le plan : celui en ligne et le précédent. Le retour arrière immédiat reste donc toujours possible, même en plan Libre.

Pour dérouler ce cycle sur un vrai projet, suis Ton premier site en 10 minutes. Côté code, c’est le loader qui consomme le snapshot publié : voir la référence du loader.