Skip to content

feat(columns + views): REV, kubectl-parity audit, k9s-style views config#271

Open
janosmiko wants to merge 22 commits into
mainfrom
feat/rev-column-per-kind-sort
Open

feat(columns + views): REV, kubectl-parity audit, k9s-style views config#271
janosmiko wants to merge 22 commits into
mainfrom
feat/rev-column-per-kind-sort

Conversation

@janosmiko
Copy link
Copy Markdown
Owner

@janosmiko janosmiko commented May 23, 2026

Summary

Closes GitHub issue #262. Two phases shipped together on this branch.

Phase 1 — REV column + column audit sweep

REV column

  • Decimal metadata.resourceVersion on Deployment, StatefulSet, DaemonSet, ReplicaSet, Job, CronJob.
  • Numeric sort comparator (new case "REV" in comparePrimaryColumn).

Audit-driven additions

Kind Added
Deployment Unavailable; fixed int64 silent-drop on Up-to-date/Available
StatefulSet Up-to-date, Update Strategy, Current/Update Revision
DaemonSet Current, Up-to-date, Available, Misscheduled, Images, REV
ReplicaSet Desired, Images, REV
Job Active, Duration, ti.Ready, ti.Status; int64 fix; REV
CronJob Active, REV
Deploy/STS/DS/RS Progressing (only when generation > observedGeneration)
Flux Interval (all kinds); Source/Path (Kustomization); URL (GitRepo/HelmRepo/OCIRepo/Bucket); Chart (HelmChart)
Argo Application Health, Sync Status, Project
Argo ApplicationSet Project
cert-manager Certificate DNS Names, Issuer
IngressClass Controller, Parameters (suppressed when sub-fields empty — CodeRabbit fix)
PriorityClass Value, Preemption Policy
HPA Last Scale Time, External metric type (spec + status)
Node Unschedulable

Phase 2 — k9s-style views: config

A unified top-level views: config (global + per-cluster) keyed by GVR primary, Kind fallback (case-insensitive).

views:
  apps/v1/deployments:
    columns:
      - Name
      - Ready
      - REV
      - "IMAGE:.spec.template.spec.containers[0].image"
      - "NODE:.spec.template.spec.nodeName|W"
      - Age
    sort_column: "REV:desc"
  pod:
    columns: [Name, Status, "Node:.spec.nodeName", Age]
    sort_column: "Age"
clusters:
  prod:
    views:
      apps/v1/deployments:
        sort_column: "Name:desc"

What it does

  • Custom columns via NAME:.jsonpath evaluated with k8s.io/client-go/util/jsonpath (kubectl-flavored).
  • Per-Kind/GVR default sort with direction. REV defaults to desc, everything else to asc when colon omitted.
  • Per-cluster overrides wins over global.
  • Sort applied at every Kind-entry path (sidebar, bookmarks, session restore).
  • Flags |R (right-align), |T (humanize timestamp), |W (wide-only) — case-insensitive, stackable.

Migration

resource_columns: continues to work — bridged into views: at config load with one deprecation logger.Warn. views: wins when both define the same key.

Error handling

  • JSONPath compile error → per-view warning, that view skipped, rest of config loads.
  • JSONPath miss at row render → empty cell, no log.

Internal changes

  • model.Item.Raw retains the source map[string]any so JSONPath can evaluate against it on every refresh.
  • New package surface in internal/ui/: View, ResolvedColumn, ColumnSpec, ResourceRef, ParseColumnSpec, BuildView, ResolveView, EvalJSONPath, CompileJSONPath, EvalCompiled.
  • Single integration site for view-driven columns (updateResourcesLoadedMain), and five sort-seeding sites covering all real Kind-entry paths.

Test plan

  • go test -race ./... green (16 commits, all TDD)
  • golangci-lint run ./... clean
  • CodeRabbit inline finding addressed (Parameters: "//" placeholder suppressed)
  • Manual smoke on a real cluster: configured views: with IMAGE JSONPath column + REV:desc sort; verify column shows, sort persists across navigation, per-cluster override wins.

Out of scope (potential Phase 3)

  • Removal of resource_columns (deprecation only).
  • Wildcard GVR keys.
  • Computed/aggregated columns (arithmetic across paths).
  • View inheritance (extends: pod).

janosmiko added 6 commits May 23, 2026 13:37
- Deployment: fix int64 silent-drop on Up-to-date/Available; add Unavailable (suppressed when zero)
- StatefulSet: add Up-to-date, Update Strategy, Current Revision, Update Revision
- DaemonSet: add REV, Current, Up-to-date, Available, Misscheduled (suppressed when zero); add container images
- ReplicaSet: add Desired, REV; add container images; signature updated to receive obj
- Extract intFromMap helper for dual int64/float64 field reads
- Job: fix int64/float64 silent-drop on Completions/Succeeded/Failed;
  add Active (suppressed when zero), Duration (start→completion or now),
  Status (Complete/Failed/Suspended/Running) on ti.Status, REV from obj
- CronJob: add Active (len of status.active, suppressed when empty),
  REV from obj; update both signatures to accept obj as first map arg
- Add jobDuration and jobStatus helpers; update client_populate.go callers
- Flux (all kinds): Interval from spec.interval
- Kustomization: Source (<kind>/<name>) and Path columns
- GitRepository/HelmRepository/OCIRepository/Bucket: URL column
- HelmChart: Chart column
- Argo Application/ApplicationSet: Project from spec.project
- Argo Application: Health (status.health.status) and Sync Status (status.sync.status)
- cert-manager Certificate: DNS Names (joined) and Issuer from spec.issuerRef.name

All columns conditional — emitted only when the underlying field is non-empty.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds numeric REV sorting and unit tests; stores raw Kubernetes objects on items and refactors populate helpers to accept the full object; extracts and emits REV, Progressing, workload/job/cronjob columns, HPA lastScaleTime and External metrics, Node Unschedulable, IngressClass Controller/Parameters, and PriorityClass Value/Preemption; adds Flux/Argo/cert-manager enrichments; implements a views system with JSONPath column specs, config bridging from resource_columns, runtime application of view columns, and comprehensive tests.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding REV column support, conducting a kubectl-parity audit sweep, and introducing k9s-style views configuration. It is specific, concise, and reflects the primary intent of the changeset.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the summary, two distinct phases, detailed changes per resource kind, technical implementation details, test plan, and out-of-scope items. It follows the template structure with sections for Summary, Type of change, Related issue, Changes, Testing, and Checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/k8s/client_populate_misc.go`:
- Around line 26-31: The current code unconditionally appends a Parameters entry
to ti.Columns using scope/kind/name which can produce "//" placeholders when
those fields are empty; change the logic in the block that handles
spec["parameters"] (the params map) to only append a
model.KeyValue{Key:"Parameters", Value:...} when at least one of scope, kind or
name is non-empty, and construct the Value string by joining only the non-empty
parts (or otherwise skip adding the column entirely) so you never emit a pure
placeholder like "//".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c07f185b-8561-4ea5-bd26-69fa20bc4599

📥 Commits

Reviewing files that changed from the base of the PR and between 2a64375 and f41d159.

📒 Files selected for processing (14)
  • internal/app/tabs_compare.go
  • internal/app/tabs_compare_rev_test.go
  • internal/k8s/client_populate.go
  • internal/k8s/client_populate_argo.go
  • internal/k8s/client_populate_coverage_test.go
  • internal/k8s/client_populate_ext.go
  • internal/k8s/client_populate_ext_test.go
  • internal/k8s/client_populate_flux.go
  • internal/k8s/client_populate_gitops_enrichments_test.go
  • internal/k8s/client_populate_hpa.go
  • internal/k8s/client_populate_kinds.go
  • internal/k8s/client_populate_misc.go
  • internal/k8s/client_populate_workloads.go
  • internal/k8s/client_populate_workloads_rev_test.go

Comment thread internal/k8s/client_populate_misc.go
janosmiko added 10 commits May 23, 2026 18:13
Wire the new views: config surface into YAML loading. Add Views fields
to configFile and clusterConfig; populate ConfigViews and
ConfigClusterViews in applyConfigMaps. Compile errors per view produce
a logger.Warn and skip that entry — consistent with other invalid-config
handling patterns in the codebase.
views supersedes resource_columns with per-resource column and sort
configuration keyed by GVR or Kind. Documents column spec syntax,
flag modifiers, sort direction defaults, and per-cluster overrides.
@janosmiko janosmiko changed the title feat(columns): REV column + kubectl-parity audit sweep feat(columns + views): REV, kubectl-parity audit, k9s-style views config May 23, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/config-reference.md`:
- Around line 225-227: The fenced code block containing
"NAME[:.jsonpath][|flag]*" is unlabeled and triggers markdownlint MD040; update
that block to include a language identifier (e.g., change the opening fence from
``` to ```text) so it reads "```text" before the line "NAME[:.jsonpath][|flag]*"
to satisfy the linter.

In `@internal/app/views_apply_test.go`:
- Line 55: The tests call ui.BuildView(&ui.ConfigView{Columns:
[]string{"X:.foo"}}) and discard the returned error, which can mask parsing
regressions; update each test invocation (the calls that assign to v, _ :=
BuildView) to capture the error (e.g., v, err := ui.BuildView(...)) and
assert/fail on non-nil err (use t.Fatalf or equivalent/assert helper) before
using v so failures surface immediately; retain the same ui.ConfigView and
variable names (v, err) and apply the same change to all occurrences referenced
in the test file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 97b5141f-3a81-47df-a527-2ad0fff5fc2d

📥 Commits

Reviewing files that changed from the base of the PR and between 1a89aed and af3b900.

📒 Files selected for processing (21)
  • docs/config-example.yaml
  • docs/config-reference.md
  • internal/app/app_sort.go
  • internal/app/app_sort_view_test.go
  • internal/app/update_bookmarks.go
  • internal/app/update_bookmarks_session.go
  • internal/app/update_navigation.go
  • internal/app/update_resources_loaded.go
  • internal/app/views_apply.go
  • internal/app/views_apply_test.go
  • internal/k8s/client_populate.go
  • internal/model/item_raw_test.go
  • internal/model/types.go
  • internal/ui/config_apply.go
  • internal/ui/config_load.go
  • internal/ui/config_views_bridge_test.go
  • internal/ui/config_views_load_test.go
  • internal/ui/views.go
  • internal/ui/views_jsonpath.go
  • internal/ui/views_jsonpath_test.go
  • internal/ui/views_test.go

Comment thread docs/config-reference.md Outdated
Comment thread internal/app/views_apply_test.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/ui/views_columns_for_kind_test.go`:
- Around line 32-33: The test currently ignores the error returned by BuildView
which can hide parser regressions; update both occurrences (where v, _ :=
BuildView(&ConfigView{Columns: []string{"Name", "X:.foo"}}) and the similar call
at lines 45-46) to capture the error (e.g., v, err := BuildView(...)) and fail
the test immediately if err != nil (use t.Fatalf or require.NoError) before
assigning ConfigViews = map[string]*View{"pod": v}; this ensures BuildView
errors surface in the test for functions/types BuildView, ConfigView,
ConfigViews and View.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 104821d2-1527-4c56-a6fe-5361913f352f

📥 Commits

Reviewing files that changed from the base of the PR and between 30314db and f1397b9.

📒 Files selected for processing (2)
  • internal/ui/config.go
  • internal/ui/views_columns_for_kind_test.go

Comment on lines +32 to +33
v, _ := BuildView(&ConfigView{Columns: []string{"Name", "X:.foo"}})
ConfigViews = map[string]*View{"pod": v}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Do not ignore BuildView errors in tests.

These calls currently discard err, which can mask parser regressions and make failures harder to diagnose. Fail fast when view construction fails.

Proposed fix
-	v, _ := BuildView(&ConfigView{Columns: []string{"Name", "X:.foo"}})
+	v, err := BuildView(&ConfigView{Columns: []string{"Name", "X:.foo"}})
+	if err != nil {
+		t.Fatal(err)
+	}
-	globalView, _ := BuildView(&ConfigView{Columns: []string{"Name", "Age"}})
-	prodView, _ := BuildView(&ConfigView{Columns: []string{"Name", "X:.foo", "Y:.bar"}})
+	globalView, err := BuildView(&ConfigView{Columns: []string{"Name", "Age"}})
+	if err != nil {
+		t.Fatal(err)
+	}
+	prodView, err := BuildView(&ConfigView{Columns: []string{"Name", "X:.foo", "Y:.bar"}})
+	if err != nil {
+		t.Fatal(err)
+	}

Also applies to: 45-46

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/ui/views_columns_for_kind_test.go` around lines 32 - 33, The test
currently ignores the error returned by BuildView which can hide parser
regressions; update both occurrences (where v, _ :=
BuildView(&ConfigView{Columns: []string{"Name", "X:.foo"}}) and the similar call
at lines 45-46) to capture the error (e.g., v, err := BuildView(...)) and fail
the test immediately if err != nil (use t.Fatalf or require.NoError) before
assigning ConfigViews = map[string]*View{"pod": v}; this ensures BuildView
errors surface in the test for functions/types BuildView, ConfigView,
ConfigViews and View.

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.

1 participant