From de825a97880c97c2e10dbc8b3726edea09313de3 Mon Sep 17 00:00:00 2001 From: Romain Billard Date: Fri, 27 Mar 2026 11:49:22 +0100 Subject: [PATCH 1/2] feat(new-nav): add "Terraform arguments" settings page --- .../settings/terraform-arguments.tsx | 3 +- .../service-settings/feature/src/index.ts | 1 + .../terraform-arguments-settings.spec.tsx} | 30 ++++++-- .../terraform-arguments-settings.tsx} | 72 +++++++++++-------- 4 files changed, 67 insertions(+), 39 deletions(-) rename libs/{pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.spec.tsx => domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.spec.tsx} (88%) rename libs/{pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.tsx => domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx} (68%) diff --git a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-arguments.tsx b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-arguments.tsx index 7a0d564518f..5869d3592a9 100644 --- a/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-arguments.tsx +++ b/apps/console-v5/src/routes/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-arguments.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' +import { TerraformArgumentsSettings } from '@qovery/domains/service-settings/feature' export const Route = createFileRoute( '/_authenticated/organization/$organizationId/project/$projectId/environment/$environmentId/service/$serviceId/settings/terraform-arguments' @@ -7,5 +8,5 @@ export const Route = createFileRoute( }) function RouteComponent() { - return
Terraform arguments
+ return } diff --git a/libs/domains/service-settings/feature/src/index.ts b/libs/domains/service-settings/feature/src/index.ts index 7ad02a8214f..9bef3cb849a 100644 --- a/libs/domains/service-settings/feature/src/index.ts +++ b/libs/domains/service-settings/feature/src/index.ts @@ -8,3 +8,4 @@ export * from './lib/application-container-storage-settings/application-containe export * from './lib/service-domain-settings/service-domain-settings/service-domain-settings' export * from './lib/service-deployment-restrictions-settings/service-deployment-restrictions-settings/service-deployment-restrictions-settings' export * from './lib/terraform-configuration-settings/terraform-configuration-settings' +export * from './lib/terraform-arguments-settings/terraform-arguments-settings' diff --git a/libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.spec.tsx b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.spec.tsx similarity index 88% rename from libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.spec.tsx rename to libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.spec.tsx index e02c700a2cd..a030a7392b6 100644 --- a/libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.spec.tsx +++ b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.spec.tsx @@ -1,12 +1,28 @@ import { wrapWithReactHookForm } from '__tests__/utils/wrap-with-react-hook-form' +import { type ReactNode } from 'react' import * as servicesDomain from '@qovery/domains/services/feature' import { terraformFactoryMock } from '@qovery/shared/factories' import { renderWithProviders, screen } from '@qovery/shared/util-tests' -import { PageSettingsTerraformArgumentsFeature } from './page-settings-terraform-arguments-feature' +import { TerraformArgumentsSettings } from './terraform-arguments-settings' const useServiceSpy = jest.spyOn(servicesDomain, 'useService') as jest.Mock const useEditServiceSpy = jest.spyOn(servicesDomain, 'useEditService') as jest.Mock +jest.mock('@tanstack/react-router', () => ({ + ...jest.requireActual('@tanstack/react-router'), + useParams: () => ({ organizationId: '1' }), + useNavigate: () => jest.fn(), + useLocation: () => ({ pathname: '/', search: '' }), + useRouter: () => ({ + buildLocation: () => ({ href: '/' }), + }), + Link: ({ children, ...props }: { children?: ReactNode; [key: string]: unknown }) => ( + + {children} + + ), +})) + jest.mock('@qovery/domains/variables/feature', () => ({ ...jest.requireActual('@qovery/domains/variables/feature'), DropdownVariable: ({ children, onChange }: { children: React.ReactNode; onChange: (value: string) => void }) => ( @@ -41,12 +57,12 @@ describe('PageSettingsTerraformArgumentsFeature', () => { }) it('should render', () => { - const { baseElement } = renderWithProviders(wrapWithReactHookForm()) + const { baseElement } = renderWithProviders(wrapWithReactHookForm()) expect(baseElement).toBeTruthy() }) it('should correctly submit the form', async () => { - const { userEvent } = renderWithProviders(wrapWithReactHookForm()) + const { userEvent } = renderWithProviders(wrapWithReactHookForm()) const submitButton = screen.getByText('Save') const inputLabelForApply = screen.getByText('Arguments for apply') const inputLabelForDestroy = screen.getByText('Arguments for destroy') @@ -89,7 +105,7 @@ describe('PageSettingsTerraformArgumentsFeature', () => { }) it('should render variable interpolation wand button for each command', () => { - renderWithProviders(wrapWithReactHookForm()) + renderWithProviders(wrapWithReactHookForm()) // Check that the wand button appears for each terraform command const wandButtons = screen.getAllByTestId('dropdown-variable') @@ -97,7 +113,7 @@ describe('PageSettingsTerraformArgumentsFeature', () => { }) it('should add variable interpolation to empty input when wand is clicked', async () => { - const { userEvent } = renderWithProviders(wrapWithReactHookForm()) + const { userEvent } = renderWithProviders(wrapWithReactHookForm()) const inputLabelForPlan = screen.getByText('Arguments for plan') const inputForPlan = inputLabelForPlan.closest('div')?.querySelector('input') @@ -114,7 +130,7 @@ describe('PageSettingsTerraformArgumentsFeature', () => { }) it('should append variable interpolation to existing input when wand is clicked', async () => { - const { userEvent } = renderWithProviders(wrapWithReactHookForm()) + const { userEvent } = renderWithProviders(wrapWithReactHookForm()) // Get the input for init command (which has default value '-auto-approve') const inputLabelForInit = screen.getByText('Arguments for init') @@ -133,7 +149,7 @@ describe('PageSettingsTerraformArgumentsFeature', () => { }) it('should correctly submit form with variable interpolation', async () => { - const { userEvent } = renderWithProviders(wrapWithReactHookForm()) + const { userEvent } = renderWithProviders(wrapWithReactHookForm()) // Get the apply input and add a variable using the wand const inputLabelForApply = screen.getByText('Arguments for apply') diff --git a/libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.tsx b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx similarity index 68% rename from libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.tsx rename to libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx index a71c90966b7..56b7485044a 100644 --- a/libs/pages/application/src/lib/feature/page-settings-terraform-arguments-feature/page-settings-terraform-arguments-feature.tsx +++ b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx @@ -1,8 +1,8 @@ +import { useParams } from '@tanstack/react-router' import { Controller, FormProvider, useForm } from 'react-hook-form' -import { useParams } from 'react-router-dom' import { useEditService, useService } from '@qovery/domains/services/feature' import { DropdownVariable } from '@qovery/domains/variables/feature' -import { NeedHelp } from '@qovery/shared/assistant/feature' +import { SettingsHeading } from '@qovery/shared/console-shared' import { Button, Heading, Icon, InputText, Section } from '@qovery/shared/ui' import { twMerge } from '@qovery/shared/util-js' import { buildEditServicePayload } from '@qovery/shared/util-services' @@ -15,8 +15,10 @@ const commands = [ hint: (
Example:{' '} - -lock=false -upgrade. - Arguments are separated by a space. + + -lock=false -upgrade + + . Arguments are separated by a space.
), }, @@ -25,9 +27,10 @@ const commands = [ description: 'Check whether the configuration is valid.', hint: (
- Example: -json or{' '} - -no-color. Arguments are - separated by a space. + Example:{' '} + -json or{' '} + -no-color + . Arguments are separated by a space.
), }, @@ -36,8 +39,11 @@ const commands = [ description: 'Show changes required by the current configuration.', hint: (
- Example: -refresh=false. - Arguments are separated by a space. + Example:{' '} + + -refresh=false + + . Arguments are separated by a space.
), }, @@ -46,8 +52,11 @@ const commands = [ description: 'Create or update infrastructure.', hint: (
- Example: -auto-approve. - Arguments are separated by a space. + Example:{' '} + + -auto-approve + + . Arguments are separated by a space.
), }, @@ -56,16 +65,17 @@ const commands = [ description: 'Destroy previously-created infrastructure.', hint: (
- Example: -target. + Example:{' '} + -target. Arguments are separated by a space.
), }, ] -export function PageSettingsTerraformArgumentsFeature() { - const { organizationId = '', projectId = '', environmentId = '', applicationId = '' } = useParams() - const { data: service } = useService({ serviceId: applicationId }) +export function TerraformArgumentsSettings() { + const { organizationId = '', projectId = '', environmentId = '', serviceId = '' } = useParams({ strict: false }) + const { data: service } = useService({ serviceId }) const { mutate: editService, isLoading: isLoadingEditService } = useEditService({ organizationId, projectId, @@ -85,6 +95,8 @@ export function PageSettingsTerraformArgumentsFeature() { }) const onSubmit = methods.handleSubmit((data) => { + console.log('data', data) + console.log('service', service) if (!service || !data) return if (service.serviceType === 'TERRAFORM') { @@ -109,26 +121,24 @@ export function PageSettingsTerraformArgumentsFeature() { }) return ( -
- -
-
- Terraform arguments -

Configure the arguments passed to each Terraform command.

- -
- + +
+ +
Commands -

Specify additional arguments for each Terraform command.

+

Specify additional arguments for each Terraform command.

{commands.map((command) => ( -
+
-

{command.name}

-

{command.description}

+

{command.name}

+

{command.description}

- -
+
+
) } From 439c09f941f19b5eef25c4ae3283e494241d58b2 Mon Sep 17 00:00:00 2001 From: Romain Billard Date: Fri, 27 Mar 2026 15:48:51 +0100 Subject: [PATCH 2/2] Refactor TerraformArgumentsSettings into content component --- .../terraform-arguments-settings.tsx | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx index 56b7485044a..fc238d757b0 100644 --- a/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx +++ b/libs/domains/service-settings/feature/src/lib/terraform-arguments-settings/terraform-arguments-settings.tsx @@ -1,5 +1,6 @@ import { useParams } from '@tanstack/react-router' import { Controller, FormProvider, useForm } from 'react-hook-form' +import { type Terraform } from '@qovery/domains/services/data-access' import { useEditService, useService } from '@qovery/domains/services/feature' import { DropdownVariable } from '@qovery/domains/variables/feature' import { SettingsHeading } from '@qovery/shared/console-shared' @@ -73,9 +74,8 @@ const commands = [ }, ] -export function TerraformArgumentsSettings() { - const { organizationId = '', projectId = '', environmentId = '', serviceId = '' } = useParams({ strict: false }) - const { data: service } = useService({ serviceId }) +const TerraformArgumentsSettingsContent = ({ service }: { service: Terraform }) => { + const { organizationId = '', projectId = '', environmentId = '' } = useParams({ strict: false }) const { mutate: editService, isLoading: isLoadingEditService } = useEditService({ organizationId, projectId, @@ -95,29 +95,25 @@ export function TerraformArgumentsSettings() { }) const onSubmit = methods.handleSubmit((data) => { - console.log('data', data) - console.log('service', service) - if (!service || !data) return + if (!data) return - if (service.serviceType === 'TERRAFORM') { - const payload = buildEditServicePayload({ - service, - request: { - action_extra_arguments: { - init: data['init'] ?? [], - validate: data['validate'] ?? [], - plan: data['plan'] ?? [], - apply: data['apply'] ?? [], - destroy: data['destroy'] ?? [], - }, + const payload = buildEditServicePayload({ + service, + request: { + action_extra_arguments: { + init: data['init'] ?? [], + validate: data['validate'] ?? [], + plan: data['plan'] ?? [], + apply: data['apply'] ?? [], + destroy: data['destroy'] ?? [], }, - }) + }, + }) - editService({ - serviceId: service.id, - payload, - }) - } + editService({ + serviceId: service.id, + payload, + }) }) return ( @@ -135,7 +131,7 @@ export function TerraformArgumentsSettings() {
{commands.map((command) => ( -
+

{command.name}

{command.description}

@@ -192,3 +188,12 @@ export function TerraformArgumentsSettings() { ) } + +export function TerraformArgumentsSettings() { + const { serviceId = '' } = useParams({ strict: false }) + const { data: service } = useService({ serviceId, suspense: true }) + + if (service?.serviceType !== 'TERRAFORM') return null + + return +}