Files
mabibli/docs/publier-une-version.md
T
mathieuandClaude Opus 5 d454e41c36 Restaure les vraies URL, et documente la production d'une copie publique
Pendant du commit du paquet. Les passages qui PARLAIENT du placeholder
annoncaient desormais la vraie URL comme etant un placeholder : ils sont
reecrits pour dire ce qui est.

docs/publier-une-version.md porte maintenant la marche a suivre pour produire
une copie publique — depot neuf sans historique, URL neutralisees, identite a
revoir — avec le rm -rf .git AVANT le git init : un git clone ne conviendrait
pas, l'historique portant les URL reelles dans chaque ancien commit.

CLAUDE.md consigne l'erreur et la regle qui en sort : on anonymise une copie,
jamais l'original.

626 tests au vert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:22:50 +02:00

331 lines
14 KiB
Markdown

# 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 |
## L'URL du dépôt, et la copie publique
Ce dépôt est le dépôt **de travail** : il porte les URL réelles du serveur de son auteur,
`https://git.akbar.nohost.me/mathieu/…`, et c'est ce qui le rend opérationnel.
**Une seule ligne les commande toutes**`depot_code`, en tête de `build/publier.sh`.
Les URL de release, d'archive et le message de fin en dérivent. `--depot-code URL` fait la
même chose sans modifier le fichier, pour un essai ponctuel.
⚠️ **`amd64.url` dans `manifest.toml` ne se change JAMAIS à la main** : `publier.sh` la
réécrit à chaque publication. La modifier hors de ce chemin produit un manifeste qui pointe
une archive introuvable — l'échec survient alors **bien plus loin**, à l'installation, dans
`ynh_setup_source`, sans rapport apparent avec la cause. C'est arrivé le 2026-08-22.
### Produire une copie publique
Pour publier le projet à destination de tiers, on **copie** — on ne transforme pas le dépôt
de travail :
```bash
cd ~/Code && rm -rf mabibli-public && cp -r mabibli mabibli-public
rm -rf mabibli-public/.git
```
⚠️ **Le `rm -rf .git` vient AVANT le `git init`**, et un `git clone` ne conviendrait pas :
l'historique porte les URL réelles dans chaque ancien commit — et, côté paquet, une archive
de 68 Mo committée par erreur à la 0.1.0 puis retirée.
Puis neutraliser les URL et l'identité :
```bash
cd mabibli-public
grep -rl 'git\.akbar\.nohost\.me' . | xargs sed -i \
-e 's|https://git\.akbar\.nohost\.me/mathieu/mabibli_ynh|https://forge.example.org/mabibli_ynh|g' \
-e 's|https://git\.akbar\.nohost\.me/mathieu/mabibli|https://forge.example.org/mabibli|g'
git init -b main && git add -A && git commit -m "MaBibli"
```
`forge.example.org` est injoignable par construction — `example.org` est réservé à la
documentation par la **RFC 2606**. C'est voulu : `publier.sh` **refuse de publier** tant
qu'une URL en `example.org` est en place, et il refuse **avant de compiler**. Celui qui
reprend le projet doit donc renseigner `depot_code` avant sa première release, plutôt que
de découvrir le problème à l'installation.
Restent à revoir à la main dans la copie : `maintainers` dans `manifest.toml`, et l'adresse
de contact et le site dans `MaBibli.Client/Pages/APropos.razor`.
## 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&nbsp;: 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://git.akbar.nohost.me/mathieu/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://git.akbar.nohost.me/mathieu/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 <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`.
---