ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Audacity 的 CI 如何校验 muse_framework 子模块指向上游 main 分支?

2026/9/15 20:36:05 拓冰建站 浏览量
Audacity 的 CI 如何校验 muse_framework 子模块指向上游 main 分支? Audacity 的 CI 如何校验 muse_framework 子模块指向上游 main 分支【免费下载链接】audacityAudio Editor项目地址: https://gitcode.com/GitHub_Trending/au/audacityAudacity 4master 分支把 MuseScore 的muse_framework仓库作为 git 子模块挂载在仓库根目录的muse路径下来消费构建代码依赖子模块所固定的那个 commit。子模块指针是很容易漂的有人在自己的 fork 上调试后.gitmodules的 URL 或muse指向的 SHA 会残留 fork 地址或游离 commit直接进 PR。为避免 CI 构建到错误的框架代码Audacity 用一个独立的 GitHub Actions 工作流 au4_check_submodules.yml 做两道检查子模块 URL 必须等于上游地址且固定 commit 必须位于上游仓库main分支的历史中。本文说明这条校验链的触发条件、每一步的具体判断逻辑以及如何在本地用同一条命令序列预检避免 PR 被 CI 打回。触发条件与检查对象工作流的触发与任务定义如下来自 au4_check_submodules.ymlon: pull_request: workflow_dispatch: jobs: check_muse_framework: runs-on: ubuntu-latest env: EXPECTED_URL: https://github.com/musescore/muse_framework.git任何 PR 以及手动触发workflow_dispatch都会运行该工作流校验常量EXPECTED_URL写死为https://github.com/musescore/muse_framework.git即上游 muse_framework 的 git 地址与构建类工作流不同这个校验工作流没有workflow_call输入、也没有覆盖子模块的机制——它只校验当前 PR 仓库里的配置不可参数化绕过。被校验的两个对象记录在 .gitmodules[submodule muse] path muse url https://github.com/musescore/muse_framework.git [submodule muse_deps] path muse_deps url https://github.com/musescore/muse_deps.git本工作流只检查musemuse_framework这一项。第一步校验子模块 URL 仍指向上游工作流先actions/checkoutv6克隆 PR 仓库然后执行ACTUAL_URL$(git config -f .gitmodules submodule.muse.url) echo Expected: ${EXPECTED_URL} echo Actual: ${ACTUAL_URL} if [ ${ACTUAL_URL} ! ${EXPECTED_URL} ]; then echo ::error file.gitmodules::muse_framework submodule URL must be ${EXPECTED_URL}, found ${ACTUAL_URL}. Did you accidentally leave it pointing at a fork? exit 1 fi做法是从.gitmodules文件里直接读出muse子模块的url与EXPECTED_URL做字符串比较。不相等就输出::error并exit 1该步骤失败、整个 job 失败。错误信息里特意点出常见原因Did you accidentally leave it pointing at a fork?——即指针 URL 被改成了个人 fork。第二步校验固定 commit 在上游 main 分支上URL 对之后还要确认子模块指向的 commit 真实存在于上游main分支。这一步的逻辑SHA$(git ls-tree HEAD muse | awk {print $3}) if [ -z ${SHA} ]; then echo ::error::Could not read muse_framework submodule SHA from index exit 1 fi echo Pinned commit: ${SHA} TMP$(mktemp -d) git clone --quiet --filtertree:0 --no-checkout --single-branch --branch main ${EXPECTED_URL} ${TMP} if ! git -C ${TMP} merge-base --is-ancestor ${SHA} origin/main; then echo ::error::muse_framework is pinned to ${SHA}, which is not on the main branch of ${EXPECTED_URL} exit 1 fi各行的作用git ls-tree HEAD muse从当前仓库的 git index 中读出muse路径指向的子模块 commit SHA子模块在父仓库里就是一个 gitlink记录的正是这个 SHA。读不到则直接报错失败。git clone --filtertree:0 --no-checkout --single-branch --branch main只克隆上游仓库的main分支引用不做 checkout目的是拿到足够做祖先判定origin/main历史的最小克隆避免为一次校验拉取全量对象。git merge-base --is-ancestor ${SHA} origin/main判断固定 SHA 是否是上游origin/main的祖先。退出码非 0 表示该 commit 不在上游 main 分支上CI 报错muse_framework is pinned to ${SHA}, which is not on the main branch of ${EXPECTED_URL}两步全部通过check_muse_frameworkjob 才算成功。本地预检PR 前先跑同一套判断CI 里的判断就是普通 git 命令在 clone 下来的 Audacity 4 源码目录里可以原样执行BUILDING.md 建议用git clone --recurse-submodules https://github.com/audacity/audacity.git获取源码见 BUILDING.md。假设当前目录是仓库根# 1. URL 是否与上游一致 git config -f .gitmodules submodule.muse.url # 期望输出: https://github.com/musescore/muse_framework.git # 2. 当前 index 固定的 commit git ls-tree HEAD muse # 3. 固定 commit 是否在上游 main 分支 TMP$(mktemp -d) git clone --quiet --filtertree:0 --no-checkout --single-branch --branch main \ https://github.com/musescore/muse_framework.git ${TMP} git -C ${TMP} merge-base --is-ancestor $(git ls-tree HEAD muse | awk {print $3}) origin/main echo exit code: $?merge-base --is-ancestor返回 0 表示固定 SHA 在上游 main 的历史中非 0 表示不在通常是 fork 上的 commit 或已 rebase 掉的提交PR 会在 CI 中失败。第 3 步会实际 clone 上游仓库到临时目录本地执行前留意这一点。CI 失败时如何定位工作流失败时会留下两类明确错误对应不同修法报错信息含义修正位置muse_framework submodule URL must be …, found ….gitmodules中muse的 URL 不是上游地址常见为指向 fork改回 .gitmodules 中submodule muse的urlCould not read muse_framework submodule SHA from index读不到muse的 gitlink SHA检查muse路径的子模块状态是否完整muse_framework is pinned to ${SHA}, which is not on the main branch of …固定 commit 不在上游main上把muse子模块更新为上游main上的 commit 后提交新的指针与构建工作流的关系override 不能代替校验各平台构建工作流如 au4_build_linux.yml、au4_build_macos.yml、au4_build_windows.yml支持通过workflow_call输入framework_repo和framework_ref覆盖子模块来源用于跨仓库/调试构建framework_repo: description: owner/repo to source muse_framework from (default: pinned submodule) framework_ref: description: Ref to check out into the muse_framework submodule (default: pinned SHA)默认情况下构建使用仓库里固定的子模块submodules: recursive克隆只有传入了framework_ref或事件是schedule定时构建时才执行actions/checkout把musescore/muse_framework的main检出到muse路径覆盖固定指针。也就是说override 只影响构建 job 临时消费哪个版本的框架不改变au4_check_submodules.yml对 PR 内容的要求合入前的子模块 URL 和固定 SHA 必须满足上述两项校验。限制说明校验只覆盖musemuse_framework子模块.gitmodules中的muse_deps不在此工作流检查范围内。判定标准是固定 SHA 是上游main的祖先因此上游main之后删除该 commit例如 force-push 重写历史会让原本通过的指针在之后的 PR 中失败需要重新把子模块指到main上存在的 commit。该工作流运行在ubuntu-latest上只做 git 层面的校验不编译任何代码因此失败原因只可能来自.gitmodules、musegitlink 与上游main历史三者的不一致。【免费下载链接】audacityAudio Editor项目地址: https://gitcode.com/GitHub_Trending/au/audacity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考