rhiza_tools.cli
CLI commands for Rhiza Tools.
This module defines the main Typer application and all command-line interface commands for rhiza-tools. It provides commands for version bumping, coverage badge generation, release management, and README updates.
The CLI can be used either as a standalone tool (rhiza-tools) or as a
subcommand of the rhiza CLI (rhiza tools).
Example:
Bump version to a specific version::
$ rhiza-tools bump 1.2.3 $ rhiza tools bump 1.2.3Bump version interactively::
$ rhiza-tools bumpGenerate a coverage badge::
$ rhiza-tools generate-coverage-badge --coverage-json _tests/coverage.jsonUpdate README with make help output::
$ rhiza-tools update-readme
1"""CLI commands for Rhiza Tools. 2 3This module defines the main Typer application and all command-line interface 4commands for rhiza-tools. It provides commands for version bumping, coverage 5badge generation, release management, and README updates. 6 7The CLI can be used either as a standalone tool (`rhiza-tools`) or as a 8subcommand of the rhiza CLI (`rhiza tools`). 9 10Example: 11 Bump version to a specific version:: 12 13 $ rhiza-tools bump 1.2.3 14 $ rhiza tools bump 1.2.3 15 16 Bump version interactively:: 17 18 $ rhiza-tools bump 19 20 Generate a coverage badge:: 21 22 $ rhiza-tools generate-coverage-badge --coverage-json _tests/coverage.json 23 24 Update README with make help output:: 25 26 $ rhiza-tools update-readme 27""" 28 29from pathlib import Path 30from typing import Annotated 31 32import typer 33 34from rhiza_tools import __version__, console 35from rhiza_tools.console import configure as configure_console 36 37from .commands.analyze_benchmarks import analyze_benchmarks_command 38from .commands.bump import bump_command 39from .commands.generate_badge import generate_coverage_badge_command 40from .commands.release import release_command 41from .commands.rollback import rollback_command 42from .commands.update_readme import update_readme_command 43from .commands.version_matrix import version_matrix_command 44 45 46def version_callback(value: bool) -> None: 47 """Display the version and exit.""" 48 if value: 49 typer.echo(f"rhiza-tools version {__version__}") 50 raise typer.Exit() 51 52 53app = typer.Typer(help="Rhiza Tools - Extra utilities for Rhiza.") 54 55# Shared option so --verbose / -v works both before and after the subcommand. 56VERBOSE_OPTION = typer.Option(False, "--verbose", "-v", help="Show verbose debug output.") 57 58 59def _apply_verbose(verbose: bool) -> None: 60 """Enable verbose output if the flag was passed on the subcommand.""" 61 if verbose: 62 configure_console(verbose=True) 63 64 65@app.callback() 66def main( 67 version: bool = typer.Option( 68 None, 69 "--version", 70 help="Show the version and exit.", 71 callback=version_callback, 72 is_eager=True, 73 ), 74 verbose: bool = VERBOSE_OPTION, 75) -> None: 76 """Rhiza Tools - Extra utilities for Rhiza.""" 77 configure_console(verbose=verbose) 78 79 80@app.command() 81def bump( 82 version: str | None = typer.Argument(None, help="The version to bump to (e.g., 1.0.1, major, minor, patch, etc)"), 83 language: str | None = typer.Option( 84 None, "--language", "-l", help="Programming language (python or go). Auto-detected if not specified." 85 ), 86 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 87 commit: bool = typer.Option(False, "--commit", help="Commit the changes to git."), 88 push: bool = typer.Option(False, "--push", help="Push changes to remote after commit (implies --commit)."), 89 branch: str | None = typer.Option( 90 None, "--branch", help="Branch to perform the bump on (default: current branch)." 91 ), 92 allow_dirty: bool = typer.Option( 93 False, "--allow-dirty", help="Allow bumping even if the working directory is dirty." 94 ), 95 verbose: bool = VERBOSE_OPTION, 96) -> None: 97 """Bump the version of the project. 98 99 This command updates the version for Python (pyproject.toml) or Go (VERSION file) 100 projects using semantic versioning. You can provide an explicit version number, 101 a bump type (patch, minor, major), or leave it blank for an interactive prompt. 102 103 Args: 104 version: The version to bump to. Can be an explicit version (e.g., "1.2.3"), 105 a bump type ("patch", "minor", "major"), a prerelease type 106 ("alpha", "beta", "rc", "dev"), or None for interactive selection. 107 language: Programming language (python or go). Auto-detected if not specified. 108 dry_run: If True, show what would change without actually changing anything. 109 commit: If True, automatically commit the version change to git. 110 push: If True, push changes to remote after commit (implies --commit). 111 branch: Branch to perform the bump on (default: current branch). 112 allow_dirty: If True, allow bumping even with uncommitted changes. 113 verbose: If True, enable verbose debug output. 114 115 Example: 116 Bump to a specific version:: 117 118 $ rhiza-tools bump 2.0.0 119 120 Bump patch version (1.2.3 -> 1.2.4):: 121 122 $ rhiza-tools bump patch 123 124 Bump a Go project explicitly:: 125 126 $ rhiza-tools bump minor --language go 127 128 Preview changes without applying them:: 129 130 $ rhiza-tools bump minor --dry-run 131 132 Interactive version selection:: 133 134 $ rhiza-tools bump 135 136 Bump and push to remote:: 137 138 $ rhiza-tools bump minor --push 139 """ 140 _apply_verbose(verbose) 141 from rhiza_tools.commands.bump import BumpOptions, Language 142 143 # Parse language if provided 144 lang_enum = None 145 if language: 146 try: 147 lang_enum = Language(language.lower()) 148 except ValueError: 149 console.error(f"Invalid language: {language}") 150 console.error("Supported languages: python, go") 151 raise typer.Exit(code=1) from None 152 153 options = BumpOptions( 154 version=version, 155 dry_run=dry_run, 156 commit=commit, 157 push=push, 158 branch=branch, 159 allow_dirty=allow_dirty, 160 language=lang_enum, 161 ) 162 bump_command(options) 163 164 165@app.command() 166def generate_coverage_badge( 167 coverage_json: Annotated[ 168 Path, 169 typer.Option( 170 "--coverage-json", 171 help="Path to coverage.json file", 172 ), 173 ] = Path("_tests/coverage.json"), 174 output: Annotated[ 175 Path, 176 typer.Option( 177 help="Path to output badge JSON", 178 ), 179 ] = Path("_book/tests/coverage-badge.json"), 180 verbose: bool = VERBOSE_OPTION, 181) -> None: 182 """Generate a coverage badge for the project. 183 184 Reads a coverage report JSON file and creates a shields.io endpoint JSON file 185 for displaying a coverage badge. The badge color automatically adjusts based 186 on the coverage percentage. 187 188 Args: 189 coverage_json: Path to the coverage.json file generated by pytest-cov. 190 output: Path where the badge JSON file should be written. 191 verbose: If True, enable verbose debug output. 192 193 Example: 194 Generate badge with default paths:: 195 196 $ rhiza-tools generate-coverage-badge 197 198 Generate badge with custom paths:: 199 200 $ rhiza-tools generate-coverage-badge \ 201 --coverage-json tests/coverage.json \ 202 --output assets/badge.json 203 """ 204 _apply_verbose(verbose) 205 generate_coverage_badge_command(coverage_json_path=coverage_json, output_path=output) 206 207 208@app.command() 209def release( 210 bump: str | None = typer.Option(None, "--bump", help="Bump type (MAJOR, MINOR, PATCH) before release."), 211 with_bump: bool = typer.Option( 212 False, 213 "--with-bump", 214 help="Interactively select bump type before release (works with --dry-run).", 215 ), 216 push: bool = typer.Option(False, "--push", help="Push changes to remote (default: prompt in interactive mode)."), 217 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 218 non_interactive: bool = typer.Option(False, "--non-interactive", "-y", help="Skip all confirmation prompts."), 219 language: str | None = typer.Option( 220 None, "--language", "-l", help="Programming language (python or go). Auto-detected if not specified." 221 ), 222 verbose: bool = VERBOSE_OPTION, 223) -> None: 224 """Push a release tag to remote to trigger the release workflow. 225 226 This command validates the repository state and pushes the git tag for the 227 current version to the remote repository, which triggers the automated release 228 workflow. Supports Python projects (pyproject.toml) and Go projects 229 (go.mod + VERSION file). The project language is auto-detected when not 230 explicitly specified. 231 232 Args: 233 bump: Bump type (MAJOR, MINOR, PATCH) to apply before release. 234 with_bump: If True, interactively select bump type before release. 235 push: If True, push changes without prompting (implies non-interactive for push). 236 dry_run: If True, show what would happen without actually pushing the tag. 237 non_interactive: If True, skip all confirmation prompts (useful for CI/CD). 238 language: Programming language (python or go). Auto-detected if not specified. 239 verbose: If True, enable verbose debug output. 240 241 Example: 242 Push a release tag (with prompts):: 243 244 $ rhiza-tools release 245 246 Preview what would happen:: 247 248 $ rhiza-tools release --dry-run 249 250 Non-interactive mode (for CI/CD):: 251 252 $ rhiza-tools release --non-interactive 253 254 Bump version and release:: 255 256 $ rhiza-tools release --bump MINOR --push 257 258 Interactive bump with dry-run preview:: 259 260 $ rhiza-tools release --with-bump --push --dry-run 261 262 Release a Go project:: 263 264 $ rhiza-tools release --language go 265 """ 266 _apply_verbose(verbose) 267 from rhiza_tools.commands.bump import Language 268 269 lang_enum = None 270 if language: 271 try: 272 lang_enum = Language(language.lower()) 273 except ValueError: 274 console.error(f"Invalid language: {language}") 275 console.error("Supported languages: python, go") 276 raise typer.Exit(code=1) from None 277 278 release_command(bump, push, dry_run, non_interactive, with_bump, lang_enum) 279 280 281@app.command() 282def rollback( 283 tag: str | None = typer.Argument(None, help="Tag to rollback (e.g., v1.2.3). Interactive if omitted."), 284 revert_bump: bool = typer.Option(False, "--revert-bump", help="Also revert the version bump commit."), 285 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 286 non_interactive: bool = typer.Option(False, "--non-interactive", "-y", help="Skip all confirmation prompts."), 287 verbose: bool = VERBOSE_OPTION, 288) -> None: 289 """Rollback a release and/or version bump. 290 291 This command safely reverses release and bump operations by deleting 292 the release tag from local and remote repositories, and optionally 293 reverting the version bump commit. 294 295 It uses ``git revert`` rather than ``git reset``, making it safe 296 even when changes have already been pushed to remote. 297 298 Args: 299 tag: The tag to rollback (e.g., "v1.2.3"). If omitted, an interactive 300 menu shows recent tags to choose from. 301 revert_bump: If True, also revert the version bump commit associated 302 with the tag. 303 dry_run: If True, show what would happen without actually making changes. 304 non_interactive: If True, skip all confirmation prompts (useful for CI/CD). 305 verbose: If True, enable verbose debug output. 306 307 Example: 308 Rollback the most recent release interactively:: 309 310 $ rhiza-tools rollback 311 312 Preview rollback of a specific tag:: 313 314 $ rhiza-tools rollback v1.2.3 --dry-run 315 316 Fully rollback including the bump commit:: 317 318 $ rhiza-tools rollback v1.2.3 --revert-bump 319 320 Non-interactive rollback (for CI/CD):: 321 322 $ rhiza-tools rollback v1.2.3 --revert-bump -y 323 """ 324 _apply_verbose(verbose) 325 from rhiza_tools.commands.rollback import RollbackOptions 326 327 options = RollbackOptions( 328 tag=tag, 329 revert_bump=revert_bump, 330 dry_run=dry_run, 331 non_interactive=non_interactive, 332 ) 333 rollback_command(options) 334 335 336@app.command(name="update-readme") 337def update_readme( 338 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 339 verbose: bool = VERBOSE_OPTION, 340) -> None: 341 """Update README.md with the current output from `make help`. 342 343 This command runs `make help` and updates the README.md file with the current 344 help output, keeping the documentation in sync with available Make targets. 345 346 Args: 347 dry_run: If True, show the help output that would be inserted without 348 actually modifying README.md. 349 verbose: If True, enable verbose debug output. 350 351 Example: 352 Update README with make help output:: 353 354 $ rhiza-tools update-readme 355 356 Preview changes without modifying README:: 357 358 $ rhiza-tools update-readme --dry-run 359 """ 360 _apply_verbose(verbose) 361 update_readme_command(dry_run) 362 363 364@app.command(name="version-matrix") 365def version_matrix( 366 pyproject: Annotated[ 367 Path, 368 typer.Option( 369 "--pyproject", 370 help="Path to pyproject.toml file", 371 ), 372 ] = Path("pyproject.toml"), 373 candidates: Annotated[ 374 str | None, 375 typer.Option( 376 "--candidates", 377 help="Comma-separated list of candidate Python versions (e.g., '3.11,3.12,3.13')", 378 ), 379 ] = None, 380 verbose: bool = VERBOSE_OPTION, 381) -> None: 382 """Emit supported Python versions from pyproject.toml as JSON. 383 384 This command reads the requires-python field from pyproject.toml and outputs 385 a JSON array of Python versions that satisfy the constraint. This is primarily 386 used in GitHub Actions to compute the test matrix. 387 388 Args: 389 pyproject: Path to the pyproject.toml file. 390 candidates: Comma-separated list of candidate Python versions to evaluate. 391 Defaults to "3.11,3.12,3.13,3.14". 392 verbose: If True, enable verbose debug output. 393 394 Example: 395 Get supported versions with defaults:: 396 397 $ rhiza-tools version-matrix 398 ["3.11", "3.12"] 399 400 Use custom pyproject.toml path:: 401 402 $ rhiza-tools version-matrix --pyproject /path/to/pyproject.toml 403 404 Use custom candidates:: 405 406 $ rhiza-tools version-matrix --candidates "3.10,3.11,3.12" 407 """ 408 _apply_verbose(verbose) 409 candidates_list = None 410 if candidates: 411 candidates_list = [v.strip() for v in candidates.split(",")] 412 413 version_matrix_command(pyproject_path=pyproject, candidates=candidates_list) 414 415 416@app.command(name="analyze-benchmarks") 417def analyze_benchmarks( 418 benchmarks_json: Annotated[ 419 Path, 420 typer.Option( 421 "--benchmarks-json", 422 help="Path to benchmarks.json file", 423 ), 424 ] = Path("_benchmarks/benchmarks.json"), 425 output_html: Annotated[ 426 Path, 427 typer.Option( 428 "--output-html", 429 help="Path to save HTML visualization", 430 ), 431 ] = Path("_benchmarks/benchmarks.html"), 432 verbose: bool = VERBOSE_OPTION, 433) -> None: 434 """Analyze pytest-benchmark results and visualize them. 435 436 This command reads a benchmarks.json file produced by pytest-benchmark, 437 prints a table with benchmark name, mean milliseconds, and operations per 438 second, and generates an interactive Plotly bar chart of mean runtimes. 439 440 Note: This command requires pandas and plotly. Install with: 441 uv pip install -e '.[dev]' or pip install 'rhiza-tools[dev]' 442 443 Args: 444 benchmarks_json: Path to the benchmarks.json file. 445 output_html: Path where the HTML visualization should be saved. 446 verbose: If True, enable verbose debug output. 447 448 Example: 449 Analyze benchmarks with default paths:: 450 451 $ rhiza-tools analyze-benchmarks 452 453 Use custom paths:: 454 455 $ rhiza-tools analyze-benchmarks \ 456 --benchmarks-json tests/benchmarks.json \ 457 --output-html reports/benchmarks.html 458 """ 459 _apply_verbose(verbose) 460 analyze_benchmarks_command(benchmarks_json=benchmarks_json, output_html=output_html)
47def version_callback(value: bool) -> None: 48 """Display the version and exit.""" 49 if value: 50 typer.echo(f"rhiza-tools version {__version__}") 51 raise typer.Exit()
Display the version and exit.
66@app.callback() 67def main( 68 version: bool = typer.Option( 69 None, 70 "--version", 71 help="Show the version and exit.", 72 callback=version_callback, 73 is_eager=True, 74 ), 75 verbose: bool = VERBOSE_OPTION, 76) -> None: 77 """Rhiza Tools - Extra utilities for Rhiza.""" 78 configure_console(verbose=verbose)
Rhiza Tools - Extra utilities for Rhiza.
81@app.command() 82def bump( 83 version: str | None = typer.Argument(None, help="The version to bump to (e.g., 1.0.1, major, minor, patch, etc)"), 84 language: str | None = typer.Option( 85 None, "--language", "-l", help="Programming language (python or go). Auto-detected if not specified." 86 ), 87 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 88 commit: bool = typer.Option(False, "--commit", help="Commit the changes to git."), 89 push: bool = typer.Option(False, "--push", help="Push changes to remote after commit (implies --commit)."), 90 branch: str | None = typer.Option( 91 None, "--branch", help="Branch to perform the bump on (default: current branch)." 92 ), 93 allow_dirty: bool = typer.Option( 94 False, "--allow-dirty", help="Allow bumping even if the working directory is dirty." 95 ), 96 verbose: bool = VERBOSE_OPTION, 97) -> None: 98 """Bump the version of the project. 99 100 This command updates the version for Python (pyproject.toml) or Go (VERSION file) 101 projects using semantic versioning. You can provide an explicit version number, 102 a bump type (patch, minor, major), or leave it blank for an interactive prompt. 103 104 Args: 105 version: The version to bump to. Can be an explicit version (e.g., "1.2.3"), 106 a bump type ("patch", "minor", "major"), a prerelease type 107 ("alpha", "beta", "rc", "dev"), or None for interactive selection. 108 language: Programming language (python or go). Auto-detected if not specified. 109 dry_run: If True, show what would change without actually changing anything. 110 commit: If True, automatically commit the version change to git. 111 push: If True, push changes to remote after commit (implies --commit). 112 branch: Branch to perform the bump on (default: current branch). 113 allow_dirty: If True, allow bumping even with uncommitted changes. 114 verbose: If True, enable verbose debug output. 115 116 Example: 117 Bump to a specific version:: 118 119 $ rhiza-tools bump 2.0.0 120 121 Bump patch version (1.2.3 -> 1.2.4):: 122 123 $ rhiza-tools bump patch 124 125 Bump a Go project explicitly:: 126 127 $ rhiza-tools bump minor --language go 128 129 Preview changes without applying them:: 130 131 $ rhiza-tools bump minor --dry-run 132 133 Interactive version selection:: 134 135 $ rhiza-tools bump 136 137 Bump and push to remote:: 138 139 $ rhiza-tools bump minor --push 140 """ 141 _apply_verbose(verbose) 142 from rhiza_tools.commands.bump import BumpOptions, Language 143 144 # Parse language if provided 145 lang_enum = None 146 if language: 147 try: 148 lang_enum = Language(language.lower()) 149 except ValueError: 150 console.error(f"Invalid language: {language}") 151 console.error("Supported languages: python, go") 152 raise typer.Exit(code=1) from None 153 154 options = BumpOptions( 155 version=version, 156 dry_run=dry_run, 157 commit=commit, 158 push=push, 159 branch=branch, 160 allow_dirty=allow_dirty, 161 language=lang_enum, 162 ) 163 bump_command(options)
Bump the version of the project.
This command updates the version for Python (pyproject.toml) or Go (VERSION file) projects using semantic versioning. You can provide an explicit version number, a bump type (patch, minor, major), or leave it blank for an interactive prompt.
Arguments:
- version: The version to bump to. Can be an explicit version (e.g., "1.2.3"), a bump type ("patch", "minor", "major"), a prerelease type ("alpha", "beta", "rc", "dev"), or None for interactive selection.
- language: Programming language (python or go). Auto-detected if not specified.
- dry_run: If True, show what would change without actually changing anything.
- commit: If True, automatically commit the version change to git.
- push: If True, push changes to remote after commit (implies --commit).
- branch: Branch to perform the bump on (default: current branch).
- allow_dirty: If True, allow bumping even with uncommitted changes.
- verbose: If True, enable verbose debug output.
Example:
Bump to a specific version::
$ rhiza-tools bump 2.0.0Bump patch version (1.2.3 -> 1.2.4)::
$ rhiza-tools bump patchBump a Go project explicitly::
$ rhiza-tools bump minor --language goPreview changes without applying them::
$ rhiza-tools bump minor --dry-runInteractive version selection::
$ rhiza-tools bumpBump and push to remote::
$ rhiza-tools bump minor --push
166@app.command() 167def generate_coverage_badge( 168 coverage_json: Annotated[ 169 Path, 170 typer.Option( 171 "--coverage-json", 172 help="Path to coverage.json file", 173 ), 174 ] = Path("_tests/coverage.json"), 175 output: Annotated[ 176 Path, 177 typer.Option( 178 help="Path to output badge JSON", 179 ), 180 ] = Path("_book/tests/coverage-badge.json"), 181 verbose: bool = VERBOSE_OPTION, 182) -> None: 183 """Generate a coverage badge for the project. 184 185 Reads a coverage report JSON file and creates a shields.io endpoint JSON file 186 for displaying a coverage badge. The badge color automatically adjusts based 187 on the coverage percentage. 188 189 Args: 190 coverage_json: Path to the coverage.json file generated by pytest-cov. 191 output: Path where the badge JSON file should be written. 192 verbose: If True, enable verbose debug output. 193 194 Example: 195 Generate badge with default paths:: 196 197 $ rhiza-tools generate-coverage-badge 198 199 Generate badge with custom paths:: 200 201 $ rhiza-tools generate-coverage-badge \ 202 --coverage-json tests/coverage.json \ 203 --output assets/badge.json 204 """ 205 _apply_verbose(verbose) 206 generate_coverage_badge_command(coverage_json_path=coverage_json, output_path=output)
Generate a coverage badge for the project.
Reads a coverage report JSON file and creates a shields.io endpoint JSON file for displaying a coverage badge. The badge color automatically adjusts based on the coverage percentage.
Arguments:
- coverage_json: Path to the coverage.json file generated by pytest-cov.
- output: Path where the badge JSON file should be written.
- verbose: If True, enable verbose debug output.
Example:
Generate badge with default paths::
$ rhiza-tools generate-coverage-badgeGenerate badge with custom paths::
$ rhiza-tools generate-coverage-badge --coverage-json tests/coverage.json --output assets/badge.json
209@app.command() 210def release( 211 bump: str | None = typer.Option(None, "--bump", help="Bump type (MAJOR, MINOR, PATCH) before release."), 212 with_bump: bool = typer.Option( 213 False, 214 "--with-bump", 215 help="Interactively select bump type before release (works with --dry-run).", 216 ), 217 push: bool = typer.Option(False, "--push", help="Push changes to remote (default: prompt in interactive mode)."), 218 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 219 non_interactive: bool = typer.Option(False, "--non-interactive", "-y", help="Skip all confirmation prompts."), 220 language: str | None = typer.Option( 221 None, "--language", "-l", help="Programming language (python or go). Auto-detected if not specified." 222 ), 223 verbose: bool = VERBOSE_OPTION, 224) -> None: 225 """Push a release tag to remote to trigger the release workflow. 226 227 This command validates the repository state and pushes the git tag for the 228 current version to the remote repository, which triggers the automated release 229 workflow. Supports Python projects (pyproject.toml) and Go projects 230 (go.mod + VERSION file). The project language is auto-detected when not 231 explicitly specified. 232 233 Args: 234 bump: Bump type (MAJOR, MINOR, PATCH) to apply before release. 235 with_bump: If True, interactively select bump type before release. 236 push: If True, push changes without prompting (implies non-interactive for push). 237 dry_run: If True, show what would happen without actually pushing the tag. 238 non_interactive: If True, skip all confirmation prompts (useful for CI/CD). 239 language: Programming language (python or go). Auto-detected if not specified. 240 verbose: If True, enable verbose debug output. 241 242 Example: 243 Push a release tag (with prompts):: 244 245 $ rhiza-tools release 246 247 Preview what would happen:: 248 249 $ rhiza-tools release --dry-run 250 251 Non-interactive mode (for CI/CD):: 252 253 $ rhiza-tools release --non-interactive 254 255 Bump version and release:: 256 257 $ rhiza-tools release --bump MINOR --push 258 259 Interactive bump with dry-run preview:: 260 261 $ rhiza-tools release --with-bump --push --dry-run 262 263 Release a Go project:: 264 265 $ rhiza-tools release --language go 266 """ 267 _apply_verbose(verbose) 268 from rhiza_tools.commands.bump import Language 269 270 lang_enum = None 271 if language: 272 try: 273 lang_enum = Language(language.lower()) 274 except ValueError: 275 console.error(f"Invalid language: {language}") 276 console.error("Supported languages: python, go") 277 raise typer.Exit(code=1) from None 278 279 release_command(bump, push, dry_run, non_interactive, with_bump, lang_enum)
Push a release tag to remote to trigger the release workflow.
This command validates the repository state and pushes the git tag for the current version to the remote repository, which triggers the automated release workflow. Supports Python projects (pyproject.toml) and Go projects (go.mod + VERSION file). The project language is auto-detected when not explicitly specified.
Arguments:
- bump: Bump type (MAJOR, MINOR, PATCH) to apply before release.
- with_bump: If True, interactively select bump type before release.
- push: If True, push changes without prompting (implies non-interactive for push).
- dry_run: If True, show what would happen without actually pushing the tag.
- non_interactive: If True, skip all confirmation prompts (useful for CI/CD).
- language: Programming language (python or go). Auto-detected if not specified.
- verbose: If True, enable verbose debug output.
Example:
Push a release tag (with prompts)::
$ rhiza-tools releasePreview what would happen::
$ rhiza-tools release --dry-runNon-interactive mode (for CI/CD)::
$ rhiza-tools release --non-interactiveBump version and release::
$ rhiza-tools release --bump MINOR --pushInteractive bump with dry-run preview::
$ rhiza-tools release --with-bump --push --dry-runRelease a Go project::
$ rhiza-tools release --language go
282@app.command() 283def rollback( 284 tag: str | None = typer.Argument(None, help="Tag to rollback (e.g., v1.2.3). Interactive if omitted."), 285 revert_bump: bool = typer.Option(False, "--revert-bump", help="Also revert the version bump commit."), 286 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 287 non_interactive: bool = typer.Option(False, "--non-interactive", "-y", help="Skip all confirmation prompts."), 288 verbose: bool = VERBOSE_OPTION, 289) -> None: 290 """Rollback a release and/or version bump. 291 292 This command safely reverses release and bump operations by deleting 293 the release tag from local and remote repositories, and optionally 294 reverting the version bump commit. 295 296 It uses ``git revert`` rather than ``git reset``, making it safe 297 even when changes have already been pushed to remote. 298 299 Args: 300 tag: The tag to rollback (e.g., "v1.2.3"). If omitted, an interactive 301 menu shows recent tags to choose from. 302 revert_bump: If True, also revert the version bump commit associated 303 with the tag. 304 dry_run: If True, show what would happen without actually making changes. 305 non_interactive: If True, skip all confirmation prompts (useful for CI/CD). 306 verbose: If True, enable verbose debug output. 307 308 Example: 309 Rollback the most recent release interactively:: 310 311 $ rhiza-tools rollback 312 313 Preview rollback of a specific tag:: 314 315 $ rhiza-tools rollback v1.2.3 --dry-run 316 317 Fully rollback including the bump commit:: 318 319 $ rhiza-tools rollback v1.2.3 --revert-bump 320 321 Non-interactive rollback (for CI/CD):: 322 323 $ rhiza-tools rollback v1.2.3 --revert-bump -y 324 """ 325 _apply_verbose(verbose) 326 from rhiza_tools.commands.rollback import RollbackOptions 327 328 options = RollbackOptions( 329 tag=tag, 330 revert_bump=revert_bump, 331 dry_run=dry_run, 332 non_interactive=non_interactive, 333 ) 334 rollback_command(options)
Rollback a release and/or version bump.
This command safely reverses release and bump operations by deleting the release tag from local and remote repositories, and optionally reverting the version bump commit.
It uses git revert rather than git reset, making it safe
even when changes have already been pushed to remote.
Arguments:
- tag: The tag to rollback (e.g., "v1.2.3"). If omitted, an interactive menu shows recent tags to choose from.
- revert_bump: If True, also revert the version bump commit associated with the tag.
- dry_run: If True, show what would happen without actually making changes.
- non_interactive: If True, skip all confirmation prompts (useful for CI/CD).
- verbose: If True, enable verbose debug output.
Example:
Rollback the most recent release interactively::
$ rhiza-tools rollbackPreview rollback of a specific tag::
$ rhiza-tools rollback v1.2.3 --dry-runFully rollback including the bump commit::
$ rhiza-tools rollback v1.2.3 --revert-bumpNon-interactive rollback (for CI/CD)::
$ rhiza-tools rollback v1.2.3 --revert-bump -y
337@app.command(name="update-readme") 338def update_readme( 339 dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."), 340 verbose: bool = VERBOSE_OPTION, 341) -> None: 342 """Update README.md with the current output from `make help`. 343 344 This command runs `make help` and updates the README.md file with the current 345 help output, keeping the documentation in sync with available Make targets. 346 347 Args: 348 dry_run: If True, show the help output that would be inserted without 349 actually modifying README.md. 350 verbose: If True, enable verbose debug output. 351 352 Example: 353 Update README with make help output:: 354 355 $ rhiza-tools update-readme 356 357 Preview changes without modifying README:: 358 359 $ rhiza-tools update-readme --dry-run 360 """ 361 _apply_verbose(verbose) 362 update_readme_command(dry_run)
Update README.md with the current output from make help.
This command runs make help and updates the README.md file with the current
help output, keeping the documentation in sync with available Make targets.
Arguments:
- dry_run: If True, show the help output that would be inserted without actually modifying README.md.
- verbose: If True, enable verbose debug output.
Example:
Update README with make help output::
$ rhiza-tools update-readmePreview changes without modifying README::
$ rhiza-tools update-readme --dry-run
365@app.command(name="version-matrix") 366def version_matrix( 367 pyproject: Annotated[ 368 Path, 369 typer.Option( 370 "--pyproject", 371 help="Path to pyproject.toml file", 372 ), 373 ] = Path("pyproject.toml"), 374 candidates: Annotated[ 375 str | None, 376 typer.Option( 377 "--candidates", 378 help="Comma-separated list of candidate Python versions (e.g., '3.11,3.12,3.13')", 379 ), 380 ] = None, 381 verbose: bool = VERBOSE_OPTION, 382) -> None: 383 """Emit supported Python versions from pyproject.toml as JSON. 384 385 This command reads the requires-python field from pyproject.toml and outputs 386 a JSON array of Python versions that satisfy the constraint. This is primarily 387 used in GitHub Actions to compute the test matrix. 388 389 Args: 390 pyproject: Path to the pyproject.toml file. 391 candidates: Comma-separated list of candidate Python versions to evaluate. 392 Defaults to "3.11,3.12,3.13,3.14". 393 verbose: If True, enable verbose debug output. 394 395 Example: 396 Get supported versions with defaults:: 397 398 $ rhiza-tools version-matrix 399 ["3.11", "3.12"] 400 401 Use custom pyproject.toml path:: 402 403 $ rhiza-tools version-matrix --pyproject /path/to/pyproject.toml 404 405 Use custom candidates:: 406 407 $ rhiza-tools version-matrix --candidates "3.10,3.11,3.12" 408 """ 409 _apply_verbose(verbose) 410 candidates_list = None 411 if candidates: 412 candidates_list = [v.strip() for v in candidates.split(",")] 413 414 version_matrix_command(pyproject_path=pyproject, candidates=candidates_list)
Emit supported Python versions from pyproject.toml as JSON.
This command reads the requires-python field from pyproject.toml and outputs a JSON array of Python versions that satisfy the constraint. This is primarily used in GitHub Actions to compute the test matrix.
Arguments:
- pyproject: Path to the pyproject.toml file.
- candidates: Comma-separated list of candidate Python versions to evaluate. Defaults to "3.11,3.12,3.13,3.14".
- verbose: If True, enable verbose debug output.
Example:
Get supported versions with defaults::
$ rhiza-tools version-matrix ["3.11", "3.12"]Use custom pyproject.toml path::
$ rhiza-tools version-matrix --pyproject /path/to/pyproject.tomlUse custom candidates::
$ rhiza-tools version-matrix --candidates "3.10,3.11,3.12"
417@app.command(name="analyze-benchmarks") 418def analyze_benchmarks( 419 benchmarks_json: Annotated[ 420 Path, 421 typer.Option( 422 "--benchmarks-json", 423 help="Path to benchmarks.json file", 424 ), 425 ] = Path("_benchmarks/benchmarks.json"), 426 output_html: Annotated[ 427 Path, 428 typer.Option( 429 "--output-html", 430 help="Path to save HTML visualization", 431 ), 432 ] = Path("_benchmarks/benchmarks.html"), 433 verbose: bool = VERBOSE_OPTION, 434) -> None: 435 """Analyze pytest-benchmark results and visualize them. 436 437 This command reads a benchmarks.json file produced by pytest-benchmark, 438 prints a table with benchmark name, mean milliseconds, and operations per 439 second, and generates an interactive Plotly bar chart of mean runtimes. 440 441 Note: This command requires pandas and plotly. Install with: 442 uv pip install -e '.[dev]' or pip install 'rhiza-tools[dev]' 443 444 Args: 445 benchmarks_json: Path to the benchmarks.json file. 446 output_html: Path where the HTML visualization should be saved. 447 verbose: If True, enable verbose debug output. 448 449 Example: 450 Analyze benchmarks with default paths:: 451 452 $ rhiza-tools analyze-benchmarks 453 454 Use custom paths:: 455 456 $ rhiza-tools analyze-benchmarks \ 457 --benchmarks-json tests/benchmarks.json \ 458 --output-html reports/benchmarks.html 459 """ 460 _apply_verbose(verbose) 461 analyze_benchmarks_command(benchmarks_json=benchmarks_json, output_html=output_html)
Analyze pytest-benchmark results and visualize them.
This command reads a benchmarks.json file produced by pytest-benchmark, prints a table with benchmark name, mean milliseconds, and operations per second, and generates an interactive Plotly bar chart of mean runtimes.
Note: This command requires pandas and plotly. Install with: uv pip install -e '.[dev]' or pip install 'rhiza-tools[dev]'
Arguments:
- benchmarks_json: Path to the benchmarks.json file.
- output_html: Path where the HTML visualization should be saved.
- verbose: If True, enable verbose debug output.
Example:
Analyze benchmarks with default paths::
$ rhiza-tools analyze-benchmarksUse custom paths::
$ rhiza-tools analyze-benchmarks --benchmarks-json tests/benchmarks.json --output-html reports/benchmarks.html