zilliz 1.4.2

TUI and CLI tool for managing Zilliz Cloud clusters and Milvus operations
Documentation
# Contributing to zilliz

This guide covers everything you need to build, test, and modify the project.

## Prerequisites

- Rust toolchain (edition 2021) -- install via [rustup]https://rustup.rs/

API model definitions (`control-plane.json` and `data-plane.json`) are embedded at compile time via `include_str!()`, so no external dependencies are needed.

## Development Setup

### Install binaries

```bash
cd vdc/zilliz-tui

# Install both `zilliz` and `zz` to ~/.cargo/bin/ (release build)
cargo install --path .

# Verify
zilliz version
```

After code changes, re-run `cargo install --path .` to update.

### Quick iteration

Use `cargo run` for faster debug builds during development:

```bash
# Launch TUI
cargo run

# Run CLI commands
cargo run -- cluster list
cargo run -- collection list -o json
```

### Type checking

```bash
cargo check
```

### Run tests

```bash
cargo test
```

### Debug logging

Logs are written to stderr (stdout is reserved for CLI/TUI output):

```bash
RUST_LOG=zilliz=debug cargo run -- cluster list
```

## Project Structure

```
src/
  api/             HTTP client (ApiClient) and error types
  bin/             Binary entry points (zilliz primary, zz alias)
  cli/             CLI commands and dispatch
    args.rs          Clap argument parser definitions
    auth.rs          OAuth and API key login logic
    auth_cmd.rs      Auth subcommand handlers (status, switch)
    configure.rs     Interactive credential setup
    context.rs       Cluster context management
    dispatch.rs      Dynamic resource operation dispatch
    formatter.rs     Output formatting (table, JSON, YAML, CSV, text)
    alert.rs         Alert rule management
    billing.rs       Billing queries (usage, invoices)
    cluster.rs       Cluster-specific operations (create)
    metrics.rs       Metrics query and display
    job_waiter.rs    Async job polling with backoff
    completion.rs    Shell completion install/uninstall
    help.rs          Custom help text generation
    error_hints.rs   User-friendly error messages
    version.rs       Version display
  config/          Config management (~/.zilliz/)
    manager.rs       ConfigManager -- reads/writes INI config files
    credentials.rs   API key extraction from login responses
    context.rs       Cluster context state
  model/           JSON model loader and type definitions
    loader.rs        ModelLoader -- parses embedded JSON models
    types.rs         CliModel, Resource, Operation, Param types
    builtin_models/  Embedded API definitions
      control-plane.json   Cloud management APIs
      data-plane.json      Milvus operation APIs
  service/         Shared operation executor
    executor.rs      OperationExecutor -- builds and invokes API calls
  tui/             Terminal UI (ratatui + crossterm)
    app.rs           Application state and screen enum
    event.rs         Event system (KeyEvent, Tick, Resize)
    handler.rs       Keyboard input routing
    render.rs        Frame rendering dispatch
    views/           Screen renderers (welcome, etc.)
    widgets/         Custom ratatui widgets
  lib.rs           Library entry point (main_impl, async_main)
  main.rs          CLI entry point
build.rs           Triggers recompile when model JSON files change
```

## Architecture

### Model-driven design

CLI commands are not hardcoded. They are generated dynamically from two JSON model files:

- `src/model/builtin_models/control-plane.json` -- cloud management APIs (cluster, project, backup, etc.)
- `src/model/builtin_models/data-plane.json` -- Milvus APIs (collection, vector, index, etc.)

These are embedded at compile time via `include_str!()` in `src/model/loader.rs`. The `build.rs` script watches these files and triggers recompilation when they change.

Each model defines resources with operations. Each operation specifies the HTTP method, URL path, parameters (with types, defaults, choices), and pagination settings. To add a new resource command, add it to the appropriate JSON file -- no Rust code changes needed for standard CRUD operations.

### Dispatch flow

1. `lib.rs` parses CLI args via clap, loads models and config
2. Built-in commands (login, context, alert, etc.) are handled directly
3. Dynamic resource commands go through `cli/dispatch.rs`:
   - Finds the resource and operation in the loaded models
   - Prompts for required parameters if missing
   - Confirms dangerous operations (delete, drop, suspend)
   - Calls `service/executor.rs` to build and execute the HTTP request
4. `cli/formatter.rs` formats the response (table, JSON, YAML, CSV, text)

### Shared executor

`service/executor.rs` is used by both CLI and TUI. It handles path parameter interpolation, body/query parameter classification, and pagination (fetching all pages with `--all`).

### TUI architecture

The TUI uses [ratatui](https://github.com/ratatui/ratatui) with [crossterm](https://github.com/crossterm-rs/crossterm) as the terminal backend:

- `tui/mod.rs` -- entry point: sets up raw mode, alternate screen, and mouse capture; runs the event loop (render -> handle input -> check quit); cleans up terminal on exit
- `tui/app.rs` -- application state (`App` struct) with current screen and quit flag
- `tui/event.rs` -- event system producing `KeyEvent`, `Tick`, and `Resize` variants
- `tui/handler.rs` -- routes keyboard events to the appropriate handler
- `tui/views/` -- screen renderers, each responsible for drawing a single view
- `tui/render.rs` -- dispatches rendering to the active view

To add a new TUI screen: add a variant to the `Screen` enum in `app.rs`, create a view in `views/`, add rendering in `render.rs`, and add key handling in `handler.rs`.

## Configuration Internals

Config files live in `~/.zilliz/` (overridable via `ZILLIZ_CONFIG_DIR`). Both files use INI format parsed by the `rust-ini` crate.

| File | Sections | Purpose |
|------|----------|---------|
| `credentials` | `[default]` | `api_key`, `user`, `org`, `plan` |
| `config` | `[default]` | `cluster_id`, `endpoint`, `database` |

On Unix, the `credentials` file is created with mode `0o600` (owner read/write only) to protect API keys.

`ConfigManager` in `config/manager.rs` handles all reads and writes. It creates the config directory and files on first use.

## Debugging Against UAT (Internal)

Zilliz contributors can point the CLI at the internal UAT control plane
(`https://api.cloud-uat3.zilliz.com`) via the hidden `--dev` flag on `login`.
The flag does not appear in `zilliz login --help` output and is not documented
in the user-facing README; it is contributor-only and may change at any time.

```bash
# Pass the API key directly
zilliz login --dev --api-key sk-uat-xxxxxxxx

# Or paste it interactively
zilliz login --dev

# All subsequent control-plane calls now hit UAT until you log out
zilliz cluster list

# Switch back to production:
zilliz logout                  # clears the persisted UAT endpoint
zilliz login --api-key sk-xxx  # plain login also clears it on success
```

Notes:

- `--dev` is API-key only. The CLI does not call Auth0 or open a browser under
  this flag. Get a UAT API key from the UAT3 console (`cloud-uat3.zilliz.com`).
- `--dev` is mutually exclusive with `--cn`.
- The persisted endpoint lives in `~/.zilliz/config [default].endpoint`. As long
  as it is set to the UAT URL, every command targets UAT — including data-plane
  and control-plane operations. `zilliz auth status` shows the active endpoint
  as `Cloud: Dev (UAT)`.
- Do not advertise this flag to customers; if you want a customer-visible
  "use the dev cloud" affordance, open a discussion first.

## Release Notes

Release notes live in `CHANGELOG.md` and are the single source of truth for what appears on each GitHub Release page.

### When you open a PR

If your PR adds a user-facing change (new command, new flag, bug fix, behavior change), add a bullet to `CHANGELOG.md` under `## [Unreleased]`, in the appropriate subsection:

- `### Added` -- new features, commands, flags, options
- `### Changed` -- behavior changes to existing features
- `### Deprecated` -- features marked for removal in a future version
- `### Removed` -- features removed in this release
- `### Fixed` -- bug fixes
- `### Security` -- security fixes

Create the subsection heading only if it does not already exist. Keep bullets short and user-facing; link to issues or PRs when it helps.

Internal refactors, test-only changes, CI tweaks, and dependency bumps do not need a changelog entry.

### When you cut a release

In the same commit that bumps `version` in `Cargo.toml`:

1. Rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD` (use today's date).
2. Add a fresh empty `## [Unreleased]` section above the versioned one.
3. Commit both changes together with a message like `chore(zilliz-tui): release v1.2.3`.

The CI release workflow (`.github/workflows/zilliz-tui.ci.yml`, triggered via `workflow_dispatch` with `release: true`) runs `scripts/extract-changelog.sh <version>` to pull the section for the version being released into the GitHub Release body. **If that section is missing, the release fails fast** -- it will not publish an empty or placeholder release.

### Testing the extractor locally

```bash
# From the repo root
vdc/zilliz-tui/scripts/extract-changelog.sh 1.0.2
```

Prints the body of the `## [1.0.2]` section to stdout. Pass a version that does not exist to see the failure path.