From d3ede461f6543cdd647b71881abf93eee250ab81 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 03:32:40 +0000 Subject: [PATCH] ci(release-please): promote graduated releases to GitHub full release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release-please marks every release it creates with prerelease=true because of the repo-level "prerelease": true flag (which is correct for rc tags but wrong for graduated vX.Y.Z tags). Add a post-release step in the dispatch-publish job that, for tags with no prerelease suffix (no '-' in the version string), flips the GitHub release's prerelease flag to false and — iff this is the highest stable semver — marks it as the repo's "Latest release". The highest-stable computation mirrors ci.yaml's versions job exactly (same tag glob, same '-' filter, same sort -V | tail), so the GitHub release's "Latest" flag stays in lockstep with the OCI ":latest" pointer on the image and chart. Co-Authored-By: kyle_hunter@bcit.ca --- .github/workflows/release-please.yaml | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index 738a4db..879d943 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -51,6 +51,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + with: + # Full history + tags needed for the highest-stable computation + # in the "Promote graduated release" step below. + fetch-depth: 0 - name: Ensure ci.yaml has a workflow_dispatch trigger run: | @@ -71,3 +75,51 @@ jobs: fi echo "Dispatching ci.yaml on tag ref: ${TAG}" gh workflow run ci.yaml --ref "${TAG}" + + # ── Promote graduated releases from Pre-release → Latest ──── + # + # release-please-config.json sets repo-level `"prerelease": true`, + # which makes release-please mark EVERY GitHub release it creates + # (rc AND graduated full-release) with prerelease=true. That is + # correct for rc tags (vX.Y.Z-rcN) but wrong for graduated stable + # tags (vX.Y.Z), which should appear as full releases in the + # GitHub UI and — iff this is the highest stable semver — as + # "Latest release". + # + # We fix this after the fact: whenever the just-created tag has + # no prerelease suffix (no `-` in the version), flip the GitHub + # release's `prerelease` flag to false and, iff this is the + # highest stable semver, set it as the repo's "Latest release". + # This mirrors the OCI-publish logic in ci.yaml's `versions` job + # exactly (same tag glob, same `-`-filter, same `sort -V | tail`), + # so the GitHub release's "Latest" flag tracks the image/chart + # `:latest` pointer. + - name: Promote graduated release to full release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ needs.release-please.outputs.tag_name }} + run: | + set -euo pipefail + if [[ -z "${TAG}" ]]; then + echo "::warning::release-please reported a release but no tag_name output; skipping promote" + exit 0 + fi + VERSION="${TAG#v}" + if [[ "${VERSION}" == *-* ]]; then + echo "Tag ${TAG} is a prerelease (contains '-'); leaving GitHub release flags as-is." + exit 0 + fi + + HIGHEST_STABLE=$(git tag -l "v[0-9]*.[0-9]*.[0-9]*" \ + | grep -v -- '-' \ + | sed "s/^v//" \ + | sort -V \ + | tail -n1) + + if [[ "${VERSION}" == "${HIGHEST_STABLE}" ]]; then + echo "Promoting ${TAG}: prerelease=false, latest=true (highest stable)." + gh release edit "${TAG}" --prerelease=false --latest=true + else + echo "Promoting ${TAG}: prerelease=false, latest=false (backport below highest stable ${HIGHEST_STABLE})." + gh release edit "${TAG}" --prerelease=false --latest=false + fi