ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

firebase-ios-sdk 的 Spec 测试工具链:精准检测 PR 中变更的 Podspec 与受影响 SDK

firebase-ios-sdk 的 Spec 测试工具链:精准检测 PR 中变更的 Podspec 与受影响 SDK firebase-ios-sdk 的 Spec 测试工具链精准检测 PR 中变更的 Podspec 与受影响 SDK【免费下载链接】firebase-ios-sdkFirebase SDK for Apple App Development项目地址: https://gitcode.com/GitHub_Trending/fi/firebase-ios-sdkfirebase-ios-sdk 是一个由数十个独立 podspec如 FirebaseAuth、FirebaseFirestore、FirebaseStorage 等组成的多模块仓库。本文基于仓库 scripts/spec_testing/README.md 展开完整解析该目录下用于「判断一次 Pull Request 中哪些 podspec 发生了变更、进而只为受影响 SDK 运行测试」的持续集成工具链包括 Shell 封装脚本get_updated_files.sh、Swift 命令行工具UpdatedFilesCollector以及路径模式映射文件file_patterns.json。读完本文你将理解这套工具链的设计思想、数据流与实现细节并掌握如何在本地复现其核心检测逻辑。一、背景与定位为什么需要 Spec Testing 目录firebase-ios-sdk 仓库根目录下平铺着几十个 podspec 文件如 FirebaseAuth.podspec、FirebaseFirestore.podspec、FirebaseStorage.podspec、FirebaseMessaging.podspec 等每个 podspec 对应一个可独立发布的 SDK。一个典型的 PR 通常只改动其中某一个或某几个模块的源码如果在每次合并前都对仓库里所有 podspec 执行 CocoaPods lint / 打包测试会浪费大量 CI 时间与计算资源。scripts/spec_testing目录正是为解决这一问题而存在。根据其 README 的说明This directory contains tooling to determine which podspecs have been modified in a pull request. This information is used by the.github/workflows/infra.spec_testing.ymlworkflow to run tests only for the affected SDKs.即该目录下的工具负责判断 PR 中哪些 podspec 发生了变更检测结果交给 .github/workflows/infra.spec_testing.yml 工作流使 CI 只为「受影响」的 SDK 运行测试。整个工具链由三个部分协同工作组成部分相对路径职责入口 Shell 脚本scripts/spec_testing/get_updated_files.sh通过git diff收集变更文件列表调用 Swift 工具并汇总输出Swift 命令行工具scripts/spec_testing/updated_files_collector/读取变更文件与模式映射做正则匹配输出需要测试的 podspec 清单路径模式映射scripts/spec_testing/file_patterns.json定义「文件路径模式 → SDK 名称」的映射关系二、Updated Files CollectorSwift 命令行工具README 明确指出get_updated_files.sh脚本背后实际运行的是一个 Swift 工具updated_files_collector/Sources/UpdatedFilesCollector即 main.swift。它是一个基于 Swift Argument Parser 的可执行命令行程序其包描述文件 Package.swift 声明可执行产品名UpdatedFilesCollector包名本身为CodeCoverage唯一外部依赖swift-argument-parserfrom: 0.2.0Swift 工具链最低版本swift-tools-version:5.3。2.1 命令行参数UpdatedFilesCollector继承自ParsableCommand共声明四个Option参数对应 main.swift参数名类型说明--changed-file-paths[String]必填一个 txt 文件路径内容为本次变更的文件路径列表按换行符拆分成数组--code-coverage-file-patterns[SDKFilePattern]必填一个 JSON 文件路径内容符合SDKFilePattern结构即 file_patterns.json--output-sdk-file-urlURL?可选输出文件路径用于写出「与变更文件相关的所有 podspec」清单--exclude-podspecs[String]可选需要从测试中排除的 podspec 列表采用parsing: .upToNextOption语法以支持多个值值得注意的是--changed-file-paths与--code-coverage-file-patterns都通过transform闭包完成文件读取与解析前者把文本文件按换行分割成字符串数组后者用JSONDecoder将 JSON 直接解码为[SDKFilePattern]数组。2.2 数据结构工具内部定义了两个可解码/可编码的结构体main.swiftSDKFilePattern由sdkSDK 名称、podspecs该 SDK 关联的 podspec 文件列表、filePatterns用于匹配文件路径的正则模式列表三个字段组成与file_patterns.json的条目一一对应SDKPodspec只有一个podspec字段用于生成形如[{podspec:FirebaseABTesting.podspec},{podspec:FirebaseAnalytics.podspec}]的 JSON 输出。2.3 核心匹配逻辑run()方法main.swift的执行流程如下打印本次检测到的全部变更文件遍历所有SDKFilePattern先将每个 SDK 的run_job标志初始化为false并以::set-output namesdk_run_job::false的形式输出这是 GitHub Actions 早期的set-output工作流命令格式用于把结果暴露给后续步骤对每个 SDK遍历其filePatterns中的每条正则用NSRegularExpression对每个变更文件路径做匹配main.swift。只要有一个变更路径命中任一模式就将该 SDK 的run_job置为true并把该 SDK 的 podspec 追加进结果数组除非它出现在--exclude-podspecs排除列表中一旦某个 SDK 命中立即break跳过该 SDK 的剩余模式进入下一个 SDK 的检测若指定了--output-sdk-file-url将结果数组用JSONEncoder编码成 JSON 字符串去除首尾空白后以原子写入方式落盘main.swift。整个匹配是「变更文件路径 → SDK 名」的单向映射只要命中一个模式就认为该 SDK 受影响属于典型的“一票命中”策略实现简单、判定快速。三、file_patterns.json文件路径到 SDK 的映射表file_patterns.json 是整套工具的“规则引擎”定义了文件路径模式与 SDK 名称之间的映射。每个条目包含三个字段sdkSDK 的逻辑名称如abtesting、analytics、auth、core、crashlytics、firestore、storage等共 19 个podspecs该 SDK 对应的一个或多个 podspec 文件名filePatterns一组正则表达式用来匹配变更文件的相对路径。例如 abtesting 的完整配置{ sdk: abtesting, podspecs: [FirebaseABTesting.podspec], filePatterns: [ ^FirebaseABTesting.*, Interop/Analytics/Public/[^/]\\.h, \\.github/workflows/abtesting\\.yml ] }从这份配置可以总结出几类典型模式SDK 源码目录前缀模式出现频率最高如^FirebaseABTesting.*、^FirebaseAuth.*、^Crashlytics.*、^FirebaseRemoteConfig.*用于匹配某个模块目录下的任何改动共享 Interop 头文件模式如Interop/Analytics/Public/[^/]\\.h、FirebaseAuth/Interop/[^/]\\.h、FirebaseMessaging/Interop/[^/]\\.h因为多个 SDK 依赖共同的互操作协议头文件这些头文件变更会级联影响多个 SDKCI 工作流文件模式如\\.github/workflows/auth\\.yml、\\.github/workflows/firestore\\.yml工作流本身的改动也会触发对应 SDK 的测试跨模块依赖模式例如firestore条目同时匹配FirebaseCore/Internal、FirebaseCore/Sources/Public、CMakeLists\\.txt、cmake/.*database条目同时匹配Example/Database/与FirebaseAuth/Interop/[^/]\\.h体现了 Firestore 对 CMake 构建基础设施和 Core/Auth 互操作层的强依赖兜底模式firebase条目对应聚合的 Firebase.podspec使用.*.podspec匹配任何podspec 文件的改动以及CoreOnly/.*匹配聚合框架源码起到全局兜底作用。另有几个值得注意的特殊条目analytics同时挂载FirebaseAnalytics.podspec与GoogleAppMeasurement.podspec两个 podspecfirestore的模式列表中包含FirebaseAppCheck/Interop/[^/]\\.h、FirebaseAuth/Interop/[^/]\\.h等多个互操作头文件以及cmake/.*构建脚本remoteconfig还匹配scripts/generate_access_token\\.sh说明该脚本与 Remote Config 测试相关。这张映射表是纯数据驱动的新增 SDK 或调整依赖关系时只需增删 JSON 条目无需改动 Swift 代码。四、get_updated_files.shShell 封装与差异收集get_updated_files.sh 是整个流程的入口脚本负责在 CI 环境中完成三件事解析命令行参数、通过git diff获取目标分支与当前提交之间的变更文件、调用 Swift 工具。4.1 参数解析脚本支持两个参数get_updated_files.sh-pspec_output_file指定输出文件路径即后面要传给 Swift 工具的--output-sdk-file-url-eexclude_specs指定要排除的 podspec 列表支持空格分隔多个值。4.2 差异计算脚本的核心差异计算逻辑如下get_updated_files.shtarget_branch_head$(git rev-parse remotes/origin/${GITHUB_BASE_REF}) echo ::set-output nametarget_branch_head::${target_branch_head} cd scripts/spec_testing/updated_files_collector git diff --name-only remotes/origin/${GITHUB_BASE_REF} ${GITHUB_SHA} updated_files.txt通过git rev-parse remotes/origin/${GITHUB_BASE_REF}拿到目标分支PR 的 base 分支头部提交哈希并以::set-output nametarget_branch_head::输出供后续代码覆盖率对比使用用git diff --name-only remotes/origin/${GITHUB_BASE_REF} ${GITHUB_SHA}对比目标分支头部与当前合并提交只列出变更文件名写入updated_files.txt——这就是 README 所述「从合并提交中列出变更文件」的实现注释明确指出该列表由 merge commit 与目标分支 head commit 比较生成。这里依赖 CI 环境变量GITHUB_BASE_REFPR 目标分支与GITHUB_SHA当前提交因此脚本设计为只在 GitHub Actions 语境下运行。4.3 调用 Swift 工具根据是否指定-p参数脚本有两种调用形态get_updated_files.shif [ -z $spec_output_file ] ; then swift run UpdatedFilesCollector --changed-file-paths updated_files.txt --code-coverage-file-patterns ../file_patterns.json else swift run UpdatedFilesCollector --changed-file-paths updated_files.txt --code-coverage-file-patterns ../file_patterns.json --output-sdk-file-url ${spec_output_file} --exclude-podspecs ${exclude_specs} mv ${spec_output_file} ${dir} fi未指定-p时仅输出各 SDK 的run_job标志用于触发代码覆盖率工作流指定-p时额外写出 podspec 清单 JSON并把产物移回仓库根目录方便后续步骤cat读取。脚本开头还注释说明了设计意图file_patterns.json中路径命中的变更文件将触发代码覆盖率工作流PR 中的更新会生成覆盖率报告。脚本整体以set -ex开启严格模式任何命令失败都会立即中止。五、与 GitHub Actions 工作流的集成工具的最终消费方是 .github/workflows/infra.spec_testing.yml。该工作流在pull_request目标分支为main和workflow_dispatch时触发由两个 job 组成5.1 specs_checking计算测试矩阵specs_checkingjobinfra.spec_testing.yml以fetch-depth: 0检出完整历史保证git diff可用然后运行./scripts/spec_testing/get_updated_files.sh -p output.json -e Firebase.podspec\ FirebaseFunctions.podspec echo matrix{\include\:$( cat output.json )} $GITHUB_OUTPUT echo podspecs$(cat output.json) $GITHUB_OUTPUT-e Firebase.podspec\ FirebaseFunctions.podspec演示了多值排除的写法空格需要转义才能被正确拆分工作流注释特别强调这一点output.json内容形如[{podspec:FirebaseABTesting.podspec},{podspec:FirebaseAnalytics.podspec}]被包装成 GHA 的include矩阵语法输出podspecs输出用于判定后续 job 是否需要运行。5.2 specs_testing按矩阵运行 podspec 测试specs_testingjobinfra.spec_testing.yml通过needs: specs_checking依赖前一个 job并在podspecs ! []时才执行。它用strategy.matrix展开成与 podspec 数量等价的并行任务每个任务执行mkdir specTestingLogs cd ReleaseTooling swift run podspecs-tester --git-root ${GITHUB_WORKSPACE} --podspec $PODSPEC --skip-tests --temp-log-dir ${GITHUB_WORKSPACE}/specTestingLogs其中podspecs-tester是 ReleaseTooling 子包中 PodspecsTester 提供的可执行命令负责对指定 podspec 做打包验证当前参数为--skip-tests即只验证 podspec 可解析、可构建不运行单元测试失败时把日志目录specTestingLogs/*.txt上传为 CI 产物方便排查。六、在本地复现检测流程尽管整套脚本面向 CI 环境依赖GITHUB_BASE_REF、GITHUB_SHA等环境变量你依然可以在本地仓库中手动复现其核心步骤验证某个改动会命中哪些 SDK# 1. 生成当前工作区相对 main 分支的变更文件列表 git diff --name-only remotes/origin/main HEAD /tmp/updated_files.txt # 2. 运行 Swift 工具输出各 SDK 的 run_job 标志 cd scripts/spec_testing/updated_files_collector swift run UpdatedFilesCollector \ --changed-file-paths /tmp/updated_files.txt \ --code-coverage-file-patterns ../file_patterns.json # 3. 指定输出文件并排除部分 podspec生成可测试清单 swift run UpdatedFilesCollector \ --changed-file-paths /tmp/updated_files.txt \ --code-coverage-file-patterns ../file_patterns.json \ --output-sdk-file-url /tmp/output.json \ --exclude-podspecs Firebase.podspec FirebaseFunctions.podspec cat /tmp/output.json前提是本地装有 Swift 5.3 工具链且能联网拉取swift-argument-parser依赖。你可以尝试修改任意 SDK 目录下的文件比如FirebaseAuth/Sources下的源码再运行上述命令观察auth_run_job标志被置为true、FirebaseAuth.podspec出现在输出清单中的效果。七、总结scripts/spec_testing是一套小而精的 CI 辅助工具链其设计要点可概括为数据驱动SDK 与文件路径的映射全部收敛在 file_patterns.json 中新增模块或调整依赖只需改 JSON单层封装Shell 脚本只做参数解析、git diff与调用转发匹配逻辑全部由 Swift 工具UpdatedFilesCollector完成职责清晰一票命中任一变更路径命中任一模式即判定 SDK 受影响判定快速且易于理解无缝对接 CI通过::set-output与 GHA 的include矩阵语法把「受影响 podspec」直接转换为并行测试任务的输入确保 PR 的测试范围始终与改动范围精确对齐。对于希望为多 podspec 仓库搭建“按需测试” CI 的开发者这套工具的「Shell 收集差异 Swift 正则匹配 JSON 驱动规则 GHA 矩阵消费」四层架构是一份可直接借鉴的参考实现。【免费下载链接】firebase-ios-sdkFirebase SDK for Apple App Development项目地址: https://gitcode.com/GitHub_Trending/fi/firebase-ios-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表