Skip to content

feat(cli): add karta workload CLI with release plumbing#64

Draft
lavianalon wants to merge 22 commits into
mainfrom
feat/cli-poc
Draft

feat(cli): add karta workload CLI with release plumbing#64
lavianalon wants to merge 22 commits into
mainfrom
feat/cli-poc

Conversation

@lavianalon
Copy link
Copy Markdown
Collaborator

Summary

  1. Tree builder — new pkg/tree library that walks any Karta definition into a structured WorkloadTree.
  2. Workload CLI — new karta binary with workload list and workload tree commands, ANSI-aware colored output, --color {auto,always,never} flag, and -A / --all-namespaces flag.
  3. Bundled definitions — 11 Karta CRs (PyTorchJob, JobSet, Ray*, MPIJob, LWS, KServe, Knative Service, Dynamo, NIMService, Milvus) shipped inside the binary via //go:embed. make sync-cli-definitions (wired into make validate) keeps the bundle in sync with the canonical docs/examples/.
  4. Release plumbing.goreleaser.yaml + .github/workflows/release-cli.yaml publish cross-platform binaries (darwin amd64/arm64, linux amd64/arm64, windows amd64) to GitHub Releases on kartacli-v* tags. Namespace-isolated from existing helm chart releases.

17 commits on branch feat/cli-poc.

What changed

Area Files Notes
Tree builder pkg/tree/** Generic walker over any Karta CRD
CLI commands cmd/karta/cmd/{root,workload,workload_list,workload_tree,version}.go Cobra-based, kubectl-style flags via genericclioptions
Rendering cmd/karta/internal/render/{table,tree,view,style}.go Color, ANSI-aware width, per-sibling-group alignment
Kube client cmd/karta/internal/kube/client.go Wraps dynamic + typed + discovery clients
Loader cmd/karta/internal/loader/workload.go Iterates registry, resolves GVK ↔ workload by name
Definitions cmd/karta/internal/definitions/community/*.yaml (11), cmd/karta/internal/definitions/registry.go Embedded at build time
Bundle sync Makefile (sync-cli-definitions), docs/examples/mpijob.yaml (newline fix) make validate runs sync + git diff --exit-code
Release .goreleaser.yaml, .github/workflows/release-cli.yaml, cmd/karta/README.md, Makefile (release-snapshot) Trigger: tag push kartacli-v*. gh release create --latest=false --prerelease.

How to cut a release

git tag -s kartacli-v0.1.0-alpha.1 -m "karta CLI v0.1.0-alpha.1"
git push origin kartacli-v0.1.0-alpha.1

Workflow strips the kartacli- prefix via GORELEASER_CURRENT_TAG, builds 5 archives, publishes to the original prefixed tag with --prerelease --latest=false --generate-notes. Existing v[0-9].[0-9].[0-9] workflow (helm chart) is untouched.

Locally verified

  • go build -o bin/karta ./cmd/karta clean; go test ./cmd/karta/... passes.
  • ./bin/karta --context master-1705 workload list -A --color always: all rows align to identical visible width (118 chars).
  • ./bin/karta workload tree rag-dynamo-deploy -n runai-alon: tree view renders correctly.
  • ./bin/karta version returns expected output with and without ldflags injection.
  • goreleaser check .goreleaser.yaml: clean, no deprecations.
  • make release-snapshot: 5 archives in dist/, each containing karta + LICENSE + README.md.
  • Full release-mode dry run via GORELEASER_CURRENT_TAG=v0.1.0-alpha.1 goreleaser release --skip=publish,validate: archives correctly named, dist/CHANGELOG.md generated.

Commit summary

Commits

SHA Description
006a9e3 feat(cli): publish CLI to GitHub Releases via goreleaser
89bd383 feat(cli): bundle all Karta definitions and add sync target
457833f fix(examples): correct malformed mpijob.yaml status mappings
4b8d2e0 feat(cli): add --all-namespaces / -A flag to workload list
c8a6d85 fix(cli): align list columns with ANSI-aware padding
03997a4 refactor(cli): drop nodes label, dim hostnames in trailing column
6d8bc55 fix(cli): consistent nodes label and color across component and pod rows
d8a4309 fix(cli): align gpu and nodes columns across component and pod rows
229f088 refactor(cli): tighter tree indent (kubectl-tree style)
0b86d9f feat(cli): per-sibling-group column alignment in tree output
927383b fix(render): per-replica desired counts in replica wrappers
a46ed4c feat(tree): replicaSelector splits per-replica subtrees
5dc9405 feat(tree): support multi-instance components for Dynamo
7c6ce5a fix(tree): non-leaf components only own pods their descendants claim
06a2ff7 feat(cli): colorize tree and list output with --color flag
7c2ecf9 feat(cli): add karta workload CLI with tree and list
61b2fc8 feat(tree): add WorkloadTree builder

Commit 006a9e3 -- feat(cli): publish CLI to GitHub Releases via goreleaser:

  • Add .goreleaser.yaml building darwin/linux amd64+arm64, windows amd64.
  • Add .github/workflows/release-cli.yaml triggered on kartacli-v* tag push.
  • Add cmd/karta/README.md shipped inside each archive (alpha banner, install, usage, supported kinds, bug-reporting link).
  • Add cmd/karta/cmd/version.go + ldflags-injected version/commit/date vars; register version subcommand in root.
  • Add release-snapshot Makefile target for local goreleaser dry-runs.

Commit 89bd383 -- feat(cli): bundle all Karta definitions and add sync target:

  • Copy 8 missing Karta CRs (jobset, knative-serving, kserve, milvus, mpijob, nimservice, raycluster, rayjob) from docs/examples/ into cmd/karta/internal/definitions/community/ so the embed-FS picks them up.
  • Add KARTA_DEFINITIONS_DIR + CLI_DEFINITIONS_DIR Makefile vars.
  • Add sync-cli-definitions Makefile target (rm + cp from canonical) and wire it into validate so CI fails on drift.

Commit 457833f -- fix(examples): correct malformed mpijob.yaml status mappings:

  • Lines 25 and 32 of docs/examples/mpijob.yaml had YAML keys glued onto value lines (status: "False" running:). Split into proper key/value pairs so kubectl apply -f and the embedded loader both succeed.

Commit 4b8d2e0 -- feat(cli): add --all-namespaces / -A flag to workload list:

  • New bool flag on workload list. When set, passes empty namespace to loader.ListWorkloads so the dynamic client and pods client list cluster-wide.
  • Sort rows by (namespace, name) so multi-namespace output stays readable.

Commit c8a6d85 -- fix(cli): align list columns with ANSI-aware padding:

  • Drop text/tabwriter from the list table. Escape brackets in tabwriter do not exclude inner content from cell-width math, so ANSI color codes were being counted as visible chars and columns drifted. Compute visible width via regex strip, pad cells manually.

Commits 03997a4 / 6d8bc55 / d8a4309 / 229f088 / 0b86d9f -- tree rendering polish:

  • Drop redundant "nodes" labels; dim hostnames in trailing column.
  • Make nodes label and color consistent across component and pod rows.
  • Align GPU and nodes columns across component and pod rows.
  • Tighter tree indent (kubectl-tree style).
  • Per-sibling-group column alignment in tree output.

Commit 927383b -- fix(render): per-replica desired counts in replica wrappers:

  • Replica wrappers in the tree now report per-replica desired counts rather than aggregated, so the displayed "got/want" matches reality.

Commits a46ed4c / 5dc9405 / 7c6ce5a -- tree-builder semantics:

  • replicaSelector splits per-replica subtrees so each replica gets its own branch.
  • Multi-instance components supported (needed for Dynamo's Frontend/decode/prefill).
  • Non-leaf components only own pods their descendants claim, preventing double-counting.

Commit 06a2ff7 -- feat(cli): colorize tree and list output with --color flag:

  • Add Style abstraction with auto/always/never modes (auto = TTY check + NO_COLOR env honored).

Commit 7c2ecf9 -- feat(cli): add karta workload CLI with tree and list:

  • New cmd/karta/ binary using cobra + cli-runtime/genericclioptions.
  • workload list and workload tree commands.

Commit 61b2fc8 -- feat(tree): add WorkloadTree builder:

  • pkg/tree library that walks any Karta definition into a structured WorkloadTree ready for rendering.

Checklist

  • Links to a ticket
  • Has an assignee
  • Has reviewers
  • Has tests
  • Pipeline passes
  • All discussions resolved
  • Documentation updated

🤖 Generated with Claude Code

lavianalon and others added 18 commits May 4, 2026 20:09
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Alon Lavian <alavian@nvidia.com>
Comment thread go.mod Outdated
k8s.io/cli-runtime v0.36.1
k8s.io/client-go v0.36.1
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2
sigs.k8s.io/controller-runtime v0.24.1
Copy link
Copy Markdown
Contributor

@AviadHayumi AviadHayumi May 19, 2026

Choose a reason for hiding this comment

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

it cant be part of the karta lib ,
it should be under /karta-cli folder or something with diffrent go.mod/go.sum

we can't bind between karta lib and controller runtime

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in f475c5ecmd/karta/ is now its own Go module with its own go.mod/go.sum. Root karta library no longer pulls in cobra, cli-runtime, client-go, or any CLI dependency. pkg/tree's use of client.Object was already replaced with resource.KubernetesObject in a7bc745 so controller-runtime stayed dropped. See the PR-level review I just left for the full breakdown.

Copy link
Copy Markdown
Collaborator Author

@lavianalon lavianalon left a comment

Choose a reason for hiding this comment

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

Good catch, addressed in f475c5e. The karta CLI is now its own Go module at cmd/karta/ with its own go.mod / go.sum. The root karta library no longer carries cobra, cli-runtime, client-go, or any other CLI-specific dependency.

What changed:

  • cmd/karta/go.mod declares github.com/run-ai/karta/cmd/karta, with replace github.com/run-ai/karta => ../.. for local development.
  • Root go.mod slimmed back to library deps only — controller-runtime stayed gone (earlier commit a7bc745 had already removed pkg/tree's use of client.Object in favor of resource.KubernetesObject).
  • .goreleaser.yaml moved to cmd/karta/; LICENSE staged via before-hook (sh -c 'cp ../../LICENSE LICENSE') and gitignored.
  • Release workflow now runs goreleaser with workdir: cmd/karta; gh release create uploads from cmd/karta/dist/.
  • make release-snapshot cd's into cmd/karta first.

Verified locally: make release-snapshot produces 5 archives (darwin amd64/arm64, linux amd64/arm64, windows amd64), each containing karta + LICENSE + README.md. Root go build ./... and go test ./... pass with no CLI deps.

Open question for you: I left the path as cmd/karta/ rather than your suggested /karta-cli since the existing files were already there and cmd/... is the standard Go monorepo pattern. Happy to rename if you'd prefer the literal karta-cli/ top-level directory.

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.

2 participants