菜单

持续集成

相关源文件

本文档介绍了 Protocol Buffers 项目用于确保跨多种编程语言、操作系统和构建配置的代码质量的持续集成 (CI) 系统。

目的和概述

Protocol Buffers CI 系统会自动测试代码更改,以检测回归并确保项目各种语言实现之间的兼容性。该系统基于 GitHub Actions 构建,并采用全面的测试矩阵,涵盖各种平台、编译器和配置选项。

来源:.github/workflows/test_cpp.yml .github/workflows/test_java.yml .github/workflows/test_python.yml .github/workflows/test_ruby.yml .github/workflows/test_php.yml .github/workflows/test_csharp.yml .github/workflows/test_objectivec.yml .github/workflows/test_rust.yml .github/workflows/test_upb.yml .github/workflows/test_bazel.yml

工作流类型

CI 系统支持两种工作流

预提交工作流

这些工作流在合并前针对拉取请求运行,侧重于关键测试,以便为开发人员提供快速反馈。目标是在不产生过多等待时间的情况下捕获明显问题。

持续工作流

这些工作流在更改合并到主分支后运行。它们包括所有预提交测试,以及其他耗时更长的测试,这些测试对于每个拉取请求来说都太慢了。

区别由工作流输入控制

在工作流文件中,测试可以标记为 continuous-only: true,以指示它们应仅在持续测试期间运行。

来源:.github/workflows/test_cpp.yml3-19 .github/workflows/test_cpp.yml32-37

测试矩阵

CI 系统在全面的配置矩阵中测试 Protocol Buffers

语言实现

每种支持的语言都有专用的工作流和特定的测试配置

语言工作流文件关键测试组件
C++test_cpp.yml核心库、优化/调试构建、 sanitizers、多个编译器
μpbtest_upb.yml小型 C 实现、wheel 生成
Javatest_java.ymlJDK 版本 (8/11/17)、兼容性测试、Maven BOM
Pythontest_python.yml多个 Python 版本、纯 Python 和 C++ 实现
Rubytest_ruby.yml多个 Ruby 版本、原生和 FFI 实现
PHPtest_php.ymlPHP 版本、内存泄漏测试、扩展编译
C#test_csharp.yml.NET 构建、一致性测试
Objective-Ctest_objectivec.ymlXcode、CocoaPods、Apple Silicon 测试
Rusttest_rust.ymlBazel、Cargo、多种配置

测试维度

来源:.github/workflows/test_cpp.yml26-40 .github/workflows/test_java.yml26-60 .github/workflows/test_python.yml26-56 .github/workflows/test_ruby.yml26-42 .github/workflows/test_php.yml26-55

工作流结构

每个工作流都遵循类似的结构

例如,在 C++ 工作流 (test_cpp.yml) 中,有以下作业组:

  • Linux 测试(各种配置)
  • Linux GCC 测试(多个版本)
  • Linux 发行版构建(x86_64、aarch64)
  • Linux CMake 测试(普通、Ninja、共享库)
  • macOS 测试(Intel 和 Apple Silicon)
  • Windows 测试(MSVC 和 clang-cl)

来源:.github/workflows/test_cpp.yml22-590 .github/workflows/test_java.yml26-60 .github/workflows/test_python.yml26-56 .github/workflows/test_ruby.yml26-42 .github/workflows/test_php.yml26-55

CI 基础设施组件

Docker 容器

大多数基于 Linux 的测试在 Docker 容器中运行,以确保环境的一致性。这些容器托管在 Google Artifact Registry (us-docker.pkg.dev/protobuf-build/containers/)

不同的容器用于特定目的

  • 基础语言容器(例如,java:8.0.1-11-b77fdae6d4771789dfc66a56bf8d806354e8011a
  • 启用了 sanitizer 的容器(例如,sanitize:8.0.1-b77fdae6d4771789dfc66a56bf8d806354e8011a
  • 特定架构的容器(例如,emulation:7.1.2-aarch64-2920199ab0090ed427413a8e422e62695c8392a8

来源:.github/workflows/test_cpp.yml72-79 .github/workflows/test_upb.yml48-57 .github/workflows/test_php.yml70-86

Bazel 构建系统

Bazel 是用于测试的主要构建系统。它提供了封闭式构建,并跨语言和平台实现了一致的依赖管理。

关键的 Bazel 配置定义在 .bazelrcci/common.bazelrc

# Build modes
build:dbg --compilation_mode=dbg
build:opt --compilation_mode=opt

# Sanitizer common settings
build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer

# Specific sanitizer configurations
build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address
build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread
build:msan --config=san-common --copt=-fsanitize=memory --linkopt=-fsanitize=memory
build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined

来源:.bazelrc1-37 ci/common.bazelrc1-84

自定义 GitHub Actions

CI 系统使用 protocolbuffers/protobuf-ci 仓库中的多个自定义 GitHub Actions

操作目的
checkout安全地检出特定提交的代码
bazel运行 Bazel 命令
bazel-docker在 Docker 容器中运行 Bazel
docker在 Docker 容器中运行命令
sccache/ccache提供编译器缓存以加快构建速度
cross-compile-protoc交叉编译 protoc 编译器
composer-setup设置 PHP Composer

来源: .github/workflows/test_cpp.yml66-79 .github/workflows/test_php.yml64-86 .github/workflows/test_ruby.yml45-57

Sanitizer 测试

CI 系统使用多个 Sanitizer 来检测细微的错误

这些 Sanitizer 在 C++ 测试中进行了配置

来源: .bazelrc8-32 ci/common.bazelrc4-35 .github/workflows/test_cpp.yml30-36

跨平台测试

CI 系统跨多个平台和架构测试 Protocol Buffers

操作系统

  • Linux(Ubuntu,配备各种工具链)
  • macOS(用于 Apple 特定测试)
  • Windows(MSVC 和 clang-cl 工具链)

架构

  • x86_64(主要架构)
  • ARM64/aarch64(用于移动和服务器兼容性)
  • 32 位 x86(用于兼容旧系统)

交叉编译示例

来源: .github/workflows/test_cpp.yml120-126 .github/workflows/test_php.yml119-126 .github/workflows/test_ruby.yml76-83

示例项目测试

仓库的 examples/ 目录包含演示 Protocol Buffers 使用不同构建系统的示例项目。这些示例也在 CI 中进行测试,以确保它们保持可用

来源: .github/workflows/test_bazel.yml25-75 examples/BUILD.bazel1-209 examples/WORKSPACE1-85 examples/MODULE.bazel1-31

在本地运行测试

开发者可以使用 Bazel 在本地运行相同的测试

常见问题和故障排除

Sanitizer 故障

当 Sanitizer 检测到问题时

  1. 检查测试日志以获取故障详情
  2. 添加调试代码或使用 Sanitizer 选项以获取更多信息
  3. 修复根本问题

跨平台问题

当测试在特定平台上失败时

  1. 尝试在相似的环境中本地重现
  2. 检查代码中特定于平台的假设
  3. 添加条件语句或使用跨平台替代方案

CI 特定问题

当测试在本地通过但在 CI 中失败时

  1. 检查环境变量或资源限制的差异
  2. 查找竞争条件或对时序敏感的代码
  3. 尝试使用相同的 Docker 容器在本地重现

结论

Protocol Buffers CI 系统在多种语言、平台和配置下提供全面的测试。通过了解其工作原理,开发者可以更有效地为项目做出贡献,并在出现测试失败时进行故障排除。