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>
331 lines
14 KiB
Markdown
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 : 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`.
|
|
|
|
---
|
|
|