From 407ab6fa86570649fae2028ef892892ecd4999c9 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Fri, 29 Sep 2023 12:27:14 -0400 Subject: [PATCH 01/12] Fixed featureFlag in scaffolder/next Signed-off-by: tperehinets --- .../src/next/components/Workflow/Workflow.tsx | 80 +++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index e7c56378a7..ff6782c512 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -23,11 +23,17 @@ import { import { stringifyEntityRef } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; -import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { + errorApiRef, + useApi, + featureFlagsApiRef, +} from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; +import cloneDeep from 'lodash/cloneDeep'; +import { useMemo, useCallback } from 'react'; const useStyles = makeStyles(() => ({ markdown: { @@ -81,6 +87,64 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { const { loading, manifest, error } = useTemplateParameterSchema(templateRef); + const featureFlagKey = 'backstage:featureFlag'; + const featureFlagApi = useApi(featureFlagsApiRef); + + // return manifest with updates steps + const filterOutStepProperties = useCallback(() => { + if (manifest) { + const filteredSteps = manifest.steps + .filter(step => { + const featureFlag = step.schema[featureFlagKey]; + return ( + typeof featureFlag !== 'string' || + featureFlagApi.isActive(featureFlag) + ); + }) + .map(step => { + const filteredStep = cloneDeep(step); + const removedPropertyKeys: Array = []; + if (filteredStep.schema.properties) { + filteredStep.schema.properties = Object.fromEntries( + Object.entries(filteredStep.schema.properties).filter( + ([key, value]) => { + if (value[featureFlagKey]) { + if (featureFlagApi.isActive(value[featureFlagKey])) { + return true; + } + + removedPropertyKeys.push(key); + return false; + } + return true; + }, + ), + ); + + // remove the feature flag property key from required if they are not active + filteredStep.schema.required = Array.isArray( + filteredStep.schema.required, + ) + ? filteredStep.schema.required?.filter( + r => !removedPropertyKeys.includes(r as string), + ) + : filteredStep.schema.required; + } + + return filteredStep; + }); + + return { ...manifest, steps: filteredSteps }; + } + + return manifest; + }, [manifest, featureFlagKey, featureFlagApi]); + + const sortedManifest = useMemo( + () => filterOutStepProperties(), + [filterOutStepProperties], + ); + useEffect(() => { if (error) { errorApi.post(new Error(`Failed to load template, ${error}`)); @@ -94,19 +158,25 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { return ( {loading && } - {manifest && ( + {sortedManifest && ( } noPadding titleTypographyProps={{ component: 'h2' }} > - + )} From cce6c04e852e11fe1c0911262ee221e4716eaf61 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Fri, 29 Sep 2023 12:30:21 -0400 Subject: [PATCH 02/12] Fixed featureFlag in scaffolder/next Signed-off-by: tperehinets --- app-config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app-config.yaml b/app-config.yaml index c53a6475f4..fae0d4c025 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -297,6 +297,10 @@ catalog: target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml rules: - allow: [Template] + # Backstage end-to-end tests of TechDocs + - type: file + target: ../../cypress/e2e-fixture.catalog.info.yaml + scaffolder: # Use to customize default commit author info used when new components are created # defaultAuthor: From 171a99816b8ad985109edcc5674d7e63707b7143 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Fri, 29 Sep 2023 12:34:16 -0400 Subject: [PATCH 03/12] Fixed featureFlag in scaffolder/next Signed-off-by: tperehinets --- .changeset/olive-otters-marry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/olive-otters-marry.md diff --git a/.changeset/olive-otters-marry.md b/.changeset/olive-otters-marry.md new file mode 100644 index 0000000000..a90e4dc5b9 --- /dev/null +++ b/.changeset/olive-otters-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fixed `backstage:featureFlag` in `scaffolder/next` by sorting out `manifest.steps`. From 80d5bf633682a0e00c59ba0a1ee0a17d0832f82a Mon Sep 17 00:00:00 2001 From: tperehinets Date: Fri, 29 Sep 2023 12:49:46 -0400 Subject: [PATCH 04/12] Fixed featureFlag in scaffolder/next Signed-off-by: tperehinets --- app-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/app-config.yaml b/app-config.yaml index fae0d4c025..adf479cd0c 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -300,7 +300,6 @@ catalog: # Backstage end-to-end tests of TechDocs - type: file target: ../../cypress/e2e-fixture.catalog.info.yaml - scaffolder: # Use to customize default commit author info used when new components are created # defaultAuthor: From 367e15404af08cb33b2b3f82ff5ca41fc6a38189 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Wed, 11 Oct 2023 14:49:05 -0400 Subject: [PATCH 05/12] Moved sorting function to hooks Signed-off-by: tperehinets --- .../src/next/components/Workflow/Workflow.tsx | 67 +--------------- .../scaffolder-react/src/next/hooks/index.ts | 1 + .../next/hooks/useFeatureFlaggedProperties.ts | 76 +++++++++++++++++++ 3 files changed, 80 insertions(+), 64 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index ff6782c512..c10b4e081e 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -23,17 +23,12 @@ import { import { stringifyEntityRef } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; -import { - errorApiRef, - useApi, - featureFlagsApiRef, -} from '@backstage/core-plugin-api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; -import cloneDeep from 'lodash/cloneDeep'; -import { useMemo, useCallback } from 'react'; +import { useFeatureFlaggedProperties } from '../../hooks/useFeatureFlaggedProperties'; const useStyles = makeStyles(() => ({ markdown: { @@ -87,63 +82,7 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { const { loading, manifest, error } = useTemplateParameterSchema(templateRef); - const featureFlagKey = 'backstage:featureFlag'; - const featureFlagApi = useApi(featureFlagsApiRef); - - // return manifest with updates steps - const filterOutStepProperties = useCallback(() => { - if (manifest) { - const filteredSteps = manifest.steps - .filter(step => { - const featureFlag = step.schema[featureFlagKey]; - return ( - typeof featureFlag !== 'string' || - featureFlagApi.isActive(featureFlag) - ); - }) - .map(step => { - const filteredStep = cloneDeep(step); - const removedPropertyKeys: Array = []; - if (filteredStep.schema.properties) { - filteredStep.schema.properties = Object.fromEntries( - Object.entries(filteredStep.schema.properties).filter( - ([key, value]) => { - if (value[featureFlagKey]) { - if (featureFlagApi.isActive(value[featureFlagKey])) { - return true; - } - - removedPropertyKeys.push(key); - return false; - } - return true; - }, - ), - ); - - // remove the feature flag property key from required if they are not active - filteredStep.schema.required = Array.isArray( - filteredStep.schema.required, - ) - ? filteredStep.schema.required?.filter( - r => !removedPropertyKeys.includes(r as string), - ) - : filteredStep.schema.required; - } - - return filteredStep; - }); - - return { ...manifest, steps: filteredSteps }; - } - - return manifest; - }, [manifest, featureFlagKey, featureFlagApi]); - - const sortedManifest = useMemo( - () => filterOutStepProperties(), - [filterOutStepProperties], - ); + const sortedManifest = useFeatureFlaggedProperties(manifest); useEffect(() => { if (error) { diff --git a/plugins/scaffolder-react/src/next/hooks/index.ts b/plugins/scaffolder-react/src/next/hooks/index.ts index ca8ce10eff..9e192c143f 100644 --- a/plugins/scaffolder-react/src/next/hooks/index.ts +++ b/plugins/scaffolder-react/src/next/hooks/index.ts @@ -19,3 +19,4 @@ export { type ParsedTemplateSchema, } from './useTemplateSchema'; export { useTemplateParameterSchema } from './useTemplateParameterSchema'; +export { useFeatureFlaggedProperties } from './useFeatureFlaggedProperties'; diff --git a/plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts b/plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts new file mode 100644 index 0000000000..ae1a6d9c67 --- /dev/null +++ b/plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import cloneDeep from 'lodash/cloneDeep'; +import { useApi, featureFlagsApiRef } from '@backstage/core-plugin-api'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; + +/** + * Returns manifest of software templates with steps without a featureFlag tag. + * @alpha + */ + +export const useFeatureFlaggedProperties = ( + manifest: TemplateParameterSchema | undefined, +) => { + const featureFlagKey = 'backstage:featureFlag'; + const featureFlagApi = useApi(featureFlagsApiRef); + + if (!manifest) { + return null; + } + + const filteredSteps = manifest?.steps + .filter(step => { + const featureFlag = step.schema[featureFlagKey]; + return ( + typeof featureFlag !== 'string' || featureFlagApi.isActive(featureFlag) + ); + }) + .map(step => { + const filteredStep = cloneDeep(step); + const removedPropertyKeys: Array = []; + if (filteredStep.schema.properties) { + filteredStep.schema.properties = Object.fromEntries( + Object.entries(filteredStep.schema.properties).filter( + ([key, value]) => { + if (value[featureFlagKey]) { + if (featureFlagApi.isActive(value[featureFlagKey])) { + return true; + } + + removedPropertyKeys.push(key); + return false; + } + return true; + }, + ), + ); + + // remove the feature flag property key from required if they are not active + filteredStep.schema.required = Array.isArray( + filteredStep.schema.required, + ) + ? filteredStep.schema.required?.filter( + r => !removedPropertyKeys.includes(r as string), + ) + : filteredStep.schema.required; + } + + return filteredStep; + }); + + return { ...manifest, steps: filteredSteps }; +}; From 20c6880c250d9991d62e5ae4fe945c5bb067c8d6 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Wed, 11 Oct 2023 18:17:21 -0400 Subject: [PATCH 06/12] Commited api reportes changes Signed-off-by: tperehinets --- plugins/scaffolder-react/alpha-api-report.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 3d9361bf18..78205460ac 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -290,6 +290,19 @@ export interface TemplateGroupsProps { templateFilter?: (entity: TemplateEntityV1beta3) => boolean; } +// @alpha +export const useFeatureFlaggedProperties: ( + manifest: TemplateParameterSchema | undefined, +) => { + steps: { + title: string; + description?: string | undefined; + schema: JsonObject; + }[]; + title: string; + description?: string | undefined; +} | null; + // @alpha export const useFormDataFromQuery: ( initialState?: Record, From 1944b1f5b95efea5915a0f7740a3b8bb1984664f Mon Sep 17 00:00:00 2001 From: tperehinets Date: Sun, 12 Nov 2023 19:21:18 -0500 Subject: [PATCH 07/12] Added tests Signed-off-by: tperehinets --- plugins/scaffolder-react/alpha-api-report.md | 2 +- .../src/next/components/Workflow/Workflow.tsx | 7 +- .../scaffolder-react/src/next/hooks/index.ts | 2 +- .../useFilteredSchemaProperties.test.tsx | 86 +++++++++++++++++++ ...ties.ts => useFilteredSchemaProperties.ts} | 2 +- 5 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx rename plugins/scaffolder-react/src/next/hooks/{useFeatureFlaggedProperties.ts => useFilteredSchemaProperties.ts} (98%) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 78205460ac..d5a3ca3cdc 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -291,7 +291,7 @@ export interface TemplateGroupsProps { } // @alpha -export const useFeatureFlaggedProperties: ( +export const useFilteredSchemaProperties: ( manifest: TemplateParameterSchema | undefined, ) => { steps: { diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index c10b4e081e..0554e76cf6 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,8 +27,9 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; -import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; -import { useFeatureFlaggedProperties } from '../../hooks/useFeatureFlaggedProperties'; + +import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties'; +import { ReviewStepProps } from '../../../components'; const useStyles = makeStyles(() => ({ markdown: { @@ -82,7 +83,7 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { const { loading, manifest, error } = useTemplateParameterSchema(templateRef); - const sortedManifest = useFeatureFlaggedProperties(manifest); + const sortedManifest = useFilteredSchemaProperties(manifest); useEffect(() => { if (error) { diff --git a/plugins/scaffolder-react/src/next/hooks/index.ts b/plugins/scaffolder-react/src/next/hooks/index.ts index 9e192c143f..63f8cda4e9 100644 --- a/plugins/scaffolder-react/src/next/hooks/index.ts +++ b/plugins/scaffolder-react/src/next/hooks/index.ts @@ -19,4 +19,4 @@ export { type ParsedTemplateSchema, } from './useTemplateSchema'; export { useTemplateParameterSchema } from './useTemplateParameterSchema'; -export { useFeatureFlaggedProperties } from './useFeatureFlaggedProperties'; +export { useFilteredSchemaProperties } from './useFilteredSchemaProperties'; diff --git a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx new file mode 100644 index 0000000000..d5f4b6e477 --- /dev/null +++ b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { TestApiProvider } from '@backstage/test-utils'; +import { useFilteredSchemaProperties } from './useFilteredSchemaProperties'; +import { TemplateParameterSchema } from '../../types'; + +describe('useFilteredSchemaProperties', () => { + it('should hide "Fill in some steps" from steps of template', () => { + const manifest: TemplateParameterSchema = { + title: 'Test Action template', + description: 'scaffolder v1beta3 template demo', + steps: [ + { + title: 'Fill in some steps', + schema: { + type: 'object', + 'backstage:featureFlag': 'experimental-feature', + properties: { + name: { + description: 'Unique name of the component', + title: 'Name', + type: 'string', + 'ui:autofocus': true, + }, + }, + }, + }, + { + title: 'Choose a location', + schema: { + type: 'object', + properties: { + repoUrl: { + type: 'string', + title: 'Repository Location', + 'ui:field': 'RepoUrlPicker', + }, + }, + }, + }, + ], + }; + + const sortedManifest = renderHook(() => + useFilteredSchemaProperties(manifest), + ); + + const expectedManifest: TemplateParameterSchema = { + title: 'Test Action template', + description: 'scaffolder v1beta3 template demo', + steps: [ + { + title: 'Choose a location', + schema: { + type: 'object', + properties: { + repoUrl: { + type: 'string', + title: 'Repository Location', + 'ui:field': 'RepoUrlPicker', + }, + }, + }, + }, + ], + }; + + expect(sortedManifest).toEqual(expectedManifest); + }); +}); diff --git a/plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts similarity index 98% rename from plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts rename to plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts index ae1a6d9c67..9c351348dc 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFeatureFlaggedProperties.ts +++ b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts @@ -22,7 +22,7 @@ import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; * @alpha */ -export const useFeatureFlaggedProperties = ( +export const useFilteredSchemaProperties = ( manifest: TemplateParameterSchema | undefined, ) => { const featureFlagKey = 'backstage:featureFlag'; From 13d3d18297749747c822dd667e72ea196bf24f09 Mon Sep 17 00:00:00 2001 From: tperehinets Date: Sun, 12 Nov 2023 19:23:23 -0500 Subject: [PATCH 08/12] added tests Signed-off-by: tperehinets --- .../src/next/hooks/useFilteredSchemaProperties.test.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx index d5f4b6e477..1264e7d2e2 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx @@ -14,9 +14,7 @@ * limitations under the License. */ -import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; -import { TestApiProvider } from '@backstage/test-utils'; import { useFilteredSchemaProperties } from './useFilteredSchemaProperties'; import { TemplateParameterSchema } from '../../types'; From 3f3977dcb0a72f746c503185f7c7a141cf67b461 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 13 Nov 2023 11:22:30 +0100 Subject: [PATCH 09/12] chore: rebase and fix Signed-off-by: blam --- plugins/scaffolder-react/alpha-api-report.md | 4 +--- .../src/next/components/Workflow/Workflow.tsx | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index d5a3ca3cdc..95bea735ca 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -301,6 +301,7 @@ export const useFilteredSchemaProperties: ( }[]; title: string; description?: string | undefined; + presentation?: TemplatePresentationV1beta3 | undefined; } | null; // @alpha @@ -330,9 +331,6 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; - components?: { - ReviewStepComponent?: React_2.ComponentType; - }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index 0554e76cf6..a838b5c5ab 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,9 +27,7 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; - import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties'; -import { ReviewStepProps } from '../../../components'; const useStyles = makeStyles(() => ({ markdown: { @@ -51,9 +49,6 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; - components?: { - ReviewStepComponent?: React.ComponentType; - }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, From 8966c44b64134f78d8ab3d97651f4499870911a0 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 13 Nov 2023 11:32:14 +0100 Subject: [PATCH 10/12] chore: fix last things Signed-off-by: blam --- app-config.yaml | 3 --- plugins/scaffolder-react/alpha-api-report.md | 14 ++++---------- .../src/next/components/Workflow/Workflow.tsx | 5 +++++ .../src/next/hooks/useFilteredSchemaProperties.ts | 4 ++-- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index adf479cd0c..c53a6475f4 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -297,9 +297,6 @@ catalog: target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml rules: - allow: [Template] - # Backstage end-to-end tests of TechDocs - - type: file - target: ../../cypress/e2e-fixture.catalog.info.yaml scaffolder: # Use to customize default commit author info used when new components are created # defaultAuthor: diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 95bea735ca..615b54df84 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -293,16 +293,7 @@ export interface TemplateGroupsProps { // @alpha export const useFilteredSchemaProperties: ( manifest: TemplateParameterSchema | undefined, -) => { - steps: { - title: string; - description?: string | undefined; - schema: JsonObject; - }[]; - title: string; - description?: string | undefined; - presentation?: TemplatePresentationV1beta3 | undefined; -} | null; +) => TemplateParameterSchema | undefined; // @alpha export const useFormDataFromQuery: ( @@ -331,6 +322,9 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React_2.ComponentType; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index a838b5c5ab..c02f3c2757 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,7 +27,9 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; + import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(() => ({ markdown: { @@ -49,6 +51,9 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React.ComponentType; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, diff --git a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts index 9c351348dc..be6f581f87 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts +++ b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.ts @@ -24,12 +24,12 @@ import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; export const useFilteredSchemaProperties = ( manifest: TemplateParameterSchema | undefined, -) => { +): TemplateParameterSchema | undefined => { const featureFlagKey = 'backstage:featureFlag'; const featureFlagApi = useApi(featureFlagsApiRef); if (!manifest) { - return null; + return undefined; } const filteredSteps = manifest?.steps From d7b057458bd807e3f26f97ec6e22ed9c145b435f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 13 Nov 2023 12:48:09 +0100 Subject: [PATCH 11/12] chore: fix linting Signed-off-by: blam --- plugins/scaffolder-react/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 24a5441488..631fa2031e 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -94,6 +94,7 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", + "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/luxon": "^3.0.0" diff --git a/yarn.lock b/yarn.lock index 81b6b6affa..07ae34399d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8973,6 +8973,7 @@ __metadata: "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 + "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 From 108bbb7858e4ffc6c73bd636327a3bdb27a4500c Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 14 Nov 2023 09:48:25 +0100 Subject: [PATCH 12/12] tests: fixing the tests Signed-off-by: blam --- plugins/scaffolder-react/package.json | 1 - .../useFilteredSchemaProperties.test.tsx | 158 +++++++++++++++++- yarn.lock | 1 - 3 files changed, 153 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 631fa2031e..24a5441488 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -94,7 +94,6 @@ "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", - "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", "@types/luxon": "^3.0.0" diff --git a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx index 1264e7d2e2..3e568fa7bd 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useFilteredSchemaProperties.test.tsx @@ -14,12 +14,21 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useFilteredSchemaProperties } from './useFilteredSchemaProperties'; import { TemplateParameterSchema } from '../../types'; +import { TestApiProvider } from '@backstage/test-utils'; +import React from 'react'; +import { featureFlagsApiRef } from '@backstage/core-plugin-api'; + +const mockFeatureFlagApi = { + isActive: jest.fn(), +}; describe('useFilteredSchemaProperties', () => { - it('should hide "Fill in some steps" from steps of template', () => { + it('should return the same manifest if no feature flag is set', () => { + mockFeatureFlagApi.isActive.mockReturnValue(true); + const manifest: TemplateParameterSchema = { title: 'Test Action template', description: 'scaffolder v1beta3 template demo', @@ -55,8 +64,147 @@ describe('useFilteredSchemaProperties', () => { ], }; - const sortedManifest = renderHook(() => - useFilteredSchemaProperties(manifest), + const filteredManifest = renderHook( + () => useFilteredSchemaProperties(manifest), + { + wrapper: ({ children }) => ( + + {children} + + ), + }, + ); + + expect(filteredManifest.result.current).toEqual(manifest); + }); + + it('should hide individual fields from steps of template', () => { + mockFeatureFlagApi.isActive.mockReturnValue(false); + + const manifest: TemplateParameterSchema = { + title: 'Test Action template', + description: 'scaffolder v1beta3 template demo', + steps: [ + { + title: 'Fill in some steps', + schema: { + type: 'object', + properties: { + name: { + description: 'Unique name of the component', + title: 'Name', + type: 'string', + 'ui:autofocus': true, + }, + }, + }, + }, + { + title: 'Choose a location', + schema: { + type: 'object', + properties: { + repoUrl: { + type: 'string', + title: 'Repository Location', + 'ui:field': 'RepoUrlPicker', + 'backstage:featureFlag': 'experimental-feature', + }, + }, + }, + }, + ], + }; + + const filteredManifest = renderHook( + () => useFilteredSchemaProperties(manifest), + { + wrapper: ({ children }) => ( + + {children} + + ), + }, + ); + + const expectedManifest: TemplateParameterSchema = { + title: 'Test Action template', + description: 'scaffolder v1beta3 template demo', + steps: [ + { + title: 'Fill in some steps', + schema: { + type: 'object', + properties: { + name: { + description: 'Unique name of the component', + title: 'Name', + type: 'string', + 'ui:autofocus': true, + }, + }, + }, + }, + { + title: 'Choose a location', + schema: { + type: 'object', + properties: {}, + }, + }, + ], + }; + + expect(filteredManifest.result.current).toEqual(expectedManifest); + }); + + it('should hide "Fill in some steps" from steps of template', () => { + mockFeatureFlagApi.isActive.mockReturnValue(false); + + const manifest: TemplateParameterSchema = { + title: 'Test Action template', + description: 'scaffolder v1beta3 template demo', + steps: [ + { + title: 'Fill in some steps', + schema: { + type: 'object', + 'backstage:featureFlag': 'experimental-feature', + properties: { + name: { + description: 'Unique name of the component', + title: 'Name', + type: 'string', + 'ui:autofocus': true, + }, + }, + }, + }, + { + title: 'Choose a location', + schema: { + type: 'object', + properties: { + repoUrl: { + type: 'string', + title: 'Repository Location', + 'ui:field': 'RepoUrlPicker', + }, + }, + }, + }, + ], + }; + + const filteredManifest = renderHook( + () => useFilteredSchemaProperties(manifest), + { + wrapper: ({ children }) => ( + + {children} + + ), + }, ); const expectedManifest: TemplateParameterSchema = { @@ -79,6 +227,6 @@ describe('useFilteredSchemaProperties', () => { ], }; - expect(sortedManifest).toEqual(expectedManifest); + expect(filteredManifest.result.current).toEqual(expectedManifest); }); }); diff --git a/yarn.lock b/yarn.lock index 07ae34399d..81b6b6affa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8973,7 +8973,6 @@ __metadata: "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 - "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9