Skip to content

feat(ui): surface PromotionRequests when promoting to target-aware Stages - #6814

Draft
jsbroks wants to merge 2 commits into
justin/create-promotion-requestsfrom
justin/promotion-request-ui
Draft

feat(ui): surface PromotionRequests when promoting to target-aware Stages#6814
jsbroks wants to merge 2 commits into
justin/create-promotion-requestsfrom
justin/promotion-request-ui

Conversation

@jsbroks

@jsbroks jsbroks commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Note

Stacked on #6805. Only the last two commits are new here. Because the repo squash-merges, this will need git rebase --onto origin/main <#6805 tip> justin/promotion-request-ui once #6805 lands.

Description

Makes drag-and-drop promotion onto a target-aware Stage work end to end in the UI, and shows what became of the resulting PromotionRequest.

Before this, dragging Freight onto a target-aware Stage left the user with nothing to look at:

  • the promote drawer's onSuccess navigated to the Promotion detail route using the returned PromotionRequest's name, landing on a page for an object that does not exist;
  • the Stage's Promotions tab lists Promotions only, so the request was invisible;
  • and there was no REST endpoint for PromotionRequests in the first place.

Back end

  • GET /v1beta1/projects/{project}/promotion-requests — list, optional ?stage= filter, watch support. Modelled on listPromotions, including the in-process stage filtering that the uncached watch-seed reader requires.
  • GET /v1beta1/projects/{project}/promotion-requests/{promotion-request} — get + watch.
  • Project users get read-only access (get/list/watch) to PromotionRequests. Still no create/update/delete for anyone — the Stage controller and API server own writes.

Front end

  • The promote drawer routes to the Stage when the Stage is target-aware, instead of to a Promotion that will never exist.
  • The Promotions tab lists that Stage's PromotionRequests above the Promotions table: phase, Freight, and either the resolved Targets or a note that the selectors are unresolved.
  • A Ready=False condition is surfaced as a warning banner with its message, so "nothing happened" arrives with its reason.
  • isStageTargetAware mirrors api.IsTargetAware, testing for a present selector list rather than a non-empty one.

A note on the RBAC change

#6789 deliberately gave users no access to PromotionRequests, so the resource would be inert. This PR softens that to read-only, on the grounds that "inert" should mean a user cannot drive the feature, not that they cannot see why their own promotion did nothing. Writes remain closed, and kubectl edit promotionrequest is still denied.

Validation

  • make lint-go, make test-chart, make typecheck-ui, pnpm --dir=ui lint
  • go test ./pkg/server/... ./pkg/controller/management/projects/...
  • New endpoint tests cover empty, populated, name ordering, and stage filtering.

Manual: drag Freight onto a target-aware Stage in the pipeline view, confirm the drawer closes to the Stage and the Promotions tab shows the request with its status.

🤖 Generated with Claude Code

Justin Brooks added 2 commits August 13, 2026 16:15
Adds GET /projects/{project}/promotion-requests (list, optionally filtered
by stage, with watch support) and GET .../promotion-requests/{name},
modelled directly on the Promotion equivalents including the in-process
stage filtering that the uncached watch-seed reader forces.

Grants project users read-only access to PromotionRequests. They still
cannot create, edit, or delete one -- the Stage controller and the API
server own that -- but they can read one, because when a target-aware
Stage stops promoting, the PromotionRequest's status is the only place
the reason is recorded. Withholding reads made the resource inert at the
cost of making the failure invisible, which is the wrong trade for the
object a user's own promotion just produced.

Signed-off-by: Justin Brooks <justin.brooks@akuity.io>
Dragging Freight onto a target-aware Stage produced a PromotionRequest,
and then the UI did two unhelpful things with it: the promote drawer
navigated to the Promotion detail route using the PromotionRequest's
name, landing on a page for an object that does not exist; and the
Stage's Promotions tab, which lists only Promotions, stayed empty. The
user was left with no evidence their promotion had happened at all.

The promote drawer now sends the user to the Stage instead when the
Stage is target-aware, and the Promotions tab lists that Stage's
PromotionRequests above the Promotions table -- phase, Freight, and
either the resolved Targets or a note that the selectors are still
unresolved. When a request carries a Ready=False condition, its message
is shown as a warning above the table, so "nothing happened" comes with
its reason attached.

isStageTargetAware mirrors api.IsTargetAware on the back end, testing for
a present selector list rather than a non-empty one, so a Stage with an
explicitly empty list is still treated as target-aware.

Signed-off-by: Justin Brooks <justin.brooks@akuity.io>
@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 Aug 13, 2026
@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 2.49252% with 978 lines in your changes missing coverage. Please review.
✅ Project coverage is 30.61%. Comparing base (2747237) to head (ab79022).

Files with missing lines Patch % Lines
...client/generated/model_promotion_request_status.go 0.00% 150 Missing ⚠️
...lient/generated/model_promotion_request_summary.go 0.00% 133 Missing ⚠️
pkg/x/client/generated/api_core.go 0.00% 131 Missing ⚠️
pkg/x/client/generated/model_promotion_request.go 0.00% 130 Missing ⚠️
...x/client/generated/model_promotion_request_list.go 0.00% 99 Missing ⚠️
...generated/model_promotion_request_target_status.go 0.00% 96 Missing ⚠️
...x/client/generated/model_promotion_request_spec.go 0.00% 93 Missing ⚠️
pkg/server/get_promotion_request.go 0.00% 55 Missing ⚠️
pkg/server/list_promotion_requests.go 26.47% 48 Missing and 2 partials ⚠️
.../client/generated/model_promotion_request_phase.go 0.00% 41 Missing ⚠️
Additional details and impacted files
@@                         Coverage Diff                          @@
##           justin/create-promotion-requests    #6814      +/-   ##
====================================================================
- Coverage                             30.96%   30.61%   -0.35%     
====================================================================
  Files                                   829      838       +9     
  Lines                                 80900    81903    +1003     
====================================================================
+ Hits                                  25048    25073      +25     
- Misses                                54390    55366     +976     
- Partials                               1462     1464       +2     

☔ 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.

@thomastaylor312 thomastaylor312 left a comment

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.

The backend changes are good. Have a UI person take a look at this once you move out of draft and they can give final approval

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