
OpenMetadata 前端代码审查指南对齐 CI UI Checkstyle 的 React/TypeScript 质量门禁【免费下载链接】OpenMetadataThe Open Context Layer for Data and AI , OpenMetadata is the open platform for building trusted data context and business semantics for humans, AI assistants, and agents.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMetadata本篇指南面向 OpenMetadata 仓库的前端开发与代码审查者系统讲解 OpenMetadata 前端工程React TypeScript如何借助 CI 的UI Checkstyle工作流强制执行代码质量规范——涵盖 ESLint/Prettier、导入组织、Apache 2.0 License 头、i18n 国际化同步、Playwright 测试规范与组件架构约定。读完本文你将掌握一套审查通过即 CI 通过的前端代码审查方法能够在提交 PR 前预判并修复 CI 会拦截的问题并按照 OpenMetadata 的组件目录分层、状态管理与测试约定写出符合仓库规范的前端代码。本文以仓库内的 frontend-reviewer.md 为骨架结合 eslint.config.mjs、package.json 与 ui-checkstyle-changed.sh 等源码逐条印证。OpenMetadata 前端技术栈与审查上下文OpenMetadata 前端位于openmetadata-ui/src/main/resources/ui以如下技术栈为基础代码审查的所有规则都围绕这些约定展开React TypeScript仅允许函数式组件Functional Components不使用 class 组件openmetadata-ui-core-components作为规范化的共享组件库其源码位于openmetadata-ui-core-components/src/main/resources/ui业务代码通过openmetadata/ui-core-components引用而不是直接引入底层第三方组件Tailwind CSS v4所有工具类必须带tw:前缀如tw:flex、tw:text-smCSS 自定义属性CSS Custom Properties承载设计令牌颜色、间距、阴影、圆角禁止硬编码色值react-i18next承载国际化UI 中不允许出现字符串字面量全部文案走t(label.xxx)Jest负责单元测试Playwright负责 E2E 测试主 UI 的测试脚本见 package.json 的test与playwright:runESLintflat config配置文件为 eslint.config.mjsPrettier统一代码格式Zustand管理全局状态组件内局部状态使用useState。审查者的核心职责是在代码进入 CI 之前就站在 CI 的角度发现问题。若审查通过CI 也应通过——这意味着审查标准必须与 eslint.config.mjs 中实际配置的规则一一对应而不是凭个人偏好。CI Checkstyle 检查项每一次 PR 都会被强制执行以下检查在每个 PR 上都会真实运行。它们由package.json中的ui-checkstyle一键聚合脚本串联ui-checkstyle: yarn organize-imports yarn lint:fix yarn pretty yarn license-header-fix yarn i18n yarn generate:app-docs而ui-checkstyle:changed脚本见 ui-checkstyle-changed.sh只对相对origin/main变更的文件或显式传入的文件执行检查使本地修复足够快与 CI 工作流完全镜像。该脚本还内置了tw-audit与tw-deprecation-guard两个审计门禁失败即整体报错。1. ESLint Prettierlint-src在本地对变更文件执行cd openmetadata-ui/src/main/resources/ui yarn organize-imports:cli changed-files yarn lint:base --fix changed-files yarn pretty:base --write changed-fileslint:base在 package.json 中定义为NODE_OPTIONS--max-old-space-size8192 eslint --no-error-on-unmatched-pattern即以 8GB 堆上限运行 ESLint。以下规则由 eslint.config.mjs 中的src/**/*.{js,jsx,ts,tsx}区块实际配置为error规则作用no-console生产代码禁止console.log、console.warn等输出eqeqeqsmart 模式强制仅null检查例外max-len200 字符代码行超过 200 字符即报错注释上限 120 字符comments: 120spaced-comment注释//后必须有空格padding-line-between-statementsfunction、class、export、return、break、continue、throw前后必须空行react-hooks/rules-of-hooksHook 只能在顶层、只能在 React 函数中调用react-hooks/exhaustive-depsuseEffect/useMemo/useCallback的依赖数组必须完整当前为 warn 级别存量 1693 处typescript-eslint/no-unused-vars禁止未使用变量_前缀允许react/self-closing-comp空组件必须自闭合Div /而非Div/Divreact/jsx-sort-propsProps 按字母序排序回调置后callbacksLast: true, shorthandFirst: truejest/consistent-test-it测试统一用it()禁止混用test()/it()jest-formatting/padding-around-alldescribe、it、beforeEach等块周围必须空行JSON 键排序src/locale/**/*.json中的键必须按字母升序排列jsonc/sort-keys需要特别注意的是配置文件还内置了大量高于原文档基线的规则审查与开发时同样需要遵守TypeScript 严格规则typescript-eslint/no-explicit-any为error仓库已清零存量违规typescript-eslint/no-non-null-assertion为error禁止!断言typescript-eslint/no-use-before-define为error。i18n 硬规则i18next/no-literal-string为error任何用户可见字符串必须走t()仓库自研规则openmetadata-i18n/no-duplicate-string为error替代被关闭的 sonarjs 重复字符串规则mock 与测试夹具文件豁免。可访问性a11yeslint-plugin-jsx-a11y全量启用alt-text、label-has-associated-control、no-noninteractive-element-interactions、anchor-is-valid等均为error。SonarJS 家族no-identical-conditions、no-collapsible-if、no-identical-functions、no-nested-conditional、no-nested-functions、expression-complexity、cyclomatic-complexity等均为errorcognitive-complexity为warn阈值 15。安全规则sonarjs/no-clear-text-protocols、no-hardcoded-passwords、no-hardcoded-ip为error测试与 mock 文件豁免。React 性能规则react/no-array-index-key、react/jsx-no-constructed-context-values、react/no-unstable-nested-components、react/no-danger均为error。Tailwind 特例no-restricted-syntax禁止使用ring-*画边框——ring会编译为box-shadowWebKit 无法像素对齐在 Safari 非 100% 缩放时边框会变细甚至消失应改用border-*或outline-*。Prettier 规则配置见ui/.prettierrc.yaml2 空格缩进、单引号、严格 HTML 空白敏感度、左括号同行、最大行宽跟随 ESLint 的 200 字符限制。2. 导入组织lint-srcyarn organize-imports:cli changed-files导入必须排序并分组顺序强制为// 1. 外部库 import React from react; import { Button } from openmetadata/ui-core-components; // 2. 内部绝对导入 import { EntityType } from generated/entity/type; import { useTranslation } from hooks/useTranslation; // 3. 相对导入 import { MyComponentProps } from ./MyComponent.interface; import { formatData } from ./utils; // 4. 资源导入 import ./MyComponent.less;类型导入单独分组且不允许未使用的导入。仓库还通过自研插件openmetadata-imports实施更细的导入架构约束多数为 warn用于治理存量债务no-circular-imports循环导入、no-cross-page-imports页面间交叉导入、no-internal-barrel-imports组件目录内的index.tsbarrel 文件即文档中组件文件夹禁止 barrel 文件的规则来源、no-api-calls-in-iteration循环中调用 API等见 eslint-rules/openmetadata-imports.mjs。3. License Headerlicense-headeryarn license-header-fix changed-files每个源文件顶部都必须有 Apache 2.0 License 头当前版权年为 2025命令通过-r $(date %Y)动态注入年份见 package.json 的license-header-fix/* * Copyright 2025 Collate. * Licensed under the Apache License, Version 2.0 (the License); * ... */不同文件类型使用不同的注释语法.ts、.tsx、.js、.jsx、.css使用/* */块注释.sh、.yml、.yaml使用#行注释.html、.xml使用!-- --注释。新增文件包括 AI 生成的代码必须包含该头部。CI 侧的校验脚本为license-header-checklicense-check-and-add check -f .licenseheaderrc.json规则文件为ui/.licenseheaderrc.json。4. i18n 同步i18n-synccd openmetadata-ui/src/main/resources/ui yarn i18ni18n脚本实际执行sync-i18n --files **/locale/languages/*.json --primary en-us --space 2 --fn。规则要点en-us.json是主语言文件source of truth路径为 en-us.json其余所有语言文件必须与en-us.json拥有完全相同的键集合——仓库实际维护了19 个语言文件ar-sa、de-de、en-us、es-es、fr-fr、gl-es、he-he、ja-jp、ko-kr、mr-in、nl-nl、pr-pr、pt-br、pt-pt、ru-ru、sv-se、th-th、tr-tr、zh-cn、zh-tw见 languages 目录在en-us.json中新增键后同步工具会自动传播到其他语言键必须使用 kebab-case并置于正确的命名空间下label.*、message.*、server.*JSON 必须 2 空格缩进、键排序与 ESLint 的jsonc/sort-keys呼应。键命名约定示例{ label: { add-entity: Add {{entity}}, activity-feed: Activity Feed, activity-feed-plural: Activity Feeds }, message: { entity-deleted-successfully: {{entity}} deleted successfully! } }插值{{paramName}}双花括号复数追加-plural后缀变体-uppercase、-lowercase、-with-colon。主 UI 之外共享组件库openmetadata-ui-core-components也维护了自己的 i18n 同步脚本sync-i18n --files src/locale/languages/*.json --primary en-us --space 2 --fn以及更严格的check-i18n-all组合校验键提取检查、语言对等检查、非英文翻译检查见其 package.json。5. 核心组件库 Lintlint-core-componentscd openmetadata-ui-core-components/src/main/resources/ui yarn lint:base --fix changed-files yarn pretty:base --write changed-files共享组件库应用与主 UI 相同的 ESLint Prettier 规则其lint/pretty脚本配置在 package.json 中保证组件库代码与消费方代码风格完全一致。6. Playwright Lintlint-playwrightcd openmetadata-ui/src/main/resources/ui yarn organize-imports:cli changed-playwright-files yarn lint:base --fix changed-playwright-files yarn pretty:base --write changed-playwright-filesPlaywright 文件位于ui/playwright/**其规则在 eslint.config.mjs 中独立配置。阻塞级规则error必须通过规则捕获问题playwright/no-networkidle禁止waitForLoadState(networkidle)——不稳定playwright/no-page-pause测试中不得遗留page.pause()playwright/no-focused-test禁止.only——会破坏 CI此外仓库还额外启用了playwright/missing-playwright-await、playwright/valid-expect、playwright/no-element-handle、playwright/no-eval、playwright/prefer-web-first-assertions、playwright/no-useless-await为error以及通过 suppressions 棘轮机制提升为error的no-wait-for-timeout、no-force-option、no-skipped-test、no-wait-for-selector。还有一批 OpenMetadata 自研 Playwright 规则playwright/eslint-rules目录下的om-playwright/*no-awaited-wait-for-response、no-positional-locator、no-blanket-test-slow、require-assertion-per-test仅 e2e spec 文件等。警示级规则应修复规则捕获问题playwright/missing-playwright-await异步 Playwright 操作缺少awaitplaywright/valid-expect非法的断言语法playwright/no-wait-for-timeout硬编码等待——应使用 web-first 断言playwright/no-force-option禁止强制点击——应修复 locatorplaywright/no-element-handle应使用 locator 而非 element handleplaywright/no-eval能避免时不要用page.evaluate()playwright/no-skipped-test无理由的.skipplaywright/prefer-web-first-assertions用expect(locator).toBeVisible()而非手动检查playwright/no-useless-await移除多余的 awaitplaywright/no-wait-for-selector使用 web-first locator API值得特别一提的是 eslint.config.mjs 中的一条硬性约束Playwright 测试不得从src/导入应用代码仅src/generated/**与src/enums/**例外二者是零依赖的生成类型与枚举。原因是从应用 util 导入会把整个应用依赖图i18n 引导、整个组件库拖入 Node 测试进程。需要的工具应复制到playwright/目录下模式参考playwright/utils/dateTime.ts。7. 应用文档生成app-docscd openmetadata-ui/src/main/resources/ui yarn generate:app-docs该命令运行node generateApplicationDocs.js。若生成器产生了变更检查即失败——即应用Applications的文档必须与代码保持同步。因此任何修改了应用相关代码的 PR 都必须重新生成文档。8. TypeScript 类型检查CI 中当前禁用但本地应通过cd openmetadata-ui/src/main/resources/ui yarn tsc:check # 主 UItsc --noEmit yarn tsc:playwright # Playwright 测试tsc:check即tsc --noEmittsc:playwright使用playwright/tsconfig.json项目配置。虽然这两项目前在 CI 中处于禁用状态但本地必须通过审查时应主动标记类型错误。超越 CI 的代码质量审查CI 只保证格式与规则真正的质量问题需要审查者结合仓库约定把关。以下约定详见 DEVELOPER_HANDBOOK.md审查任何新增文件前都应先通读该手册。9. 类型安全禁止any——使用精确类型、unknown 类型守卫或generated/下由后端 schema 生成的 TypeScript 接口所有组件 props 定义在.interface.ts文件中API 响应使用生成的 TypeScript 接口进行类型标注除非绝对必要避免类型断言as Typeaction 类型与状态变体使用可辨识联合discriminated unions。10. 结构、命名与组件模式放置位置分层保持顶层components/、pages/、rest/、utils/、hooks/层内按domain/feature/分组如components/governance/glossary/GlossaryList/。领域为discovery、governance、observability、insights、platform跨领域能力lineage、data-contract、entity、activity-feed位于领域层。若新文件被直接丢进components/或utils/而无领域目录应标记。文件命名新文件单一词干后缀表示角色——GlossaryList.tsx、.types.ts、.utils.ts、.constants.ts、.style.less、.test.tsx、.mock.ts。不要对历史遗留的.component.tsx/.interface.ts文件要求重命名——后缀标记了迁移状态仅大小写/后缀重命名会搅乱 git 历史。业务逻辑放*.utils.ts写成纯函数无 React、无 JSX从而无需渲染即可单元测试。组件目录内禁止index.tsbarrel 文件——no-internal-barrel-imports会报告。仅函数式组件无 class 组件。传给子组件的回调使用useCallback昂贵计算使用useMemouseEffect依赖数组必须正确——无缺失依赖、无过度请求。多个加载状态使用useStateRecordstring, boolean({})。错误处理使用 ToastUtils 的showErrorToast/showSuccessToast。导航使用 react-router-dom 的useNavigate而非window.location。11. 样式所有 Tailwind 类使用tw:前缀tw:flex、tw:text-sm颜色使用 CSS 自定义属性var(--color-text-primary)绝不硬编码 hex间距与圆角使用设计令牌design tokens不再新增.less文件——新组件一律使用 Tailwind。12. 状态管理全局状态用 Zustand store如useLimitStore、useWelcomeStore无需共享的状态用局部useState特性级共享状态使用 Context Providerprop drilling 不超过 2 层。13. 测试组件测试使用同目录共置的.test.ts/.test.tsx文件测试用户可见行为screen.getByText、screen.getByRole而非内部实现统一使用it()不用test()describe、it、beforeEach块前后空行面向用户的新功能必须有 Playwright E2E 测试遵循 PLAYWRIGHT_DEVELOPER_HANDBOOK.md。Pre-Submit Checklist提交 PR 前的完整检查序列在创建 PR 之前按以下顺序在本地执行与 CI 将检查的内容一一对应cd openmetadata-ui/src/main/resources/ui # 1. 组织导入 yarn organize-imports:cli src/path/to/changed/files # 2. Lint 自动修复 yarn lint:fix # 3. 格式化 yarn pretty:base --write src/path/to/changed/files # 4. License 头 yarn license-header-fix src/path/to/changed/files # 5. i18n 同步若新增了键 yarn i18n # 6. 生成应用文档若改动应用 yarn generate:app-docs # 7. 类型检查 npx tsc --noEmit # 8. 运行测试 yarn test src/path/to/changed/component更快捷的方式是直接运行yarn ui-checkstyle:changed自动检测相对origin/main的变更文件或yarn ui-checkstyle:changed src/components/Foo.tsx显式指定文件脚本会一次性完成导入组织、lint、pretty、license 头、i18n 同步与应用文档生成并执行tw-audit与tw-deprecation-guard门禁详见 ui-checkstyle-changed.sh。审查优先级当变更文件较多、时间有限时按下述优先级依次排查CI 阻塞项是否会挂掉 lint-src、license-header、i18n-sync 或 lint-playwright类型安全是否存在any、缺失接口或未校验的 casti18nJSX 中是否有字符串字面量而非t(label.xxx)组件模式hooks 使用是否正确加载/错误状态是否完备样式tw:前缀、CSS 自定义属性、无硬编码值测试组件是否有 Jest 测试用户可见功能是否有 Playwright 测试审查输出格式审查结论建议按以下结构化模板输出便于作者逐条修复## Frontend Review: [component or feature name] ### CI Checkstyle Issues (will fail CI) - [file:line] **[lint-src]** Issue and fix - [file:line] **[license-header]** Missing Apache 2.0 header - [file:line] **[i18n-sync]** New key not added to en-us.json - [file:line] **[lint-playwright]** Using page.pause() in test ### Must Fix (wont fail CI but is wrong) - [file:line] **[Type Safety]** any type — use EntityReference ### Should Fix - [file:line] **[Component]** Missing useCallback for handler passed to child ### Positive Notes - What the code does well使用统一的类别标签便于聚合统计[lint-src]、[license-header]、[i18n-sync]、[lint-playwright]、[lint-core]、[app-docs]、[Type Safety]、[Component]、[Styling]、[Testing]、[State]。小结OpenMetadata 前端质量体系的核心思路是把 CI 的检查逻辑完全前置到审查与本地开发阶段审查者只要以 eslint.config.mjs 中实际生效的规则、DEVELOPER_HANDBOOK.md 中定义的架构分层为基准配合 package.json 提供的ui-checkstyle:changed一键脚本就能在 PR 提交前消化绝大多数 CI 失败。对于希望参与 OpenMetadata 前端贡献的开发者把上述 Pre-Submit Checklist 固化为肌肉记忆将大幅缩短从提交到合并的周期。【免费下载链接】OpenMetadataThe Open Context Layer for Data and AI , OpenMetadata is the open platform for building trusted data context and business semantics for humans, AI assistants, and agents.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMetadata创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考