fix(cli): render the literal [suffix] in --tag help and rejection message - #3800
Open
jawwad-ali wants to merge 1 commit into
Open
fix(cli): render the literal [suffix] in --tag help and rejection message#3800jawwad-ali wants to merge 1 commit into
[suffix] in --tag help and rejection message#3800jawwad-ali wants to merge 1 commit into
Conversation
…sage
Both places a user learns the `specify self upgrade --tag` syntax silently drop
the `[suffix]` token, because Rich parses the literal square brackets as a
markup tag and discards them:
rejected tag -> "Invalid --tag: expected vMAJOR.MINOR.PATCH"
(constant is "Invalid --tag: expected vMAJOR.MINOR.PATCH[suffix]")
--help -> "Pin the target version (vX.Y.Z). Without --tag, ..."
So the CLI implies a bare vX.Y.Z is the ONLY accepted form, when v1.0.0-rc1,
v0.8.0.dev0 and v0.8.0+build.42 are all valid -- and the shipped docs advertise
the suffix in four places (docs/upgrade.md x3, README.md x2).
Escape the rejection message at the PRINT site rather than baking `\[` into
_INVALID_TAG_MESSAGE: the same constant is raised through typer.BadParameter,
which Click renders without Rich, so it must stay plain text. Escape the literal
bracket in the option help, which Typer renders through Rich.
Same literal-bracket class as the existing precedents in workflows/_commands.py
(`\[disabled]`, `\[<type>]`). Static CLI text only -- no validation semantics
change and `_validate_tag` is untouched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jawwad-ali
force-pushed
the
fix/tag-suffix-literal-brackets
branch
from
July 28, 2026 14:57
6f04536 to
49c17cc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Both places a user learns the
specify self upgrade --tagsyntax silently drop the[suffix]token, because Rich parses the literal square brackets as a markup tag and discards them.1. The rejection message (
_INVALID_TAG_MESSAGE, printed viaconsole.print(str(exc))):The constant itself is intact —
'Invalid --tag: expected vMAJOR.MINOR.PATCH[suffix]'— so Rich is the culprit.2. The
--tagoption help (Typer renders help through the same Rich pipeline):So the CLI implies a bare
vX.Y.Zis the only accepted form, whenv1.0.0-rc1,v0.8.0.dev0andv0.8.0+build.42are all valid — and the shipped docs advertise the suffix in four places (docs/upgrade.md×3,README.md×2). The CLI contradicts its own documentation.Fix
_INVALID_TAG_MESSAGEis also raised throughtyper.BadParameter(three call sites), which Click renders without Rich — baking\[into the constant would leak a stray backslash there. So_INVALID_TAG_MESSAGEstays byte-identical and the existing assertion on it keeps passing.vX.Y.Z\[suffix]), since Typer renders it through Rich.Same literal-bracket class as the existing precedents in
workflows/_commands.py(\[disabled],\[<type>]).After:
Verification
test_rejection_message_keeps_the_suffix_tokenandtest_tag_option_help_keeps_the_suffix_token: both fail before, pass after.tests/test_self_upgrade_verification.py: 42 passed (40 pre-existing untouched, includingtest_invalid_tags_rejected).uvx ruff@0.15.0 check src testsclean.Static CLI text only — no validation semantics change,
_validate_taguntouched, valid tags behave identically.AI-assisted: authored with Claude Code. I confirmed the constant was intact and Rich was eating the token (rather than assuming a typo), and checked why escaping belongs at the print site instead of in the shared constant.