ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

DataHub Selective CI 指南:按连接器精准触发集成测试的智能测试矩阵系统

DataHub Selective CI 指南:按连接器精准触发集成测试的智能测试矩阵系统 DataHub Selective CI 指南按连接器精准触发集成测试的智能测试矩阵系统【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub本指南完整解析 DataHub 仓库中metadata-ingestion模块的Selective CI选择性持续集成机制。该机制通过分析 PR 变更文件仅运行与改动连接器Connector相关的集成测试替代每次全量跑完整测试套件的低效策略。读者将掌握其决策规则、连接器自动发现原理约定式 entry-point 式、connector.yaml异常配置、import 依赖图分析、本地调试命令以及 GitHub Actions 中的落地方式含run-all-ingestion-tests等标签的用法。背景为什么要做 Selective CIDataHub 的metadata-ingestion模块源码位于 metadata-ingestion/src/datahub/ingestion包含上百个数据源连接器如powerbi、kafka、clickhouse、bigquery_v2等每个连接器在 tests/integration/ 下有独立的集成测试目录。如果每次 PR 都全量运行所有集成测试不仅耗时巨大还会让与改动无关的连接器测试白白消耗 CI 资源。Selective CI 系统的核心思想是只运行与 PR 改动相关的集成测试。它的大脑是脚本 scripts/selective_ci_checks.py脚本借鉴了 Apache Airflow 的selective_checks.py设计见脚本模块 docstring输出一个 JSON 对象run_all_integrationtest_matrix供下游 GitHub Actions 作业消费。核心决策流程一个 PR 的测试如何被判定脚本的入口是classify(changed_files, repo_root)函数selective_ci_checks.py 中classify定义。变更文件列表来自get_changed_files()执行的git diff --name-only origin/base-ref...HEAD因此本地运行前必须git fetch确保origin/base-ref可达。判定逻辑遵循以下优先级1. 任何核心/非连接器文件变更 → 全量跑一旦变更文件满足以下任一条件直接返回run_all_integrationtrue文件位于metadata-ingestion/下但不在source/{connector}/路径内例如api/、emitter/、setup.py文件位于metadata-models/模型变更影响所有连接器的元数据结构文件位于tests/integration/但直接在该目录下如conftest.py——属于共享测试基础设施。脚本通过常量CONNECTOR_SOURCE_PREFIXmetadata-ingestion/src/datahub/ingestion/source/与INTEGRATION_TEST_PREFIXmetadata-ingestion/tests/integration/进行前缀匹配其余落在metadata-ingestion/或metadata-models/下的文件一律视为核心变更。注意classify()对非metadata-ingestion/、metadata-models/前缀的文件如.github/workflows/*.yml、根目录docs/直接忽略既不触发全量也不进入矩阵。2. 仅连接器源码变更 → 构建精准测试矩阵每个被变更连接器的集成测试进入矩阵若连接器 A 从连接器 B 导入了模块变更 B 也会触发 A 的测试。依赖通过 Pythonast解析 import 自动解析详见下文import 分析。3. 集成测试或 golden 文件变更 → 触发对应连接器例如编辑tests/integration/powerbi/golden.json会运行 PowerBI 测试具体实现上classify()将tests/integration/{connector_name}/下的文件解析出第一级子目录名反查对应连接器的测试路径直接位于tests/integration/根目录无子目录的文件触发全量套件。4. 脚本/文档/单元测试专属变更 → 完全跳过集成测试以下前缀SAFE_PREFIXES内的变更不触发任何集成测试SAFE_PREFIXES [ metadata-ingestion/tests/unit/, metadata-ingestion/tests/performance/, metadata-ingestion/tests/conftest, metadata-ingestion/tests/integration/bigquery_wif/, metadata-ingestion/scripts/, metadata-ingestion/docs/, ]单元测试、性能测试、脚本与文档改动不会影响连接器运行时行为因此跳过集成测试是安全的。连接器自动发现两种互补机制load_connector_registry()负责扫描并注册所有连接器不依赖手工维护清单。1. 约定式发现Convention-based若source/{name}/目录存在且tests/integration/{name}/目录存在连接器即被自动注册无需任何配置对于单文件连接器如source/feast.py脚本通过src.glob(*.py)扫描并采用精确路径匹配语义避免feast_enterprise.py误匹配feast.py匹配到tests/integration/feast/即注册以下划线开头的目录如__pycache__被显式跳过不会误判为连接器。2. Entry-point 式发现针对共享目录对于源码位于共享目录如source/sql/、source/usage/的薄封装连接器约定式发现无法区分具体子模块。此时build_source_to_test_dirs()从 setup.py 中读取datahub.ingestion.source.pluginsentry points# setup.py 中的 entry point 示例line 1182 附近 clickhouse datahub.ingestion.source.sql.clickhouse:ClickHouseSource,脚本用正则([a-z][a-z0-9_-]*)\s*\s*(datahub\.ingestion\.source\.[^:]):[^]解析 entry points再通过_register_plugin_variants()注册名称变体连字符/下划线互换、剥离datahub-前缀从而将tests/integration/clickhouse/精确映射到source/sql/clickhouse.py。这实现了per-file 窄化修改source/sql/clickhouse.py只跑tests/integration/clickhouse/而不会连带触发 redshift、bigquery 等其他 SQL 连接器的测试。共享工具文件的处理当共享目录中被修改的文件找不到任何 entry-point 匹配如source/sql/sql_common.py是共享工具类_narrow_ep_tests()返回None窄化被禁用转而咨询 import 依赖图——所有从sql/导入的连接器都会被触发测试。何时需要 connector.yamlconnector.yaml是源目录下的可选配置文件仅为异常情况而设。真实仓库中目前只有一处使用powerbi/connector.yaml# Exception: powerbi_report_server source is also covered by powerbi tests. extra_source_paths: - src/datahub/ingestion/source/powerbi_report_server/场景一测试目录名与源目录名不一致# 示例src/datahub/ingestion/source/myconnector/connector.yaml # 假设场景——仅当测试目录名与源目录名不匹配时需要 test_path: tests/integration/my-connector-tests/场景二源码跨多个目录# src/datahub/ingestion/source/powerbi/connector.yaml仓库真实存在 extra_source_paths: - src/datahub/ingestion/source/powerbi_report_server/场景三测试跨多个目录# 示例src/datahub/ingestion/source/myconnector/connector.yaml # 假设场景——仅当连接器有多个测试目录时需要 extra_test_paths: - tests/integration/myconnector-extra/重要说明位于共享源目录如source/sql/中的连接器不需要connector.yaml——它们的测试通过 entry-point 分析自动发现。此外load_connector_registry()对 YAML 解析异常有严格处理语法错误或非字典结构的connector.yaml会直接sys.exit(1)使检测失败而空文件则回退到约定式发现测试用例test_empty_yaml_uses_convention验证了这一点。新增连接器三种情形对照情形需要做的事测试目录名 源目录名什么都不用做。创建source/myconnector/与tests/integration/myconnector/系统自动发现测试目录名不同在源目录创建connector.yaml声明test_path: tests/integration/my-connector-tests/连接器位于共享源目录如source/sql/什么都不用做。在setup.py中注册 entry point 即可connector.yaml中的test_path与extra_test_paths也会被validate()校验对于共享目录场景系统自动完成两级响应连接器自身源文件变更时只跑它的测试共享工具如sql_common.py变更时通过 import 图分析跑全部 SQL 连接器测试。import 依赖图分析捕捉非显而易见的依赖build_import_graph()是选择性触发的关键底层能力扫描每个连接器源目录下所有.py文件单文件连接器只扫自身用 Python 标准库ast解析import X与from X import ...语句ast.Import/ast.ImportFrom将导入的模块名通过_source_path_to_module()转成点分模块路径src/datahub/ingestion/source/sql→datahub.ingestion.source.sql再映射回已知连接器源目录最长前缀匹配_find_source_dir()构建依赖图connector_a → {connector_b, connector_c}。当connector_b变更时classify()遍历全量 registry凡是import_graph.get(source_dir)与changed_source_dirs有交集的连接器其测试路径都会被加入矩阵。这正是文档中所强调的价值像dbt导入sql/sql_types.py这种隐性依赖靠人肉维护依赖清单极易遗漏而 ast 解析能自动捕捉。单元测试TestImportGraph专门验证了mysql依赖sql、powerbi不依赖sql、无自导入、裸import datahub.ingestion.source.sql.sql_common也能被检测以及语法错误的.py文件不会导致整个图构建崩溃仅打印 WARNING 跳过。本地运行脚本# 查看给定变更会跑什么需要 git fetch保证 origin/base-ref 可达 cd metadata-ingestion python scripts/selective_ci_checks.py --dry-run --base-ref master # 校验所有 connector.yaml 映射 python scripts/selective_ci_checks.py --validate # 强制全量run-all-ingestion-tests 标签在 CI 中使用的正是此逻辑 python scripts/selective_ci_checks.py --force-all脚本 CLI 完整参数__main__段参数默认值说明--base-refmaster与之 diff 的基准分支--outputgha输出格式json或ghaGitHub Actions 键值对--validate关闭校验connector.yaml映射并交叉检查共享基目录覆盖--dry-run关闭打印结果而不写 GITHUB_OUTPUT--force-all关闭强制run_all_integrationtrue输出机制脚本总是将完整决策写入ci-decisions.json用于 artifact 上传/调试gha模式下将run_all_integration、test_matrix写入GITHUB_OUTPUT并把人类可读的决策摘要含矩阵表格与完整 JSON写入GITHUB_STEP_SUMMARY。CIDecisions数据类还强制不变量run_all_integrationtrue与非空test_matrix互斥违反会抛ValueError测试用例TestCIDecisionsInvariant验证。安全默认值宁可多跑绝不漏测Selective CI 在追求效率的同时把漏测视为最不可接受的失败模式未知文件source/下不属于任何已知连接器的文件含未知扩展名如.parquet、.yaml、.json触发全量套件非连接器文件api/、emitter/、setup.py、metadata-models/等永远触发全量共享测试基础设施直接位于tests/integration/的文件如conftest.py触发全量文档文件连接器源目录内的.md文件被忽略常量IGNORED_SOURCE_EXTENSIONS (.md,)其余所有文件类型都会触发测试run-all-ingestion-tests标签PR 上添加该标签强制全量无视具体变更内容脚本崩溃即失败检测脚本异常退出会直接 fail 闸门作业gate job绝不静默通过安全网Safety net若变更的源目录产出的测试矩阵为空例如源目录既无测试路径也无 entry-point 覆盖则回退到全量并打印 WARNING——变更代码永远不会被静默地不测试对应classify()尾部逻辑与测试用例TestSafetyNet。connector.yaml 字段参考字段必填描述test_path否覆盖默认测试目录默认tests/integration/{源目录名}/extra_source_paths否该连接器测试额外覆盖的源目录extra_test_paths否该连接器的额外测试目录test_paths否测试目录的遗留列表形式仅用于 validate 校验优先使用test_pathextra_test_pathsvalidate()函数的职责包括检查所有声明的测试路径在磁盘上真实存在不存在的路径会作为错误导致退出码非零并对未被任何连接器覆盖的测试目录给出 WARNING这类目录只在run_all_integrationtrue时才会运行。共享基目录如source/sql/、source/usage/不再需要connector.yaml——entry-point 分析自动处理其中所有连接器的测试发现。GitHub Actions 中的落地方式1. 主工作流 .github/workflows/metadata-ingestion.ymldetect作业约 line 30-109是流水线的决策中枢先检查 PR 是否带run-all-ingestion-tests标签label-check步骤非 PR 事件push 到 master、release、手动 dispatch或标签存在时执行--force-all否则执行--base-ref $BASE_REFbuild-matrix步骤将决策拼入 CI 矩阵testQuickPython 3.10/3.11/3.12与testPerformance3.11永远执行run_all_integrationtrue时追加静态定义的testIntegrationBatch0~5testIntegrationBatchRecording全量批次选择性模式下将test_matrix中每个条目追加python-version: 3.11组成动态矩阵否则集成测试为空数组决策 JSON 以ci-decisionsartifact 上传供下游消费。工作流中还包含--validate步骤校验 selective CI 连接器映射与integration-tests-gate闸门作业确保决策脚本自身的健康度。2. 外部连接器测试触发 .github/workflows/connector-tests-trigger.yml该工作流在 Python Build 与 Metadata Ingestion 两个上游作业成功后下载ci-decisionsartifact 判断是否派发到外部acryldata/connector-tests若run_all_integrationtrue派发全部连接器测试否则从test_matrix提取连接器名经静态映射表转换如bigquery_v2 → bigquery、unity → databricks、fabric → fabric_onelake后派发对应连接器skip-connector-tests标签且由 org 成员添加可整体跳过无匹配连接器时创建skipped状态的 check run 并写明原因。单元测试行为的可验证保障test_selective_ci_checks.py 用 1061 行测试构建了合成仓库结构tmp_pathfixture系统性地验证了本文所述全部行为TestNonConnectorChangesapi/、setup.py、metadata-models/、emitter/变更 → 全量TestSharedBasesql/sql_common.py变更 → mysql、postgresimport 分析 clickhouseentry-point测试触发而 powerbi 不受影响TestDirectConnector仅 powerbi/kafka 自身测试触发TestIntegrationTestChanges测试文件与 golden 文件均触发对应连接器TestSQLNarrowingclickhouse.py变更只跑 clickhouse不外溢到 powerbisql_common.py变更跑全部 SQL 连接器TestKnownConnectorWithoutTestsglue 场景source/aws/glue.py是已知 entry-point 但无集成测试变更它不会通过 import 图级联触发 athena/s3/kafka而共享工具aws_common.py变更仍会级联到所有依赖者TestExtraSourcePaths/TestExtraTestPathsconnector.yaml的扩展路径正确纳入矩阵TestMalformedYAML坏 YAML 退出、空 YAML 回退约定TestSafePrefixConftesttests/conftest.py安全、tests/integration/conftest.py触发全量二者严格区分。结语Selective CI 是 DataHub 元数据摄取工程效率与测试可靠性的平衡点约定式 entry-point 式的双轨发现让零配置成为常态ast解析的 import 依赖图自动捕捉隐性依赖connector.yaml只为命名、跨目录等异常场景存在而层层安全网未知文件全量、空矩阵回退、脚本崩溃即失败确保了效率优化永远不会以牺牲测试覆盖为代价。对于新增连接器的开发者多数情况下只需要照常创建源码与测试目录即可其余交给这套系统自动处理。【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表