# Publier une version de MaBibli Pour vous, qui sortez les versions. Pour installer, voir [installer.md](installer.md) ; pour comprendre le code, [architecture.md](architecture.md). | | | |---|---| | [Avant de publier ailleurs](#avant-de-publier-ce-projet-quelque-part) | l'URL de dépôt, à configurer une fois | | [Compiler](#compilation) | en développement, et le publish self-contained | | [La chaîne de publication](#publication) | ce que `publier.sh` fait, et ce qu'il refuse | | [Monter de version](#b-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 ""`. ## Compilation Prérequis : le SDK **.NET 10** (`dotnet --version`). ### En développement ```bash dotnet build dotnet test ``` Pour lancer l'application en local (l'API sert aussi le client Blazor compilé) : ```bash 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 : ```bash 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 : ```bash 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 : ```bash ./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](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](#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é. ```bash 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` : ```bash ./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 ```bash 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 : ```bash 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 ```bash 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 : ```bash sudo yunohost backup create --apps mabibli ``` ```bash 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 ```bash 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 : ```bash sudo yunohost backup list ``` ```bash sudo yunohost app remove mabibli --purge ``` ```bash sudo yunohost backup restore --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`. ---