Le README faisait 691 lignes, dont 295 de procedure de mise en production — que personne ne lit avant d'avoir decide d'installer le projet. Or c'est le premier document lu. Il tombe a 86 lignes et devient un aiguillage. Un document, un lecteur, une question : README.md c'est quoi ? un visiteur docs/installer.md comment je l'heberge ? qui installe docs/publier-une-version.md comment je sors une v. ? qui maintient docs/architecture.md pourquoi le code ainsi ? qui contribue Trois defauts sortis de la comparaison entre le README et le tour du projet, dont deux introduits ce matin : ⚠ Le README se contredisait sur example.org. Son « Journal du paquet » documentait comme une panne reglee (« l'installation s'arretait net ») le placeholder que le nettoyage vient de retablir. Ce n'est pas une regression — publier.sh refuse desormais de publier avec, ce qui etait precisement le garde-fou manquant en aout — mais qui lisait le journal concluait l'inverse. Le journal est supprime : c'est de l'historique, il vit dans les commits et dans CLAUDE.md. ⚠ La fusion des migrations n'etait nulle part. La section « Monter de version » decrivait pas a pas une procedure qui echouerait depuis toute version anterieure a la 0.5.0, et son « Si la mise a jour echoue » ne mentionnait pas cette cause. L'avertissement est desormais en tete du README, d'installer.md et de la section concernee. ⚠ Les trois portees — commune, personnelle, trace — decident de tout dans ce projet et etaient absentes de son point d'entree. Elles ouvrent architecture.md. Verifie : aucune ancre morte, aucun lien mort, et les 41 lignes non reprises sont soit condensees dans le nouveau README, soit du journal supprime a dessein. Trois d'entre elles sont revenues (build/dist ignore, l'inspiration radarr_ynh, le renvoi aux commentaires de systemd.service). 626 tests au vert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
14 KiB
Publier une version de MaBibli
Pour vous, qui sortez les versions. Pour installer, voir installer.md ; pour comprendre le code, architecture.md.
| Avant de publier ailleurs | l'URL de dépôt, à configurer une fois |
| Compiler | en développement, et le publish self-contained |
| La chaîne de publication | ce que publier.sh fait, et ce qu'il refuse |
| Monter de version | pas à pas |
Avant de publier ce projet quelque part
Les URL de dépôt sont un placeholder volontaire, https://forge.example.org/mabibli
(le domaine example.org est réservé à la documentation par la RFC 2606, donc
définitivement injoignable). Rien ne fonctionnera tant qu'il n'est pas remplacé.
Une seule ligne commande tout le reste — depot_code, en tête de
mabibli_ynh/build/publier.sh. Elle produit les URL de release, celles d'archive, et le
message de fin. Pour un essai ponctuel, --depot-code https://… fait la même chose sans
modifier le fichier.
⚠️ publier.sh refuse de publier tant que le placeholder est en place, et il refuse
avant de compiler. C'est délibéré : publier avec une URL morte écrirait dans
manifest.toml une amd64.url que personne ne peut télécharger, et l'échec surviendrait
bien plus tard, à l'installation, sous la forme d'un ynh_setup_source en erreur — sans
rapport apparent avec la cause.
Restent à changer à la main, une fois seulement :
| Fichier | Quoi |
|---|---|
mabibli_ynh/manifest.toml |
code = "…", et maintainers |
mabibli_ynh/conf/systemd.service |
Documentation=… |
mabibli_ynh/doc/ADMIN.md |
le lien de bas de page |
mabibli_ynh/README.md, ce fichier |
les liens et les commandes d'exemple |
MaBibli.Client/Pages/APropos.razor |
Depot, Site, et l'adresse de contact |
⚠️ amd64.url dans le manifeste n'est PAS à changer à la main : publier.sh la
réécrit à chaque publication. La corriger donnerait l'illusion que c'est fait alors que la
source du problème est ailleurs.
⚠️ Le dépôt du code doit être PUBLIC. ynh_setup_source télécharge sans jeton, et
Gitea comme GitHub répondent 404 — pas 403 — à un anonyme sur un dépôt privé. Le
symptôme est alors rigoureusement identique à « la release n'existe pas ». Contrôle qui
tranche, hors session authentifiée : curl -fsSLI "<url de l'archive>".
Compilation
Prérequis : le SDK .NET 10 (dotnet --version).
En développement
dotnet build
dotnet test
Pour lancer l'application en local (l'API sert aussi le client Blazor compilé) :
dotnet run --project MaBibli.Api
Publication self-contained (ce que le serveur reçoit réellement)
Le serveur YunoHost ne compile jamais : il télécharge une archive déjà publiée et la déploie telle quelle (voir « Publication » ci-dessous). Pour produire ce même artefact en local, à des fins de vérification :
dotnet publish MaBibli.Api --configuration Release --runtime linux-x64 --self-contained
MaBibli.Api référence MaBibli.Client : le client Blazor WebAssembly est compilé au
passage et atterrit dans wwwroot/ du publish. Un seul projet à publier suffit donc
pour les trois (MaBibli.Client, MaBibli.Shared, MaBibli.Api). --self-contained
embarque le runtime .NET dans le dossier produit : aucun dotnet-runtime n'est requis
côté serveur.
Pour un hébergement sans YunoHost (Synology, VPS), voir « Installer ailleurs que sur
YunoHost » plus bas : le Dockerfile de la racine fait ce même publish, mais sans
--self-contained — dans un conteneur, l'image aspnet fournit déjà le runtime.
⚠️ Ne jamais compiler sur le serveur YunoHost lui-même : ce serait imposer le SDK
complet à une machine qui n'en a pas besoin, pour une compilation lente. Voir
CLAUDE.md, section « Chaîne de publication ».
Publication
⚠️ build/dist/ est ignoré par git, et doit le rester : l'archive vit dans la
release du dépôt. Committée, elle ajouterait ~65 Mo d'historique par version,
définitivement — c'est arrivé une fois, à la 0.1.0.
Le geste courant tient en une commande, build/publier.sh du dépôt du paquet :
cd ../mabibli_ynh
./build/publier.sh
Il reprend la version déjà publiée (tag le plus élevé, recoupé avec manifest.toml),
propose l'incrément, puis enchaîne tout ce qui suit : archive, manifeste, commit et push
du paquet, tag et push du code, avec vérification côté distant. Il ne reste qu'à créer
la release dans Gitea et y téléverser l'archive — le script en rappelle l'URL.
⚠️ Il n'y a qu'un seul script, et c'est délibéré. Un second, publier-release.sh,
a existé jusqu'au 2026-08-21 : il compilait, archivait et réécrivait le manifeste, à
charge pour l'appelant de committer. Son nom inspirait plus confiance que celui du vrai
point d'entrée, et lancé seul il produisait exactement la panne du 2026-08-21 — un
manifest.toml corrigé mais non poussé, et une release v0.4.0 contenant en réalité six
commits de plus que son tag. Les deux scripts sont fondus ; ce que le second savait
faire subsiste sous la même commande :
./build/publier.sh --archive-seule
Ce mode compile et archive, sans toucher ni au manifeste ni à git : il ne peut donc rien laisser à moitié publié.
⚠️ À quoi il sert vraiment : à reprendre une publication à la main quand
publier.sh a échoué en cours de route (voir B.3). Ce n'est pas « une brique pour une
CI » — c'était la justification écrite jusqu'au 2026-08-22, et elle désignait un usage
qui n'a jamais eu lieu, là où la reprise après échec, elle, est documentée pas à pas.
⚠️ Les contrôles ne sont PAS désactivés dans ce mode, contrairement à ce qui a été vrai jusqu'au 2026-08-22 : ils s'exécutent tous, et avertissent au lieu de refuser, puisque rien n'est publié et que rien ne peut donc mentir. Le dépôt sale, en particulier, n'était alors pas signalé du tout — l'archive contenait en silence du travail non committé.
Ce script compile ce dépôt (mabibli) en Release self-contained, vérifie le
résultat (binaire présent, wwwroot/ embarqué, toutes les ressources d'index.html
réellement sur disque, aucun placeholder d'empreinte non substitué), produit une
archive .tar.gz reproductible, calcule son sha256, et met à jour version,
amd64.url et amd64.sha256 dans mabibli_ynh/manifest.toml — sauf en
--archive-seule.
Il injecte au passage, dans l'assembly, la version (-p:Version) et un
horodatage de build (-p:MaBibliDateBuild), que la page « À propos » de
l'application affiche via GET /api/version.
⚠️ L'horodatage est le témoin de l'injection : sans lui, l'application se déclare
« version de développement » plutôt que d'afficher le 1.0.0 que le SDK .NET pose par
défaut. Ce numéro-là se lirait comme une vraie version alors qu'il ne désigne rien — or
c'est précisément la valeur qu'on va chercher pour diagnostiquer un appareil dont le
cache est dépareillé. Un dotnet build local n'annonce donc aucune version, et c'est
voulu.
⚠️ YunoHost lit le manifeste depuis Gitea, jamais une copie locale : un manifeste
corrigé mais non poussé n'existe pas pour le serveur. C'est précisément ce que
publier.sh empêche d'oublier.
Il refuse par ailleurs de publier dans deux cas, avant de compiler :
| Refus | Ce qu'il évite |
|---|---|
le tag vX.Y.Z existe déjà |
une release qui ne contient pas le code que son tag désigne — arrivé le 2026-08-21, six commits d'écart, sans que rien ne le signale |
| le dépôt du code a des modifications non committées | une archive contenant du travail que le tag, lui, ne contient pas |
Dans les deux cas il nomme le commit en cause et rappelle --patch. ⚠️ En
--archive-seule, les mêmes contrôles avertissent au lieu de refuser — le constat
s'affiche, le conseil « choisissez un numéro libre » non : en reprise, le tag visé
est justement celui qu'on veut retrouver.
La marche à suivre complète et éprouvée, pour les cas que publier.sh ne couvre
pas — première mise en production, montée de version pas à pas, retour arrière,
désinstallation — est en « Mettre en production » ci-dessous.
⚠️ Monter de version depuis une installation antérieure à la 0.5.0
Impossible : les migrations ont été fondues en une seule, et l'historique de la base
ne correspond plus. Il faut remove --purge puis réinstaller, avec perte du catalogue —
voir installer.md. Ce qui suit vaut pour les montées entre versions
0.5.0 et ultérieures.
B. Monter de version
B.1 Ce qui distingue une version applicative d'une révision de paquet
| Ce qui change | Version | Nouvelle archive ? |
|---|---|---|
| Le code C# | 0.1.0 → 0.1.1~ynh1 |
oui |
| Seulement le paquet (conf systemd/nginx, scripts) | 0.1.0~ynh1 → 0.1.0~ynh2 |
non |
Le second cas est le plus simple : bump du suffixe ~ynhN à la main dans
manifest.toml, commit, push, puis directement l'étape B.5. L'archive et son sha256
ne bougent pas. (C'est ce qui a été fait pour ~ynh2 et ~ynh3.)
La suite décrit le premier cas.
B.2 En une commande : publier.sh
C'est le geste courant, décrit en « Publication » plus haut : il enchaîne B.3, B.4 et B.5 (archive, manifeste, commit et push du paquet, tag et push du code), et vérifie sur le distant que tout est arrivé.
cd ../mabibli_ynh && ./build/publier.sh
La suite décrit ces mêmes étapes à la main, pour comprendre ce que le script fait et
pour les cas qu'il ne couvre pas : révision ~ynhN seule, reprise après un échec en
cours de route.
B.3 Compiler et vérifier la nouvelle version
Le code est prêt et committé dans mabibli. Depuis mabibli_ynh :
./build/publier.sh --archive-seule --patch
⚠️ --version n'est plus obligatoire ici, depuis le 2026-08-22. Le mode reprenait
alors la version de manifest.toml — c'est-à-dire celle déjà publiée — et
reproduisait donc 0.1.0 tant qu'on ne le corrigeait pas à la main. Les deux modes
calculent maintenant la version de la même façon : --patch propose 0.1.1, et
--version ne sert plus qu'à viser un autre numéro (par exemple celui d'un tag déjà
créé, si la publication a échoué après le tag).
⚠️ --archive-seule ne touche pas au manifeste : version (avec son suffixe
~ynh1 — une nouvelle version applicative repart toujours de 1), amd64.url et
amd64.sha256 sont alors à réécrire à la main. C'est le prix de la marche à pied ;
publier.sh sans option le fait, et ne peut pas l'oublier.
Note le sha256 affiché — il ne sera plus jamais le même, même à code identique si les
dépendances bougent.
B.4 Tag et release
cd ../mabibli && git tag v0.1.1 && git push origin main --tags
Créer la release v0.1.1 dans Gitea, y téléverser
build/dist/mabibli-0.1.1-linux-x64.tar.gz, puis vérifier sans authentification :
curl -fsSLI "https://forge.example.org/mabibli/releases/download/v0.1.1/mabibli-0.1.1-linux-x64.tar.gz" | head -1
B.5 Pousser le paquet
cd ../mabibli_ynh && git add -A && git commit -m "Publier la version 0.1.1" && git push
B.6 Sauvegarder, puis mettre à jour
YunoHost prend lui-même une sauvegarde de sécurité avant la mise à jour
(mabibli-pre-upgrade1), mais elle ne contient pas le répertoire de données
(BACKUP_CORE_ONLY) : elle sert à restaurer l'application, pas la bibliothèque. Prendre
une sauvegarde complète reste donc utile avant une version qui touche au schéma :
sudo yunohost backup create --apps mabibli
sudo yunohost app upgrade mabibli -u https://forge.example.org/mabibli_ynh --debug
⚠️ L'option -u n'est pas facultative ici. MaBibli n'est pas dans le catalogue
officiel : sans elle, YunoHost ne sait pas où retrouver le paquet et refuse d'emblée —
« mabibli is not in the catalog (anymore?) », puis « No apps can be upgraded ». Rien
n'est cassé pour autant, la commande n'a simplement pas commencé. C'est la même URL
qu'à l'installation, celle du dépôt _ynh, jamais celle de l'archive.
(Ajouter --force seulement pour réappliquer une version identique, par exemple en
mise au point du paquet.)
Le script arrête le service avant de remplacer les binaires — deux processus sur la
même base SQLite pendant une migration est exactement ce qu'il faut éviter — puis
attend Application started, avec un délai de 120 s : une migration sur base remplie
prend plus de temps que la création d'un schéma vide.
B.7 Vérifier après mise à jour
sudo systemctl status mabibli --no-pager && sudo journalctl -u mabibli -n 30 --no-pager
Puis, dans le navigateur, le contrôle qui compte vraiment : les livres sont toujours
là. C'est ce qui valide que la base vit bien dans le répertoire de données et non à
côté du binaire — upgrade remplace intégralement /var/www/mabibli.
Vider le cache du navigateur n'est pas nécessaire : le service worker compare les empreintes et propose « Mettre à jour ». Sur mobile, un onglet resté ouvert peut retarder la bascule — c'est précisément ce que le bandeau de mise à jour sert à débloquer.
B.8 Si la mise à jour échoue
YunoHost restaure automatiquement la sauvegarde de sécurité quand le script échoue. Si le service démarre mais que l'application se comporte mal, revenir en arrière à la main :
sudo yunohost backup list
sudo yunohost app remove mabibli --purge
sudo yunohost backup restore <nom-de-l-archive> --apps mabibli
⚠️ --purge efface le répertoire de données. Ne le faire qu'avec une archive contenant
la bibliothèque sous la main — celle de B.5, pas mabibli-pre-upgrade1.