diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e768ccd1c3..dfc2fea68b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4.0.3 + uses: actions/setup-node@v4.0.4 with: node-version: ${{ matrix.node-version }} - name: Node.js modules cache, repository diff --git a/.github/workflows/vuln_scan.yml b/.github/workflows/vuln_scan.yml index 610ff461b4..8f327e6c7b 100644 --- a/.github/workflows/vuln_scan.yml +++ b/.github/workflows/vuln_scan.yml @@ -17,7 +17,7 @@ jobs: trivy-config: .github/trivy.yaml - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'scan_result.sarif' diff --git a/frontend/src/concepts/pipelines/content/createRun/useRunFormData.ts b/frontend/src/concepts/pipelines/content/createRun/useRunFormData.ts index 11fad9ef67..3e20a3241b 100644 --- a/frontend/src/concepts/pipelines/content/createRun/useRunFormData.ts +++ b/frontend/src/concepts/pipelines/content/createRun/useRunFormData.ts @@ -144,7 +144,7 @@ const useRunFormData = ( const { project } = usePipelinesAPI(); const { pipeline, version, experiment, nameDesc } = initialFormData || {}; - const formState = useGenericObjectState({ + const formState = useGenericObjectState(() => ({ project, nameDesc: nameDesc ?? { name: '', description: '' }, pipeline: pipeline ?? null, @@ -161,7 +161,7 @@ const useRunFormData = ( {}, ), ...initialFormData, - }); + })); const [, setFormValue] = formState; useUpdateExperimentFormData(formState, experiment); diff --git a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx index 78ec983789..5bf60dc589 100644 --- a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx +++ b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx @@ -16,8 +16,7 @@ import { Link } from 'react-router-dom'; import FormSection from '~/components/pf-overrides/FormSection'; import ApplicationsPage from '~/pages/ApplicationsPage'; import { modelRegistryUrl, registeredModelUrl } from '~/pages/modelRegistry/screens/routeUtils'; -import { ValueOf } from '~/typeHelpers'; -import { useRegisterModelData, RegistrationCommonFormData } from './useRegisterModelData'; +import { useRegisterModelData } from './useRegisterModelData'; import { isRegisterModelSubmitDisabled, registerModel } from './utils'; import RegistrationCommonFormSections from './RegistrationCommonFormSections'; import { useRegistrationCommonState } from './useRegistrationCommonState'; @@ -90,10 +89,7 @@ const RegisterModel: React.FC = () => { , - ) => setData(propKey, propValue)} + setData={setData} isFirstVersion /> diff --git a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterVersion.tsx b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterVersion.tsx index 257998be4c..f6bbf50b1d 100644 --- a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterVersion.tsx +++ b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterVersion.tsx @@ -16,8 +16,7 @@ import ApplicationsPage from '~/pages/ApplicationsPage'; import { modelRegistryUrl, registeredModelUrl } from '~/pages/modelRegistry/screens/routeUtils'; import useRegisteredModels from '~/concepts/modelRegistry/apiHooks/useRegisteredModels'; import { filterLiveModels } from '~/concepts/modelRegistry/utils'; -import { ValueOf } from '~/typeHelpers'; -import { RegistrationCommonFormData, useRegisterVersionData } from './useRegisterModelData'; +import { useRegisterVersionData } from './useRegisterModelData'; import { isRegisterVersionSubmitDisabled, registerVersion } from './utils'; import RegistrationCommonFormSections from './RegistrationCommonFormSections'; import { useRegistrationCommonState } from './useRegistrationCommonState'; @@ -119,10 +118,7 @@ const RegisterVersion: React.FC = () => { , - ) => setData(propKey, propValue)} + setData={setData} isFirstVersion={false} latestVersion={latestVersion} /> diff --git a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx index 19618234d8..9041268205 100644 --- a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx +++ b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx @@ -22,22 +22,28 @@ import { ModelVersion } from '~/concepts/modelRegistry/types'; import { ModelLocationType, RegistrationCommonFormData } from './useRegisterModelData'; import { ConnectionModal } from './ConnectionModal'; -type RegistrationCommonFormSectionsProps = { - formData: RegistrationCommonFormData; - setData: UpdateObjectAtPropAndValue; +type RegistrationCommonFormSectionsProps = { + formData: D; + setData: UpdateObjectAtPropAndValue; isFirstVersion: boolean; latestVersion?: ModelVersion; }; -const RegistrationCommonFormSections: React.FC = ({ +const RegistrationCommonFormSections = ({ formData, setData, isFirstVersion, latestVersion, -}) => { +}: RegistrationCommonFormSectionsProps): React.ReactNode => { const [isAutofillModalOpen, setAutofillModalOpen] = React.useState(false); - const connectionDataMap: Record = { + const connectionDataMap: Record< + string, + keyof Pick< + RegistrationCommonFormData, + 'modelLocationEndpoint' | 'modelLocationBucket' | 'modelLocationRegion' + > + > = { AWS_S3_ENDPOINT: 'modelLocationEndpoint', AWS_S3_BUCKET: 'modelLocationBucket', AWS_DEFAULT_REGION: 'modelLocationRegion', diff --git a/frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/InferenceServiceServingRuntimeSection.tsx b/frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/InferenceServiceServingRuntimeSection.tsx index c62eaa2ebd..e3a947f01a 100644 --- a/frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/InferenceServiceServingRuntimeSection.tsx +++ b/frontend/src/pages/modelServing/screens/projects/InferenceServiceModal/InferenceServiceServingRuntimeSection.tsx @@ -66,7 +66,9 @@ const InferenceServiceServingRuntimeSection: React.FC< } onChange={(option) => { setData('servingRuntimeName', option); - setData('format', ''); + setData('format', { + name: '', + }); }} /> diff --git a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/AuthServingRuntimeSection.tsx b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/AuthServingRuntimeSection.tsx index e365356048..1c09124365 100644 --- a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/AuthServingRuntimeSection.tsx +++ b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/AuthServingRuntimeSection.tsx @@ -11,28 +11,23 @@ import { } from '@patternfly/react-core'; import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; import { UpdateObjectAtPropAndValue } from '~/pages/projects/types'; -import { - CreatingInferenceServiceObject, - CreatingServingRuntimeObject, -} from '~/pages/modelServing/screens/types'; +import { CreatingModelServingObjectCommon } from '~/pages/modelServing/screens/types'; import ServingRuntimeTokenSection from './ServingRuntimeTokenSection'; -type AuthServingRuntimeSectionProps = { - data: CreatingServingRuntimeObject | CreatingInferenceServiceObject; - setData: - | UpdateObjectAtPropAndValue - | UpdateObjectAtPropAndValue; +type AuthServingRuntimeSectionProps = { + data: D; + setData: UpdateObjectAtPropAndValue; allowCreate: boolean; publicRoute?: boolean; }; -const AuthServingRuntimeSection: React.FC = ({ +const AuthServingRuntimeSection = ({ data, setData, allowCreate, publicRoute, -}) => { +}: AuthServingRuntimeSectionProps): React.ReactNode => { const createNewToken = React.useCallback(() => { const name = 'default-name'; const duplicated = data.tokens.filter((token) => token.name === name); diff --git a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeExpandedField.tsx b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeExpandedField.tsx index 398c3da730..99599aaf36 100644 --- a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeExpandedField.tsx +++ b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeExpandedField.tsx @@ -2,27 +2,22 @@ import * as React from 'react'; import { FormGroup, Grid } from '@patternfly/react-core'; import IndentSection from '~/pages/projects/components/IndentSection'; import { UpdateObjectAtPropAndValue } from '~/pages/projects/types'; -import { - CreatingInferenceServiceObject, - CreatingServingRuntimeObject, -} from '~/pages/modelServing/screens/types'; +import { CreatingModelServingObjectCommon } from '~/pages/modelServing/screens/types'; import { ContainerResourceAttributes, ContainerResources } from '~/types'; import CPUField from '~/components/CPUField'; import MemoryField from '~/components/MemoryField'; -type ServingRuntimeSizeExpandedFieldProps = { - data: CreatingServingRuntimeObject | CreatingInferenceServiceObject; - setData: - | UpdateObjectAtPropAndValue - | UpdateObjectAtPropAndValue; +type ServingRuntimeSizeExpandedFieldProps = { + data: D; + setData: UpdateObjectAtPropAndValue; }; type ResourceKeys = keyof ContainerResources; -const ServingRuntimeSizeExpandedField: React.FC = ({ +const ServingRuntimeSizeExpandedField = ({ data, setData, -}) => { +}: ServingRuntimeSizeExpandedFieldProps): React.ReactNode => { const handleChange = ( type: ContainerResourceAttributes.CPU | ContainerResourceAttributes.MEMORY, variant: ResourceKeys, diff --git a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeSection.tsx b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeSection.tsx index 0d2286cf30..635037914e 100644 --- a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeSection.tsx +++ b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeSizeSection.tsx @@ -3,8 +3,7 @@ import { FormGroup, Stack, StackItem, Popover, Icon } from '@patternfly/react-co import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons'; import { UpdateObjectAtPropAndValue } from '~/pages/projects/types'; import { - CreatingInferenceServiceObject, - CreatingServingRuntimeObject, + CreatingModelServingObjectCommon, ModelServingSize, } from '~/pages/modelServing/screens/types'; import { ServingRuntimeKind } from '~/k8sTypes'; @@ -17,11 +16,9 @@ import { AcceleratorProfileState } from '~/utilities/useAcceleratorProfileState' import SimpleSelect from '~/components/SimpleSelect'; import ServingRuntimeSizeExpandedField from './ServingRuntimeSizeExpandedField'; -type ServingRuntimeSizeSectionProps = { - data: CreatingServingRuntimeObject | CreatingInferenceServiceObject; - setData: - | UpdateObjectAtPropAndValue - | UpdateObjectAtPropAndValue; +type ServingRuntimeSizeSectionProps = { + data: D; + setData: UpdateObjectAtPropAndValue; sizes: ModelServingSize[]; servingRuntimeSelected?: ServingRuntimeKind; acceleratorProfileState: AcceleratorProfileState; @@ -30,7 +27,7 @@ type ServingRuntimeSizeSectionProps = { infoContent?: string; }; -const ServingRuntimeSizeSection: React.FC = ({ +const ServingRuntimeSizeSection = ({ data, setData, sizes, @@ -39,7 +36,7 @@ const ServingRuntimeSizeSection: React.FC = ({ selectedAcceleratorProfile, setSelectedAcceleratorProfile, infoContent, -}) => { +}: ServingRuntimeSizeSectionProps): React.ReactNode => { const [supportedAcceleratorProfiles, setSupportedAcceleratorProfiles] = React.useState< string[] | undefined >(); diff --git a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenInput.tsx b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenInput.tsx index 4e6cb115ad..94366915af 100644 --- a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenInput.tsx +++ b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenInput.tsx @@ -13,27 +13,24 @@ import { import { ExclamationCircleIcon, MinusCircleIcon } from '@patternfly/react-icons'; import { UpdateObjectAtPropAndValue } from '~/pages/projects/types'; import { - CreatingInferenceServiceObject, - CreatingServingRuntimeObject, + CreatingModelServingObjectCommon, ServingRuntimeToken, } from '~/pages/modelServing/screens/types'; import { translateDisplayNameForK8s } from '~/concepts/k8s/utils'; -type ServingRuntimeTokenInputProps = { - data: CreatingServingRuntimeObject | CreatingInferenceServiceObject; - setData: - | UpdateObjectAtPropAndValue - | UpdateObjectAtPropAndValue; +type ServingRuntimeTokenInputProps = { + data: D; + setData: UpdateObjectAtPropAndValue; token: ServingRuntimeToken; disabled?: boolean; }; -const ServingRuntimeTokenInput: React.FC = ({ +const ServingRuntimeTokenInput = ({ data, setData, token, disabled, -}) => { +}: ServingRuntimeTokenInputProps): React.ReactNode => { const checkDuplicates = (name: string): boolean => { const duplicates = data.tokens.filter( (currentToken) => diff --git a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenSection.tsx b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenSection.tsx index 363a4ddd5f..d40aa85197 100644 --- a/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenSection.tsx +++ b/frontend/src/pages/modelServing/screens/projects/ServingRuntimeModal/ServingRuntimeTokenSection.tsx @@ -3,27 +3,22 @@ import { Alert, Button, Checkbox, FormGroup, Stack, StackItem } from '@patternfl import { PlusCircleIcon } from '@patternfly/react-icons'; import IndentSection from '~/pages/projects/components/IndentSection'; import { UpdateObjectAtPropAndValue } from '~/pages/projects/types'; -import { - CreatingInferenceServiceObject, - CreatingServingRuntimeObject, -} from '~/pages/modelServing/screens/types'; +import { CreatingModelServingObjectCommon } from '~/pages/modelServing/screens/types'; import ServingRuntimeTokenInput from './ServingRuntimeTokenInput'; -type ServingRuntimeTokenSectionProps = { - data: CreatingServingRuntimeObject | CreatingInferenceServiceObject; - setData: - | UpdateObjectAtPropAndValue - | UpdateObjectAtPropAndValue; +type ServingRuntimeTokenSectionProps = { + data: D; + setData: UpdateObjectAtPropAndValue; allowCreate: boolean; createNewToken: () => void; }; -const ServingRuntimeTokenSection: React.FC = ({ +const ServingRuntimeTokenSection = ({ data, setData, allowCreate, createNewToken, -}) => ( +}: ServingRuntimeTokenSectionProps): React.ReactNode => ( ; +}; + +export type CreatingModelServingObjectCommon = { + name: string; + modelSize: ModelServingSize; externalRoute: boolean; tokenAuth: boolean; tokens: ServingRuntimeToken[]; - labels?: Record; }; export enum InferenceServiceStorageType { diff --git a/frontend/src/pages/projects/screens/detail/storage/ManageStorageModal.tsx b/frontend/src/pages/projects/screens/detail/storage/ManageStorageModal.tsx index cb5d4ccd67..807fb54607 100644 --- a/frontend/src/pages/projects/screens/detail/storage/ManageStorageModal.tsx +++ b/frontend/src/pages/projects/screens/detail/storage/ManageStorageModal.tsx @@ -174,7 +174,7 @@ const ManageStorageModal: React.FC = ({ existingData, isOp setCreateData(key, value)} + setData={setCreateData} currentSize={existingData?.status?.capacity?.storage} autoFocusName disableStorageClassSelect={!!existingData} diff --git a/frontend/src/pages/projects/screens/spawner/storage/CreateNewStorageSection.tsx b/frontend/src/pages/projects/screens/spawner/storage/CreateNewStorageSection.tsx index 57117d87ad..ca59d342be 100644 --- a/frontend/src/pages/projects/screens/spawner/storage/CreateNewStorageSection.tsx +++ b/frontend/src/pages/projects/screens/spawner/storage/CreateNewStorageSection.tsx @@ -6,23 +6,23 @@ import NameDescriptionField from '~/concepts/k8s/NameDescriptionField'; import { SupportedArea, useIsAreaAvailable } from '~/concepts/areas'; import StorageClassSelect from './StorageClassSelect'; -type CreateNewStorageSectionProps = { - data: CreatingStorageObject; - setData: UpdateObjectAtPropAndValue; +type CreateNewStorageSectionProps = { + data: D; + setData: UpdateObjectAtPropAndValue; currentSize?: string; autoFocusName?: boolean; menuAppendTo?: HTMLElement; disableStorageClassSelect?: boolean; }; -const CreateNewStorageSection: React.FC = ({ +const CreateNewStorageSection = ({ data, setData, currentSize, menuAppendTo, autoFocusName, disableStorageClassSelect, -}) => { +}: CreateNewStorageSectionProps): React.ReactNode => { const isStorageClassesAvailable = useIsAreaAvailable(SupportedArea.STORAGE_CLASSES).status; return ( diff --git a/frontend/src/pages/projects/types.ts b/frontend/src/pages/projects/types.ts index 1c892902fa..b882168ca7 100644 --- a/frontend/src/pages/projects/types.ts +++ b/frontend/src/pages/projects/types.ts @@ -9,14 +9,16 @@ import { Volume, VolumeMount, } from '~/types'; -import { ValueOf } from '~/typeHelpers'; import { AWSSecretKind } from '~/k8sTypes'; import { AcceleratorProfileState } from '~/utilities/useAcceleratorProfileState'; import { AcceleratorProfileSelectFieldState } from '~/pages/notebookController/screens/server/AcceleratorProfileSelectField'; import { K8sNameDescriptionFieldData } from '~/concepts/k8s/K8sNameDescriptionField/types'; import { AwsKeys } from './dataConnections/const'; -export type UpdateObjectAtPropAndValue = (propKey: keyof T, propValue: ValueOf) => void; +export type UpdateObjectAtPropAndValue = ( + propKey: K, + propValue: T[K], +) => void; export type NameDescType = { name: string; diff --git a/frontend/src/utilities/useGenericObjectState.ts b/frontend/src/utilities/useGenericObjectState.ts index ae2808256d..b5b985fd83 100644 --- a/frontend/src/utilities/useGenericObjectState.ts +++ b/frontend/src/utilities/useGenericObjectState.ts @@ -7,14 +7,14 @@ export type GenericObjectState = [ resetDefault: () => void, ]; -const useGenericObjectState = (defaultData: T): GenericObjectState => { +const useGenericObjectState = (defaultData: T | (() => T)): GenericObjectState => { const [value, setValue] = React.useState(defaultData); const setPropValue = React.useCallback>((propKey, propValue) => { setValue((oldValue) => ({ ...oldValue, [propKey]: propValue })); }, []); - const defaultDataRef = React.useRef(defaultData); + const defaultDataRef = React.useRef(value); const resetToDefault = React.useCallback(() => { setValue(defaultDataRef.current); }, []);