diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 740d905..0920ac2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -184,6 +184,16 @@ jobs: VERSION: ${{ steps.version.outputs.version }} run: | TAG="v$VERSION" + # A SemVer pre-release label (anything after '-') marks the GitHub Release as a pre-release, + # matching how NuGet lists it, so a preview never shows up as the repo's "Latest" release. + # Build metadata '+...' is already rejected in "Resolve version", so a '-' here is + # unambiguously the pre-release separator (-preview.1, -beta.1, -rc.1, ...). + PRERELEASE=false + case "$VERSION" in *-*) PRERELEASE=true ;; esac + # On a re-run the release already exists, so `gh release create` fails and the fallback + # runs: `gh release upload` refreshes the assets but cannot change the prerelease flag, + # so `gh release edit` reconciles it — keeping a repair run idempotent in both directions. gh release create "$TAG" artifacts/*.nupkg artifacts/*.snupkg \ - --title "$TAG" --generate-notes --target "$GITHUB_SHA" \ - || gh release upload "$TAG" artifacts/*.nupkg artifacts/*.snupkg --clobber + --title "$TAG" --generate-notes --target "$GITHUB_SHA" --prerelease="$PRERELEASE" \ + || { gh release upload "$TAG" artifacts/*.nupkg artifacts/*.snupkg --clobber \ + && gh release edit "$TAG" --prerelease="$PRERELEASE"; } diff --git a/maintainers/workflows/release.en.md b/maintainers/workflows/release.en.md index 4568aae..a0d1198 100644 --- a/maintainers/workflows/release.en.md +++ b/maintainers/workflows/release.en.md @@ -28,6 +28,27 @@ skipping the publish steps. - On **`workflow_dispatch`** with two inputs: `version` and `dry_run` (**default `true`**). A manual run publishes only if `dry_run` is explicitly unticked. +## Pre-release labels + +The version is a SemVer string (a tag's leading `v` is stripped). A **stable** release +has no label (`1.4.2`); anything after a `-` is a **pre-release** label, which the +workflow flags as a pre-release on GitHub — and which nuget.org lists the same way. +Common labels, from least to most mature: + +| Label | Meaning | +| - | - | +| `alpha` | Earliest phase — incomplete features, unstable, API may change wholesale. Internal / very-early testers; expect breakage. | +| `beta` | Feature-frozen but still stabilising; the API may still shift at the edges. Open to a wider audience for feedback. | +| `preview` | The .NET-flavoured term (≈ beta / early access). The label this project uses for its previews, e.g. `0.1.0-preview.1`. | +| `rc` | Release candidate — the final build unless a blocker turns up; critical fixes only, no new features. Promoted to stable as-is. | +| `nightly` / `dev` / `canary` | Automated bleeding-edge builds (nightly or per-commit), uncurated. Not part of this project's tag-driven release flow — listed for reference. | +| `dry` | Not a real release: this repo's convention for the manual dry-run placeholder (`0.0.0-dry.1`, the `version` input's example). Never published. | + +SemVer precedence: a pre-release always sorts **below** its stable (`1.0.0-rc.1` < `1.0.0`), +and labels compare alphanumerically, so `-preview.1` < `-preview.2`. On nuget.org these +never install by default — a consumer needs `--prerelease`, which is why the README badge +uses `nuget/vpre`. + ## How it runs One job, `pack-push`: checkout → setup .NET → **resolve & validate version** → @@ -82,6 +103,11 @@ deliberate: --clobber` fallback keeps a re-run idempotent. - **`concurrency` sets `cancel-in-progress: false`.** Never cancel a half-finished publish. +- **The GitHub Release is flagged `--prerelease` when the version carries a + SemVer pre-release label** (any `-…`, e.g. `-preview.1`, `-beta.1`, `-rc.1`), + so a preview never appears as the repository's "Latest" release. Build + metadata (`+…`) is rejected upstream, so a `-` is unambiguously the + pre-release marker — this matches how nuget.org lists the same package. ## Related diff --git a/maintainers/workflows/release.fr.md b/maintainers/workflows/release.fr.md index 6e7e16c..64eac84 100644 --- a/maintainers/workflows/release.fr.md +++ b/maintainers/workflows/release.fr.md @@ -28,6 +28,27 @@ l'attestation incluse tout en sautant les étapes de publication. - Sur **`workflow_dispatch`** avec deux entrées : `version` et `dry_run` (**défaut `true`**). Un run manuel ne publie que si `dry_run` est explicitement décoché. +## Étiquettes de pré-version + +La version est une chaîne SemVer (le `v` d'un tag est retiré). Une release **stable** +n'a pas d'étiquette (`1.4.2`) ; tout ce qui suit un `-` est une étiquette de +**pré-version**, que le workflow marque comme pre-release sur GitHub — et que nuget.org +liste de la même façon. Étiquettes courantes, du moins mûr au plus mûr : + +| Étiquette | Signification | +| - | - | +| `alpha` | Toute première phase — fonctionnalités incomplètes, instable, API pouvant changer du tout au tout. Test interne / adopteurs très précoces ; cassures attendues. | +| `beta` | Périmètre gelé mais encore en stabilisation ; l'API peut bouger à la marge. Ouverte à un public plus large pour retours. | +| `preview` | Le terme « à la .NET » (≈ beta / accès anticipé). L'étiquette que ce projet utilise pour ses previews, p. ex. `0.1.0-preview.1`. | +| `rc` | Release candidate — la version finale sauf blocage ; correctifs critiques uniquement, aucune nouvelle fonctionnalité. Promue stable telle quelle. | +| `nightly` / `dev` / `canary` | Builds automatiques « bleeding edge » (chaque nuit ou chaque commit), non curés. Ne font pas partie du flux de release piloté par tag de ce projet — listés pour référence. | +| `dry` | Pas une vraie release : la convention de ce dépôt pour le placeholder du dry-run (`0.0.0-dry.1`, l'exemple de l'input `version`). Jamais publiée. | + +Précédence SemVer : une pré-version se classe **toujours sous** son stable +(`1.0.0-rc.1` < `1.0.0`), et les étiquettes se comparent alphanumériquement, donc +`-preview.1` < `-preview.2`. Sur nuget.org, elles ne s'installent jamais par défaut — +un consommateur doit passer `--prerelease`, d'où le badge README en `nuget/vpre`. + ## Comment il s'exécute Un seul job, `pack-push` : checkout → setup .NET → **résoudre & valider la @@ -87,6 +108,12 @@ suivants est délibéré : `|| … upload --clobber` garde un re-run idempotent. - **`concurrency` met `cancel-in-progress: false`.** Ne jamais annuler une publication à moitié faite. +- **La GitHub Release est marquée `--prerelease` quand la version porte une + étiquette de pré-version SemVer** (tout `-…`, p. ex. `-preview.1`, `-beta.1`, + `-rc.1`), pour qu'une preview n'apparaisse jamais comme la release « Latest » + du dépôt. Les métadonnées de build (`+…`) étant rejetées en amont, un `-` est + sans ambiguïté le marqueur de pré-version — c'est ainsi que nuget.org liste + le même package. ## En rapport