premier essaie

This commit is contained in:
mathieu
2026-08-18 15:15:53 +02:00
commit f942f41f34
18 changed files with 1889 additions and 0 deletions
Binary file not shown.
+272
View File
@@ -0,0 +1,272 @@
#!/bin/bash
#
# Produit l'archive de release de MaBibli et met à jour manifest.toml.
#
# Pourquoi ce script vit dans `mabibli_ynh` et non dans `mabibli` :
# sa sortie utile n'est pas l'archive, c'est le couple (url, sha256) que le
# manifeste doit porter. Le garder ici permet de compiler, d'archiver et de mettre à
# jour le manifeste en une commande, puis de committer le tout d'un bloc — le
# manifeste ne peut pas se désynchroniser de l'archive qu'il décrit.
#
# Réutilisable en CI (Gitea Actions) sans modification : aucune interaction, aucune
# variable propre à un environnement d'intégration, tout passe par des options ou des
# variables d'environnement, et le script échoue au premier problème.
#
# Exemple d'usage en CI :
# ./build/publier-release.sh \
# --source-dir "$GITHUB_WORKSPACE/mabibli" \
# --version 0.2.0 \
# --base-url "https://gitea.exemple.org/mathieu/mabibli/releases/download"
#
set -euo pipefail
#=================================================
# VALEURS PAR DÉFAUT
#=================================================
racine_paquet="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source_dir="${MABIBLI_SOURCE_DIR:-$(cd "$racine_paquet/../mabibli" 2>/dev/null && pwd || true)}"
version="${MABIBLI_VERSION:-}"
base_url="${MABIBLI_BASE_URL:-https://gitea.example.org/mathieu/mabibli/releases/download}"
output_dir="${MABIBLI_OUTPUT_DIR:-$racine_paquet/build/dist}"
maj_manifeste=1
runtime="linux-x64"
projet="MaBibli.Api"
#=================================================
# OPTIONS
#=================================================
usage() {
cat <<'FIN'
Usage : publier-release.sh [options]
--source-dir CHEMIN Dépôt du code C# (défaut : ../mabibli)
--version X.Y.Z Version de la release (défaut : déduite de manifest.toml)
--base-url URL Racine des URL de release, sans le tag ni le fichier
--output-dir CHEMIN Où déposer l'archive (défaut : build/dist)
--no-manifest-update Ne pas réécrire manifest.toml
-h, --help Cette aide
Variables d'environnement équivalentes : MABIBLI_SOURCE_DIR, MABIBLI_VERSION,
MABIBLI_BASE_URL, MABIBLI_OUTPUT_DIR.
FIN
}
while [ $# -gt 0 ]; do
case "$1" in
--source-dir) source_dir="$2"; shift 2 ;;
--version) version="$2"; shift 2 ;;
--base-url) base_url="$2"; shift 2 ;;
--output-dir) output_dir="$2"; shift 2 ;;
--no-manifest-update) maj_manifeste=0; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "Option inconnue : $1" >&2; usage >&2; exit 2 ;;
esac
done
manifeste="$racine_paquet/manifest.toml"
#=================================================
# CONTRÔLES PRÉALABLES
#=================================================
echoerr() { echo "$@" >&2; }
if [ -z "$source_dir" ] || [ ! -d "$source_dir" ]; then
echoerr "Dépôt du code introuvable : '${source_dir:-<vide>}'"
echoerr "Précisez-le avec --source-dir."
exit 1
fi
source_dir="$(cd "$source_dir" && pwd)"
if [ ! -d "$source_dir/$projet" ]; then
echoerr "'$source_dir' ne contient pas de projet $projet."
exit 1
fi
if ! command -v dotnet >/dev/null; then
echoerr "Le SDK .NET est introuvable. Il n'est nécessaire QUE sur cette machine :"
echoerr "le serveur YunoHost reçoit un publish self-contained et n'a pas de SDK."
exit 1
fi
# La version par défaut se lit dans le manifeste, en retirant le suffixe ~ynhN :
# le tag et le nom de fichier portent la version applicative, pas celle du paquet.
if [ -z "$version" ]; then
version="$(sed -n 's/^version *= *"\([^"~]*\).*"/\1/p' "$manifeste" | head -1)"
if [ -z "$version" ]; then
echoerr "Impossible de déduire la version depuis $manifeste ; utilisez --version."
exit 1
fi
echo "Version déduite de manifest.toml : $version"
fi
#=================================================
# COMPILATION
#=================================================
travail="$(mktemp -d)"
# shellcheck disable=SC2064
trap "rm -rf '$travail'" EXIT
publish="$travail/publish"
echo
echo "=== Compilation self-contained $runtime ==="
echo " source : $source_dir"
echo " version: $version"
# `--self-contained` embarque le runtime .NET dans le dossier publié : c'est ce qui
# permet au paquet YunoHost de ne dépendre d'aucun `dotnet-runtime` côté serveur.
#
# `MaBibli.Api` référence `MaBibli.Client` : le client Blazor WebAssembly est compilé
# au passage et atterrit dans `wwwroot/`. Un seul publish suffit donc pour les trois
# projets.
dotnet publish "$source_dir/$projet" \
--configuration Release \
--runtime "$runtime" \
--self-contained \
--output "$publish" \
-p:Version="$version"
#=================================================
# CONTRÔLES SUR LE RÉSULTAT
#=================================================
echo
echo "=== Vérification du publish ==="
if [ ! -x "$publish/$projet" ]; then
echoerr "Binaire '$projet' absent ou non exécutable dans le publish."
exit 1
fi
# Sans `wwwroot`, le service démarrerait et répondrait — en ne servant aucune page.
# C'est le défaut qui est passé inaperçu pendant trois phases du projet, faute de
# regarder ailleurs que la racine. On le vérifie donc ici, à la source.
if [ ! -f "$publish/wwwroot/index.html" ]; then
echoerr "wwwroot/index.html absent : le client Blazor n'a pas été embarqué."
exit 1
fi
# `index.html` doit référencer un script réellement présent. Un placeholder non
# substitué (`blazor.webassembly#[.{fingerprint}].js`) donnerait une page blanche
# alors que `/` répondrait 200.
if grep -q '#\[\.{fingerprint}\]' "$publish/wwwroot/index.html"; then
echoerr "index.html contient des placeholders d'empreinte non substitués."
echoerr "Voir CLAUDE.md, « Empreintes WASM désactivées »."
exit 1
fi
for ressource in $(grep -oE '(src|href)="[^"]+"' "$publish/wwwroot/index.html" \
| sed -E 's/^(src|href)="//; s/"$//' \
| grep -vE '^(https?:|data:|#|/$|\.$)'); do
if [ ! -f "$publish/wwwroot/$ressource" ]; then
echoerr "index.html référence '$ressource', absent du publish."
exit 1
fi
done
echo " binaire, wwwroot et ressources d'index.html : OK"
#=================================================
# ARCHIVE
#=================================================
archive_nom="mabibli-$version-$runtime.tar.gz"
mkdir -p "$output_dir"
archive="$output_dir/$archive_nom"
echo
echo "=== Archive ==="
# Fichiers à la racine de l'archive, sans dossier intermédiaire : cohérent avec
# `in_subdir = false` dans manifest.toml.
#
# Options de reproductibilité : sans elles, deux compilations identiques donneraient
# deux sha256 différents (dates, ordre de parcours, uid/gid). En CI comme en local,
# on veut pouvoir vérifier qu'une archive correspond bien à un commit.
tar --create --gzip \
--file="$archive" \
--directory="$publish" \
--owner=0 --group=0 --numeric-owner \
--mtime="@${SOURCE_DATE_EPOCH:-0}" \
--sort=name \
.
somme="$(sha256sum "$archive" | cut -d' ' -f1)"
taille="$(du -h "$archive" | cut -f1)"
taille_octets="$(stat -c%s "$archive")"
echo " fichier : $archive"
echo " taille : $taille ($taille_octets octets)"
echo " sha256 : $somme"
#=================================================
# MISE À JOUR DU MANIFESTE
#=================================================
url="$base_url/v$version/$archive_nom"
if [ "$maj_manifeste" -eq 1 ]; then
echo
echo "=== Mise à jour de manifest.toml ==="
# Le suffixe ~ynhN est conservé s'il existe déjà pour cette version, sinon
# remis à ~ynh1 : un changement de version applicative repart toujours de 1.
version_actuelle="$(sed -n 's/^version *= *"\([^"]*\)".*/\1/p' "$manifeste" | head -1)"
if [[ "$version_actuelle" == "$version~ynh"* ]]; then
version_paquet="$version_actuelle"
echo " version : $version_paquet (inchangée)"
else
version_paquet="$version~ynh1"
echo " version : $version_actuelle -> $version_paquet"
fi
python3 - "$manifeste" "$version_paquet" "$url" "$somme" <<'PY'
import re, sys
chemin, version, url, somme = sys.argv[1:5]
with open(chemin, encoding="utf-8") as f:
texte = f.read()
remplacements = [
(r'^version = ".*"$', f'version = "{version}"'),
(r'^ amd64\.url = ".*"$', f' amd64.url = "{url}"'),
(r'^ amd64\.sha256 = ".*"$', f' amd64.sha256 = "{somme}"'),
]
for motif, valeur in remplacements:
texte, n = re.subn(motif, valeur, texte, count=1, flags=re.MULTILINE)
if n != 1:
sys.exit(f"Motif introuvable dans le manifeste : {motif}")
with open(chemin, "w", encoding="utf-8") as f:
f.write(texte)
PY
echo " url : $url"
echo " sha256 : $somme"
fi
#=================================================
# SUITE À DONNER
#=================================================
cat <<FIN
=== Terminé ===
Archive prête : $archive
Il reste à faire, à la main (le dépôt Gitea et la release ne sont pas automatisés) :
1. Créer le tag v$version sur le dépôt du code, puis la release correspondante.
2. Y téléverser $archive_nom.
3. Vérifier que l'URL du manifeste répond :
curl -fsSLI "$url"
4. Committer manifest.toml dans mabibli_ynh.
FIN