Skip to content

feat(ui): add a project-level Targets page - #7205

Open
jsbroks wants to merge 2 commits into
justin/stage-fleet-tabfrom
justin/targets-page
Open

jsbroks wants to merge 2 commits into
justin/stage-fleet-tabfrom
justin/targets-page

Conversation

@jsbroks

@jsbroks jsbroks commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Stacked on #7200, which adds the Fleet tab and the Target endpoints this page reads. Diff shown against that branch; merge it first.

Summary

A project that promotes through Targets had no page listing them. The Stage drawer's Fleet tab shows one Stage's Targets; nothing showed the project's Targets themselves or which Stages govern each. This adds a Targets page at /project/<name>/targets.

What

  • One row per Target with its labels and, in a Stages column, the Stages that govern it as the coloured pills the pipeline paints Stages with. A pill opens that Stage's drawer, which for a target-aware Stage opens on its Fleet tab (feat(ui): add a Fleet tab to the Stage drawer listing governed Targets #7200), where that Stage's view of the Target lives. When the Target's status records its health under a Stage, the pill leads with the health icon, as the pipeline's Stage tags do.
  • Governance is evaluated client-side from each Stage's selectors, mirroring the controller. A Target no Stage selects still appears and says so.
  • Group by any label key the Targets carry, discovered from the labels rather than declared. Filter by Target name, label, or Stage.
  • Entry point. A Targets button joins Events and Settings in the project header, shown only once the project has a Target, and the breadcrumb reads Projects > <project> > Targets as the Events and Settings pages do.
  • Pagination. Tables page client-side, since the whole list is already loaded and kept live. The ungrouped table starts at twenty rows with a page-size choice and a running total; each group's table keeps a fixed page of ten and hides its pager when the group fits.
  • Stages and Targets stay live via the existing list-then-watch pattern. The Fleet tab's useWatchTargets gains a project-wide mode when no Stage is given.

Verified

  • pnpm typecheck, pnpm lint, and pnpm vitest run (35 files, 441 tests) pass. targets-utils.test.ts covers selector evaluation, governance, row construction with per-Stage health, grouping, and search.
  • Live against a kind cluster: the header button appears on a project with Targets, the page renders for a 3-Target project and a 40-Target project across 21 Stages, grouping by region works, and clicking a Stage pill lands on the drawer's Fleet tab.

Not in this PR

Per-Stage Freight or Promotion on the page (one click away in the drawer), and a two-pane layout for very large fleets.

Checklist

Eligibility

  • Linked to an existing issue with no blocking labels.
  • Changes documentation only.
  • Changes ten lines or fewer.

Quality

  • Adds or updates corresponding tests.
  • Adds or updates corresponding documentation.

AI Use Disclosure

This PR was written:

  • By a human without AI assistance.
  • By a human with AI assistance. A human has reviewed every line prior to opening the PR.
  • By an AI with human supervision. A human has reviewed every line prior to opening the PR.
  • Entirely by an AI. No human has reviewed this prior to opening the PR.

Sign-Off

All commits:

  • Are signed off by their author (git commit -s) (required)
  • Are cryptographically signed (git commit -S) (encouraged)

🤖 Generated with Claude Code

@kargo-governance-bot kargo-governance-bot Bot added needs/area Issue or PR needs to be labeled to indicate what parts of the code base are affected needs/kind Issue or PR needs to be labeled to clarify its nature needs/priority Priority has not yet been determined; a good signal that maintainers aren't fully committed labels Sep 14, 2026
@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.96%. Comparing base (76978fd) to head (f9df20c).

Additional details and impacted files
@@                   Coverage Diff                   @@
##           justin/stage-fleet-tab    #7205   +/-   ##
=======================================================
  Coverage                   64.96%   64.96%           
=======================================================
  Files                         513      513           
  Lines                       38541    38541           
=======================================================
  Hits                        25040    25040           
  Misses                      13501    13501           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jsbroks
jsbroks force-pushed the justin/stage-fleet-tab branch from 9fa5046 to 76978fd Compare September 14, 2026 22:58
Justin Brooks and others added 2 commits September 14, 2026 19:31
A project that promotes through Targets had no page listing them. The
Stage drawer's Fleet tab shows one Stage's Targets; nothing showed the
project's Targets themselves, or which Stages govern each.

The Targets page lists every Target in the project with its labels and,
for each, the Stages that govern it as the coloured pills the pipeline
paints Stages with. A pill opens that Stage's drawer, which for a
target-aware Stage opens on its Fleet tab, where that Stage's view of the
Target lives. When the Target's status records its health under a Stage,
the pill leads with the health icon, as the pipeline's Stage tags do.

Governance is evaluated client-side from each Stage's selectors, mirroring
the controller, so a Target no Stage selects still appears and says so.
Rows can be grouped by any label key the Targets carry, discovered from
the labels rather than declared, and filtered by Target name, label, or
Stage. Stages and Targets stay live through the existing list-then-watch
pattern; the Fleet tab's Target watch gains a project-wide mode when no
Stage is given.

The page lives at /project/<name>/targets. A Targets button joins Events
and Settings in the project header, shown only once the project has a
Target, and the breadcrumb reads Projects > <project> > Targets as the
Events and Settings pages do.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Justin Brooks <[email protected]>
A fleet can run to hundreds of Targets, and the page rendered every row
at once. Tables now paginate client-side: the whole list is still loaded
and kept live through the watch, only the rendering is paged.

The single ungrouped table starts at twenty rows with a choice of page
size and a running "1-20 of 40 Targets" total. A group's table is one of
many on the page, so it keeps a fixed page of ten and hides its pager
when the group fits.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Justin Brooks <[email protected]>
@jsbroks
jsbroks force-pushed the justin/targets-page branch from 89f6166 to f9df20c Compare September 14, 2026 23:32
@jsbroks
jsbroks marked this pull request as ready for review September 15, 2026 17:24
@jsbroks
jsbroks requested a review from a team as a code owner September 15, 2026 17:24
Comment thread ui/src/pages/project.tsx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we prepare a dedicated component for Targets? Extending Project complicates this component without benefits.

Comment on lines +118 to +127
{row.stages.map(({ stage, health }) => (
<StagePill
key={stage.metadata?.name}
projectName={project}
stage={stage}
health={health}
stageColorMap={stageColorMap}
/>
))}
</Flex>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's limit this to 6, maybe? And add + x more label.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we reuse StageTag?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs/area Issue or PR needs to be labeled to indicate what parts of the code base are affected needs/kind Issue or PR needs to be labeled to clarify its nature needs/priority Priority has not yet been determined; a good signal that maintainers aren't fully committed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants