Skip to content

Comments

feat(cli): harden and polish issue commands#211

Merged
anderdc merged 10 commits intoentrius:testfrom
MkDev11:feature/issue-210-cli-improvements
Feb 20, 2026
Merged

feat(cli): harden and polish issue commands#211
anderdc merged 10 commits intoentrius:testfrom
MkDev11:feature/issue-210-cli-improvements

Conversation

@MkDev11
Copy link
Contributor

@MkDev11 MkDev11 commented Feb 18, 2026

Summary

Hardens and polishes the gitt CLI across all issue commands to make it production-grade. This PR addresses the issue: input validation that catches bad data before it hits the chain, a precision fix for bounty amounts (--bounty is parsed as a string and converted via Decimal, so no IEEE 754 float is ever created), consistent formatting with a shared format_alpha() helper (Decimal-based), non-interactive register support, and correct exit codes so scripts and CI can detect failures. Invalid input and missing contract config now raise click.ClickException and exit non-zero instead of printing and returning 0.

The goal is to make gitt solid and scriptable — no silent precision bugs, no wasted gas on invalid addresses, and reliable exit codes for automation.

This PR ensures non-zero exit codes on all validation and config errors (so CI and scripts can fail fast) and adds 66 automated tests. SS58 uses the existing substrate stack (no extra deps). Closed-issue handling follows the issue spec: warn with "Issue #{number} is already closed." and continue (no reject).


Task-by-task (issue #210)

# Task Done
1 Bounty precision--bounty as string → Decimal only. Min 10, max 100M ALPHA (u128-safe), max 9 decimals, isfinite.
2 Repo validation — Regex owner/repo; optional GitHub API existence check before register.
3 GitHub issue — Exists, is issue not PR; closed → warning. Issue number capped at u32 max (2³²−1).
4 On-chain ID & SS58 — Issue ID 1–999999 (vote/admin). SS58 via substrateinterface.utils.ss58 + regex fallback. PR ≥ 1, number or URL; invalid → param_hint.
5 Shared formattingformat_alpha(raw, decimals) + constants. All validators set param_hint.
6 Deprecated helper cleanup — Remove get_ws_endpoint() and unused code. ✅ N/A — get_ws_endpoint() is not present in the codebase; only resolve_network() is used.
7 CLI polish & UX — Rich spinners, Panel for tx summaries, color-coded status in table, --json for read commands, network/contract header, empty-state hints, screenshots of CLI theme. ✅ — Spinners (console.status()), Panel (register/vote/admin), colorize_status in issues table, --json on list/bounty-pool/pending-harvest/vote list/admin info, print_network_header() before output, helpful empty states. Screenshots below. Help/option text normalization left as optional follow-up.

What changed (by area)

Input validation

  • --bounty is type=str at the Click boundary — the raw string is parsed directly with Decimal, so no IEEE 754 float is ever created. Enforced 10 ALPHA minimum, capped at 100M ALPHA (u128-safe), max 9 decimal places, isfinite guard, and rejection of non-numeric / empty input.
  • Repository format validated with regex; optional GitHub API check before on-chain register.
  • GitHub issues checked for existence, that they are issues (not PRs); closed issues get a warning with the spec verbatim message "Issue #{number} is already closed." and the command continues (per issue gitt cli improvements #210 Task 3).
  • GitHub issue number capped at u32 max (2³²−1) for register; on-chain issue ID range 1–999999 (u32-friendly) on vote, admin cancel/payout.
  • SS58 addresses validated via substrateinterface.utils.ss58.ss58_decode() (existing substrate stack) with regex fallback on every command that takes hotkey/coldkey/address.
  • PR number in vote solution must be ≥ 1; accepts plain number or GitHub PR URL; invalid input raises with param_hint='pr_number_or_url'.

Helpers & constants

  • format_alpha(raw_amount, decimals) uses Decimal for display so ALPHA amounts don’t suffer float rounding. Replaces scattered / 1e9.
  • Constants: ALPHA_*, MAX_ISSUE_*. Validators set param_hint.

Exit codes & display

  • Missing contract or validation failure → click.ClickException (non-zero) on register, vote, admin, harvest, view. Register: --yes/non-TTY skip confirm.
  • Issues list table: bounty column uses format_alpha + Decimal; status column uses colorize_status (green Active, yellow Registered, dim Completed/Cancelled); resilient to malformed storage.

Test breakdown (66 total)

Category Count Covered
Unit — format_alpha 6 Zero, fractional, whole, large, precision, decimals.
Unit — validate_bounty_amount 15 Min, at min, max decimals ok/rejected, negative, inf, nan, precision, large, zero, param_hint, invalid/empty string, at max, over max.
Unit — parse_pr_number 4 Plain number, URL, invalid, empty.
Unit — validate_repository 8 Valid, hyphens/dots, no slash, empty part, invalid chars, strip, double slash, param_hint.
Unit — validate_issue_id 5 Valid range, zero, negative, at max, param_hint.
Unit — validate_github_issue 1 Closed issue → warn (spec verbatim "already closed"), returns data.
Unit — validate_ss58_address 5 Empty, strip, short, invalid chars, param_hint.
Unit — constants 5 ALPHA_DECIMALS, MAX_ISSUE_ID, MAX_BOUNTY_ALPHA, MAX_ISSUE_NUMBER, format_alpha raw unit.
Unit — colorize_status 3 Known statuses, unknown → white, STATUS_COLORS dict.
CLI — register 4 Low bounty, bad repo, issue 0, issue over u32 max.
CLI — vote 3 issue_id 0, PR 0, invalid PR.
CLI — admin & vote cancel 3 Admin cancel/payout, vote cancel (issue_id 0).
CLI — missing contract 4 Register, vote, admin, harvest.

Related Issues

Closes #210

Type of Change

  • Bug fix (bounty precision, exit code on errors)
  • New feature (--yes, non-interactive, strict validation)
  • Refactor (format_alpha, ClickException)
  • Documentation
  • Other

Screenshots

Per issue #210: images of the resulting CLI theme/look.

Help & commands Issue list (table, detail, JSON) Validation errors & exit codes
image image image

Suggested captures:

  1. Helpgitt --help and gitt issues --help (or gitt admin --help / gitt vote --help).
  2. Listgitt issues list (table), gitt issues list --id 1 (detail panel), gitt issues list --json (scripting).
  3. Validationgitt admin cancel-issue 0 (Error + non-zero exit), gitt issues register --repo x/y --issue 1 --bounty 5 -y (minimum bounty or repo error).

Testing

  • Tests added/updated
  • Manually tested

Commands run:

.venv/bin/python -m pytest tests/cli/test_cli_helpers.py -q
# 66 passed

.venv/bin/python -m ruff check gittensor/cli/issue_commands/ tests/cli/
.venv/bin/python -m ruff format gittensor/cli/issue_commands/ tests/cli/
# 0 errors

Verification (copy-paste):

# Validation: issue_id 0 → non-zero exit
gitt admin cancel-issue 0
# Expect: Error: issue_id must be between 1 and 999999 (got 0); exit code ≠ 0

# Validation: bounty below minimum (repo must exist so bounty check runs)
gitt issues register --repo opentensor/btcli --issue 99999 --bounty 5 -y
# Expect: Error about minimum bounty (10 ALPHA); exit code ≠ 0

# Missing contract → non-zero exit (register and harvest)
CONTRACT_ADDRESS= gitt issues register --repo owner/repo --issue 1 --bounty 10 -y
# Expect: Error: Contract address not configured...; exit code ≠ 0
CONTRACT_ADDRESS= gitt harvest
# Expect: Error: Contract address not configured...; exit code ≠ 0

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Changes are documented (if applicable)

Files Changed

File Purpose
gittensor/cli/issue_commands/helpers.py Decimal format_alpha, _is_interactive(), validation helpers, constants; bounty/issue_id docstrings (100M cap, u32-friendly range)
gittensor/cli/issue_commands/mutations.py --yes/-y, skip confirm when non-interactive, raise ClickException on validation/missing contract; harvest raises on missing contract (non-zero exit)
gittensor/cli/issue_commands/vote.py Raise ClickException on validation failure and missing contract; invalid PR input raises BadParameter with param_hint='pr_number_or_url'
gittensor/cli/issue_commands/admin.py Raise ClickException on validation failure and missing contract
gittensor/cli/issue_commands/view.py Raise ClickException when contract not configured; issues list table uses format_alpha + Decimal for bounty, colorize_status for status column; resilient to malformed storage
tests/cli/__init__.py Package for CLI tests
tests/cli/test_cli_helpers.py 66 tests: unit (format_alpha, validators, parse_pr_number, validate_github_issue, colorize, constants, param_hint) + CLI wiring (register, vote solution/cancel, admin cancel/payout, harvest, missing contract)

@MkDev11
Copy link
Contributor Author

MkDev11 commented Feb 18, 2026

@anderdc @LandynDev please review the pr and let me know your feedback

@MkDev11 MkDev11 force-pushed the feature/issue-210-cli-improvements branch from c53781f to a253072 Compare February 18, 2026 04:35
- Fix bounty precision loss using Decimal conversion with max 9 decimal places
- Add minimum bounty validation (10 ALPHA)
- Validate repository format (regex) and verify existence on GitHub API
- Validate GitHub issue exists, is open, and is not a PR
- Validate on-chain issue IDs are in range (1-999999)
- Validate SS58 addresses with scalecodec fallback to regex
- Extract format_alpha() shared helper replacing 12 inconsistent / 1e9 conversions
- Remove deprecated get_ws_endpoint() function
- Add Rich spinners for all long-running operations (RPC, contract reads, tx)
- Add Rich Panels for all transaction commands (vote, admin, register)
- Color-code status column in issue list (green/yellow/dim)
- Add --json flag to read commands (list, bounty-pool, pending-harvest, vote list, admin info)
- Standardize help text, success/error messages, and wallet option descriptions
- Add print_success/print_error/print_network_header UX helpers
@MkDev11 MkDev11 force-pushed the feature/issue-210-cli-improvements branch from a253072 to f00a130 Compare February 18, 2026 04:41
… inputs

Add is_finite() check for bounty to handle NaN/Inf floats, cap bounty
at 100M ALPHA to prevent u128 encoding overflow, and cap issue number
at u32 max to prevent struct.pack crash.
Improve issue/admin/vote/view command reliability by enforcing non-zero exits on invalid input/missing contract config, adding non-interactive register confirmation bypass, and switching ALPHA formatting to Decimal. Add focused CLI helper/integration tests to cover validation paths and regression cases.
- Apply ruff --fix for import order (helpers, mutations, test_cli_helpers)
- Apply ruff format to CLI and test files
- Remove duplicate assert result.exit_code in test_vote_solution_rejects_issue_id_zero
@MkDev11 MkDev11 changed the title feat: harden and polish gitt CLI (closes #210) feat(cli): harden and polish issue commands Feb 20, 2026
Accept --bounty as type=str at the Click boundary and parse with
Decimal directly, eliminating any float intermediary. Update constants
from float to int and align tests with string-based inputs.
- view: issues list table uses format_alpha + Decimal for bounty column (no float precision loss); resilient to malformed storage values
- mutations: harvest raises ClickException when contract not configured (exit non-zero, consistent with register/vote/admin)
- tests: add test_harvest_missing_contract_fails (55 tests)
- vote: invalid PR input raises BadParameter with param_hint=pr_number_or_url
- helpers: docstrings note bounty cap 100M (u128), issue_id 1–999999 (u32-friendly)
- tests: parse_pr_number (plain, URL, invalid, empty), bounty max/over-max,
  register issue over u32 max, vote invalid PR, constants (MAX_BOUNTY_ALPHA,
  MAX_ISSUE_NUMBER); 65 tests total
Switch from scalecodec to substrateinterface.utils.ss58.ss58_decode so
SS58 validation uses the same dependency as the rest of the CLI; no
extra lib. Regex fallback unchanged.
Use exact closed-issue warning text and add unit test for warn-and-continue.
@skyrocket2026
Copy link

I don’t think this PR fully addresses issue #210.

What’s missing vs. the issue scope
Task 6 — Deprecated helper cleanup: The issue asks to remove get_ws_endpoint() and other unused code. I don’t see that in this PR.
Task 7 — CLI polish and UX: The issue explicitly asks for:

  • Rich console.status() spinners for long-running operations (RPC, contract reads, tx submission)
  • Consistent use of Rich Panel for transaction summaries (register, vote, admin)
  • Color-coded status in the issues table (green Active, yellow Registered, dim Completed/Cancelled)
  • --json output for read commands (list, bounty-pool, etc.) for scripting
  • Standardized help text and descriptions across commands
  • A brief banner/header for top-level commands (network + contract context)
  • Improved empty states with clear next steps

The PR adds validation, format_alpha, and tests, but the UX and visual polish described above are not clearly implemented. The issue also asks for images of the resulting CLI theme/look, which are not included.

Conclusion
The validation and precision fixes are useful, but the PR does not fully resolve #210. Task 6 and most of Task 7 are still open. I’d suggest either extending this PR to cover those items or splitting it so we can merge the validation work first and handle the UX polish in a follow-up.

@MkDev11
Copy link
Contributor Author

MkDev11 commented Feb 20, 2026

@skyrocket2026 I suggest reviewing the entire code before commenting.

Copy link
Collaborator

@anderdc anderdc left a comment

Choose a reason for hiding this comment

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

LGTM!

@anderdc anderdc merged commit 3a1fb25 into entrius:test Feb 20, 2026
2 checks passed
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.

gitt cli improvements

3 participants