Envoy 移动端文档系统全解析:Sphinx 本地构建、版本化发布与 CI 自动化流程
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
本篇指南围绕 Envoy 仓库中mobile/docs/README.md所描述的 Envoy Mobile 文档工程展开,完整讲解其基于 Sphinx 的文档生成机制、本地构建命令、版本化输出目录,以及合并到 main 后自动发布到文档网站的 CI 流程。读完本文,你将掌握 Envoy Mobile 文档从源码.rst到可发布 HTML 的完整链路,并能独立在本地复现构建、理解发布脚本的行为分支,以及按需定制文档版本与发布目标。
一、文档体系概览:为什么选择 Sphinx
Envoy Mobile 的文档(位于 mobile/docs)与 Envoy 主仓库其他模块的文档一样,使用 Sphinx 生成。Sphinx 以 reStructuredText(.rst)为源文件格式,能够生成结构化的 HTML 站点,并支持自动目录树(toctree)、跨文件引用、环境变量注入与自定义指令扩展,非常适合维护一套体量大、版本多的项目文档。
文档源文件按主题组织在 mobile/docs/root 下,顶层入口为 mobile/docs/root/index.rst,它通过toctree将四大板块串成一个整体:
intro/intro:介绍、对比、版本历史等入门材料;start/start:构建与 Hello World 示例等起步指南;api/api:以功能分组、同时提供 iOS 与 Android 示例的公共 API 文档(见 mobile/docs/root/api/api.rst);development/development:面向 Envoy Mobile 开发者的性能、发布、测试、工具与本地调试文档(见 mobile/docs/root/development/development.rst)。
其中 API 文档尤其强调「跨平台一致性」是 Envoy Mobile 的明确目标,因此每个功能小节都会同时给出 iOS 与 Android 的示例(对应 starting_envoy.rst、http.rst、grpc.rst、stats.rst 等页面)。
注:
index.rst中有一段条件渲染逻辑——当release_level为pre-release时,文档页首会显示「This is pre-release documentation」的警告横幅,提示读者文档可能与当前实现存在不一致。这一机制由conf.py中的环境变量驱动,详见下文。
二、在本地生成文档:一条命令的完整解析
mobile/docs/README.md给出的本地构建命令非常简洁:
./docs/build.sh运行完成后,生成的 HTML 输出位于generated/docs目录。这条命令背后隐藏了相当多的工程细节,下面结合 mobile/docs/build.sh 与 mobile/docs/BUILD 逐步拆解。
1. 版本号与发布级别检查
脚本开头使用set -e(任何一步失败立即退出),随后执行两类版本校验:
VERSION_NUMBER=$(cat VERSION) if [[ "$GITHUB_REF_TYPE" == "tag" ]] && [[ "${VERSION_NUMBER}" =~ ^[0-9]+\.[0-9]+\.[0-9]$ ]] then # 校验 git tag 与 VERSION 文件内容一致 if [ "v${VERSION_NUMBER}" != "${GITHUB_REF_NAME}" ]; then echo "Given git tag does not match the VERSION file content:" echo "${GITHUB_REF_NAME} vs $(cat VERSION)" exit 1 fi # 校验 version_history.rst 已收录当前发布版本 grep --fixed-strings "$VERSION_NUMBER" docs/root/intro/version_history.rst \ || (echo "Git tag not found in version_history.rst" && exit 1) DOCS_TARGET=//docs else DOCS_TARGET=//docs:html fi其逻辑要点:
- 从仓库根目录的 VERSION.txt 读取当前版本号;
- 只有满足「GitHub 触发类型为 tag」且版本号严格匹配
X.Y.Z(主.次.修订)时,才走发布标签路径:此时要求 git tag(即GITHUB_REF_NAME)与 VERSION 文件完全一致(格式为vX.Y.Z),并且版本号必须已出现在version_history.rst中,任何一项不满足都会报错退出; - 形如
vX.Y.Z.ddmmyy的每日/预发布标签不会发布带标签的文档; - 发布标签场景下构建 Bazel 目标
//docs(即html_release),其余场景构建//docs:html。
2. 输出目录与 Bazel 打包解包
版本校验之后,脚本确定输出目录并交给 Bazel 完成实际构建:
[[ -z "${DOCS_OUTPUT_DIR}" ]] && DOCS_OUTPUT_DIR=generated/docs rm -rf "${DOCS_OUTPUT_DIR}" mkdir -p "${DOCS_OUTPUT_DIR}" DOCS_OUTPUT_DIR="$(realpath "$DOCS_OUTPUT_DIR")" bazel run \ "--@envoy//tools/tarball:target=$DOCS_TARGET" \ @envoy//tools/tarball:unpack \ "$DOCS_OUTPUT_DIR"- 默认输出目录为
generated/docs,可通过环境变量DOCS_OUTPUT_DIR覆盖; - 构建由 Bazel 驱动:
@envoy//tools/tarball:unpack是一个通用的「构建 tar 包并解压到目标目录」工具,通过--@envoy//tools/tarball:target指定要构建并解包的 Bazel 目标; - 实际构建发生在 mobile/docs/BUILD 的
genrule中:将conf.py与root/**下的所有*.rst、图片、CSS 等源文件打包成 tar(sphinx_root/rst目标),再调用定制的sphinx二进制以-b html生成 HTML,最后再次打成html.tar.gz或html_release.tar.gz交由解包工具落地到generated/docs。
3. Sphinx 二进制与文档自定义
BUID 文件 中值得注意的几点工程实践:
py_console_script_binary声明了一个名为sphinx的 Python 控制台脚本目标,其底层依赖sphinx_rtd_theme(Read the Docs 主题)、sphinxcontrib.googleanalytics(Google Analytics 埋点)与sphinxcontrib.httpdomain(HTTP/REST 文档扩展)三个 Python 包;genrule的构建命令会先执行$(location @envoy//bazel:volatile_env)注入 Bazel 的版本信息(BUILD_SHA/BUILD_SCM_REVISION),再导出 Sphinx 必需的环境变量,最后以-W(警告即错误)和--keep-going(尽量收集全部错误)两个严格模式运行sphinx-build,保证文档质量;html_release(即//docs)与html两个目标的差异仅在于是否依赖@envoy//bazel:volatile_env注入真实提交 SHA——发布场景使用真实 SHA,普通场景退化为UNKNOWN。
三、Sphinx 配置中的关键环境变量
构建能否成功,强依赖于 mobile/docs/conf.py 开头强制要求的环境变量:
if not (release_level := os.environ.get('ENVOY_DOCS_RELEASE_LEVEL')): raise Exception("ENVOY_DOCS_RELEASE_LEVEL env var must be defined") if not (blob_sha := os.environ.get("ENVOY_BLOB_SHA")): raise Exception("ENVOY_BLOB_SHA env var must be defined") if not (version := os.environ.get("ENVOY_DOCS_VERSION_STRING")): raise Exception("ENVOY_DOCS_VERSION_STRING env var must be defined")三个变量缺一不可,含义如下:
| 环境变量 | 用途 | 在 build.sh / BUILD 中的取值来源 |
|---|---|---|
ENVOY_DOCS_VERSION_STRING | 作为 Sphinx 的version/release,决定文档页脚等处展示的版本号 | VERSION 文件内容-提交SHA前6位,例如1.6.0-abc123 |
ENVOY_DOCS_RELEASE_LEVEL | 驱动index.rst中pre-release警告横幅的显隐 | 固定为pre-release |
ENVOY_BLOB_SHA | 用于extlinks中repo快捷链接的 blob 提交号,即文档内链接指向的源码版本 | 发布时取自 Bazel 版本信息,否则为UNKNOWN |
其余配置要点:
- 主题:使用
sphinx_rtd_theme,自定义样式位于 mobile/docs/root/_static/css/envoy.css,favicon 为 mobile/docs/root/favicon.ico; - 扩展:
sphinxcontrib.httpdomain、sphinx.ext.extlinks、sphinx.ext.ifconfig、sphinxcontrib.googleanalytics,其中ifconfig正是index.rst条件渲染警告横幅的实现基础; - 自定义指令:
conf.py定义了一个substitution-code-block指令(SubstitutionCodeBlock类),可在代码块中按配置的键值对做占位符替换,便于在示例代码里注入动态版本号等信息; - 源文件格式:
source_suffix = '.rst',主文档master_doc = 'index',排除_build、_venv等目录。
四、发布流程:合并到 main 即自动更新网站
mobile/docs/README.md说明:每当一个 commit 被合并到 main,文档网站就会自动用最新文档刷新。这一机制由 mobile/docs/publish.sh 实现,它在 CI(GitHub Actions)中运行,且假设文档已经通过build.sh构建完毕。
1. 前置条件与目录策略
DOCS_DIR=generated/docs BUILD_SHA="$(git rev-parse HEAD)" if [[ -z "$MOBILE_DOCS_CHECKOUT_DIR" ]]; then echo "MOBILE_DOCS_CHECKOUT_DIR is not set, exiting" >&2 exit 1 fi if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then PUBLISH_DIR="$MOBILE_DOCS_CHECKOUT_DIR"/docs/envoy-mobile/"$GITHUB_REF_NAME" else PUBLISH_DIR="$MOBILE_DOCS_CHECKOUT_DIR"/docs/envoy-mobile/latest fi- 必须通过环境变量
MOBILE_DOCS_CHECKOUT_DIR指定文档网站仓库(envoy-mobile.github.io)的本地检出路径,否则脚本直接退出; - 发布目录按 commit 性质分流:
- 标签提交(如
v1.6.0):发布到版本化目录docs/envoy-mobile/v1.6.0; - main 分支普通提交:发布到latest 目录
docs/envoy-mobile/latest; - 其他情况:脚本不做任何事(noop)。
- 标签提交(如
2. 提交与推送逻辑
git -C "$MOBILE_DOCS_CHECKOUT_DIR" checkout -B master origin/master rm -fr "$PUBLISH_DIR" mkdir -p "$PUBLISH_DIR" cp -r "$DOCS_DIR"/* "$PUBLISH_DIR" git -C "${MOBILE_DOCS_CHECKOUT_DIR}" config user.name "envoy-mobile-docs(ci)" git -C "${MOBILE_DOCS_CHECKOUT_DIR}" config user.email envoy-mobile-docs@users.noreply.github.com git -C "${MOBILE_DOCS_CHECKOUT_DIR}" add . if [[ "$(git -C "${MOBILE_DOCS_CHECKOUT_DIR}" status --porcelain)" ]]; then git -C "${MOBILE_DOCS_CHECKOUT_DIR}" commit -m "docs envoy-mobile@$BUILD_SHA" fi值得注意的工程细节:
- 文档网站仓库使用
master分支而非main,脚本注释中明确解释:使用main作为默认分支目前会导致 404,因此git checkout -B master origin/master固定跟踪origin/master; - 发布采用「清空目标目录后整体复制」的策略(
rm -fr+cp -r),确保旧页面被彻底移除,不会残留过期内容; - CI 提交时使用固定的机器人身份
envoy-mobile-docs(ci),提交信息为docs envoy-mobile@<提交SHA>,便于追溯某次文档更新对应的源码提交; - 只有工作区确实发生变化(
status --porcelain非空)才创建提交,避免产生空提交。
五、完整工作流串联:从提交到线上文档
综合build.sh、publish.sh、conf.py与BUILD,一条 commit 从合并到上线文档的完整链路如下:
- 提交合并到 main:CI 检出最新代码,运行
mobile/docs/build.sh; - 构建:脚本校验 VERSION 与 tag(仅 tag 场景),通过 Bazel 打包
root/**下的.rst与静态资源,注入ENVOY_DOCS_VERSION_STRING/ENVOY_DOCS_RELEASE_LEVEL/ENVOY_BLOB_SHA三个环境变量,用定制 Sphinx 二进制在-W --keep-going严格模式下生成 HTML,输出到generated/docs; - 发布:CI 接着运行
mobile/docs/publish.sh,将generated/docs整体复制到文档网站仓库的docs/envoy-mobile/latest(或 tag 对应的版本化目录),由机器人身份提交并推送,网站随即更新; - 版本归档:每当发布
vX.Y.Z标签时,该版本的文档被独立归档到版本化目录,与latest并存,供用户按版本查阅。
六、FAQ 与常见问题排查
Q1:本地运行./docs/build.sh提示 tag 校验失败?build.sh只有在GITHUB_REF_TYPE == "tag"时才执行 tag 强校验。本地手动运行时该变量通常为空,因此走//docs:html分支,不校验 tag;若你确实在 tag 环境遇到「Given git tag does not match the VERSION file content」或「Git tag not found in version_history.rst」,请核对 git tag 是否为v+ VERSION 文件内容,并确认版本号已写入 mobile/docs/root/intro/version_history.rst。
Q2:构建时报ENVOY_DOCS_RELEASE_LEVEL env var must be defined?conf.py在加载时强制要求这三个环境变量,普通 Sphinx 构建不会自动注入。本地如需直接调试sphinx-build,需手动导出:
export ENVOY_DOCS_RELEASE_LEVEL=pre-release export ENVOY_DOCS_VERSION_STRING=1.6.0-abc123 export ENVOY_BLOB_SHA=abc123不过更推荐直接使用./docs/build.sh,它通过 Bazel 完整复现 CI 环境。
Q3:想自定义输出目录?设置环境变量DOCS_OUTPUT_DIR即可,例如DOCS_OUTPUT_DIR=/tmp/envoy-docs ./docs/build.sh。
Q4:为什么文档网站用master分支?这是 publish.sh 中的明确工程决策——main作为默认分支在当前环境下会导致 404,因此发布流程始终检出origin/master。
七、总结
Envoy Mobile 的文档工程是一套「源码即文档、CI 即发布」的成熟实践:Sphinx 负责内容组织与静态站点生成,Bazel 负责可复现的构建与依赖管理(见 mobile/docs/BUILD),build.sh负责本地/CI 一致的构建入口,publish.sh负责按 commit 性质将文档分流发布到latest或版本化目录。无论是为 Envoy Mobile 贡献文档,还是在自己的项目里搭建类似的文档发布流水线,这套「严格版本校验 + 环境变量驱动 + 标签/主干分流发布」的组合都极具参考价值。
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考