Le manifeste de la 0.5.0, deja publiee, s'est mis a pointer une archive introuvable — l'installation echouait sur ynh_setup_source, sans que le symptome designe la cause. Le remplacement global des URL avait reecrit amd64.url, c'est-a-dire precisement le champ que la documentation ecrite le meme jour designait comme « a ne jamais changer a la main », puisque publier.sh le regenere a chaque publication. ⚠ L'erreur de conception est plus large : le placeholder avait sa place dans la COPIE publique, pas dans le depot de travail, qui sert au deploiement reel et doit rester operationnel. Anonymiser un depot qui sert encore, c'est le casser. Ce qui reste, et qui vaut : depot_code commande toujours toutes les URL derivees, et le garde-fou refuse toujours de publier avec une URL en example.org — il ne se declenche simplement plus ici, puisqu'il sert a la copie publique. sha256 inchange : seule l'URL avait bouge, le manifeste retrouve exactement son etat de publication. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
531 lines
21 KiB
Bash
Executable File
531 lines
21 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Publie une version de MaBibli de bout en bout, en une commande.
|
|
#
|
|
# 1. choisir la version, à partir de celle déjà publiée
|
|
# 2. compiler self-contained, vérifier le publish, produire l'archive
|
|
# 3. réécrire manifest.toml (version, url, sha256)
|
|
# 4. committer et pousser mabibli_ynh (le serveur lit Gitea, jamais le local)
|
|
# 5. taguer et pousser mabibli (le tag porte le code de la release)
|
|
#
|
|
# La seule chose qui reste manuelle est le dépôt de l'archive dans la release Gitea :
|
|
# l'URL est rappelée en fin de sortie.
|
|
#
|
|
# ⚠️ POURQUOI UN SEUL SCRIPT, ET PAS DEUX
|
|
#
|
|
# Ce fichier était jusqu'au 2026-08-21 un orchestrateur appelant `publier-release.sh`,
|
|
# qui compilait et réécrivait le manifeste. Deux scripts, dont le mauvais portait le nom
|
|
# le plus convaincant : lancé seul, `publier-release.sh` réécrivait le manifeste sans le
|
|
# committer, et acceptait de recompiler une version dont le tag existait déjà.
|
|
#
|
|
# Les deux moitiés de la panne du 2026-08-21 en sont sorties : une release `v0.4.0`
|
|
# contenant en réalité six commits de plus que son tag, et un `manifest.toml` corrigé
|
|
# mais jamais poussé — donc un `yunohost app upgrade` qui échoue sur le sha256, et dont
|
|
# le retour arrière échoue pour la même raison.
|
|
#
|
|
# D'où la fusion. Le mode `--archive-seule` conserve la brique réutilisable en CI
|
|
# (compiler et archiver, sans toucher ni au manifeste ni à git), mais sous CE nom : il
|
|
# n'y a plus deux commandes voisines entre lesquelles se tromper.
|
|
#
|
|
set -euo pipefail
|
|
|
|
#=================================================
|
|
# VALEURS PAR DÉFAUT
|
|
#=================================================
|
|
|
|
racine_paquet="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
manifeste="$racine_paquet/manifest.toml"
|
|
|
|
# ⚠️ Chaque réglage a UNE seule façon de se donner : son option en ligne de commande.
|
|
# Cinq variables d'environnement jumelles (MABIBLI_SOURCE_DIR, MABIBLI_BASE_URL…) ont
|
|
# existé jusqu'au 2026-08-22, chacune doublant une option qu'elle ne faisait que
|
|
# répéter : l'aide en listait dix pour cinq réglages, et rien ne disait laquelle
|
|
# l'emportait sur l'autre. Ne pas les réintroduire pour une CI hypothétique — une CI
|
|
# passe des options aussi bien que des variables.
|
|
# ⚠️ LA SEULE LIGNE À CHANGER pour héberger ce projet ailleurs.
|
|
# Tout ce qui suit en dérive : URL de release, URL d'archive, message de fin.
|
|
#
|
|
# Une copie publique du projet porte ici `https://forge.example.org/mabibli`, injoignable
|
|
# par construction (example.org est réservé à la documentation par la RFC 2606). Le
|
|
# contrôle préalable plus bas REFUSE alors de publier, et refuse AVANT de compiler :
|
|
# celui qui reprend le projet doit renseigner cette ligne avant sa première release,
|
|
# plutôt que de découvrir le problème à l'installation, dans ynh_setup_source.
|
|
depot_code="https://git.akbar.nohost.me/mathieu/mabibli"
|
|
|
|
source_dir="$(cd "$racine_paquet/../mabibli" 2>/dev/null && pwd || true)"
|
|
base_url="$depot_code/releases/download"
|
|
url_releases="$depot_code/releases"
|
|
output_dir="$racine_paquet/build/dist"
|
|
|
|
version=""
|
|
increment=""
|
|
sans_confirmation=0
|
|
archive_seule=0
|
|
runtime="linux-x64"
|
|
projet="MaBibli.Api"
|
|
|
|
usage() {
|
|
cat <<'FIN'
|
|
Usage : publier.sh [options]
|
|
|
|
--version X.Y.Z Version à publier (sinon : demandée, à partir de la précédente)
|
|
--patch Incrémenter le dernier chiffre (0.3.0 -> 0.3.1)
|
|
--minor Incrémenter le chiffre du milieu (0.3.0 -> 0.4.0)
|
|
--major Incrémenter le premier chiffre (0.3.0 -> 1.0.0)
|
|
--oui, -y Ne rien demander (pour une CI)
|
|
--archive-seule Compiler et archiver SEULEMENT : ni manifeste, ni commit, ni tag.
|
|
Pour REPRENDRE une publication à la main après un échec en cours
|
|
de route ; ne publie rien et ne modifie aucun dépôt. Les contrôles
|
|
restent les mêmes, mais avertissent au lieu de refuser.
|
|
--source-dir CHEMIN Dépôt du code C# (défaut : ../mabibli)
|
|
--depot-code URL Dépôt public du code, d'où dérivent les URL de release
|
|
--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)
|
|
-h, --help Cette aide
|
|
FIN
|
|
}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--version) version="$2"; shift 2 ;;
|
|
--patch|--minor|--major) increment="${1#--}"; shift ;;
|
|
--oui|-y) sans_confirmation=1; shift ;;
|
|
--archive-seule) archive_seule=1; shift ;;
|
|
--source-dir) source_dir="$2"; shift 2 ;;
|
|
--depot-code) depot_code="$2"; base_url="$2/releases/download"; url_releases="$2/releases"; shift 2 ;;
|
|
--base-url) base_url="$2"; shift 2 ;;
|
|
--output-dir) output_dir="$2"; shift 2 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Option inconnue : $1" >&2; usage >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
echoerr() { echo "$@" >&2; }
|
|
|
|
# ⚠️ LE SEUL ENDROIT où `--archive-seule` assouplit quoi que ce soit.
|
|
#
|
|
# Les garde-fous ci-dessous protègent la *publication* : ils empêchent qu'une release
|
|
# contienne autre chose que le code que son tag désigne. En `--archive-seule`, rien n'est
|
|
# publié — ni manifeste, ni commit, ni tag — donc rien ne peut mentir, et un refus n'a
|
|
# plus lieu d'être. Il reste un avertissement, car ce qu'il signale est toujours vrai.
|
|
#
|
|
# Chaque garde-fou s'écrit donc UNE fois, sans savoir dans quel mode il tourne. C'est ce
|
|
# qui empêche d'assouplir par inadvertance un contrôle qui devait rester dur.
|
|
# ⚠️ Le CONSTAT et le CONSEIL sont séparés, et ce n'est pas de la cosmétique : le constat
|
|
# reste vrai dans les deux modes, le conseil non. « Choisissez un numéro libre » est le
|
|
# bon conseil pour une publication, et un mauvais conseil en reprise — où le tag visé est
|
|
# justement celui qu'on veut retrouver.
|
|
refuser() { # refuser <conseil> <constat> [<constat>...]
|
|
local conseil="$1"; shift
|
|
if [ "$archive_seule" -eq 1 ]; then
|
|
printf ' ⚠ %s\n' "$@"
|
|
echo " (poursuite : --archive-seule ne publie rien)"
|
|
else
|
|
printf '%s\n' "$@" >&2
|
|
[ -n "$conseil" ] && echoerr "$conseil"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
#=================================================
|
|
# CONTRÔLES PRÉALABLES
|
|
#=================================================
|
|
|
|
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
|
|
|
|
# ⚠️ Exigé dans les DEUX modes. `--archive-seule` sert à reprendre une publication à la
|
|
# main, jamais à compiler un arbre quelconque : sans dépôt, il ne saurait ni proposer une
|
|
# version, ni dire si l'archive correspond au code d'un tag. L'exiger ici plutôt qu'à
|
|
# quatre endroits plus bas est ce qui rend le reste du script inconditionnel.
|
|
if [ ! -d "$source_dir/.git" ]; then
|
|
echoerr "'$source_dir' n'est pas un dépôt git."
|
|
echoerr "publier.sh compile ce qu'un commit désigne : sans dépôt, rien ne le désigne."
|
|
exit 1
|
|
fi
|
|
|
|
# ⚠️ Refuser AVANT de compiler, comme les autres garde-fous. Publier avec le placeholder
|
|
# écrirait dans manifest.toml une `amd64.url` que personne ne peut télécharger — et
|
|
# `ynh_setup_source` échouerait à l'installation, loin d'ici et sans rapport apparent.
|
|
if [ "$archive_seule" -eq 0 ] && [[ "$base_url" == *example.org* ]]; then
|
|
echoerr "Le dépôt public n'est pas configuré : $depot_code"
|
|
echoerr "Changez « depot_code » en tête de ce script, ou passez --depot-code URL."
|
|
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
|
|
#=================================================
|
|
|
|
# Le tag fait foi : c'est lui qui désigne le code publié. Le manifeste ne porte que la
|
|
# dernière version *empaquetée*, qui peut être en retard si une publication a échoué en
|
|
# cours de route. On prend le plus élevé des deux pour ne jamais proposer un numéro déjà pris.
|
|
version_tag="$(git -C "$source_dir" tag --list 'v[0-9]*' --sort=-v:refname | head -1 | sed 's/^v//')"
|
|
version_manifeste="$(sed -n 's/^version *= *"\([^"~]*\).*"/\1/p' "$manifeste" | head -1)"
|
|
|
|
precedente="$(printf '%s\n%s\n' "$version_tag" "$version_manifeste" \
|
|
| grep -E '^[0-9]+(\.[0-9]+)*$' | sort -V | tail -1 || true)"
|
|
|
|
suivante() { # suivante <version> <patch|minor|major>
|
|
IFS=. read -r maj min cor <<<"$1"
|
|
case "$2" in
|
|
major) echo "$((maj + 1)).0.0" ;;
|
|
minor) echo "$maj.$((min + 1)).0" ;;
|
|
patch) echo "$maj.$min.$((cor + 1))" ;;
|
|
esac
|
|
}
|
|
|
|
# ⚠️ Le calcul de la version est le MÊME dans les deux modes, et c'est délibéré.
|
|
# `--archive-seule` retombait auparavant sur la version du manifeste, c'est-à-dire sur
|
|
# celle **déjà publiée** : reprendre une publication à la main reproduisait donc le
|
|
# numéro précédent tant qu'on ne passait pas `--version`. Le README devait avertir de ce
|
|
# piège ; il n'existe plus. Une reprise après échec veut la version qu'on était en train
|
|
# de publier, et c'est exactement ce que l'incrément propose.
|
|
if [ -z "$precedente" ]; then
|
|
echoerr "Aucune version précédente trouvée (ni tag, ni manifest.toml) ; utilisez --version."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Dernière version publiée : $precedente"
|
|
[ "$version_tag" != "$version_manifeste" ] &&
|
|
echo " ⚠ tag v${version_tag:-—} et manifest.toml ${version_manifeste:-—} divergent"
|
|
|
|
if [ -z "$version" ] && [ -n "$increment" ]; then
|
|
version="$(suivante "$precedente" "$increment")"
|
|
fi
|
|
|
|
if [ -z "$version" ]; then
|
|
if [ "$sans_confirmation" -eq 1 ] || [ ! -t 0 ]; then
|
|
echoerr "Pas de terminal pour demander la version ; utilisez --version ou --patch/--minor/--major."
|
|
exit 1
|
|
fi
|
|
echo
|
|
echo " 1) $(suivante "$precedente" patch) (correction)"
|
|
echo " 2) $(suivante "$precedente" minor) (nouveautés)"
|
|
echo " 3) $(suivante "$precedente" major) (rupture)"
|
|
echo " 4) autre — à saisir"
|
|
echo
|
|
read -rp "Version à publier [1] ? " choix
|
|
case "${choix:-1}" in
|
|
1) version="$(suivante "$precedente" patch)" ;;
|
|
2) version="$(suivante "$precedente" minor)" ;;
|
|
3) version="$(suivante "$precedente" major)" ;;
|
|
4) read -rp "Numéro de version : " version ;;
|
|
*) version="$choix" ;; # un numéro tapé directement passe aussi
|
|
esac
|
|
fi
|
|
|
|
if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echoerr "Version invalide : '$version' (attendu X.Y.Z)."
|
|
exit 1
|
|
fi
|
|
|
|
#=================================================
|
|
# CE QUI DOIT ÊTRE VRAI AVANT DE COMPILER
|
|
#=================================================
|
|
|
|
# ⚠️ Le garde-fou qui manquait le 2026-08-21. Recompiler une version dont le tag existe
|
|
# déjà produit une archive qui ne correspond PAS au code que ce tag désigne : la release
|
|
# se met alors à mentir, et l'écran « À propos » avec elle, sans que rien ne le signale.
|
|
if git -C "$source_dir" rev-parse "v$version" >/dev/null 2>&1; then
|
|
commit_tag="$(git -C "$source_dir" rev-list -n1 "v$version")"
|
|
commit_head="$(git -C "$source_dir" rev-parse HEAD)"
|
|
if [ "$commit_tag" != "$commit_head" ]; then
|
|
refuser "Choisissez un numéro libre (--patch)." \
|
|
"Le tag v$version existe et désigne ${commit_tag:0:7} ; HEAD est ${commit_head:0:7}." \
|
|
"L'archive ne serait donc PAS le code que ce tag désigne."
|
|
else
|
|
refuser "Choisissez un numéro libre (--patch)." \
|
|
"Le tag v$version existe déjà (${commit_tag:0:7}) : ce numéro est pris."
|
|
fi
|
|
fi
|
|
|
|
# Le tag va désigner le HEAD du dépôt du code : un travail non committé ne serait donc
|
|
# pas dans la release, alors même que l'archive, elle, le contiendrait.
|
|
#
|
|
# ⚠️ Ce contrôle était auparavant SAUTÉ en `--archive-seule`, qui produisait donc en
|
|
# silence une archive contenant du travail non committé. Il s'exécute désormais toujours,
|
|
# et se contente d'avertir quand rien n'est publié : c'est précisément l'écart qu'on veut
|
|
# voir quand on reprend une publication à la main.
|
|
if [ -n "$(git -C "$source_dir" status --porcelain)" ]; then
|
|
git -C "$source_dir" status --short >&2
|
|
refuser "" \
|
|
"Le dépôt du code a des modifications non committées (ci-dessus)." \
|
|
"Le tag désignera HEAD : ce travail ne serait pas dans la release."
|
|
fi
|
|
|
|
echo
|
|
echo "=== À publier ==="
|
|
echo " version : ${precedente:-—} -> $version"
|
|
branche="$(git -C "$source_dir" rev-parse --abbrev-ref HEAD)"
|
|
echo " code : $source_dir ($branche, $(git -C "$source_dir" rev-parse --short HEAD))"
|
|
echo " paquet : $racine_paquet"
|
|
[ "$archive_seule" -eq 1 ] &&
|
|
echo " mode : --archive-seule (ni manifeste, ni commit, ni tag)"
|
|
|
|
if [ "$sans_confirmation" -ne 1 ]; then
|
|
read -rp "Continuer ? [O/n] " reponse
|
|
case "${reponse:-o}" in
|
|
[oO]*) ;;
|
|
*) echo "Abandon."; exit 1 ;;
|
|
esac
|
|
fi
|
|
|
|
#=================================================
|
|
# COMPILATION
|
|
#=================================================
|
|
|
|
# Horodatage du build, injecté dans l'assembly à côté de la version.
|
|
#
|
|
# ⚠️ Il sert de TÉMOIN : l'application ne montre sa version que si cet horodatage est présent.
|
|
# Sans lui, le numéro lu serait le « 1.0.0 » que le SDK pose par défaut, qui se lirait comme une
|
|
# vraie version alors qu'il ne désigne rien — et c'est précisément la valeur qu'on va chercher
|
|
# pour diagnostiquer un appareil dépareillé. Un binaire compilé à la main se déclare donc
|
|
# « version de développement », ce qui est vrai.
|
|
#
|
|
# `SOURCE_DATE_EPOCH` est respecté, comme pour l'archive : sans cela, deux compilations du même
|
|
# commit donneraient deux binaires — donc deux sha256 — pour la seule raison que l'heure a
|
|
# changé, et la reproductibilité visée plus bas ne vaudrait plus rien.
|
|
if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then
|
|
date_build="$(date -u -d "@$SOURCE_DATE_EPOCH" +%Y-%m-%dT%H:%M:%SZ)"
|
|
else
|
|
date_build="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
fi
|
|
|
|
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"
|
|
echo " build : $date_build"
|
|
|
|
# `--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" \
|
|
-p:MaBibliDateBuild="$date_build"
|
|
|
|
#=================================================
|
|
# 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"
|
|
|
|
url_archive="$base_url/v$version/$archive_nom"
|
|
|
|
if [ "$archive_seule" -eq 1 ]; then
|
|
cat <<FIN
|
|
|
|
=== Terminé (--archive-seule) ===
|
|
|
|
Archive prête : $archive
|
|
sha256 : $somme
|
|
|
|
Rien n'a été publié : manifest.toml est inchangé, aucun commit, aucun tag.
|
|
Pour publier réellement cette version, relancez sans --archive-seule.
|
|
|
|
FIN
|
|
exit 0
|
|
fi
|
|
|
|
#=================================================
|
|
# MANIFESTE
|
|
#=================================================
|
|
|
|
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_archive" "$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_archive"
|
|
echo " sha256 : $somme"
|
|
|
|
#=================================================
|
|
# LE PAQUET (le serveur lit Gitea, jamais la copie locale)
|
|
#=================================================
|
|
|
|
echo
|
|
echo "=== Paquet : commit et push ==="
|
|
git -C "$racine_paquet" add -A
|
|
if git -C "$racine_paquet" diff --cached --quiet; then
|
|
echo " rien à committer (manifeste déjà à jour)"
|
|
else
|
|
git -C "$racine_paquet" commit -m "Publier la version $version"
|
|
fi
|
|
git -C "$racine_paquet" push
|
|
|
|
#=================================================
|
|
# LE CODE : tag et push
|
|
#=================================================
|
|
|
|
echo
|
|
echo "=== Code : tag v$version et push ==="
|
|
git -C "$source_dir" tag "v$version"
|
|
git -C "$source_dir" push origin "$branche" --tags
|
|
|
|
# Un push qui échoue à demi ne se voit pas dans la sortie de git : on redemande au distant.
|
|
verifier_pousse() { # verifier_pousse <dépôt> <ref>
|
|
if git -C "$1" ls-remote --exit-code origin "$2" >/dev/null 2>&1; then
|
|
echo " ✓ $2 présent sur origin"
|
|
else
|
|
echoerr " ✗ $2 ABSENT sur origin — le push n'a pas abouti."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
echo
|
|
echo "=== Vérification côté distant ==="
|
|
verifier_pousse "$source_dir" "refs/tags/v$version"
|
|
verifier_pousse "$racine_paquet" "refs/heads/$(git -C "$racine_paquet" rev-parse --abbrev-ref HEAD)"
|
|
|
|
#=================================================
|
|
# CE QUI RESTE À FAIRE À LA MAIN
|
|
#=================================================
|
|
|
|
cat <<FIN
|
|
|
|
=== Publié : $version ===
|
|
|
|
Il ne reste qu'une chose, dans Gitea : créer la release v$version et y téléverser
|
|
l'archive.
|
|
|
|
Releases : $url_releases
|
|
Archive : $archive
|
|
|
|
Ensuite, vérifier que le manifeste pointe sur un fichier réellement téléchargeable
|
|
(sans être authentifié) :
|
|
|
|
curl -fsSLI "$url_archive" | head -1
|
|
|
|
Puis, sur le serveur :
|
|
|
|
sudo yunohost app upgrade mabibli -u ${depot_code}_ynh
|
|
|
|
FIN
|