feat(tekton): Pipeline/PipelineRun/TaskRun integration — detail views, live DAG, CI/CD fleet tab - #1627
feat(tekton): Pipeline/PipelineRun/TaskRun integration — detail views, live DAG, CI/CD fleet tab#1627jfillman wants to merge 33 commits into
Conversation
…rogress Tekton had zero integration despite the Helm chart already granting tekton.dev read RBAC by default. Adds detail-drawer support for Pipeline, PipelineRun, and TaskRun (topology-graph integration deliberately deferred to a later PR — this is detail-view only): - Pipeline: renders its declared task-dependency graph (parsed from spec.tasks[].runAfter plus implicit ordering inferred from $(tasks.<name>.results.*) references), reusing @xyflow/react at a small, static-diagram scale rather than a new hand-rolled SVG. - PipelineRun: the same graph with live per-task coloring, sourced from tekton.dev/v1's status.childReferences (a PipelineRun only names its child TaskRuns, not their outcome, so the host wrapper fans out one fetch per child — same pattern as CompositeRenderer's composed-resource status resolution). Deliberately DAG-only, not DAG-plus-linear-list: unlike Argo Rollouts' single sequential promotion path, Tekton tasks form a genuine DAG with parallel branches that a list would misrepresent. - TaskRun: per-step status, parameters, results. Table columns, resource icons, and docs (README + integrations.md) updated per the CRD Integration Guide's non-topology steps.
Feedback from live testing on the first cut: the embedded drawer DAG had overlapping, hard-to-follow lines, tasks weren't clickable, and the graph had no business being in the compact drawer in the first place. - PipelineDagView now lays out with ELK.js (same engine + options as the main Topology view: layered/RIGHT/ORTHOGONAL/NETWORK_SIMPLEX) instead of a hand-rolled rank/row placement — NETWORK_SIMPLEX minimizes edge crossings, which is what was actually missing. Task nodes mirror K8sResourceNode's visual language (topology-node-card, icon + kind-label header, status dot) so a task reads as the same kind of thing as a real topology node, without extending the shared NodeKind enum or wiring Tekton into pkg/topology/builder.go. - The DAG moved out of the compact drawer entirely into the resource's fullscreen "full view" (TektonPipelineFullscreen, wired via renderExpandedOverview — the same seam Argo Workflows/Jobs already use for their own execution views). The compact PipelineRenderer / PipelineRunRenderer now just point at the full view instead of trying to cram a graph into a few hundred pixels. - Task nodes are clickable when they have a live TaskRun (taskRunName now flows through TektonTaskNode) and open that TaskRun's own page via onNavigateToResource — reusing the existing resource-navigation pattern instead of a bespoke panel. - TaskRun's Steps section gained per-step "Logs" buttons wired to the dock's useOpenLogs (Tekton names each step's container `step-<name>`) — real streaming step logs, not just exit codes. - Running tasks keep the spinning Loader2 + blue coloring from the first cut (confirmed against a live run) plus a pulse on the card itself. Live-verified end-to-end against a throwaway 5-task Pipeline with a real in-flight task: clean non-overlapping layout, correct running/pending/ succeeded coloring, click-through to the TaskRun page, and real log streaming from its pod.
Clicking a task node opens its TaskRun via the app's generic "drill into a related resource while expanded" navigation, which — by design, for every kind, not just Tekton — points the backdrop route at the new resource's own list rather than back at the resource you came from. So "Go back"/collapse lands on the bare TaskRun list, not the PipelineRun you clicked from. Rather than change that shared, heavily-used mechanism, surface an explicit way back — the same idea as GitOps's parent-lineage breadcrumb. TaskRuns always carry an ownerReference to their PipelineRun, so this needs no click-time breadcrumb param and works from any entry point (direct link, search, not just the DAG). A small "↑ Back to PipelineRun <name>" link now sits at the top of the TaskRun view and navigates there directly. Live-verified: click a task in a PipelineRun's full view → TaskRun page → click the new link → back on the same PipelineRun's full view.
Two issues from live testing:
1. The TaskRun's Logs tab fell through to the generic MultiPodLogsTab (a
pod-picker built for N-pod workloads), rendering a row of pod bubbles for
a resource that only ever has one pod. A TaskRun's real shape is one pod
with one container per step (Tekton names them `step-<name>`), running
sequentially — the opposite of what that picker is for.
Added TaskRunLogsTab: fetches every step's container in one call to the
existing /api/pods/{ns}/{pod}/logs endpoint (already returns all
containers when no `container` param is given), splits each into
per-line entries client-side, and combines them into one sequential
LogCore view in declared step order. Each line is labeled by step via a
new `showContainerName` prop on LogCore, mirroring the existing
`showPodName` used by the multi-pod viewer — same pattern, other axis.
2. Run Info's "Pod" field was plain text. It's now a ResourceLink (the same
component GitOps/RBAC use for cross-resource links) into the pod itself.
Live-verified against a real 3-step TaskRun: Logs tab shows all three
steps' output concatenated in order with real timestamps, no pod-picker;
Pod field navigates to the Pod's own page.
The link lived inside the TaskRun's Overview body — easy to miss below the badges and "Managed by" chip. Moved it into the same header chip row as ManagedByChip/OpenInGitOpsChip (in both the compact drawer and full view headers), styled the same way (a small skyhook-colored pill), instead of a plain text link buried in the content. The derivation itself is unchanged (TaskRun's ownerReferences), just relocated from TaskRunRenderer's body to WorkloadView's shared header — consistent with how GitOps ownership already gets a header chip there rather than living in each renderer.
Step names were truncating at 140px — too tight for real pipelines whose step names run 20+ characters (e.g. "step-start-build-stage-span").
A dedicated top-level view (new left-rail entry, /cicd) for operating on
Tekton PipelineRuns as a fleet, rather than only reachable one at a time
through the generic Resources browser:
- Header stat tiles (Total/Running/Succeeded/Failed/Success Rate, plus a
Tasks Running count from TaskRuns) — each status tile doubles as a
one-click filter, same pattern as GitOps's fleet header.
- Status and Pipeline facets in a filter rail, plus a search box, all
computed client-side from the already-cached PipelineRun list (no new
backend endpoints).
- Rich table rows: status badge, referenced Pipeline, a progress bar keyed
off status.childReferences vs declared task count (colored by outcome,
pulsing while running), duration, and age. The bar's denominator uses
whichever of {declared, started} is larger so a `matrix`-strategy task
(one declared task expanding into several childReferences) never renders
as a backwards fraction like "12/7".
- Clicking a row opens the PipelineRun directly in the expanded full view
(skipping the collapsed drawer, since the DAG only renders there) via the
same navigateToResource-records-the-peek-owner mechanism GitOps and
Applications already use — so the header's "Go back"/collapse control
returns to the CI/CD tab instead of the generic PipelineRuns list.
Live-verified end-to-end: stat tiles and facets against 5 real PipelineRuns,
row click opening a running PipelineRun straight into its live DAG, and
back-navigation returning to /cicd.
panOnScroll + zoomOnScroll were both enabled with no translateExtent bound, so an ordinary wheel/trackpad scroll over the panel (which has no page scroll of its own) silently panned the graph's nodes off- screen — reported as "the diagram appears, then blanks out". Drop panOnScroll to match the other two ReactFlow views in this codebase (TopologyGraph, GitOpsTreeGraph), which rely on the zoom-on-scroll default with no pan-on-scroll, and bound min/max zoom like GitOpsTreeGraph. Also adds the Controls (zoom in/out/fit-to-screen).
- Column headers are now clickable and sort the PipelineRun table (name, status, pipeline, progress, duration, started). - Header restyled to match GitOps: PageHeader (left-aligned title + description, right-aligned FreshnessControl + stat tiles) instead of a hand-rolled title row. - Filter sidebar gets a "Filters" header with a Clear link, matching GitOpsFilterSidebar. - Root layout gets flex-1 min-w-0, fixing a right-edge gap where the view stopped short of the window width instead of filling it.
navigateToResource opens a peek outside /resources (CICD, GitOps, Applications) purely via React state, with no URL backing — that's what lets "Go back" return to the origin page. But drilling one hop further (e.g. PipelineRun -> TaskRun via the DAG, or TaskRun -> back to its PipelineRun) went through the other onNavigateToResource handler, which unconditionally navigates to /resources/<kind>. That silently relocated the backdrop into the Resources page, so a later "Go back" landed on the generic resource list instead of back on the CICD tab (or wherever the peek started). Branch on the current pathname: only navigate to /resources/<kind> when already there (the existing "list follows the drill" behavior for genuine Resources-page drilling); otherwise update state only, same as navigateToResource, so the backdrop never moves.
A peek opened directly to fullscreen (CICD table rows skip the small drawer entirely) had nothing for "Go back"/collapse to fall back to, so it collapsed into a small drawer the user never saw — confusing, since there was no smaller state to "return" to. Track whether the current peek ever visited the small state (peekOpenedFullRef, reset on every normal navigateToResource open, set by the CICD opener right after); onCollapse now closes outright for peeks that skipped it.
Each PipelineRun row gets a trailing actions menu (reusing the shared RowActionMenu): - Cancel run — patches spec.status to "Cancelled", enabled only while the run is actually running. - Delete PipelineRun — the existing generic delete endpoint, behind a confirmation dialog. Rows switch from <button> to a keyboard-accessible div (role="button", Enter/Space handled) since a real <button> can't host the menu's own nested button without producing invalid HTML.
…ve pipelines Root-caused via a real platform-cicd pipeline with 11 tasks/28 edges, comparing DOM state (node visibility, edge count, ReactFlow viewport transform) between a healthy render and a blanked one — the data layer (task statuses, ELK layout, taskKey) was identical in both; only the DOM differed. @xyflow/system's adoptUserNodes rebuilds a node's internal record from scratch whenever the incoming node object isn't the exact same reference as last render — true on every poll here, since the task array was rebuilt fresh each time (useQueries returns a new array every render; the outer tasks/onTaskClick were unstabilized on top of that). The rebuild resets `measured` to undefined and clears cached handle bounds, so the node goes visibility:hidden and its edges drop out until a ResizeObserver fires to remeasure it — which never happens once the card's on-screen size stops changing, since there's nothing new to report. Denser real pipelines hit this far more (more polling, more edges converging on shared "hub" tasks like tracing spans) than the sparse synthetic pipelines used earlier, which is why it didn't reproduce there. Two changes close it: - PipelineDagView: give every node explicit `measured` (width/height) and `handles` (position/x/y for its target+source connection points) up front, so both node visibility and edge connection points are answered from data instead of a live DOM measurement, independent of object identity. Also wraps the ReactFlow render in an error boundary so a future bad state renders a message instead of a silent blank. - TektonPipelineFullscreen: stabilize the tasks array by a content signature (only produces a new reference when a task's status/reason/ taskRunName actually changed) and memoize the task-click handler — removes the poll-driven churn that was the recurring trigger.
Matches the "Select multiple resources" pattern from the main Resources table: a toggle button enters select mode (checkboxes per row + a select-all header checkbox, row clicks toggle selection instead of opening the drawer, the per-row actions menu hides), a selection bar shows the count with Delete/Cancel, and Delete goes through the existing useBulkDeleteResources mutation (parallel, partial-failure-safe) behind a confirmation dialog listing the targets.
Resolves the PipelineRun's pipelineRef to a real, navigable Pipeline resource and opens it in the drawer on click — a direct name ref lives in the run's own namespace, a cluster resolver ref carries its own namespace param (platform-cicd's catalog pipelines live in a shared namespace, not the run's, confirmed live). Other resolvers (git/http/bundle) fetch the spec from outside the cluster, so there's no live Pipeline object to open — those stay plain text. Opens as a normal small drawer (not straight-to-fullscreen like a PipelineRun row) since a Pipeline is a static template, not something actively progressing.
…arrows Pipeline task graphs fan out/in much more densely than the topology view's own ownership hierarchy (several governance-check tasks depending on one upstream task, converging on one downstream task) - the default spacing (carried over from Topology's own numbers, and even tighter in edge/edge and edge/node spacing, which wasn't set at all) let parallel edges visually run together. Widens node/edge spacing, adds edge-edge/edge-node spacing that wasn't set before, turns on mergeEdges so edges sharing an endpoint bundle into one trunk instead of fanning out the whole way, and raises crossing- minimization thoroughness (cheap at this task-graph size).
nodesDraggable was hardcoded off with no persistence path. Now nodes are draggable, and dropping one persists every node's current position to localStorage keyed by the task set's own shape (names + dependency edges) - so a saved layout is naturally shared across every PipelineRun of the same underlying Pipeline, not tied to one specific run. A "Reset layout" panel button (shown only once a manual layout exists) clears the override and restores ELK's auto-computed positions. Structural re-layout (ELK) still only runs when the task set/dependency shape changes; live status polling updates node data in place without touching positions, whether auto-laid-out or hand-placed - unchanged from before, just applied to a mutable node-position state (useNodesState) instead of a derived-every-render array.
The pulsing opacity + spinning icon alone were easy to miss at a glance across a busy pipeline DAG. Adds a sky-hued background wash and ring, matching the icon's existing sky-500 running color, so a running task is readable without having to spot the animation.
animate-pulse animates the whole card element's opacity, not just its color - combined with the alpha-blended sky background from the previous change, the card became translucent at the pulse's low point and let the DAG's edge lines show straight through it (user-reported live testing). Switched to a solid (non-alpha) background wash and removed animate-pulse from the card entirely; the icon's own animate-spin still carries the "in progress" motion cue.
Rebasing onto current upstream/main conflicted on the pinned counts this branch's foundational commit set (upstream's own curated-column table grew independently in the meantime). Resolved to upstream's current baseline plus this branch's own +3 (Pipeline/PipelineRun/TaskRun), then verified against a real test run rather than computed by hand.
PR Summary by QodoAdd Tekton pipeline views, live DAG, and CI/CD fleet
AI Description
Diagram
High-Level Assessment
Files changed (24)
|
Code Review by Qodo
1.
|
buildPipelineTaskGraph correctly infers a task dependency from a $(tasks.X.results.Y) param reference in addition to explicit runAfter — but real pipelines commonly pipe a value (a trace ID, a shared config blob) from an early task into nearly every later task's params. Each of those is a genuine Tekton ordering constraint, but when it's already implied by a longer runAfter chain, drawing it as a direct edge too puts a fan of redundant arrows into one node instead of the single "runs right after X" edge a reader expects. Found live on the real "build" Pipeline (platform-catalog namespace): build-source's only runAfter is start-build-stage-span, but it also references start-flow's and validate-config's results for tracing/ config — both already ancestors of start-build-stage-span — producing 3 arrows into build-source instead of 1. Added a standard transitive-reduction pass: drop a dependency only when it's also reachable through one of the task's other direct dependencies, so genuinely independent deps (a real fan-in) are left untouched. New tests pin both the real-pipeline scenario and a diamond fan-out/fan-in case that must survive unreduced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
buildPipelineTaskGraph only read pipelineSpec.tasks, so a Pipeline's
finally tasks — cleanup/notify steps Tekton always runs after every
regular task settles, success or failure — were invisible in Pipeline
and PipelineRun DAGs, and undercounted in every "N tasks" readout
(PipelineRenderer, the Resources table's Pipeline column, the CI/CD
fleet's progress fraction).
finally tasks don't support runAfter (Tekton rejects the field there),
and the real ordering constraint is absolute — every finally task
waits for the WHOLE regular task graph to settle, not just the tasks
it happens to read a result from. Modeled that as a dependency on
every regular task with nothing else depending on it (the graph's own
terminal/leaf tasks), plus each finally task's own explicit
$(tasks.X.results.Y) refs; the existing transitive-reduction pass then
drops any of those that are already implied by a barrier edge.
Verified against the real "build" Pipeline (platform-catalog
namespace, 5 finally tasks including end-flow, notify, and
send-cdevent) — every finally task now correctly depends on the 3 true
terminal regular tasks (pipelinerun-started, image-scan,
generate-sbom), matching Tekton's actual scheduling.
Found independently by both the qodo-code-review and cursor[bot]
automated PR reviews ("Finally tasks omitted").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… last one buildChildTaskRunRefs keyed its map by pipelineTaskName alone, so a matrix-strategy task's several childReferences (one per parameter combination, all sharing that name) overwrote each other — only the last-listed sibling's status ever reached the DAG, and a click could land on an arbitrary matrix child instead of an actionable one. Return every childReference per task name instead of one, fan out a query per actual TaskRun (not per declared task), and collapse the results with worst-status-wins ranking (failed > running > unknown/ pending > skipped > succeeded) — a single failure among nine successes now surfaces as failed, and the DAG node's navigation target is the failed sibling, not whichever happened to be listed last. Also fixed a second, related staleness bug in the same component: the fullscreen DAG's array-stabilization signature covered name/status/ reason/taskRunName but not dependsOn, so a Pipeline edit that changed runAfter or a result-ref dependency without renaming any task left the DAG showing the old topology until something else (a status change) happened to bust the cache. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A task Tekton decides not to run (a false when guard, or a parent that failed/was itself skipped) never gets a childReference — the same absence-from-the-map signal applyTaskRunStatuses used for "not reached yet." A completed PipelineRun with a skipped task therefore showed it as permanently pending, with no way to tell "hasn't started" from "was never going to run." Tekton already records the distinction in status.skippedTasks[], with the reason it decided to skip each one. Read that and mark a matching task 'skipped' (surfacing the real reason) before falling back to 'pending' — PipelineDagView already has skipped styling, it just never got exercised for this case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
qodo/cursor flagged the TaskRun-to-parent-PipelineRun chip as always
null, blaming a plural/singular mismatch — that specific claim doesn't
hold: WorkloadView's kind prop is a plural ("taskruns"), but the
component already derives a singular `kind = pluralToKind(kindProp)`
before the comparison, and once API discovery has populated the
dynamic map (effectively always, by the time a user can navigate to a
TaskRun), pluralToKind('taskruns') correctly resolves to 'TaskRun'.
There's a real, narrower gap behind the same finding though:
BUILTIN_PLURAL_TO_KIND (the fallback used before discovery completes)
never had Tekton's kinds, even though it already seeds Argo Workflow's
for exactly this reason. Tekton's "Run" suffix doesn't naively
de-pluralize to the right casing either — the heuristic fallback would
produce "Taskrun", not "TaskRun" — so a very early render, or a
restricted-RBAC cluster where Tekton CRD discovery is delayed, could
still show the chip as missing. Seeded pipelines/pipelineruns/taskruns
the same way workflows already are.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…y list runsQuery.data falling back to `?? []` on a failed fetch meant an RBAC denial, a backend error, or a discovery failure all rendered as "No PipelineRuns found" — a healthy-looking empty fleet indistinguishable from an actual problem. Added an explicit error branch (special-cased for 403) with a Retry button. The Tasks Running tile now also treats its own query error the same as still-loading — a 0 there was a false zero, not a real count, same reasoning the component's own loading prop already documents. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…x a log race Three related TaskRun log bugs, found by qodo-code-review: - Container names were synthesized as step-<name> in three places instead of reading status.steps[].container, the field Tekton actually reports. Every live example checked matches the synthesized form today, but Tekton doesn't guarantee it once a step name gets sanitized or truncated to fit Kubernetes' container-name limit — the authoritative field is one field access away and was sitting unused (one comment even claimed it wasn't reported back, which isn't true). Kept the synthesized form only as a fallback for an older/stripped status shape. - TaskRunLogsTab fetched one snapshot on mount and never again unless the user manually refreshed — output from a currently running step stayed invisible. Added polling every 5s while the TaskRun's Succeeded condition hasn't settled, stopping as soon as it does (or the component unmounts). - The same fetch had no guard against out-of-order responses: if podName changed (a different TaskRun) while a previous fetch was still in flight, a late-arriving stale response could overwrite the fresh one. Added a request-generation guard, and clear the buffer when the pod actually changes (not on a plain manual refresh of the same pod, which intentionally leaves it alone so the view doesn't flash empty). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e it Opening a PipelineRun from the CI/CD table selects the resource and pushes ?full=1 straight to fullscreen — there's no small-drawer state underneath it (peekOpenedFullRef already exists to mark exactly this case, consulted by the collapse button's onCollapse handler). Browser Back naturally pops that history entry, dropping ?full=1 while leaving selectedResource set — correct behavior for a peek that WAS expanded from an already-open small drawer (it correctly collapses back to one), but for the never-small CI/CD case it left a compact drawer reappearing over the CI/CD table instead of actually closing. Added a Pop-only effect that closes the peek outright in that specific case, mirroring what the collapse button already does via the same peekOpenedFullRef flag — no URL writes, so it can't interact with the file's existing Pop/URL-write-suppression machinery. This file has no automated routing tests and I don't have browser tooling in this session to click through the actual back-button flow — worth a manual spot-check (open a PipelineRun from CI/CD, hit Back) before relying on it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Results
Two comments in PipelineDagView described prior behavior ("not set at
all before", "previously relied on... now a solid...") instead of just
the current rationale — rewritten to state only why the code is what
it is, per this repo's own comment rule.
TaskRun's Parameters and Results sections explicitly defaulted to
collapsed; every other populated section on the same page (Steps, Run
Info) relies on the shared Section component's own default (expanded)
per this repo's stated convention (defaultExpanded unless empty/low-
priority). Parameters/Results are the same plain PropertyList shape as
Run Info, not verbose or low-priority — often the single most useful
thing on a TaskRun page (what it was given, what it produced) —
dropped the override so they expand by default too.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
There are 3 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit db1d377. Configure here.
…r outranks known statuses Two real bugs cursor found in the fixes from the last round, both confirmed against the actual code: - peekOpenedFullRef was reset only at the top of navigateToResource (a fresh peek open) — every other setSelectedResource(null) call site in this file (list-kind change, route mismatch, Escape, several others) left it untouched. After one CI/CD fullscreen visit, if the peek later closed through any of those other paths, the ref stayed stale true — misclassifying a LATER, legitimately small-drawer-backed peek as never-small the next time either the new Back-close effect or the existing collapse button consulted it, closing it outright instead of collapsing. Added a catch-all effect that clears the ref the instant there's no peek left, regardless of which path closed it. - STATUS_SEVERITY ranked 'unknown' above pending/skipped/succeeded, so aggregateMatrixStatuses could let one matrix sibling's in-flight or permanently-404ing fetch (a garbage-collected TaskRun/pod — a normal race, not an error) mask that the other nine siblings were already known to have succeeded. unknown now ranks last: every other status is something Tekton actually reported, so any of them is more informative than "we don't know" and should win the aggregate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
getTektonPipelineStatus only counted spec.tasks, while the DAG, table, and drawer already count finally tasks too via buildPipelineTaskGraph — a Pipeline with cleanup/notify finally tasks showed a smaller total in its header badge than in its own Tasks section. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
logsTabVisible required allPods.length > 0, and pod discovery for these two kinds only ever succeeds through relationships/timeline attribution — there's no topology-graph awareness of Tekton kinds at all, and the timeline path depends on Radar's own Pod-lifecycle event for that specific pod still being in the fixed-size event ring buffer (ExtractOwner resolves ownerReferences for a Pod's own tracked event, but K8s Event objects attribute to their involvedObject, i.e. the Pod itself, not up the owner chain). On a busy cluster, or for a run from a while ago, that event rotates out and allPods comes up empty — the tab disappears instead of falling back. Added taskruns/pipelineruns to LOGS_TAB_WITHOUT_PODS_KINDS, the same set Jobs/CronJobs/Workflows already use for the identical problem. Each kind's own logs view already handles "no pod found" gracefully (TaskRunLogsTab's "may have been garbage-collected" message, or MultiPodLogsTab's "No pods available" state for PipelineRun) — the tab itself just needs to stay reachable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

A full Tekton integration:
Pipeline/PipelineRun/TaskRundetail views with an embedded, live-updating task DAG, plus a new CI/CD fleet tab for browsing PipelineRuns across the cluster.Test plan
go test ./...make tscnpx vitest run(k8s-ui) — 3388 tests passing🤖 Generated with Claude Code
Note
Medium Risk
Adds cluster list/watch for Tekton CRDs and new mutate/delete/cancel paths from the CI/CD table; log and TaskRun fetch traffic scales with pipeline size and polling, but changes are scoped to Tekton UX rather than core auth or data stores.
Overview
Adds first-class Tekton Pipelines support end to end: the backend dynamic cache watches
Pipeline,PipelineRun, andTaskRun(tekton.devv1/v1beta1), and the UI gets resource-browser columns, detail drawers, status badges, icons, and navigation fixes for*Runkind names.Pipeline / PipelineRun use compact drawers for params, workspaces, and run metadata; the task dependency graph lives only in the fullscreen expanded view (
PipelineDagView+TektonPipelineFullscreen). The graph is built fromrunAfterand implicit$(tasks.*.results.*)deps (includingfinallytasks), with transitive edge reduction, ELK layout, live per-task coloring on PipelineRuns (child TaskRun fetches, matrix aggregation, skipped-task handling), draggable nodes with optional saved layout, and clicks through to TaskRuns.TaskRuns get step status with per-step Logs (dock) and a dedicated Logs tab that merges all step containers sequentially via new
LogCoreshowContainerName. A header chip links back to the owning PipelineRun.A new
/cicdCI/CD view lists PipelineRuns fleet-wide with stats, facets, sort, cancel/delete (including bulk delete), task-start progress bars, and row open straight to fullscreen DAG;App.tsxpeek/back behavior is adjusted so CI/CD–opened full drawers close correctly on browser Back and in-drawer drill-down stays on the origin page when not on/resources.Documentation in README and
docs/integrations.mddescribes supported CRDs and UX.Reviewed by Cursor Bugbot for commit e707104. Bugbot is set up for automated code reviews on this repo. Configure here.