From 78492d11e73f14336547d637d44f2c56f3155437 Mon Sep 17 00:00:00 2001 From: GnomeZworc Date: Mon, 17 Aug 2026 21:15:30 +0200 Subject: [PATCH] main: ci: update release jobs Signed-off-by: GnomeZworc --- .../{prerelease.yml => release-pipeline.yml} | 27 ++++++-- .forgejo/workflows/release.yml | 64 +++++++++++++++---- 2 files changed, 74 insertions(+), 17 deletions(-) rename .forgejo/workflows/{prerelease.yml => release-pipeline.yml} (76%) diff --git a/.forgejo/workflows/prerelease.yml b/.forgejo/workflows/release-pipeline.yml similarity index 76% rename from .forgejo/workflows/prerelease.yml rename to .forgejo/workflows/release-pipeline.yml index e648f9b..aad37ff 100644 --- a/.forgejo/workflows/prerelease.yml +++ b/.forgejo/workflows/release-pipeline.yml @@ -1,15 +1,23 @@ -name: Pre Release Workflow +name: Release Pipeline +# Un seul pipeline pour les préversions et les releases finales : les cinq jobs +# (cible, build, assets, manifeste, publication) sont identiques dans les deux +# cas, seul le drapeau `prerelease` change. Le dupliquer dans un second fichier +# recopierait tout pour une ligne de différence. +# +# Le filtre `[0-9]*` couvre les deux formes de tag (0.1.0, 0.1.0rc016) tout en +# ignorant les tags de travail qui ne commencent pas par un chiffre. on: push: tags: - - '*rc*' + - '[0-9]*' jobs: set-release-target: runs-on: docker outputs: release_cible: ${{ steps.setvar.outputs.release_cible }} + prerelease: ${{ steps.setvar.outputs.prerelease }} steps: - name: Déterminer la release cible id: setvar @@ -23,8 +31,18 @@ jobs: echo "release_cible=unknown" >> $GITHUB_OUTPUT fi + # Un tag contenant « rc » est une préversion ; tout le reste est une + # release finale, qui exige des notes (cf. release.yml). + if [[ "${GITHUB_REF#refs/tags/}" == *rc* ]]; then + echo "prerelease=true" >> $GITHUB_OUTPUT + else + echo "prerelease=false" >> $GITHUB_OUTPUT + fi + - name: Afficher la variable - run: echo "Release cible = ${{ steps.setvar.outputs.release_cible }}" + run: | + echo "Release cible = ${{ steps.setvar.outputs.release_cible }}" + echo "Prerelease = ${{ steps.setvar.outputs.prerelease }}" build: needs: [set-release-target] strategy: @@ -97,7 +115,7 @@ jobs: with: name: SHA256SUMS-${{ needs.set-release-target.outputs.release_cible }} path: SHA256SUMS - prerelease: + publish: # Tous les producteurs d'artefacts sont dans les needs : sans ça, le job # release peut appeler download-artifact avant la fin des uploads et publier # une release incomplète (assets ou manifeste manquants de façon non @@ -106,4 +124,5 @@ jobs: uses: ./.forgejo/workflows/release.yml with: tag: ${{ needs.set-release-target.outputs.release_cible }} + prerelease: ${{ needs.set-release-target.outputs.prerelease }} secrets: inherit diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index efc7694..8372c80 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -4,6 +4,9 @@ on: tag: required: true type: string + prerelease: + required: true + type: string jobs: release: @@ -11,7 +14,9 @@ jobs: env: TOKEN: ${{ secrets.RELEASE }} TAG: ${{ inputs.tag }} + PRERELEASE: ${{ inputs.prerelease }} steps: + - uses: actions/checkout@v3 - name: Download all build artifacts uses: actions/download-artifact@v3 with: @@ -22,21 +27,50 @@ jobs: run: | apt-get update apt-get install -y jq - - name: Create prerelease + - name: Préparer les notes de version run: | - curl -X POST \ - -H "Authorization: token $TOKEN" \ + NOTES="release_notes/${TAG}.md" + if [[ -f "${NOTES}" ]] + then + echo "notes trouvées : ${NOTES}" + cp "${NOTES}" body.md + elif [[ "${PRERELEASE}" == "true" ]] + then + echo "aucune note pour ${TAG}, texte générique (préversion)" + echo "Prerelease automatique générée par la CI" > body.md + else + echo "release finale ${TAG} sans notes de version" >&2 + echo "créer ${NOTES} avant de pousser le tag" >&2 + exit 1 + fi + echo "--- body ---"; cat body.md + - name: Create release + run: | + jq -n \ + --arg tag "${TAG}" \ + --rawfile body body.md \ + --argjson prerelease "${PRERELEASE}" \ + '{ + tag_name: $tag, + name: $tag, + body: $body, + draft: false, + prerelease: $prerelease, + hide_archive_links: true + }' > payload.json + cat payload.json | jq -c '.body |= (.[0:60] + "…")' + + # Code HTTP vérifié explicitement plutôt qu'avec --fail-with-body, qui + # exige curl >= 7.76 : sans ça un échec (409 tag déjà publié, 401 token + # invalide) passerait inaperçu et la release resterait sans assets. + HTTP=$(curl -sS -o resp.json -w '%{http_code}' -X POST \ + -H "Authorization: token ${TOKEN}" \ -H "Content-Type: application/json" \ "https://git.g3e.fr/api/v1/repos/${{ github.repository }}/releases" \ - -d @- <&2; exit 1; } - name: Upload asset run: | RELEASE_ID=$(curl -s \ @@ -44,6 +78,10 @@ jobs: https://git.g3e.fr/api/v1/repos/${{ github.repository }}/releases/tags/${TAG} \ | jq -r .id) echo ${RELEASE_ID} + # Sans ce garde-fou, un id absent (null) enverrait chaque asset sur + # .../releases/null/assets : une cascade de 404 silencieux et une + # release publiée sans aucun binaire. + [[ "${RELEASE_ID}" =~ ^[0-9]+$ ]] || { echo "id de release introuvable pour ${TAG}" >&2; exit 1; } ls dist | while read tmp do FILE=$(ls "./dist/${tmp}") @@ -53,4 +91,4 @@ jobs: -H "Content-Type: application/octet-stream" \ --data-binary @dist/${tmp}/${FILE} \ "https://git.g3e.fr/api/v1/repos/${{ github.repository }}/releases/${RELEASE_ID}/assets?name=${FILE}" - done \ No newline at end of file + done