
后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载Read the Docs 在创建项目时会为每个项目自动生成一对 SSH 密钥主仓库正是通过这把密钥获得克隆权限的。如果你的私有仓库中还引用了私有的 Git 子模块submodule那么这些子模块也需要能通过同一机制被克隆。本文以 readthedocs.org 开源仓库为背景讲解私有子模块的完整授权思路、各 Git 托管平台GitHub / Azure DevOps / GitLab / Bitbucket的具体配置步骤以及如何通过.readthedocs.yaml配置文件的submodules段精细控制“克隆哪些子模块、是否递归克隆”并结合仓库源码说明子模块检查与克隆的实际执行流程。适用前提本指南面向 Read the Docs **商业版readthedocs.com**用户私有仓库与私有子模块的克隆能力依赖商业版的 SSH 密钥授权机制。相关说明见 商业版文档。核心原理项目级 SSH 密钥 子模块复用当你在 Read the Docs 上创建一个项目时系统会自动为该项目生成一对 SSH 密钥公钥 私钥。构建时Read the Docs 使用这把私钥去克隆你的仓库你只需要把公钥配置到托管平台一侧即可授予克隆权限。主仓库的授权方式在 创建私有仓库项目指南 中有详细说明项目Settings → SSH keys页面可复制公钥。私有子模块的授权思路与此完全一致把同一把公钥同时授予所有需要克隆的仓库主仓库 各子模块仓库。差异只在于不同托管平台对“一把 SSH 密钥能否跨仓库复用”的限制不同因此配置方法分为三种场景GitHub不允许多个仓库共用同一把 deploy key需要用“机器用户machine user”中转Azure DevOps密钥挂载在用户上只要该用户同时拥有主仓库和所有子模块的访问权限即可GitLab、Bitbucket允许同一把 SSH 密钥跨仓库复用只需把公钥添加到每个子模块仓库。前提检查.gitmodules必须使用 SSH URL在开始配置托管平台之前先确认你的.gitmodules文件中子模块的 URL 是SSH 格式而不是 HTTP(S) 格式。例如[submodule theme] path theme url gitgithub.com:readthedocs/readthedocs.org.git原因很直接Read the Docs 的构建环境通过 SSH 密钥进行认证HTTP(S) URL 无法携带项目 SSH 密钥会导致子模块克隆失败。这是排查“主仓库克隆成功但子模块报 Permission denied”时的首要检查项。用配置文件控制要克隆的子模块除了把公钥授权给子模块仓库你还可以通过.readthedocs.yamlv2 配置文件的submodules段决定哪些子模块参与克隆。完整的submodules配置参考见 配置文件参考v2核心要点如下配置项类型默认值说明submodules.includelist 或all[]仅克隆列表中的子模块all表示克隆全部submodules.excludelist 或all[]排除列表中的子模块all表示全部排除等价于include: []submodules.recursiveboolfalse是否递归克隆子模块自身的子模块示例——只克隆one和two两个子模块并递归克隆它们的嵌套子模块version: 2 submodules: include: - one - two recursive: true示例——克隆全部子模块version: 2 submodules: include: all示例——排除全部子模块相当于完全不克隆子模块version: 2 submodules: exclude: all需要注意的约束源码层明确校验当前仅支持 Git子模块include与exclude不能同时使用。在 配置校验实现 中validate_submodules()会同时检查两者是否非空若同时配置则抛出SUBMODULES_INCLUDE_EXCLUDE_TOGETHER错误对应的用户提示文案见 notifications.pyrecursive只有在确实存在待克隆子模块时才生效。配置校验的默认值行为从 validate_submodules 的源码可以看到一个容易被忽略的细节当未配置include时exclude的默认值是ALL一旦配置了includeexclude默认变为空列表[]。也就是说默认情况下不写任何 submodules 配置子模块是被全部排除、不会克隆的只有显式写了include或非空 exclude后子模块克隆流程才会真正执行。对应地配置文件测试 中有一组test_submodules_*用例覆盖了这些默认值、all关键字与“include/exclude 互斥”的校验逻辑。按托管平台配置子模块授权下面按平台给出具体步骤。所有步骤中提到的“项目的公钥”均指从 Read the Docs 项目Settings → SSH keys页面复制的Public SSH key。GitHub使用机器用户Machine UserGitHub 的 deploy key 是单仓库绑定的不允许同一把 key 跨仓库复用。要让一把项目公钥能同时克隆主仓库和所有私有子模块推荐做法是创建一个专门的 GitHub 账号机器用户来持有这把公钥再把这个账号以只读权限加入所有相关仓库。具体分三步第 1 步删除主仓库上的 Read the Docs deploy key进入 GitHub 上的项目仓库点击Settings点击左侧Deploy Keys删除由Read the Docs Commercial (readthedocs.com)添加的那把 key。提示如果你使用的是 GitHub App 方式连接仓库而非 deploy key仓库的访问权限由 App 统一管控可以跳过这一步。第 2 步创建 GitHub 用户并授予只读权限创建一个 GitHub 账号可以是个人账号或专门的服务账号把它以只读身份加入主仓库及所有需要克隆的子模块仓库。GitHub 提供了三种加入方式作为个人仓库的collaborator协作者作为组织仓库的outside collaborator外部协作者作为组织内某个team团队的成员团队对相关仓库拥有只读权限。第 3 步把项目公钥挂到该 GitHub 用户上进入该 GitHub 用户的Settings点击SSH and GPG keys点击New SSH key填写一个描述性标题粘贴从 Read the Docs 项目复制的公钥获取方式见 创建私有仓库项目指南的“配置你的仓库”一节点击Add SSH key。完成之后Read the Docs 构建时使用的项目私钥其公钥就“挂在”一个有权限访问所有相关仓库的账号下主仓库与全部私有子模块即可一次性克隆成功。Azure DevOps密钥挂载到用户Azure DevOps没有按仓库维度的 SSH deploy keySSH 密钥只能添加到用户上。因此配置非常简单将项目的公钥添加到 Azure DevOps 用户的User settings → SSH public keys → New key确保该用户对主仓库及其全部子模块都有访问权限。只要满足“同一用户同时能访问主仓库与所有子模块”Read the Docs 就可以用这一把密钥克隆全部仓库。更完整的 Azure DevOps 仓库授权步骤参见 创建私有仓库项目指南 中“Configuring your repository”一节Azure DevOps标签页。GitLab、Bitbucket 及其他平台直接复用密钥GitLab 和 Bitbucket允许同一把 SSH 密钥跨多个仓库复用。由于 Read the Docs 已经将项目公钥添加到了你的主仓库你只需要再把同一把公钥分别添加到每一个子模块仓库即可GitLabSettings → Repository → Deploy Keys添加只读 deploy keyBitbucketRepository Settings → Access keys添加只读 access key其他平台如果以上平台都不适用请查阅你的托管平台关于“在私有仓库上管理 SSH 密钥”的文档把项目公钥以只读方式配置到主仓库和所有子模块仓库。源码视角子模块在构建流程中如何被克隆理解源码可以帮你更精准地排查问题。整个子模块处理逻辑集中在 Git 后端 readthedocs/vcs_support/backends/git.py 中调用链如下构建入口构建编排器在加载完配置文件后立即调用self.vcs_repository.update_submodules(self.data.config)见 doc_builder/director.py#L303此时正处于 checkout 阶段是否执行子模块克隆are_submodules_available(config)git.py#L322-L331先判断配置文件里是否显式涉及子模块exclude ! ALL或include非空再检查仓库里是否真的存在子模块计算克隆清单get_available_submodules(config)git.py#L333-L379根据include/exclude计算出最终要克隆的子模块路径列表——列表为空表示“全部克隆”返回(False, [])则表示没有需要克隆的子模块发现子模块submodules属性git.py#L472-L530通过git config --null --file .gitmodules --get-regexp ^submodule\..*\.path$直接解析.gitmodules文件不初始化任何子模块即可拿到全部子模块路径这也解释了为什么.gitmodules中的 URL 格式至关重要执行克隆checkout_submodules(submodules, recursive)git.py#L559-L577依次运行git submodule sync与git submodule update --init --force当submodules.recursive为true时追加--recursive参数最后以--分隔符传入待克隆的子模块列表。此外Git 后端还提供了has_ssh_key_with_write_access()git.py#L168-L272构建初期会以git push --dry-run的方式试探项目密钥是否具备写权限用于安全防护例如禁止带写权限的密钥配合post_checkout构建钩子被滥用。这与子模块授权属于同一套 SSH 密钥体系如果你把公钥误配成了“可写”角色也可能影响这一检查结果。仓库自带的测试用例可以帮你验证上述行为例如test_backend.py 中的test_check_for_submodules、test_parse_submodules、test_skip_submodule_checkout等用例验证了对.gitmodules的解析、子模块可用性判断以及不带 URL 的无效子模块处理test_config.py 中的test_submodules_*用例验证了配置校验默认值、all关键字、include/exclude 互斥、recursive 类型。常见排查要点按以下顺序快速定位私有子模块克隆失败的问题.gitmodulesURL 是否为 SSH 格式——HTTP(S) URL 无法携带项目 SSH 密钥必然失败公钥是否已授权给子模块仓库——GitHub 需要机器用户方案Azure DevOps 需要把密钥挂到有权限的用户GitLab/Bitbucket 直接加到每个子模块仓库配置文件是否误排除了子模块——确认没有写submodules: { exclude: all }之类的配置是否需要递归克隆——若子模块还有嵌套子模块记得设置submodules.recursive: true是否同时写了include和exclude——配置校验会直接让构建失败请二选一。延伸阅读创建私有仓库项目含 SSH 公钥获取与各平台授权步骤配置文件参考v2——submodules 段完整参数GitHub App 集成参考商业版与组织Organizations文档赞分享后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载相关推荐从私有仓库创建 Read the Docs 项目自动连接与手动配置完整指南从私有仓库创建 Read the Docs 项目自动连接与手动配置完整指南 本文基于 readthedocs.org 开源仓库中的官方文档编写。核心主题是在后端文档Rainbond项目中私有镜像仓库配置与授权问题解析Rainbond项目中私有镜像仓库配置与授权问题解析 背景介绍 在Rainbond项目中当用户尝试通过Dockerfile构建应用并从私有镜像仓库拉取基础镜像云原生后端微服务DevOpsAI 应用Read the Docs 隐私级别Privacy Levels完全指南项目与版本的公开/私有控制Read the Docs 隐私级别Privacy Levels完全指南项目与版本的公开/私有控制 本指南基于 readthedocs.org 开源仓库中后端文档上一篇OpenProject 打包安装迁移指南跨主机/环境搬迁 DEB/RPM 安装实例下一篇Bytebase Query Span Catalog Loader 设计解析Eager 逐对象安装与 Inline Root-Pseudo 降级方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考