From 0350e1d0e6509ba13573fe8729fdd8c77e5422b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Salavisa?= Date: Thu, 6 Aug 2026 03:18:24 +0200 Subject: [PATCH] ci(web): gate frontend CI on typecheck (#2304) Co-authored-by: Kandev Agent --- .github/workflows/frontend-tests.yml | 6 ++++++ .../sections/settings/settings-tree-render.test.tsx | 7 +++++-- apps/web/components/vcs/vcs-dialogs.tsx | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/frontend-tests.yml b/.github/workflows/frontend-tests.yml index 02f5b2e554..632b807686 100644 --- a/.github/workflows/frontend-tests.yml +++ b/.github/workflows/frontend-tests.yml @@ -154,6 +154,12 @@ jobs: - name: Run lint run: pnpm --filter @kandev/web lint + # `build` below is Vite, which strips types with esbuild and never checks + # them, so nothing in this job used to fail on a type error. Runs before + # the tests to fail fast on the cheaper check. + - name: Run typecheck + run: pnpm --filter @kandev/web typecheck + # Unlike the eslint literal-string guard (scoped to already-migrated paths # via i18nGuardFiles), these four checks scan components/app/hooks/lib # repo-wide. Each one pins a class of i18n bug that fails silently at diff --git a/apps/web/components/app-sidebar/sections/settings/settings-tree-render.test.tsx b/apps/web/components/app-sidebar/sections/settings/settings-tree-render.test.tsx index 36c4b47c9f..ea35af16d8 100644 --- a/apps/web/components/app-sidebar/sections/settings/settings-tree-render.test.tsx +++ b/apps/web/components/app-sidebar/sections/settings/settings-tree-render.test.tsx @@ -225,8 +225,11 @@ describe("Workspace settings order", () => { expect(automationsIndex).toBeGreaterThanOrEqual(0); expect(secretsIndex).toBeGreaterThan(automationsIndex); - expect(screen.getByRole("link", { name: "Secrets", exact: true })).toBeTruthy(); - expect(screen.queryByRole("link", { name: "Workspace Secrets", exact: true })).toBeNull(); + // Anchored so the leaf must be labelled exactly "Secrets" — a rename to + // "Workspace Secrets" has to fail here. `ByRoleOptions` has no `exact` + // flag; a RegExp is how ByRole expresses a strict accessible-name match. + expect(screen.getByRole("link", { name: /^Secrets$/ })).toBeTruthy(); + expect(screen.queryByRole("link", { name: /^Workspace Secrets$/ })).toBeNull(); }); }); diff --git a/apps/web/components/vcs/vcs-dialogs.tsx b/apps/web/components/vcs/vcs-dialogs.tsx index b44db24244..9efd73d837 100644 --- a/apps/web/components/vcs/vcs-dialogs.tsx +++ b/apps/web/components/vcs/vcs-dialogs.tsx @@ -369,7 +369,10 @@ export function pickRepoLabel( scopedRepo: string, isMultiRepo: boolean, resolveDisplayName: (name: string) => string | undefined, - t: ReturnType["t"], + // Structural, matching the other translate-taking helpers in the app: this + // only ever looks a key up, so both the hook's `t` and the module-level one + // from `@/lib/i18n` qualify. The branded `TFunction` excluded the latter. + t: (key: string) => string, ): string { if (scopedRepo) return resolveDisplayName(scopedRepo) || scopedRepo; if (isMultiRepo) return t("integrations:allRepos");