feat(ui): Headlamp K8s ResourceClasses, CommonComponents & app-bar actions - #5385
Merged
Conversation
…tions Extend the window.pluginLib Headlamp-compat facade so plugins that list and render cluster resources run unmodified: - K8s.ResourceClasses.<Kind>.useList() class hierarchy (KubeObject instances) over the read-only kube-proxy, covering the common core/apps/batch/networking kinds, scoped to the live active cluster. - CommonComponents.SectionBox/SectionHeader (KSail-styled, no MUI dependency). - registerAppBarAction now accepts a bare ReactNode (the canonical headlamp-plugin scaffold form), rendered via a new PluginAppBarActions header slot (DRYed with PluginDetailSections through a shared helper). Verified end-to-end on a kind cluster: a faithful Headlamp-shaped plugin rendered ResourceClasses.Pod.useList() -> 9 live pods inside a SectionBox, plus the app-bar action, sidebar/route, and detail section -- zero errors. The heavier MUI/Redux/React-Router externals remain staged for a follow-up increment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
devantler
marked this pull request as ready for review
June 22, 2026 15:59
devantler
added a commit
that referenced
this pull request
Jun 23, 2026
The Headlamp-compat list surfaces added in #5385 inlined the same cluster-scoped fetch-on-change React effect in two places — makeResourceClass.useList (k8s.ts) and makeK8sShim.useResourceList (pluginLib.ts) — differing only in the item type, the fetch call, and the extra effect deps. jscpd (MegaLinter COPYPASTE, threshold 0%) flagged the two blocks as clones, failing the `🧹 Lint - mega-linter` check on every open PR (MegaLinter full-scans the repo on each PR's merge ref). Extract the shared effect into a generic useClusterScopedList<T>(getCluster, fetchList, deps) hook and have both call sites delegate to it. Behaviour is preserved: same [items, error] return, same cluster-keyed re-fetch, same extra deps (kind/namespace for useResourceList). Drops the now-unused React import from k8s.ts. Validated: web/ui `tsc --noEmit` clean; jscpd reports 0 clones (was 2). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on the now-merged kube-proxy (#5379) and Headlamp plugin foundation (#5370) — both in
main. The diff here is 5 frontend files.What
Extends the
window.pluginLibHeadlamp-compat facade so plugins that list and render cluster resources run unmodified — the next slice of Phase 4c after the proxy:K8s.ResourceClasses.<Kind>.useList()— the Headlamp K8s class hierarchy: auseList()-bearing class per common core/apps/batch/networking kind, yieldingKubeObjectinstances (metadata/spec/status/getName()/getNamespace()), backed by the read-only kube-proxy and scoped to the live active cluster.CommonComponents.SectionBox/SectionHeader— Headlamp's titled layout panels, KSail-styled (no Material UI dependency).registerAppBarActionnow accepts a bareReactNode— the canonicalheadlamp-pluginscaffold form (registerAppBarAction(<span>Hello</span>)) — rendered in the app bar via a newPluginAppBarActionsheader slot (DRYed withPluginDetailSectionsthrough a shared helper).Verified live on a kind cluster
A faithful Headlamp-shaped plugin (hand-written: the
@kinvolk/headlamp-plugintoolchain can't build under Node 26 locally, so this references the exactpluginLibglobals a real bundle would) rendered end-to-end against a real apiserver, with zero errors:K8s.ResourceClasses.Pod.useList()→ 9 live pods (matchedkubectlground truth) inside aSectionBoxregisterAppBarAction(<ReactNode>)) in the headerScope
The heavier UI externals — Material UI / Redux / React-Router (a lazily-loaded
pluginLibchunk so KSail's own bundle stays lean) — remain staged for a follow-up increment. A plugin that imports those does not run yet; one that uses React +register*+ the K8s data layer +CommonComponentsdoes.web/uionly (MegaLinter-excluded); the gate is tsc + vite build, both green.🤖 Generated with Claude Code