Skip to content

feat(engine-v2): add platform configuration UI - #2817

Open
pggb25 wants to merge 3 commits into
stagingfrom
feat/engine-v2-slice4-platform-configuration
Open

feat(engine-v2): add platform configuration UI#2817
pggb25 wants to merge 3 commits into
stagingfrom
feat/engine-v2-slice4-platform-configuration

Conversation

@pggb25

@pggb25 pggb25 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Here is a PR for self-managed clusters within the scope of the engine V2 POC.
All changes is under feature flag.

Preview can be found here
https://p80-z9693eb24-z7d62c7cc-gtw.zc531a994.rustrocks.cloud/

Existing test cluster is here
https://p80-z9693eb24-z7d62c7cc-gtw.zc531a994.rustrocks.cloud/organization/460616f0-94da-4d35-b631-6fa4ed08eb9a/cluster/8a494a2b-ce45-4499-a3c2-f5c75fbd38dd/settings/platform

What we reuse from the Service Catalog is the normalized field vocabulary and the generic form renderer: field types, defaults, constraints, sensitivity, local validation, and widget selection.
The change on the Service Catalog side was mainly an extraction: Blueprint-specific field utilities and rendering were moved into shared catalog primitives. Blueprints now adapt their DTOs to those primitives, and Platform Configuration does the same with its own q-core DTOs.
The goal is to share the configuration mechanism while keeping the two domains independent.

Screenshots / Recordings

Adding new "Platform configurations" panel in the edit and creation of a self-managed cluster

Screenshot 2026-07-20 at 10 59 04

The idea of the review is to check the godd separation and the good utilisation of the existing service catalogue feature

Testing

  • Changes tested locally in the relevant Console's pages and Storybooks
  • yarn test or yarn test -u (if you need to regenerate snapshots)
  • yarn format
  • yarn lint

PR Checklist

  • I followed naming, styling, and TypeScript rules (see .cursor/rules)
  • I performed a self-review (diff inspected, dead code removed)
  • I titled the PR using Conventional Commits with a scope when possible (e.g. feat(service): add new Terraform service) - required for semantic-release
  • I only kept necessary comments, written in English (watch for useless AI comments)
  • I involved a designer to validate UI changes if I am not a designer
  • I covered new business logic with tests (unit)
  • I confirmed CI is green (Codecov red can be accepted)
  • I reviewed and executed locally any AI-assisted code

@pggb25
pggb25 force-pushed the feat/engine-v2-slice4-platform-configuration branch 4 times, most recently from 84b9344 to 4234d9b Compare July 15, 2026 12:02
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.53846% with 210 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.65%. Comparing base (b6560c5) to head (5d4a623).

Files with missing lines Patch % Lines
.../platform-configuration/platform-configuration.tsx 0.00% 53 Missing ⚠️
...ster-creation-flow/step-platform/step-platform.tsx 61.53% 8 Missing and 22 partials ⚠️
...n-guide-modal/cluster-installation-guide-modal.tsx 37.03% 4 Missing and 13 partials ⚠️
.../catalog-variable-input/catalog-variable-input.tsx 31.81% 6 Missing and 9 partials ⚠️
...luster-creation-flow/step-summary/step-summary.tsx 52.17% 5 Missing and 6 partials ⚠️
...form-configuration/platform-configuration-utils.ts 81.81% 3 Missing and 7 partials ⚠️
...atform-configuration/hooks/use-cluster-operator.ts 0.00% 9 Missing ⚠️
...b/platform-configuration/platform-configuration.ts 70.83% 7 Missing ⚠️
...s/use-platform-template-component-configuration.ts 0.00% 7 Missing ⚠️
.../cluster-creation-flow/cluster-new/cluster-new.tsx 71.42% 5 Missing and 1 partial ⚠️
... and 16 more
Additional details and impacted files
@@             Coverage Diff             @@
##           staging    #2817      +/-   ##
===========================================
- Coverage    48.89%   47.65%   -1.24%     
===========================================
  Files         1212     1272      +60     
  Lines        26400    27678    +1278     
  Branches      7877     8139     +262     
===========================================
+ Hits         12908    13190     +282     
- Misses       11282    12239     +957     
- Partials      2210     2249      +39     
Flag Coverage Δ
unittests 47.65% <61.53%> (-1.24%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

@pggb25
pggb25 force-pushed the feat/engine-v2-slice4-platform-configuration branch 8 times, most recently from e140985 to a2a0d1a Compare July 17, 2026 13:21

@RemiBonnet RemiBonnet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @pggb25! I added few comments and I think you can probably share with @TheoGrandin74 to check if the UI is ok for him. I added after my comments:

  • I'm not sure why I've an error when I click on the Qovery stack in the creation flow, is it something expected?
Image
  • Label aren't supported right now for this kind of cluster, could we hide it?

}

// These endpoints are not generated by qovery-typescript-axios yet. Keeping the raw
// calls behind this data-access module avoids leaking their transport details into UI code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When do you want to add it in the qovery-typescript-axios package?

type PlatformComponentConfigurationPreviewRequest,
PlatformConfigurationApi,
} from 'qovery-typescript-axios'
import { isHttpStatus } from '../http/is-http-status'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure to understand why do you need to return null if it's a 404? Same for cluster-operator.ts file

enabled?: boolean
}

export function useClusterOperatorStatus({ organizationId, clusterId, enabled = true }: ClusterOperatorQueryProps) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You need to have one file per query

<div className="rounded-lg border border-neutral bg-surface-neutral p-5">
<div className="mb-5 flex items-start justify-between gap-3">
<div>
<Heading level={2}>{formatCatalogKey(component.key)}</Heading>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You need to have <Section> component before your Heading

) : null}

{fields.length > 0 ? (
<section className="flex flex-col gap-3">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This one should be <Section>

const { data: binding } = usePlatformBinding({ organizationId, clusterId, suspense: true })
const { mutate: updateBinding, isLoading: isSaving } = useUpdatePlatformBinding()

const [state, setState] = useState<PlatformConfigurationState | null>(() => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you rename it with a more explicit name? platformConfigurationState and setPlatformConfigurationState, in react state is generic

value: CatalogVariableValue | undefined
}

export function CatalogVariableInput({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This component is not enough generic to be in the UI shared library, could you add it in a domain?

)
}

const saveConfiguration = () =>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Inputs that are no longer required remain in customerProvidedInputs, could we filter them against preview.requirements, as we already do in the creation flow?

})}
</Accordion.Root>

<div className="flex justify-between border-t border-neutral pt-4">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can users continue without validating the components of an enabled layer?

const { data: binding } = usePlatformBinding({ organizationId, clusterId, suspense: true })
const { mutate: updateBinding, isLoading: isSaving } = useUpdatePlatformBinding()

const [state, setState] = useState<PlatformConfigurationState | null>(() => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The creation and settings flows duplicate template selection, preview, field updates and payload cleanup, could this shared controller logic live in a domain hook?

const isOperatorGuideLoading =
isFeatureFlagLoading ||
(canUseOperator && (isOperatorStatusLoading || (isOperatorManaged && isOperatorBootstrapLoading)))
// Only a bootstrap failure of a confirmed operator-managed cluster blocks the guide;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should a status request failure fall back to the legacy guide? A transient API error could show incorrect instructions for an operator-managed cluster, I would expect an error state with Retry instead

templateId: string
}

export function PlatformConfiguration({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add small test for this one?

@pggb25
pggb25 force-pushed the feat/engine-v2-slice4-platform-configuration branch from a2a0d1a to 2b24b90 Compare August 17, 2026 08:48
@nx-cloud

nx-cloud Bot commented Aug 17, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 2b24b90

Command Status Duration Result
nx run console:build --parallel=3 --configurati... ✅ Succeeded 1m 5s View ↗
nx affected --target=test --parallel=3 --config... ✅ Succeeded 3m 26s View ↗
nx affected --target=lint --parallel=3 ✅ Succeeded 2m 41s View ↗
nx-cloud record -- yarn nx format:check ✅ Succeeded 7s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-17 09:01:55 UTC

@pggb25
pggb25 force-pushed the feat/engine-v2-slice4-platform-configuration branch from 2b24b90 to 5d4a623 Compare August 17, 2026 08:53
pggb25 and others added 2 commits August 18, 2026 14:07
- guard operator queries against the undefined PostHog flag state (modal,
  create/settings platform routes) so flag-off orgs never hit operator
  endpoints and refreshes no longer bounce users off the platform step
- make engine-v2 cluster creation idempotent on retry and redirect to the
  platform step when platform data is missing instead of failing silently
- fix bool cluster-input requirements round-trip and keep requirement
  inputs mounted during preview refreshes (no more focus loss per keystroke)
- keep cleared field values empty instead of resurrecting schema defaults;
  omit cleared markers from resolver and save payloads
- make components without catalog fields openable so requirement-only
  components can be configured
- exclude Stop / Upgrade K8s actions for self-managed clusters
- restore bool-before-allowedValues precedence in CatalogVariableInput
  (blueprint regression) with a non-regression test
- key PlatformConfiguration by cluster and re-seed when the template list
  changes; surface binding fetch errors instead of redirecting
- add Back navigation to step-platform error/empty states
- drop dead validationMode/componentsConfigurable props, use ts-pattern
  for enum mappers, import catalog types directly from util-js

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pggb25
pggb25 force-pushed the feat/engine-v2-slice4-platform-configuration branch from 5d4a623 to dac7c40 Compare August 18, 2026 12:23
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.

2 participants