ci: rendre lisible l'échec d'attache de release (401 / 403 distingués)
CI / No em/en dashes (push) Successful in 3s
Deploy site (production) / build-and-deploy (push) Successful in 47s
CI / Build & test (Node 24) (push) Successful in 10m12s
CI / Build & test (Node 22) (push) Successful in 10m23s
CI / Pack & boot smoke (Node 22) (push) Successful in 9m55s
CI / No em/en dashes (push) Successful in 3s
Deploy site (production) / build-and-deploy (push) Successful in 47s
CI / Build & test (Node 24) (push) Successful in 10m12s
CI / Build & test (Node 22) (push) Successful in 10m23s
CI / Pack & boot smoke (Node 22) (push) Successful in 9m55s
Le parsing JSON du script n'était pas tolérant à une réponse vide : sur un 401, deux « SyntaxError: Unexpected end of JSON input » de Node s'affichaient AVANT le message d'erreur utile et noyaient le diagnostic. La lecture de champ est désormais tolérante, et le script nomme la cause selon le code HTTP : 401 = token invalide ou expiré, 403 = portées insuffisantes. Testé contre un faux serveur pour les trois cas (401, 403, succès) : messages attendus et codes de sortie corrects (1 en échec, 0 en succès).
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
# Usage : attach-release-assets.sh <tag> <release-name> <fichier...>
|
||||
# Env : RELEASE_TOKEN (token Gitea avec write:repository), GITHUB_SERVER_URL, GITHUB_REPOSITORY.
|
||||
#
|
||||
# Partagé par tous les jobs de release desktop (Linux, Windows, canal flottant) : la logique était
|
||||
# dupliquée dans chaque job, et toute correction devait être faite trois fois.
|
||||
# Partagé par tous les jobs de release desktop et par le VSIX : la logique était dupliquée, et toute
|
||||
# correction devait être faite trois fois.
|
||||
set -uo pipefail
|
||||
|
||||
tag="${1:?tag manquant}"
|
||||
@@ -23,40 +23,74 @@ fi
|
||||
|
||||
api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
||||
auth="Authorization: token ${RELEASE_TOKEN}"
|
||||
body=$(mktemp)
|
||||
trap 'rm -f "$body"' EXIT
|
||||
|
||||
release_id=$(curl -fsSL -H "$auth" "${api}/releases/tags/${tag}" \
|
||||
| node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).id || ''" || true)
|
||||
# Lecture d'un champ JSON TOLÉRANTE : une réponse vide ou non-JSON (401, 403, 404) doit donner une
|
||||
# chaîne vide, pas une pile d'appels Node. Sans ça, deux `SyntaxError: Unexpected end of JSON input`
|
||||
# s'affichaient avant le vrai message d'erreur et noyaient le diagnostic.
|
||||
json_field() {
|
||||
node -e "let s='';process.stdin.on('data',(d)=>{s+=d}).on('end',()=>{try{const o=JSON.parse(s);const v=o?.[process.argv[1]];process.stdout.write(v==null?'':String(v))}catch{process.stdout.write('')}})" "$1"
|
||||
}
|
||||
|
||||
# `curl` silencieux qui écrit le corps dans $body et renvoie le code HTTP sur stdout.
|
||||
http_call() {
|
||||
curl -sS -o "$body" -w '%{http_code}' "$@"
|
||||
}
|
||||
|
||||
# --- résolution de la release (existante, sinon création) -------------------------------------
|
||||
code=$(http_call -H "$auth" "${api}/releases/tags/${tag}")
|
||||
release_id=$(json_field id < "$body")
|
||||
|
||||
if [ -z "$release_id" ]; then
|
||||
release_id=$(curl -fsSL -X POST -H "$auth" -H 'Content-Type: application/json' \
|
||||
-d "{\"tag_name\":\"${tag}\",\"name\":\"${release_name}\"}" \
|
||||
"${api}/releases" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).id || ''")
|
||||
fi
|
||||
|
||||
if [ -z "$release_id" ]; then
|
||||
echo "::error::impossible de résoudre ou créer la release ${tag} avec le token fourni."
|
||||
echo "::error::vérifier que le secret porte les portées write:repository et write:package, et qu'il n'a pas expiré."
|
||||
exit 1
|
||||
# 401/403 sur une simple lecture : inutile de tenter la création, le token est en cause.
|
||||
case "$code" in
|
||||
401)
|
||||
echo "::error::le token de release est refusé (HTTP 401) : il est invalide, révoqué ou expiré."
|
||||
echo "::error::régénérer un token Gitea et mettre à jour le secret NPM_TOKEN du dépôt."
|
||||
exit 1
|
||||
;;
|
||||
403)
|
||||
echo "::error::le token de release manque de droits (HTTP 403) sur ${GITHUB_REPOSITORY}."
|
||||
echo "::error::portées attendues : write:repository (releases et assets) et write:package (publication npm)."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
create_code=$(http_call -X POST -H "$auth" -H 'Content-Type: application/json' \
|
||||
-d "{\"tag_name\":\"${tag}\",\"name\":\"${release_name}\"}" "${api}/releases")
|
||||
release_id=$(json_field id < "$body")
|
||||
if [ -z "$release_id" ]; then
|
||||
echo "::error::impossible de créer la release ${tag} (HTTP ${create_code})."
|
||||
echo "::error::réponse de l'API : $(head -c 300 "$body")"
|
||||
exit 1
|
||||
fi
|
||||
echo "release ${tag} créée (id ${release_id})."
|
||||
else
|
||||
echo "release ${tag} trouvée (id ${release_id})."
|
||||
fi
|
||||
|
||||
# --- attache des fichiers ----------------------------------------------------------------------
|
||||
failed=0
|
||||
for f in "$@"; do
|
||||
[ -f "$f" ] || continue
|
||||
name=$(basename "$f")
|
||||
# L'API Gitea refuse un asset de même nom : on supprime l'ancien pour que le dernier build gagne.
|
||||
existing=$(curl -fsSL -H "$auth" "${api}/releases/${release_id}/assets" \
|
||||
| node -e "const a=JSON.parse(require('fs').readFileSync(0,'utf8'));const m=Array.isArray(a)?a.find(x=>x.name===process.argv[1]):null;process.stdout.write(m?String(m.id):'')" "$name" || true)
|
||||
http_call -H "$auth" "${api}/releases/${release_id}/assets" > /dev/null
|
||||
existing=$(node -e "let s='';process.stdin.on('data',(d)=>{s+=d}).on('end',()=>{try{const a=JSON.parse(s);const m=Array.isArray(a)?a.find((x)=>x.name===process.argv[1]):null;process.stdout.write(m?String(m.id):'')}catch{process.stdout.write('')}})" "$name" < "$body")
|
||||
if [ -n "$existing" ]; then
|
||||
echo "replacing existing $name (asset $existing)"
|
||||
curl -fsSL -X DELETE -H "$auth" "${api}/releases/${release_id}/assets/${existing}" || true
|
||||
echo "remplacement de $name (asset $existing)"
|
||||
http_call -X DELETE -H "$auth" "${api}/releases/${release_id}/assets/${existing}" > /dev/null
|
||||
fi
|
||||
echo "attaching $name"
|
||||
if ! curl -fsSL -X POST -H "$auth" -F "attachment=@${f}" "${api}/releases/${release_id}/assets?name=${name}"; then
|
||||
echo "::error::échec de l'upload de ${name}"
|
||||
upload_code=$(http_call -X POST -H "$auth" -F "attachment=@${f}" "${api}/releases/${release_id}/assets?name=${name}")
|
||||
if [ "$upload_code" -ge 200 ] && [ "$upload_code" -lt 300 ]; then
|
||||
echo "attaché : $name"
|
||||
else
|
||||
echo "::error::échec de l'upload de ${name} (HTTP ${upload_code}) : $(head -c 200 "$body")"
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${failed:-0}" != "0" ]; then
|
||||
if [ "$failed" != "0" ]; then
|
||||
echo "::error::au moins un asset n'a pas pu être attaché à ${tag}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user