diff --git a/apps/console-v5/src/routeTree.gen.ts b/apps/console-v5/src/routeTree.gen.ts index e65e7d13fd6..9cb81a38cb4 100644 --- a/apps/console-v5/src/routeTree.gen.ts +++ b/apps/console-v5/src/routeTree.gen.ts @@ -13,6 +13,8 @@ import { Route as AuthenticatedRouteImport } from './routes/_authenticated' import { Route as IndexRouteImport } from './routes/index' import { Route as LoginIndexRouteImport } from './routes/login/index' import { Route as LoginAuth0CallbackRouteImport } from './routes/login/auth0-callback' +import { Route as AuthenticatedPreviewCodeRouteImport } from './routes/_authenticated/preview-code' +import { Route as AuthenticatedHelmDefaultValuesRouteImport } from './routes/_authenticated/helm-default-values' import { Route as AuthenticatedOrganizationRouteRouteImport } from './routes/_authenticated/organization/route' import { Route as AuthenticatedOrganizationIndexRouteImport } from './routes/_authenticated/organization/index' import { Route as AuthenticatedAcceptInvitationIndexRouteImport } from './routes/_authenticated/accept-invitation/index' @@ -101,15 +103,21 @@ import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnviron import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdOverviewRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/cloud-shell' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/deployment/$deploymentId/pre-check-logs' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/route' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/route' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/route' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsRouteRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/route' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringRouteRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/route' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/index' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/index' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/index' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/index' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/index' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsIndexRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/index' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' +import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseResourcesRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources' import { Route as AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseGeneralRouteImport } from './routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general' @@ -161,6 +169,18 @@ const LoginAuth0CallbackRoute = LoginAuth0CallbackRouteImport.update({ path: '/login/auth0-callback', getParentRoute: () => rootRouteImport, } as any) +const AuthenticatedPreviewCodeRoute = + AuthenticatedPreviewCodeRouteImport.update({ + id: '/preview-code', + path: '/preview-code', + getParentRoute: () => AuthenticatedRoute, + } as any) +const AuthenticatedHelmDefaultValuesRoute = + AuthenticatedHelmDefaultValuesRouteImport.update({ + id: '/helm-default-values', + path: '/helm-default-values', + getParentRoute: () => AuthenticatedRoute, + } as any) const AuthenticatedOrganizationRouteRoute = AuthenticatedOrganizationRouteRouteImport.update({ id: '/organization', @@ -859,6 +879,14 @@ const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironm getParentRoute: () => AuthenticatedOrganizationOrganizationIdRouteRoute, } as any, ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteImport.update( + { + id: '/project/$projectId/environment/$environmentId/service/create/helm', + path: '/project/$projectId/environment/$environmentId/service/create/helm', + getParentRoute: () => AuthenticatedOrganizationOrganizationIdRouteRoute, + } as any, + ) const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRoute = AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteImport.update( { @@ -891,6 +919,15 @@ const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironm getParentRoute: () => AuthenticatedOrganizationOrganizationIdRouteRoute, } as any, ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRouteImport.update( + { + id: '/', + path: '/', + getParentRoute: () => + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute, + } as any, + ) const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRoute = AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRouteImport.update( { @@ -935,6 +972,42 @@ const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironm getParentRoute: () => AuthenticatedOrganizationOrganizationIdRouteRoute, } as any, ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRouteImport.update( + { + id: '/values-override-file', + path: '/values-override-file', + getParentRoute: () => + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute, + } as any, + ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRouteImport.update( + { + id: '/values-override-arguments', + path: '/values-override-arguments', + getParentRoute: () => + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute, + } as any, + ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRouteImport.update( + { + id: '/summary', + path: '/summary', + getParentRoute: () => + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute, + } as any, + ) +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRouteImport.update( + { + id: '/general', + path: '/general', + getParentRoute: () => + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute, + } as any, + ) const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRoute = AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRouteImport.update( { @@ -1217,6 +1290,8 @@ const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironm export interface FileRoutesByFullPath { '/': typeof IndexRoute '/organization': typeof AuthenticatedOrganizationRouteRouteWithChildren + '/helm-default-values': typeof AuthenticatedHelmDefaultValuesRoute + '/preview-code': typeof AuthenticatedPreviewCodeRoute '/login/auth0-callback': typeof LoginAuth0CallbackRoute '/login': typeof LoginIndexRoute '/organization/$organizationId': typeof AuthenticatedOrganizationOrganizationIdRouteRouteWithChildren @@ -1302,6 +1377,7 @@ export interface FileRoutesByFullPath { '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsRouteRouteWithChildren '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRouteWithChildren '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteWithChildren + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteWithChildren '/organization/$organizationId/project/$projectId/environment/$environmentId/deployment/$deploymentId/pre-check-logs': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/cloud-shell': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdOverviewRoute @@ -1338,17 +1414,24 @@ export interface FileRoutesByFullPath { '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseGeneralRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseResourcesRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsLogsExecutionIdRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsAlertIdEditRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsCreateMetricMetricRoute } export interface FileRoutesByTo { '/': typeof IndexRoute + '/helm-default-values': typeof AuthenticatedHelmDefaultValuesRoute + '/preview-code': typeof AuthenticatedPreviewCodeRoute '/login/auth0-callback': typeof LoginAuth0CallbackRoute '/login': typeof LoginIndexRoute '/onboarding/personalize': typeof AuthenticatedOnboardingPersonalizeRoute @@ -1458,11 +1541,16 @@ export interface FileRoutesByTo { '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseGeneralRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseResourcesRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRoute + '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsLogsExecutionIdRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsAlertIdEditRoute '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsCreateMetricMetricRoute @@ -1472,6 +1560,8 @@ export interface FileRoutesById { '/': typeof IndexRoute '/_authenticated': typeof AuthenticatedRouteWithChildren '/_authenticated/organization': typeof AuthenticatedOrganizationRouteRouteWithChildren + '/_authenticated/helm-default-values': typeof AuthenticatedHelmDefaultValuesRoute + '/_authenticated/preview-code': typeof AuthenticatedPreviewCodeRoute '/login/auth0-callback': typeof LoginAuth0CallbackRoute '/login/': typeof LoginIndexRoute '/_authenticated/organization/$organizationId': typeof AuthenticatedOrganizationOrganizationIdRouteRouteWithChildren @@ -1557,6 +1647,7 @@ export interface FileRoutesById { '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsRouteRouteWithChildren '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRouteWithChildren '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteWithChildren + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteWithChildren '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/deployment/$deploymentId/pre-check-logs': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/cloud-shell': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdOverviewRoute @@ -1593,11 +1684,16 @@ export interface FileRoutesById { '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseGeneralRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseResourcesRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseSummaryRoute + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsIndexRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringIndexRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsIndexRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugIndexRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseIndexRoute + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsLogsExecutionIdRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsAlertIdEditRoute '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric': typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringAlertsCreateMetricMetricRoute @@ -1607,6 +1703,8 @@ export interface FileRouteTypes { fullPaths: | '/' | '/organization' + | '/helm-default-values' + | '/preview-code' | '/login/auth0-callback' | '/login' | '/organization/$organizationId' @@ -1692,6 +1790,7 @@ export interface FileRouteTypes { | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' | '/organization/$organizationId/project/$projectId/environment/$environmentId/deployment/$deploymentId/pre-check-logs' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/cloud-shell' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview' @@ -1728,17 +1827,24 @@ export interface FileRouteTypes { | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric' fileRoutesByTo: FileRoutesByTo to: | '/' + | '/helm-default-values' + | '/preview-code' | '/login/auth0-callback' | '/login' | '/onboarding/personalize' @@ -1848,11 +1954,16 @@ export interface FileRouteTypes { | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database' + | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit' | '/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric' @@ -1861,6 +1972,8 @@ export interface FileRouteTypes { | '/' | '/_authenticated' | '/_authenticated/organization' + | '/_authenticated/helm-default-values' + | '/_authenticated/preview-code' | '/login/auth0-callback' | '/login/' | '/_authenticated/organization/$organizationId' @@ -1946,6 +2059,7 @@ export interface FileRouteTypes { | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/deployment/$deploymentId/pre-check-logs' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/cloud-shell' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/overview' @@ -1982,11 +2096,16 @@ export interface FileRouteTypes { | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/general' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/resources' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug/' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/' + | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/deployments/logs/$executionId' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit' | '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/create/metric/$metric' @@ -2029,6 +2148,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LoginAuth0CallbackRouteImport parentRoute: typeof rootRouteImport } + '/_authenticated/preview-code': { + id: '/_authenticated/preview-code' + path: '/preview-code' + fullPath: '/preview-code' + preLoaderRoute: typeof AuthenticatedPreviewCodeRouteImport + parentRoute: typeof AuthenticatedRoute + } + '/_authenticated/helm-default-values': { + id: '/_authenticated/helm-default-values' + path: '/helm-default-values' + fullPath: '/helm-default-values' + preLoaderRoute: typeof AuthenticatedHelmDefaultValuesRouteImport + parentRoute: typeof AuthenticatedRoute + } '/_authenticated/organization': { id: '/_authenticated/organization' path: '/organization' @@ -2645,6 +2778,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRouteImport parentRoute: typeof AuthenticatedOrganizationOrganizationIdRouteRoute } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' + path: '/project/$projectId/environment/$environmentId/service/create/helm' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdRouteRoute + } '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database': { id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database' path: '/project/$projectId/environment/$environmentId/service/create/database' @@ -2673,6 +2813,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdMonitoringRouteRouteImport parentRoute: typeof AuthenticatedOrganizationOrganizationIdRouteRoute } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/' + path: '/' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute + } '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/': { id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/' path: '/' @@ -2708,6 +2855,34 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdDeploymentsIndexRouteImport parentRoute: typeof AuthenticatedOrganizationOrganizationIdRouteRoute } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' + path: '/values-override-file' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute + } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' + path: '/values-override-arguments' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute + } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' + path: '/summary' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute + } + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general': { + id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' + path: '/general' + fullPath: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' + preLoaderRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRouteImport + parentRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute + } '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary': { id: '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database/summary' path: '/summary' @@ -3312,6 +3487,33 @@ const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironm AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteChildren, ) +interface AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteChildren { + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute +} + +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteChildren: AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteChildren = + { + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmGeneralRoute, + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmSummaryRoute, + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideArgumentsRoute, + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmValuesOverrideFileRoute, + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmIndexRoute, + } + +const AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteWithChildren = + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute._addFileChildren( + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteChildren, + ) + interface AuthenticatedOrganizationOrganizationIdRouteRouteChildren { AuthenticatedOrganizationOrganizationIdAlertsRouteRoute: typeof AuthenticatedOrganizationOrganizationIdAlertsRouteRouteWithChildren AuthenticatedOrganizationOrganizationIdSettingsRouteRoute: typeof AuthenticatedOrganizationOrganizationIdSettingsRouteRouteWithChildren @@ -3344,6 +3546,7 @@ interface AuthenticatedOrganizationOrganizationIdRouteRouteChildren { AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsRouteRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdSettingsRouteRouteWithChildren AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRouteWithChildren AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteWithChildren + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteWithChildren AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRoute AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdOverviewRoute: typeof AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdOverviewRoute @@ -3420,6 +3623,8 @@ const AuthenticatedOrganizationOrganizationIdRouteRouteChildren: AuthenticatedOr AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateSlugRouteRouteWithChildren, AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRoute: AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateDatabaseRouteRouteWithChildren, + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRoute: + AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceCreateHelmRouteRouteWithChildren, AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute: AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdDeploymentDeploymentIdPreCheckLogsRoute, AuthenticatedOrganizationOrganizationIdProjectProjectIdEnvironmentEnvironmentIdServiceServiceIdCloudShellRoute: @@ -3466,6 +3671,8 @@ const AuthenticatedOrganizationRouteRouteWithChildren = interface AuthenticatedRouteChildren { AuthenticatedOrganizationRouteRoute: typeof AuthenticatedOrganizationRouteRouteWithChildren + AuthenticatedHelmDefaultValuesRoute: typeof AuthenticatedHelmDefaultValuesRoute + AuthenticatedPreviewCodeRoute: typeof AuthenticatedPreviewCodeRoute AuthenticatedOnboardingPersonalizeRoute: typeof AuthenticatedOnboardingPersonalizeRoute AuthenticatedOnboardingPlansRoute: typeof AuthenticatedOnboardingPlansRoute AuthenticatedOnboardingProjectRoute: typeof AuthenticatedOnboardingProjectRoute @@ -3475,6 +3682,8 @@ interface AuthenticatedRouteChildren { const AuthenticatedRouteChildren: AuthenticatedRouteChildren = { AuthenticatedOrganizationRouteRoute: AuthenticatedOrganizationRouteRouteWithChildren, + AuthenticatedHelmDefaultValuesRoute: AuthenticatedHelmDefaultValuesRoute, + AuthenticatedPreviewCodeRoute: AuthenticatedPreviewCodeRoute, AuthenticatedOnboardingPersonalizeRoute: AuthenticatedOnboardingPersonalizeRoute, AuthenticatedOnboardingPlansRoute: AuthenticatedOnboardingPlansRoute, diff --git a/apps/console-v5/src/routes/_authenticated/helm-default-values.tsx b/apps/console-v5/src/routes/_authenticated/helm-default-values.tsx new file mode 100644 index 00000000000..44cd9d8d470 --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/helm-default-values.tsx @@ -0,0 +1,27 @@ +import { createFileRoute } from '@tanstack/react-router' +import { z } from 'zod' +import { HelmDefaultValuesPreview } from '@qovery/domains/service-helm/feature' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +const helmDefaultValuesSearchSchema = z.object({ + payload: z + .union([ + z.string(), + z.object({ + environmentId: z.string(), + helmDefaultValuesRequest: z.unknown(), + }), + ]) + .optional(), +}) + +export const Route = createFileRoute('/_authenticated/helm-default-values')({ + component: HelmDefaultValues, + validateSearch: helmDefaultValuesSearchSchema, +}) + +function HelmDefaultValues() { + useDocumentTitle('Default values.yaml') + + return +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general.tsx new file mode 100644 index 00000000000..2c5bda85eaf --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general.tsx @@ -0,0 +1,29 @@ +import { createFileRoute, useNavigate } from '@tanstack/react-router' +import { AnnotationSetting, LabelSetting } from '@qovery/domains/organizations/feature' +import { HelmStepGeneral } from '@qovery/domains/service-helm/feature' +import { serviceCreateParamsSchema } from '@qovery/shared/router' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/general' +)({ + component: General, + validateSearch: serviceCreateParamsSchema, +}) + +function General() { + const { organizationId = '', projectId = '', environmentId = '' } = Route.useParams() + const search = Route.useSearch() + const navigate = useNavigate() + const creationFlowUrl = `/organization/${organizationId}/project/${projectId}/environment/${environmentId}/service/create/helm` + + useDocumentTitle('General - Create Helm') + + return ( + navigate({ to: `${creationFlowUrl}/values-override-file`, search })} + labelSetting={} + annotationSetting={} + /> + ) +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/index.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/index.tsx new file mode 100644 index 00000000000..fb79a20e01d --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/index.tsx @@ -0,0 +1,23 @@ +import { Navigate, createFileRoute, useParams } from '@tanstack/react-router' +import { serviceCreateParamsSchema } from '@qovery/shared/router' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/' +)({ + component: RouteComponent, + validateSearch: serviceCreateParamsSchema, +}) + +function RouteComponent() { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) + const search = Route.useSearch() + + return ( + + ) +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/route.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/route.tsx new file mode 100644 index 00000000000..0485a7d153a --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/route.tsx @@ -0,0 +1,19 @@ +import { Outlet, createFileRoute, useParams } from '@tanstack/react-router' +import { HelmCreationFlow } from '@qovery/domains/service-helm/feature' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm' +)({ + component: RouteComponent, +}) + +function RouteComponent() { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) + const creationFlowUrl = `/organization/${organizationId}/project/${projectId}/environment/${environmentId}/service/create/helm` + + return ( + + + + ) +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary.tsx new file mode 100644 index 00000000000..8b9b0ef817f --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary.tsx @@ -0,0 +1,22 @@ +import { createFileRoute } from '@tanstack/react-router' +import { useAnnotationsGroups, useLabelsGroups } from '@qovery/domains/organizations/feature' +import { HelmStepSummary } from '@qovery/domains/service-helm/feature' +import { serviceCreateParamsSchema } from '@qovery/shared/router' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/summary' +)({ + component: Summary, + validateSearch: serviceCreateParamsSchema, +}) + +function Summary() { + const { organizationId = '' } = Route.useParams() + const { data: labelsGroup = [] } = useLabelsGroups({ organizationId }) + const { data: annotationsGroup = [] } = useAnnotationsGroups({ organizationId }) + + useDocumentTitle('Summary - Create Helm') + + return +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments.tsx new file mode 100644 index 00000000000..5dbbcdbfd30 --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments.tsx @@ -0,0 +1,37 @@ +import { Navigate, createFileRoute } from '@tanstack/react-router' +import { HelmStepValuesOverrideArguments, useHelmCreateContext } from '@qovery/domains/service-helm/feature' +import { serviceCreateParamsSchema } from '@qovery/shared/router' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-arguments' +)({ + component: ValuesOverrideArguments, + validateSearch: serviceCreateParamsSchema, +}) + +function ValuesOverrideArguments() { + const { organizationId = '', projectId = '', environmentId = '' } = Route.useParams() + const search = Route.useSearch() + const { generalForm } = useHelmCreateContext() + const generalValues = generalForm.getValues() + + useDocumentTitle('Values override as arguments - Create Helm') + + if (!generalValues.name || !generalValues.source_provider) { + return ( + + ) + } + + return +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file.tsx new file mode 100644 index 00000000000..b0260a4a5bc --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file.tsx @@ -0,0 +1,37 @@ +import { Navigate, createFileRoute } from '@tanstack/react-router' +import { HelmStepValuesOverrideFile, useHelmCreateContext } from '@qovery/domains/service-helm/feature' +import { serviceCreateParamsSchema } from '@qovery/shared/router' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +export const Route = createFileRoute( + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm/values-override-file' +)({ + component: ValuesOverrideFile, + validateSearch: serviceCreateParamsSchema, +}) + +function ValuesOverrideFile() { + const { organizationId = '', projectId = '', environmentId = '' } = Route.useParams() + const search = Route.useSearch() + const { generalForm } = useHelmCreateContext() + const generalValues = generalForm.getValues() + + useDocumentTitle('Values override as file - Create Helm') + + if (!generalValues.name || !generalValues.source_provider) { + return ( + + ) + } + + return +} diff --git a/apps/console-v5/src/routes/_authenticated/organization/route.tsx b/apps/console-v5/src/routes/_authenticated/organization/route.tsx index 89aa1572e87..5aa5e114588 100644 --- a/apps/console-v5/src/routes/_authenticated/organization/route.tsx +++ b/apps/console-v5/src/routes/_authenticated/organization/route.tsx @@ -420,6 +420,7 @@ const bypassLayoutRouteIds: FileRouteTypes['id'][] = [ '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/monitoring/alerts/$alertId/edit', '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/$slug', '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/database', + '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/create/helm', ] function useBypassLayout(): boolean { diff --git a/apps/console-v5/src/routes/_authenticated/preview-code.tsx b/apps/console-v5/src/routes/_authenticated/preview-code.tsx new file mode 100644 index 00000000000..2773c83a138 --- /dev/null +++ b/apps/console-v5/src/routes/_authenticated/preview-code.tsx @@ -0,0 +1,99 @@ +import { createFileRoute, useLocation } from '@tanstack/react-router' +import { z } from 'zod' +import { CodeEditor, CopyToClipboardButtonIcon, EmptyState, Heading, Section } from '@qovery/shared/ui' +import { useDocumentTitle } from '@qovery/shared/util-hooks' + +interface PreviewCodeRouteState { + code?: string +} + +const previewCodeSearchSchema = z.object({ + language: z.string().optional(), + title: z.string().optional(), + description: z.string().optional(), +}) + +type PreviewCodeRouteSearch = z.infer + +function isPreviewCodeRouteState(value: unknown): value is PreviewCodeRouteState { + return typeof value === 'object' && value !== null && (!('code' in value) || typeof value.code === 'string') +} + +function getPreviewCodeState(state: unknown): PreviewCodeRouteState | undefined { + return isPreviewCodeRouteState(state) ? state : undefined +} + +function getPreviewMetadata(search: PreviewCodeRouteSearch) { + return { + title: search.title ?? 'Preview code', + description: search.description ?? 'Read-only preview.', + language: search.language ?? 'yaml', + } +} + +function hasPreviewContent(state?: PreviewCodeRouteState, search?: PreviewCodeRouteSearch) { + return Boolean(state?.code || search?.title || search?.description || search?.language) +} + +interface PreviewCodeHeaderProps { + title: string + description: string + language: string + code: string +} + +function PreviewCodeHeader({ title, description, language, code }: PreviewCodeHeaderProps) { + return ( +
+
+ {title} +

{description}

+
+ +
+ + {language} + + +
+
+ ) +} + +export const Route = createFileRoute('/_authenticated/preview-code')({ + component: PreviewCode, + validateSearch: previewCodeSearchSchema, +}) + +function PreviewCode() { + const location = useLocation() + const state = getPreviewCodeState(location.state) + const search = Route.useSearch() + const { title, description, language } = getPreviewMetadata(search) + const code = state?.code ?? '' + + useDocumentTitle(title) + + if (!hasPreviewContent(state, search)) { + return ( +
+ +
+ ) + } + + return ( +
+ + +
+ +
+
+ ) +} diff --git a/apps/console/src/app/app.tsx b/apps/console/src/app/app.tsx index ee7d2a7a8c4..19e391c9bfe 100644 --- a/apps/console/src/app/app.tsx +++ b/apps/console/src/app/app.tsx @@ -14,7 +14,6 @@ import { useNavigationType, } from 'react-router-dom' import { KubeconfigPreview } from '@qovery/domains/clusters/feature' -import { HelmDefaultValuesPreview } from '@qovery/domains/service-helm/feature' import { DarkModeEnabler, Layout } from '@qovery/pages/layout' import { PageLogin, PageLogoutFeature } from '@qovery/pages/login' import { AssistantContext } from '@qovery/shared/assistant/feature' @@ -22,7 +21,7 @@ import { useAuth, useInviteMember } from '@qovery/shared/auth' import { devopsCopilotAxios } from '@qovery/shared/devops-copilot/data-access' import { DevopsCopilotContext } from '@qovery/shared/devops-copilot/feature' import { ProtectedRoute } from '@qovery/shared/router' -import { HELM_DEFAULT_VALUES, KUBECONFIG, LOGIN_URL, LOGOUT_URL, PREVIEW_CODE } from '@qovery/shared/routes' +import { KUBECONFIG, LOGIN_URL, LOGOUT_URL, PREVIEW_CODE } from '@qovery/shared/routes' import { LoadingScreen } from '@qovery/shared/ui' import { useCaptureUtmParams, useDocumentTitle } from '@qovery/shared/util-hooks' import { DEVOPS_COPILOT_API_BASE_URL } from '@qovery/shared/util-node-env' @@ -126,7 +125,6 @@ export function App() { } /> } /> } /> - } /> } /> {ROUTER.map((route) => route.layout ? ( diff --git a/libs/domains/service-helm/feature/src/index.ts b/libs/domains/service-helm/feature/src/index.ts index 58af04aec8d..ac49c51d2c9 100644 --- a/libs/domains/service-helm/feature/src/index.ts +++ b/libs/domains/service-helm/feature/src/index.ts @@ -9,3 +9,8 @@ export * from './lib/hooks/use-helm-repositories/use-helm-repositories' export * from './lib/hooks/use-create-helm-service/use-create-helm-service' export * from './lib/hooks/use-helm-default-values/use-helm-default-values' export * from './lib/hooks/use-kubernetes-services/use-kubernetes-services' +export * from './lib/helm-creation-flow/helm-creation-flow' +export * from './lib/helm-creation-flow/step-general/step-general' +export * from './lib/helm-creation-flow/step-values-override-arguments/step-values-override-arguments' +export * from './lib/helm-creation-flow/step-values-override-files/step-values-override-files' +export * from './lib/helm-creation-flow/step-summary/step-summary' diff --git a/libs/domains/service-helm/feature/src/lib/deployment-setting/deployment-setting.tsx b/libs/domains/service-helm/feature/src/lib/deployment-setting/deployment-setting.tsx index 42a37b36bab..0673fe9f0a6 100644 --- a/libs/domains/service-helm/feature/src/lib/deployment-setting/deployment-setting.tsx +++ b/libs/domains/service-helm/feature/src/lib/deployment-setting/deployment-setting.tsx @@ -45,7 +45,7 @@ export function DeploymentSetting() {

{((watchCmdArguments && watchChartName && watchVersion) || watchBranch) && ( -
+
Helm install format: {!watchBranch ? ( diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-create-utils/helm-create-utils.ts b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-create-utils/helm-create-utils.ts new file mode 100644 index 00000000000..82ab2b3770f --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-create-utils/helm-create-utils.ts @@ -0,0 +1,19 @@ +import { serviceTemplates } from '@qovery/domains/services/feature' + +export interface HelmTemplateMatch { + templateTitle?: string + iconUri?: string +} + +export function findHelmTemplateMatch(template?: string): HelmTemplateMatch { + if (!template) { + return {} + } + + const helmTemplate = serviceTemplates.find((serviceTemplate) => serviceTemplate.slug === template) + + return { + templateTitle: helmTemplate?.title, + iconUri: helmTemplate?.icon_uri, + } +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.spec.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.spec.tsx new file mode 100644 index 00000000000..883c941198e --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.spec.tsx @@ -0,0 +1,53 @@ +import { renderWithProviders, screen } from '@qovery/shared/util-tests' +import { HelmCreationFlow, useHelmCreateContext } from './helm-creation-flow' + +const mockNavigate = jest.fn() +const mockSearch = { + template: 'kubecost', +} + +jest.mock('@qovery/shared/assistant/feature', () => ({ + AssistantTrigger: () => null, +})) + +jest.mock('@tanstack/react-router', () => ({ + ...jest.requireActual('@tanstack/react-router'), + useParams: () => ({ + organizationId: 'org-1', + projectId: 'proj-1', + environmentId: 'env-1', + }), + useNavigate: () => mockNavigate, + useSearch: () => mockSearch, +})) + +function ContextConsumer() { + const { currentStep, creationFlowUrl, generalForm, valuesOverrideFileForm, valuesOverrideArgumentsForm } = + useHelmCreateContext() + + return ( +
+ step={currentStep} url={creationFlowUrl} name={generalForm.getValues('name')} icon= + {generalForm.getValues('icon_uri')} valuesType={valuesOverrideFileForm.getValues('type')} argumentsCount= + {valuesOverrideArgumentsForm.getValues('arguments').length} +
+ ) +} + +describe('HelmCreationFlow', () => { + it('renders and provides helm creation context', () => { + renderWithProviders( + + + + ) + + expect(screen.getByText('General data')).toBeInTheDocument() + expect(screen.getByTestId('context-consumer')).toHaveTextContent('step=1') + expect(screen.getByTestId('context-consumer')).toHaveTextContent('url=/create/helm') + expect(screen.getByTestId('context-consumer')).toHaveTextContent('name=kubecost') + expect(screen.getByTestId('context-consumer')).toHaveTextContent('icon=app://qovery-console/kubecost') + expect(screen.getByTestId('context-consumer')).toHaveTextContent('valuesType=GIT_REPOSITORY') + expect(screen.getByTestId('context-consumer')).toHaveTextContent('argumentsCount=0') + }) +}) diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.tsx new file mode 100644 index 00000000000..f0ad96ad2ce --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-creation-flow.tsx @@ -0,0 +1,110 @@ +import { useNavigate, useParams, useSearch } from '@tanstack/react-router' +import { type Dispatch, type PropsWithChildren, type SetStateAction, createContext, useContext, useState } from 'react' +import { type UseFormReturn, useForm } from 'react-hook-form' +import { type HelmGeneralData } from '@qovery/domains/services/feature' +import { AssistantTrigger } from '@qovery/shared/assistant/feature' +import { FunnelFlow } from '@qovery/shared/ui' +import { type HelmValuesArgumentsData } from '../values-override-arguments-setting/values-override-arguments-setting' +import { type HelmValuesFileData } from '../values-override-files-setting/values-override-files-setting' +import { findHelmTemplateMatch } from './helm-create-utils/helm-create-utils' + +export interface HelmCreateContextInterface { + currentStep: number + setCurrentStep: Dispatch> + creationFlowUrl: string + generalForm: UseFormReturn + valuesOverrideFileForm: UseFormReturn + valuesOverrideArgumentsForm: UseFormReturn +} + +export const HelmCreateContext = createContext(undefined) + +export const useHelmCreateContext = () => { + const helmCreateContext = useContext(HelmCreateContext) + + if (!helmCreateContext) { + throw new Error('useHelmCreateContext must be used within a HelmCreateContext') + } + + return helmCreateContext +} + +export const helmCreationSteps: { title: string }[] = [ + { title: 'General data' }, + { title: 'Values override as file' }, + { title: 'Values override as arguments' }, + { title: 'Summary' }, +] + +export interface HelmCreationFlowProps extends PropsWithChildren { + creationFlowUrl: string +} + +export function HelmCreationFlow({ children, creationFlowUrl }: HelmCreationFlowProps) { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) + const { template } = useSearch({ strict: false }) + const navigate = useNavigate() + const [currentStep, setCurrentStep] = useState(1) + + const templateMatch = findHelmTemplateMatch(template) + + const generalForm = useForm({ + defaultValues: { + name: template ?? '', + icon_uri: templateMatch.iconUri ?? 'app://qovery-console/helm', + arguments: '--wait --atomic --debug', + timeout_sec: 600, + labels_groups: [], + annotations_groups: [], + }, + mode: 'onChange', + }) + + const valuesOverrideFileForm = useForm({ + defaultValues: { + type: 'GIT_REPOSITORY', + }, + mode: 'onChange', + }) + + const valuesOverrideArgumentsForm = useForm({ + defaultValues: { + arguments: [], + }, + mode: 'onChange', + }) + + return ( + + { + if (window.confirm('Do you really want to leave?')) { + navigate({ + to: '/organization/$organizationId/project/$projectId/environment/$environmentId/service/new', + params: { + organizationId, + projectId, + environmentId, + }, + }) + } + }} + totalSteps={helmCreationSteps.length} + currentStep={currentStep} + currentTitle={helmCreationSteps[currentStep - 1]?.title} + > + {children} + + + + ) +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.spec.ts b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.spec.ts new file mode 100644 index 00000000000..f17873d0a60 --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.spec.ts @@ -0,0 +1,149 @@ +import { buildHelmCreatePayload, buildHelmValuesOverrideFile, splitHelmOverridePaths } from './helm-summary-utils' + +describe('helm-summary-utils', () => { + describe('splitHelmOverridePaths', () => { + it('splits override paths on commas and semi-colons and trims blank values', () => { + expect(splitHelmOverridePaths('values/a.yaml; values/b.yaml, ,values/c.yaml;;')).toEqual([ + 'values/a.yaml', + 'values/b.yaml', + 'values/c.yaml', + ]) + }) + + it('returns an empty array when paths are missing', () => { + expect(splitHelmOverridePaths()).toEqual([]) + }) + }) + + describe('buildHelmValuesOverrideFile', () => { + it('returns null for NONE file override type', () => { + expect( + buildHelmValuesOverrideFile({ + type: 'NONE', + }) + ).toBeNull() + }) + }) + + describe('buildHelmCreatePayload', () => { + it('builds a complete HELM create payload with file overrides and arguments', () => { + const payload = buildHelmCreatePayload({ + generalData: { + name: 'helm-app', + description: 'Helm service', + icon_uri: 'app://qovery-console/helm', + source_provider: 'GIT', + provider: 'GITHUB', + branch: 'main', + root_path: '/', + auto_deploy: true, + timeout_sec: '600', + arguments: '--wait --atomic', + allow_cluster_wide_resources: true, + git_repository: { + id: 'repo-1', + name: 'Qovery/console', + url: 'https://github.com/Qovery/console', + default_branch: 'main', + is_private: false, + }, + }, + valuesOverrideFileData: { + type: 'GIT_REPOSITORY', + provider: 'GITHUB', + git_token_id: 'token-1', + branch: 'staging', + repository: 'https://github.com/Qovery/values', + paths: 'values/dev.yaml; values/common.yaml,values/extra.yaml', + auto_deploy: false, + git_repository: { + id: 'repo-2', + name: 'Qovery/values', + url: 'https://github.com/Qovery/values', + default_branch: 'main', + is_private: true, + }, + }, + valuesOverrideArgumentsData: { + arguments: [ + { type: '--set', key: 'image.tag', value: 'v1' }, + { type: '--set-string', key: 'env.NODE_ENV', value: 'production' }, + { type: '--set-json', key: 'resources', value: '', json: '{"limits":{"cpu":"500m"}}' }, + ], + }, + }) + + expect(payload).toEqual({ + name: 'helm-app', + description: 'Helm service', + icon_uri: 'app://qovery-console/helm', + source: { + git_repository: { + url: 'https://github.com/Qovery/console', + branch: 'main', + root_path: '/', + git_token_id: undefined, + }, + }, + allow_cluster_wide_resources: true, + arguments: ['--wait', '--atomic'], + timeout_sec: 600, + auto_deploy: true, + values_override: { + set: [['image.tag', 'v1']], + set_string: [['env.NODE_ENV', 'production']], + set_json: [['resources', '{"limits":{"cpu":"500m"}}']], + file: { + git: { + git_repository: { + provider: 'GITHUB', + url: 'https://github.com/Qovery/values', + branch: 'staging', + git_token_id: 'token-1', + }, + paths: ['values/dev.yaml', 'values/common.yaml', 'values/extra.yaml'], + }, + }, + }, + }) + }) + + it('builds raw yaml values overrides and parses invalid timeout values to 0', () => { + const payload = buildHelmCreatePayload({ + generalData: { + name: 'helm-app', + source_provider: 'HELM_REPOSITORY', + repository: 'helm-repo-1', + chart_name: 'nginx', + chart_version: '1.2.3', + timeout_sec: 'not-a-number', + arguments: '', + auto_deploy: false, + allow_cluster_wide_resources: false, + }, + valuesOverrideFileData: { + type: 'YAML', + content: 'replicaCount: 2', + }, + valuesOverrideArgumentsData: { + arguments: [], + }, + }) + + expect(payload.timeout_sec).toBe(0) + expect(payload.values_override.file).toEqual({ + raw: { + values: [ + { + name: 'override', + content: 'replicaCount: 2', + }, + ], + }, + }) + expect(payload.values_override.set).toEqual([]) + expect(payload.values_override.set_string).toEqual([]) + expect(payload.values_override.set_json).toEqual([]) + }) + }) +}) diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.ts b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.ts new file mode 100644 index 00000000000..c72dfc797eb --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/helm-summary-utils/helm-summary-utils.ts @@ -0,0 +1,100 @@ +import { + type HelmRequest, + type HelmRequestAllOfValuesOverride, + type HelmRequestAllOfValuesOverrideFile, +} from 'qovery-typescript-axios' +import { match } from 'ts-pattern' +import { type HelmGeneralData, buildHelmSourceFromGeneralData } from '@qovery/domains/services/feature' +import { parseCmd } from '@qovery/shared/util-js' +import { + type ArgumentTypes, + type HelmValuesArgumentsData, +} from '../../values-override-arguments-setting/values-override-arguments-setting' +import { type HelmValuesFileData } from '../../values-override-files-setting/values-override-files-setting' + +export interface BuildHelmCreatePayloadProps { + generalData: HelmGeneralData + valuesOverrideFileData: HelmValuesFileData + valuesOverrideArgumentsData: HelmValuesArgumentsData +} + +export function splitHelmOverridePaths(paths?: string): string[] { + if (!paths) { + return [] + } + + return paths + .split(/[;,]/) + .map((path) => path.trim()) + .filter(Boolean) +} + +function getValuesByType( + valuesOverrideArgumentsData: HelmValuesArgumentsData, + type: ArgumentTypes +): Array> { + return valuesOverrideArgumentsData.arguments + .filter((argument) => argument.type === type) + .map((argument) => [argument.key, argument.json ?? argument.value]) +} + +export function buildHelmValuesOverrideFile( + valuesOverrideFileData: HelmValuesFileData +): HelmRequestAllOfValuesOverrideFile | null { + return match(valuesOverrideFileData.type) + .with('GIT_REPOSITORY', () => ({ + git: { + git_repository: { + provider: valuesOverrideFileData.provider ?? 'GITHUB', + url: valuesOverrideFileData.git_repository?.url ?? valuesOverrideFileData.repository ?? '', + branch: valuesOverrideFileData.branch ?? '', + git_token_id: valuesOverrideFileData.git_token_id, + }, + paths: splitHelmOverridePaths(valuesOverrideFileData.paths), + }, + })) + .with('YAML', () => ({ + raw: { + values: [ + { + name: 'override', + content: valuesOverrideFileData.content ?? '', + }, + ], + }, + })) + .with('NONE', () => null) + .exhaustive() +} + +export function buildHelmValuesOverride( + valuesOverrideFileData: HelmValuesFileData, + valuesOverrideArgumentsData: HelmValuesArgumentsData +): HelmRequestAllOfValuesOverride { + return { + set: getValuesByType(valuesOverrideArgumentsData, '--set'), + set_string: getValuesByType(valuesOverrideArgumentsData, '--set-string'), + set_json: getValuesByType(valuesOverrideArgumentsData, '--set-json'), + file: buildHelmValuesOverrideFile(valuesOverrideFileData), + } +} + +export function buildHelmCreatePayload({ + generalData, + valuesOverrideFileData, + valuesOverrideArgumentsData, +}: BuildHelmCreatePayloadProps): HelmRequest { + const timeoutSec = Number.parseInt(String(generalData.timeout_sec), 10) + + return { + name: generalData.name, + description: generalData.description, + icon_uri: generalData.icon_uri, + source: buildHelmSourceFromGeneralData(generalData), + allow_cluster_wide_resources: generalData.allow_cluster_wide_resources, + arguments: parseCmd(generalData.arguments), + timeout_sec: Number.isNaN(timeoutSec) ? 0 : timeoutSec, + auto_deploy: Boolean(generalData.auto_deploy || valuesOverrideFileData.auto_deploy), + values_override: buildHelmValuesOverride(valuesOverrideFileData, valuesOverrideArgumentsData), + } +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.spec.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.spec.tsx new file mode 100644 index 00000000000..e8f86a90513 --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.spec.tsx @@ -0,0 +1,77 @@ +import type { ReactNode } from 'react' +import { renderWithProviders, screen } from '@qovery/shared/util-tests' +import { HelmCreationFlow } from '../helm-creation-flow' +import { HelmStepGeneral } from './step-general' + +const mockOnSubmit = jest.fn() + +jest.mock('@qovery/shared/assistant/feature', () => ({ + AssistantTrigger: () => null, +})) + +jest.mock('@qovery/domains/organizations/feature', () => ({ + GitBranchSettings: () =>
, + GitProviderSetting: () =>
, + GitPublicRepositorySettings: () =>
, + GitRepositorySetting: () =>
, +})) + +jest.mock('../../source-setting/source-setting', () => ({ + SourceSetting: () =>
, +})) + +jest.mock('../../deployment-setting/deployment-setting', () => ({ + DeploymentSetting: () =>
, +})) + +jest.mock('@tanstack/react-router', () => ({ + ...jest.requireActual('@tanstack/react-router'), + useParams: () => ({ + organizationId: 'org-1', + projectId: 'proj-1', + environmentId: 'env-1', + }), + useSearch: () => ({}), + useNavigate: () => jest.fn(), +})) + +jest.mock('@qovery/shared/ui', () => ({ + ...jest.requireActual('@qovery/shared/ui'), + Link: ({ children, ...props }: { children?: ReactNode; [key: string]: unknown }) => {children}, +})) + +const defaultProps = { + labelSetting:
Labels
, + annotationSetting:
Annotations
, + onSubmit: mockOnSubmit, +} + +function renderStepGeneral() { + return renderWithProviders( + + + + ) +} + +describe('HelmStepGeneral', () => { + beforeEach(() => { + mockOnSubmit.mockClear() + }) + + it('renders the general helm form', () => { + renderStepGeneral() + + expect(screen.getByRole('heading', { name: 'General information' })).toBeInTheDocument() + expect(screen.getByRole('heading', { name: 'General' })).toBeInTheDocument() + expect(screen.getByRole('heading', { name: 'Source' })).toBeInTheDocument() + expect(screen.getByTestId('source-setting')).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Continue' })).toBeInTheDocument() + }) + + it('does not render extra labels section before a source is selected', () => { + renderStepGeneral() + + expect(screen.queryByRole('heading', { name: 'Extra labels/annotations' })).not.toBeInTheDocument() + }) +}) diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.tsx new file mode 100644 index 00000000000..4432580ceea --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-general/step-general.tsx @@ -0,0 +1,215 @@ +import * as Collapsible from '@radix-ui/react-collapsible' +import { useNavigate, useParams } from '@tanstack/react-router' +import { type FormEventHandler, type ReactNode, useEffect, useState } from 'react' +import { FormProvider } from 'react-hook-form' +import { + GitBranchSettings, + GitProviderSetting, + GitPublicRepositorySettings, + GitRepositorySetting, +} from '@qovery/domains/organizations/feature' +import { AutoDeploySetting, GeneralSetting, type HelmGeneralData } from '@qovery/domains/services/feature' +import { Button, Callout, FunnelFlowBody, Heading, Icon, Section } from '@qovery/shared/ui' +import { DeploymentSetting } from '../../deployment-setting/deployment-setting' +import { SourceSetting } from '../../source-setting/source-setting' +import { useHelmCreateContext } from '../helm-creation-flow' + +export interface HelmStepGeneralProps { + labelSetting: ReactNode + annotationSetting: ReactNode + onSubmit: (data: HelmGeneralData) => void +} + +export function HelmStepGeneral({ onSubmit, labelSetting, annotationSetting }: HelmStepGeneralProps) { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) + const navigate = useNavigate() + const { generalForm, setCurrentStep } = useHelmCreateContext() + const [openExtraAttributes, setOpenExtraAttributes] = useState(false) + + useEffect(() => { + setCurrentStep(1) + }, [setCurrentStep]) + + const methods = generalForm + + const watchSourceProvider = methods.watch('source_provider') + const watchGitProvider = methods.watch('provider') + const watchGitTokenId = methods.watch('git_token_id') + const watchGitRepository = methods.watch('git_repository') + const watchIsPublicRepository = methods.watch('is_public_repository') + + const isGitSettingsValid = watchSourceProvider === 'GIT' ? Boolean(methods.watch('branch')) : true + + const handleSubmit: FormEventHandler = methods.handleSubmit((data) => { + const nextData = { + ...data, + auto_deploy: data.is_public_repository ? false : data.auto_deploy, + } + + methods.reset(nextData) + onSubmit(nextData) + }) + + return ( + + +
+ General information +

+ These general settings allow you to set up the service name, its source and deployment parameters. +

+ +
+
+ General + +
+ +
+ Source + + + {watchSourceProvider === 'GIT' && ( +
+ + {watchIsPublicRepository ? ( + <> + + + + + + + Git automations are disabled when using public repos (auto-deploy, automatic preview + environments) + + + + ) : ( + <> + {watchGitProvider && ( + + )} + {watchGitProvider && watchGitRepository && ( + + )} + + )} +
+ )} +
+ + {watchSourceProvider && ( + <> +
+ Deploy + + {watchSourceProvider === 'GIT' && !watchIsPublicRepository && } + {watchSourceProvider === 'HELM_REPOSITORY' && ( + + + + + + + Git automations are disabled when using Helm repositories (auto-deploy, automatic preview + environments) + + + + )} +
+ + +
+
+ Extra labels/annotations + + {openExtraAttributes ? ( + <> + Hide + + ) : ( + <> + Show + + )} + +
+ + {labelSetting} + {annotationSetting} + +
+
+ + )} + +
+ + +
+
+
+
+
+ ) +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.spec.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.spec.tsx new file mode 100644 index 00000000000..55fcd2b8497 --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.spec.tsx @@ -0,0 +1,96 @@ +import { renderWithProviders, screen } from '@qovery/shared/util-tests' +import { HelmSummaryView } from './helm-summary-view' + +const defaultProps = { + generalData: { + name: 'helm-app', + description: 'Helm service', + source_provider: 'HELM_REPOSITORY' as const, + repository: 'helm-repo-1', + chart_name: 'nginx', + chart_version: '1.2.3', + arguments: '--wait', + timeout_sec: '600', + allow_cluster_wide_resources: true, + auto_deploy: false, + labels_groups: ['label-1'], + annotations_groups: ['annotation-1'], + }, + valuesOverrideFileData: { + type: 'GIT_REPOSITORY' as const, + provider: 'GITHUB', + repository: 'https://github.com/Qovery/values', + branch: 'main', + paths: 'values.yaml', + auto_deploy: true, + git_repository: { + id: 'repo-2', + name: 'Qovery/values', + url: 'https://github.com/Qovery/values', + default_branch: 'main', + is_private: true, + }, + }, + valuesOverrideArgumentsData: { + arguments: [{ type: '--set' as const, key: 'image.tag', value: 'v1' }], + }, + helmRepositories: [{ id: 'helm-repo-1', name: 'Qovery Helm Repository' }], + labelsGroup: [{ id: 'label-1', name: 'platform' }], + annotationsGroup: [{ id: 'annotation-1', name: 'monitoring' }], + onEditGeneral: jest.fn(), + onEditValuesOverrideFile: jest.fn(), + onEditValuesOverrideArguments: jest.fn(), + onBack: jest.fn(), + onSubmit: jest.fn(), + isLoadingCreate: false, + isLoadingCreateAndDeploy: false, +} + +describe('HelmSummaryView', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('renders all summary sections', () => { + renderWithProviders() + + expect(screen.getByRole('heading', { name: 'Ready to create your Helm chart' })).toBeInTheDocument() + expect(screen.getByText('General information')).toBeInTheDocument() + expect(screen.getByText('Values override as file')).toBeInTheDocument() + expect(screen.getByText('Values override as arguments')).toBeInTheDocument() + expect(screen.getByText(/Qovery Helm Repository/)).toBeInTheDocument() + expect(screen.getByText(/platform/)).toBeInTheDocument() + expect(screen.getByText(/monitoring/)).toBeInTheDocument() + }) + + it('calls edit and submit actions', async () => { + const { userEvent } = renderWithProviders() + + await userEvent.click(screen.getByTestId('edit-general-button')) + await userEvent.click(screen.getByTestId('edit-values-file-button')) + await userEvent.click(screen.getByTestId('edit-values-arguments-button')) + await userEvent.click(screen.getByRole('button', { name: 'Back' })) + await userEvent.click(screen.getByTestId('button-create')) + await userEvent.click(screen.getByTestId('button-create-deploy')) + + expect(defaultProps.onEditGeneral).toHaveBeenCalled() + expect(defaultProps.onEditValuesOverrideFile).toHaveBeenCalled() + expect(defaultProps.onEditValuesOverrideArguments).toHaveBeenCalled() + expect(defaultProps.onBack).toHaveBeenCalled() + expect(defaultProps.onSubmit).toHaveBeenCalledWith(false) + expect(defaultProps.onSubmit).toHaveBeenCalledWith(true) + }) + + it('renders the empty argument state', () => { + renderWithProviders( + + ) + + expect(screen.getByText('No argument override defined')).toBeInTheDocument() + }) +}) diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.tsx new file mode 100644 index 00000000000..be69c71668f --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/helm-summary-view.tsx @@ -0,0 +1,263 @@ +import { + type HelmRepositoryResponse, + type OrganizationAnnotationsGroupResponse, + type OrganizationLabelsGroupEnrichedResponse, +} from 'qovery-typescript-axios' +import { match } from 'ts-pattern' +import { type HelmGeneralData } from '@qovery/domains/services/feature' +import { Button, Heading, Icon, Section, Truncate } from '@qovery/shared/ui' +import { type HelmValuesArgumentsData } from '../../values-override-arguments-setting/values-override-arguments-setting' +import { type HelmValuesFileData } from '../../values-override-files-setting/values-override-files-setting' + +export interface HelmSummaryViewProps { + generalData: HelmGeneralData + valuesOverrideFileData: HelmValuesFileData + valuesOverrideArgumentsData: HelmValuesArgumentsData + helmRepositories: HelmRepositoryResponse[] + labelsGroup: OrganizationLabelsGroupEnrichedResponse[] + annotationsGroup: OrganizationAnnotationsGroupResponse[] + onEditGeneral: () => void + onEditValuesOverrideFile: () => void + onEditValuesOverrideArguments: () => void + onBack: () => void + onSubmit: (withDeploy: boolean) => void + isLoadingCreate: boolean + isLoadingCreateAndDeploy: boolean +} + +function EditSectionButton({ onClick, label, testId }: { onClick: () => void; label: string; testId: string }) { + return ( + + ) +} + +function SummaryValue({ label, value, testId }: { label: string; value: string | number | boolean; testId?: string }) { + return ( +
  • + {label}: {String(value)} +
  • + ) +} + +export function HelmSummaryView({ + generalData, + valuesOverrideFileData, + valuesOverrideArgumentsData, + helmRepositories, + labelsGroup, + annotationsGroup, + onEditGeneral, + onEditValuesOverrideFile, + onEditValuesOverrideArguments, + onBack, + onSubmit, + isLoadingCreate, + isLoadingCreateAndDeploy, +}: HelmSummaryViewProps) { + const selectedLabels = labelsGroup + .filter(({ id }) => generalData.labels_groups?.includes(id)) + .map(({ name }) => name) + .join(', ') + const selectedAnnotations = annotationsGroup + .filter(({ id }) => generalData.annotations_groups?.includes(id)) + .map(({ name }) => name) + .join(', ') + + const autoDeployLabel = match({ + sourceProvider: generalData.source_provider, + chartAutoDeploy: Boolean(generalData.auto_deploy), + valuesType: valuesOverrideFileData.type, + valuesAutoDeploy: Boolean(valuesOverrideFileData.auto_deploy), + }) + .with( + { + sourceProvider: 'GIT', + chartAutoDeploy: true, + valuesType: 'GIT_REPOSITORY', + valuesAutoDeploy: true, + }, + () => 'On (chart and values)' + ) + .with({ sourceProvider: 'GIT', chartAutoDeploy: true }, () => 'On (chart)') + .with( + { sourceProvider: 'HELM_REPOSITORY', valuesType: 'GIT_REPOSITORY', valuesAutoDeploy: true }, + () => 'On (values)' + ) + .otherwise(() => 'Off') + + return ( +
    +
    + Ready to create your Helm chart +

    + The Helm setup is ready. Review your configuration, then create the service or create and deploy it. +

    +
    + +
    +
    +
    + General information + +
    +
      + + {generalData.description ? ( +
    • + Description: +
      + {generalData.description} +
    • + ) : null} +
    • +
      +
    • + + {generalData.source_provider === 'GIT' ? ( + <> + + + + + ) : ( + <> + id === generalData.repository)?.name ?? + generalData.repository ?? + '-' + } + /> + + + + )} + +
    • +
      +
    • + + + + + {selectedLabels ? : null} + {selectedAnnotations ? : null} +
    +
    + +
    +
    + Values override as file + +
    +
      + {match(valuesOverrideFileData.type) + .with('GIT_REPOSITORY', () => ( + <> + + + + + + + + )) + .with('YAML', () => ( + <> + +
    • + Override content:{' '} + +
    • + + )) + .with('NONE', () => ) + .exhaustive()} +
    +
    + +
    +
    + Values override as arguments + +
    + {valuesOverrideArgumentsData.arguments.length > 0 ? ( +
      + + {valuesOverrideArgumentsData.arguments.map((argument, index) => ( +
    • + {argument.type} {argument.key}:{' '} + +
    • + ))} +
    + ) : ( +
      + +
    + )} +
    +
    + +
    + +
    + + +
    +
    +
    + ) +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.spec.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.spec.tsx new file mode 100644 index 00000000000..fe70066ba6e --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.spec.tsx @@ -0,0 +1,200 @@ +import { renderWithProviders, screen, waitFor } from '@qovery/shared/util-tests' +import { HelmStepSummary } from './step-summary' + +const mockNavigate = jest.fn() +const mockSetCurrentStep = jest.fn() +const mockCreateHelmService = jest.fn() +const mockDeployService = jest.fn() +const mockCapture = jest.fn() +const mockUseHelmCreateContext = jest.fn() + +jest.mock('posthog-js', () => ({ + capture: (...args: unknown[]) => mockCapture(...args), +})) + +jest.mock('@tanstack/react-router', () => ({ + ...jest.requireActual('@tanstack/react-router'), + useParams: () => ({ + organizationId: 'org-1', + projectId: 'proj-1', + environmentId: 'env-1', + }), + useSearch: () => ({ + template: 'kubecost', + }), + useNavigate: () => mockNavigate, +})) + +jest.mock('@qovery/domains/services/feature', () => ({ + ...jest.requireActual('@qovery/domains/services/feature'), + useDeployService: () => ({ mutateAsync: mockDeployService }), +})) + +jest.mock('../../hooks/use-create-helm-service/use-create-helm-service', () => ({ + useCreateHelmService: () => ({ mutateAsync: mockCreateHelmService }), +})) + +jest.mock('../../hooks/use-helm-repositories/use-helm-repositories', () => ({ + useHelmRepositories: () => ({ data: [] }), +})) + +jest.mock('../helm-creation-flow', () => ({ + helmCreationSteps: Array.from({ length: 4 }, () => ({ title: 'step' })), + useHelmCreateContext: () => mockUseHelmCreateContext(), +})) + +jest.mock('./helm-summary-view', () => ({ + HelmSummaryView: ({ onSubmit }: { onSubmit: (withDeploy: boolean) => void }) => ( +
    +

    Ready to create your Helm chart

    + + +
    + ), +})) + +const baseContextValue = { + creationFlowUrl: '/organization/org-1/project/proj-1/environment/env-1/service/create/helm', + setCurrentStep: mockSetCurrentStep, + generalForm: { + getValues: () => ({ + name: 'helm-app', + description: 'Helm service', + icon_uri: 'app://qovery-console/helm', + source_provider: 'GIT', + provider: 'GITHUB', + branch: 'main', + root_path: '/', + auto_deploy: true, + timeout_sec: '600', + arguments: '--wait --atomic', + allow_cluster_wide_resources: true, + git_repository: { + id: 'repo-1', + name: 'Qovery/console', + url: 'https://github.com/Qovery/console', + default_branch: 'main', + is_private: false, + }, + }), + }, + valuesOverrideFileForm: { + getValues: () => ({ + type: 'GIT_REPOSITORY', + provider: 'GITHUB', + git_token_id: 'token-1', + branch: 'staging', + repository: 'https://github.com/Qovery/values', + paths: 'values/dev.yaml; values/common.yaml', + auto_deploy: false, + git_repository: { + id: 'repo-2', + name: 'Qovery/values', + url: 'https://github.com/Qovery/values', + default_branch: 'main', + is_private: true, + }, + }), + }, + valuesOverrideArgumentsForm: { + getValues: () => ({ + arguments: [ + { type: '--set', key: 'image.tag', value: 'v1' }, + { type: '--set-json', key: 'resources', value: '', json: '{"limits":{"cpu":"500m"}}' }, + ], + }), + }, +} + +function setup() { + mockUseHelmCreateContext.mockReturnValue(baseContextValue) + + return renderWithProviders() +} + +describe('HelmStepSummary', () => { + beforeEach(() => { + jest.clearAllMocks() + mockUseHelmCreateContext.mockReturnValue(baseContextValue) + mockCreateHelmService.mockResolvedValue({ id: 'helm-1' }) + mockDeployService.mockResolvedValue(undefined) + }) + + it('creates the HELM service and navigates to overview', async () => { + const { userEvent } = setup() + + expect(screen.getByRole('heading', { name: 'Ready to create your Helm chart' })).toBeInTheDocument() + expect(mockSetCurrentStep).toHaveBeenCalledWith(4) + + await userEvent.click(screen.getByTestId('button-create')) + + await waitFor(() => { + expect(mockCreateHelmService).toHaveBeenCalledWith({ + environmentId: 'env-1', + helmRequest: { + name: 'helm-app', + description: 'Helm service', + icon_uri: 'app://qovery-console/helm', + source: { + git_repository: { + url: 'https://github.com/Qovery/console', + branch: 'main', + root_path: '/', + git_token_id: undefined, + }, + }, + allow_cluster_wide_resources: true, + arguments: ['--wait', '--atomic'], + timeout_sec: 600, + auto_deploy: true, + values_override: { + set: [['image.tag', 'v1']], + set_string: [], + set_json: [['resources', '{"limits":{"cpu":"500m"}}']], + file: { + git: { + git_repository: { + provider: 'GITHUB', + url: 'https://github.com/Qovery/values', + branch: 'staging', + git_token_id: 'token-1', + }, + paths: ['values/dev.yaml', 'values/common.yaml'], + }, + }, + }, + }, + }) + }) + + expect(mockNavigate).toHaveBeenCalledWith({ + to: '/organization/$organizationId/project/$projectId/environment/$environmentId/overview', + params: { + organizationId: 'org-1', + projectId: 'proj-1', + environmentId: 'env-1', + }, + }) + expect(mockCapture).toHaveBeenCalledWith('create-service', { + selectedServiceType: 'helm', + selectedServiceSubType: 'kubecost', + }) + }) + + it('deploys after create when create and deploy is clicked', async () => { + const { userEvent } = setup() + + await userEvent.click(screen.getByTestId('button-create-deploy')) + + await waitFor(() => { + expect(mockDeployService).toHaveBeenCalledWith({ + serviceId: 'helm-1', + serviceType: 'HELM', + }) + }) + }) +}) diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.tsx new file mode 100644 index 00000000000..961e6b18041 --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-summary/step-summary.tsx @@ -0,0 +1,106 @@ +import { useNavigate, useParams, useSearch } from '@tanstack/react-router' +import posthog from 'posthog-js' +import { + type OrganizationAnnotationsGroupResponse, + type OrganizationLabelsGroupEnrichedResponse, +} from 'qovery-typescript-axios' +import { useEffect, useState } from 'react' +import { useDeployService } from '@qovery/domains/services/feature' +import { FunnelFlowBody } from '@qovery/shared/ui' +import { useCreateHelmService } from '../../hooks/use-create-helm-service/use-create-helm-service' +import { useHelmRepositories } from '../../hooks/use-helm-repositories/use-helm-repositories' +import { helmCreationSteps, useHelmCreateContext } from '../helm-creation-flow' +import { buildHelmCreatePayload } from '../helm-summary-utils/helm-summary-utils' +import { HelmSummaryView } from './helm-summary-view' + +export interface HelmStepSummaryProps { + labelsGroup: OrganizationLabelsGroupEnrichedResponse[] + annotationsGroup: OrganizationAnnotationsGroupResponse[] +} + +export function HelmStepSummary({ labelsGroup, annotationsGroup }: HelmStepSummaryProps) { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) + const search = useSearch({ strict: false }) + const navigate = useNavigate() + const { creationFlowUrl, generalForm, valuesOverrideFileForm, valuesOverrideArgumentsForm, setCurrentStep } = + useHelmCreateContext() + const [submitMode, setSubmitMode] = useState<'create' | 'create-and-deploy' | null>(null) + + const generalData = generalForm.getValues() + const valuesOverrideFileData = valuesOverrideFileForm.getValues() + const valuesOverrideArgumentsData = valuesOverrideArgumentsForm.getValues() + + const { mutateAsync: createHelmService } = useCreateHelmService() + const { mutateAsync: deployService } = useDeployService({ organizationId, projectId, environmentId }) + const { data: helmRepositories = [] } = useHelmRepositories({ organizationId }) + + useEffect(() => { + setCurrentStep(helmCreationSteps.length) + }, [setCurrentStep]) + + useEffect(() => { + if (!generalData.name || !generalData.source_provider) { + navigate({ to: `${creationFlowUrl}/general`, search }) + } + }, [creationFlowUrl, generalData.name, generalData.source_provider, navigate, search]) + + const handleSubmit = async (withDeploy: boolean) => { + setSubmitMode(withDeploy ? 'create-and-deploy' : 'create') + + try { + const service = await createHelmService({ + environmentId, + helmRequest: buildHelmCreatePayload({ + generalData, + valuesOverrideFileData, + valuesOverrideArgumentsData, + }), + }) + + if (withDeploy) { + await deployService({ + serviceId: service.id, + serviceType: 'HELM', + }) + } + + posthog.capture('create-service', { + selectedServiceType: 'helm', + selectedServiceSubType: search.template ?? 'current', + }) + + navigate({ + to: '/organization/$organizationId/project/$projectId/environment/$environmentId/overview', + params: { + organizationId, + projectId, + environmentId, + }, + }) + } catch { + // errors are surfaced by mutation notifications + } finally { + setSubmitMode(null) + } + } + + return ( + + navigate({ to: `${creationFlowUrl}/general`, search })} + onEditValuesOverrideFile={() => navigate({ to: `${creationFlowUrl}/values-override-file`, search })} + onEditValuesOverrideArguments={() => navigate({ to: `${creationFlowUrl}/values-override-arguments`, search })} + onBack={() => navigate({ to: `${creationFlowUrl}/values-override-arguments`, search })} + onSubmit={handleSubmit} + isLoadingCreate={submitMode === 'create'} + isLoadingCreateAndDeploy={submitMode === 'create-and-deploy'} + /> + + ) +} diff --git a/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-values-override-arguments/step-values-override-arguments.spec.tsx b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-values-override-arguments/step-values-override-arguments.spec.tsx new file mode 100644 index 00000000000..3cfd9b9214d --- /dev/null +++ b/libs/domains/service-helm/feature/src/lib/helm-creation-flow/step-values-override-arguments/step-values-override-arguments.spec.tsx @@ -0,0 +1,105 @@ +import { useForm } from 'react-hook-form' +import { type HelmGeneralData } from '@qovery/domains/services/feature' +import { renderHook, renderWithProviders, screen } from '@qovery/shared/util-tests' +import { type HelmValuesArgumentsData } from '../../values-override-arguments-setting/values-override-arguments-setting' +import { type HelmValuesFileData } from '../../values-override-files-setting/values-override-files-setting' +import { HelmCreateContext } from '../helm-creation-flow' +import { HelmStepValuesOverrideArguments } from './step-values-override-arguments' + +const mockNavigate = jest.fn() + +jest.mock('@qovery/domains/variables/feature', () => ({ + CodeEditorVariable: ({ value, onChange }: { value?: string; onChange?: (value?: string) => void }) => ( + + +
  • -
    + +