Skip to content

Mark pre-release versions as pre-releases in create-release - #4204

Draft
aleozlx wants to merge 1 commit into
flashinfer-ai:mainfrom
aleozlx:fix/release-mark-prerelease
Draft

aleozlx wants to merge 1 commit into
flashinfer-ai:mainfrom
aleozlx:fix/release-mark-prerelease

Conversation

@aleozlx

@aleozlx aleozlx commented Jul 28, 2026

Copy link
Copy Markdown
Member

📌 Description

create-release invokes:

gh release create "$TAG"   --title "Release v${{ needs.setup.outputs.version }}"   --notes "$NOTES"

with no --prerelease, so every tag becomes a full GitHub release. GitHub then treats the newest such release as the repository's "Latest release" and serves it from /releases/latest — so a release candidate supersedes the last stable release both on the repo page and for anything reading that endpoint programmatically.

This surfaced with v0.6.16rc3, the first rc ever to reach create-release (earlier rcs never got past the build jobs). It became "Latest release" and had to be re-flagged by hand.

Fix: derive the flag from the version string. Only PEP 440 pre-release suffixes (rc/a/b/alpha/beta/dev) qualify — .postN is a post-release of a stable version and must remain a full release.

Nightly releases are created elsewhere and already set prerelease correctly, so they are unaffected.

🔍 Related Issues

🚀 Pull Request Checklist

Thank you for contributing to FlashInfer! Before we review your pull request, please make sure the following items are complete.

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

If you are unsure about how to set up pre-commit, see the pre-commit documentation.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (`unittest`, etc.).

This is a workflow-only change with no unit-testable surface, so no tests were added. Verified two ways instead:

  1. The classifier was exercised directly against every relevant version form:
version result
0.6.16rc3 PRERELEASE
0.6.16a1 PRERELEASE
0.6.16b2 PRERELEASE
0.6.16.dev1 PRERELEASE
0.7.0rc1 PRERELEASE
0.6.16 full release
0.6.15 full release
0.6.16.post1 full release
1.2.3.post2 full release
  1. release.yml re-parsed as YAML after the edit; all 7 jobs still present.

Reviewer Notes

  • Accepted suffixes are a superset of what the workflow's own tag-format check allows (^v[0-9]+\.[0-9]+\.[0-9]+(\.?[a-z][a-z0-9]*)?$), so nothing that currently passes validation changes classification except actual pre-releases.
  • The --title now uses the \$VERSION shell variable rather than re-expanding the workflow output twice; behaviour is identical.
  • No effect on stable releases: they take the same path as before with an empty flag.
  • v0.6.16rc3 has already been corrected manually, so this only prevents recurrence.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Release Management
    • Releases with pre-release version suffixes are now automatically marked as pre-releases.
    • Release titles consistently display the computed version number.

gh release create is invoked without --prerelease, so every tag becomes a full
GitHub release. GitHub then reports the newest such release as the repository
"Latest release" and serves it from /releases/latest, so an rc supersedes the
last stable release for anyone browsing the repo or reading that endpoint
programmatically.

This surfaced with v0.6.16rc3, the first rc to reach create-release (earlier
rcs never got past the build jobs): it became "Latest release" and had to be
re-flagged by hand.

Derive the flag from the version string. Only PEP 440 pre-release suffixes
(rc/a/b/alpha/beta/dev) qualify -- .postN is a post-release of a stable
version and must remain a full release. Verified against 0.6.16rc3, 0.6.16,
0.6.16.post1, 0.6.16a1, 0.6.16b2, 0.6.16.dev1 and 1.2.3.post2.

Nightly releases are created elsewhere and already set prerelease correctly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The release workflow now detects common pre-release version suffixes, conditionally adds the --prerelease flag, and uses a computed version variable for the GitHub Release title.

Changes

Release workflow

Layer / File(s) Summary
Version classification and release creation
.github/workflows/release.yml
The workflow classifies versions using pre-release suffix patterns, conditionally passes --prerelease to gh release create, and uses VERSION for the release title.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: dierksen, bkryu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main workflow change: marking release candidates as pre-releases in create-release.
Description check ✅ Passed The description follows the template well, covering the change, related issue context, checklist items, tests, and reviewer notes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 296-301: Update the prerelease-gating condition in the VERSION
release classification to recognize every suffix accepted by the tag regex,
including c, pre, and preview alongside the existing aliases. Ensure valid PEP
440 prerelease tags such as c1 set PRERELEASE_FLAG to --prerelease rather than
being classified as full releases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e3a64e1c-a42b-48c3-b181-8a81f10379ab

📥 Commits

Reviewing files that changed from the base of the PR and between e1eb406 and fe181be.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Comment on lines +296 to +301
if [[ "$VERSION" =~ \.?(rc|a|b|alpha|beta|dev)[0-9]*$ ]]; then
PRERELEASE_FLAG="--prerelease"
echo "✓ $VERSION is a pre-release; marking it accordingly"
else
echo "✓ $VERSION is a full release"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== release workflow version logic =="
sed -n '260,315p' .github/workflows/release.yml 2>/dev/null || true

echo
echo "== version assignment/validation references =="
rg -n "VERSION|GITHUB_REF|gh release|\.?(rc|c|pre|preview|alpha|beta|dev|a|b)[0-9]*" .github/workflows/release.yml .github/workflows || true

echo
echo "== all workflow refs to VERSION =="
rg -n '\$\{?\$?VERSION' .github/workflows/release.yml .github/workflows 2>/dev/null | head -80 || true

Repository: flashinfer-ai/flashinfer

Length of output: 50381


🌐 Web query:

PEP 440 pre-release segment canonical spellings a b alpha beta rc c pre preview

💡 Result:

According to PEP 440, the canonical pre-release identifiers are "a" (alpha), "b" (beta), and "rc" (release candidate) [1][2]. While these are the standard canonical forms, PEP 440 allows several additional spellings for these segments that normalize to the canonical versions [1][3]: - "alpha" and "a" normalize to "a" [1][4]. - "beta" and "b" normalize to "b" [1][4]. - "c", "pre", and "preview" are all treated as equivalent to "rc" and normalize to "rc" [1][4]. In practice, these additional spellings are considered equivalent to their canonical forms, meaning versions like 1.1alpha1, 1.1beta2, and 1.1c3 normalize to 1.1a1, 1.1b2, and 1.1rc3, respectively [1][5]. Published version identifiers are encouraged to use the canonical format [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re

tag_re = re.compile(r'^v[0-9]+\.[0-9]+\.[0-9]+(\.?[a-z][a-z0-9]*)?$')
pre_re = re.compile(r'^\.?(rc|a|b|alpha|beta|dev)[0-9]*$', re.I)
missing = []
examples = [
    "v0.6.16c1",
    "v0.6.16.pre1",
    "v0.6.16.preview1",
    "v0.6.16.post1",
]
for v in examples:
    print(f"{v}: tag={tag_re.match(v).group() if tag_re.match(v) else 'NO'}, pre_re={bool(pre_re.search(v))}, all_rc_spellings={'c4c' in ['c' in v[2:] for v in [v]]}")
PY

echo
echo "== tag validation and prerelease matching with sample versions =="
python3 - <<'PY'
from pathlib import Path
from dataclasses import dataclass

`@dataclass`
class Case:
    version: str
    input_tag: str = ""

tag_re = re.compile(r'^v[0-9]+\.[0-9]+\.[0-9]+(\.?[a-z][a-z0-9]*)?$')
old_pre_re = re.compile(r'\.?(rc|a|b|alpha|beta|dev)[0-9]*$', re.I)

cases = [
    Case("0.6.16c1", "v0.6.16c1"),
    Case("1.2.3rc1"),
    Case("1.2.3alpha1"),
    Case("1.2.3beta1"),
    Case("1.2.3pre1"),
    Case("1.2.3preview1"),
    Case("1.2.3.post1", "v1.2.3.post1"),
]

for c in cases:
    tag = c.input_tag or f"v{c.version}"
    tag_ok = bool(tag_re.match(tag))
    prerelease_flag = "--prerelease" if old_pre_re.search(c.version) else ""
    post_flag = "--prerelease" if re.search(r'\.?post[0-9]+$', c.version) else ""
    print(f"version={c.version} tag={tag} tag_ok={tag_ok} prerelease={prerelease_flag} post_prerelease_flag={post_flag}")
PY

Repository: flashinfer-ai/flashinfer

Length of output: 618


Handle the full set of accepted PEP 440 pre-release suffixes.

The tag regex accepts c, pre, and preview variants, but the prerelease-gating regex only includes rc, a, b, alpha, beta, and dev. A valid tag like v0.6.16c1 would be created as a stable release instead of using --prerelease, which can make it serve as /releases/latest. Add these aliases, or narrow the supported version contract instead of calling it a full “PEP 440 pre-release” contract.

Proposed fix
-          if [[ "$VERSION" =~ \.?(rc|a|b|alpha|beta|dev)[0-9]*$ ]]; then
+          if [[ "$VERSION" =~ \.?(rc|c|pre、preview|a|b|alpha|beta|dev)[0-9]*$ ]]; then
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 296 - 301, Update the
prerelease-gating condition in the VERSION release classification to recognize
every suffix accepted by the tag regex, including c, pre, and preview alongside
the existing aliases. Ensure valid PEP 440 prerelease tags such as c1 set
PRERELEASE_FLAG to --prerelease rather than being classified as full releases.

@aleozlx
aleozlx marked this pull request as draft July 28, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant