diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a24ffebdc8..5bd2d2122e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -44,7 +44,7 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} - lint-ui: + lint-and-typecheck-ui: runs-on: ubuntu-latest steps: - name: Checkout code @@ -65,6 +65,8 @@ jobs: node-version: "22.8.0" cache: "pnpm" cache-dependency-path: "**/pnpm-lock.yaml" + - name: Run typecheck + run: make typecheck-ui - name: Run linter run: make lint-ui diff --git a/Makefile b/Makefile index 18321d3997..84258f16dd 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,11 @@ lint-ui: pnpm --dir=ui install --dev pnpm --dir=ui run lint +.PHONY: typecheck-ui +typecheck-ui: + pnpm --dir=ui install + pnpm --dir=ui run typecheck + .PHONY: format-ui format-ui: pnpm --dir=ui install --dev diff --git a/ui/src/features/common/code-editor/yaml-editor-lazy.tsx b/ui/src/features/common/code-editor/yaml-editor-lazy.tsx index 2ee42ca252..c69b5f735b 100644 --- a/ui/src/features/common/code-editor/yaml-editor-lazy.tsx +++ b/ui/src/features/common/code-editor/yaml-editor-lazy.tsx @@ -89,6 +89,7 @@ const YamlEditor: FC = (props) => { validate: true, isKubernetes: true, format: true, + // @ts-expect-error correct schema schemas: schema && [ { uri: `https://raw.githubusercontent.com/akuity/kargo/${__UI_VERSION__ && __UI_VERSION__ !== 'development' ? __UI_VERSION__ : 'main'}/ui/src/gen/schema/${resourceType || 'stages'}.kargo.akuity.io_v1alpha1.json`, diff --git a/ui/src/features/project/credentials/create-credentials-modal.tsx b/ui/src/features/project/credentials/create-credentials-modal.tsx index 94f5359f4c..ea88abb17c 100644 --- a/ui/src/features/project/credentials/create-credentials-modal.tsx +++ b/ui/src/features/project/credentials/create-credentials-modal.tsx @@ -10,11 +10,11 @@ import { FieldContainer } from '@ui/features/common/form/field-container'; import { ModalComponentProps } from '@ui/features/common/modal/modal-context'; import { SegmentLabel } from '@ui/features/common/segment-label'; import { dnsRegex } from '@ui/features/common/utils'; +import { Secret } from '@ui/gen/k8s.io/api/core/v1/generated_pb'; import { createCredentials, updateCredentials } from '@ui/gen/service/v1alpha1/service-KargoService_connectquery'; -import { Secret } from '@ui/gen/v1alpha1/types_pb'; import { zodValidators } from '@ui/utils/validators'; import { constructDefaults, labelForKey, typeLabel } from './utils'; @@ -151,6 +151,7 @@ export const CreateCredentialsModal = ({ project, onSuccess, editing, init, ...p control={control} > {({ field }) => ( + // @ts-expect-error repoUrlInRegex won't be here so no boolean only strings - p.metadata?.name.toLowerCase().includes(filter.toLowerCase()) + p.metadata?.name?.toLowerCase().includes(filter.toLowerCase()) ); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && filteredProjects?.length === 1) { const selectedProject = filteredProjects[0].metadata?.name; - navigate(paths.project.replace(':name', selectedProject)); + if (selectedProject) { + navigate(paths.project.replace(':name', selectedProject)); + } } }; diff --git a/ui/src/features/project/pipelines/nodes/freight-indicators.tsx b/ui/src/features/project/pipelines/nodes/freight-indicators.tsx index 22cfec31aa..db8f8c2b16 100644 --- a/ui/src/features/project/pipelines/nodes/freight-indicators.tsx +++ b/ui/src/features/project/pipelines/nodes/freight-indicators.tsx @@ -32,7 +32,7 @@ export const FreightIndicators = ({ style={{ width: '10px', height: '10px', - backgroundColor: warehouseColorMap[freight?.warehouse || ''] + backgroundColor: warehouseColorMap[freight?.origin?.name || ''] }} onClick={(e) => { e.stopPropagation(); diff --git a/ui/src/features/project/pipelines/utils/useImages.ts b/ui/src/features/project/pipelines/utils/useImages.ts index 0ce11c2422..4e7c6aff06 100644 --- a/ui/src/features/project/pipelines/utils/useImages.ts +++ b/ui/src/features/project/pipelines/utils/useImages.ts @@ -12,24 +12,26 @@ export const useImages = (stages: Stage[]) => { return useMemo(() => { const images = new Map>(); stages.forEach((stage) => { - const len = stage.status?.history?.length || 0; - stage.status?.history?.forEach((freight, i) => { - freight.images?.forEach((image) => { - let repo = image.repoURL ? images.get(image.repoURL) : undefined; - if (!repo) { - repo = new Map(); - images.set(image.repoURL!, repo); - } - let curStages = image.tag ? repo.get(image.tag) : undefined; - if (!curStages) { - curStages = {} as StageStyleMap; - } - curStages[stage.metadata?.name as string] = { - opacity: 1 - i / len, - backgroundColor: stageColorMap[stage.metadata?.name as string] - }; - repo.set(image.tag!, curStages); - }); + const len = stage.status?.freightHistory?.length || 0; + stage.status?.freightHistory?.forEach((freight, i) => { + for (const warehouseValue of Object.values(freight?.items)) { + warehouseValue.images?.forEach((image) => { + let repo = image.repoURL ? images.get(image.repoURL) : undefined; + if (!repo) { + repo = new Map(); + images.set(image.repoURL!, repo); + } + let curStages = image.tag ? repo.get(image.tag) : undefined; + if (!curStages) { + curStages = {} as StageStyleMap; + } + curStages[stage.metadata?.name as string] = { + opacity: 1 - i / len, + backgroundColor: stageColorMap[stage.metadata?.name as string] + }; + repo.set(image.tag!, curStages); + }); + } }); const existingImages = getCurrentFreight(stage).flatMap((freight) => freight.images || []); diff --git a/ui/tsconfig.json b/ui/tsconfig.json index e2140715f4..065bc798d3 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -21,5 +21,6 @@ "@kargo-public/*": ["./public/*"] } }, - "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx"] + "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx"], + "exclude": ["src/**/*.test.ts"] }