From 996611aa839e9fba0f76ddc5fdeec5bff341e4db Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 2 Apr 2024 16:21:36 +0200 Subject: [PATCH] Avoid leaking analytics details to external consumers Signed-off-by: Eric Peterson --- .changeset/scaffolder-create-time-saved.md | 4 +++- plugins/scaffolder-react/api-report-alpha.md | 1 - .../src/next/components/Stepper/Stepper.tsx | 13 +++++----- .../src/next/components/Workflow/Workflow.tsx | 24 +++++++++++++++---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/.changeset/scaffolder-create-time-saved.md b/.changeset/scaffolder-create-time-saved.md index c975783a50..44739bf0f1 100644 --- a/.changeset/scaffolder-create-time-saved.md +++ b/.changeset/scaffolder-create-time-saved.md @@ -2,4 +2,6 @@ '@backstage/plugin-scaffolder-react': patch --- -The `value` sent on the `create` analytics event (fired when a Scaffolder template is executed) is now set to the number of minutes saved by executing the template. This value is derived from the `backstage.io/time-saved` annotation on the template entity. +The `value` sent on the `create` analytics event (fired when a Scaffolder template is executed) is now set to the number of minutes saved by executing the template. This value is derived from the `backstage.io/time-saved` annotation on the template entity, if available. + +Note: the `create` event is now captured in the `` component. If you are directly making use of the alpha-exported `` component, an analytics `create` event will no longer be captured on your behalf. diff --git a/plugins/scaffolder-react/api-report-alpha.md b/plugins/scaffolder-react/api-report-alpha.md index 6674592920..683b8cf8be 100644 --- a/plugins/scaffolder-react/api-report-alpha.md +++ b/plugins/scaffolder-react/api-report-alpha.md @@ -157,7 +157,6 @@ export type StepperProps = { manifest: TemplateParameterSchema; extensions: FieldExtensionOptions[]; templateName?: string; - minutesSaved?: number; formProps?: FormProps; initialState?: Record; onCreate: (values: Record) => Promise; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index efa100b578..d0ce60fd79 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -75,8 +75,12 @@ const useStyles = makeStyles(theme => ({ export type StepperProps = { manifest: TemplateParameterSchema; extensions: FieldExtensionOptions[]; + /** + * @deprecated This was only ever used for analytics tracking purposes, which + * is now handled in the `` component. Passing it in will have no + * effect. + */ templateName?: string; - minutesSaved?: number; formProps?: FormProps; initialState?: Record; onCreate: (values: Record) => Promise; @@ -148,12 +152,7 @@ export const Stepper = (stepperProps: StepperProps) => { const handleCreate = useCallback(() => { props.onCreate(formState); - const name = - typeof formState.name === 'string' ? formState.name : undefined; - analytics.captureEvent('create', name ?? props.templateName ?? 'unknown', { - value: props.minutesSaved, - }); - }, [props, formState, analytics]); + }, [props, formState]); const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index d0d818f772..e16af5abb9 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useEffect } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { Content, InfoCard, @@ -23,13 +23,14 @@ import { } from '@backstage/core-components'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core'; -import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { errorApiRef, useAnalytics, 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'; import { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved'; +import { JsonValue } from '@backstage/types'; const useStyles = makeStyles({ markdown: { @@ -69,9 +70,10 @@ export type WorkflowProps = { * @alpha */ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { - const { title, description, namespace, templateName, ...props } = + const { title, description, namespace, templateName, onCreate, ...props } = workflowProps; + const analytics = useAnalytics(); const styles = useStyles(); const templateRef = stringifyEntityRef({ kind: 'Template', @@ -87,6 +89,19 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { const minutesSaved = useTemplateTimeSavedMinutes(templateRef); + const workflowOnCreate = useCallback( + async (formState: Record) => { + onCreate(formState); + + const name = + typeof formState.name === 'string' ? formState.name : undefined; + analytics.captureEvent('create', name ?? templateName ?? 'unknown', { + value: minutesSaved, + }); + }, + [onCreate, analytics, templateName, minutesSaved], + ); + useEffect(() => { if (error) { errorApi.post(new Error(`Failed to load template, ${error}`)); @@ -116,8 +131,7 @@ export const Workflow = (workflowProps: WorkflowProps): JSX.Element | null => { >