给一个私有 GitHub 仓库补完工程门禁后,我马上碰到两个很实际的问题:仓库里突然多出的 governance.yml 会不会影响私有性?刚才那次 git commit 为什么又等了半分钟?
答案并不复杂:项目里其实多了两道检查。一道在自己的电脑上,另一道在 GitHub。它们触发时间、能否拦住代码、检查失败后的通知方式都不一样。分清这两层,就不容易把“提交慢”和“GitHub Actions 慢”混在一起。
governance.yml 不是公开声明
governance.yml 只是一个普通文件名,不是 GitHub 强制生成的公开治理文件。真正让它生效的是目录与格式:扩展名为 .yml 或 .yaml、语法有效并且位于 .github/workflows/ 的文件,才会被 GitHub Actions 当作工作流加载。
文件名完全可以换成 ci.yml、quality-gate.yml 或其他名称。它也不会把私有仓库改成公开仓库,更不会因为名字里有 governance,就额外开放代码权限。
一个最小工作流通常会写明触发时机、运行环境和权限:
on:
push:
pull_request:
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
这里的 ubuntu-latest 表示任务运行在 GitHub 提供的临时 Linux Runner 上,而不是自己的电脑。contents: read 表示内置 GITHUB_TOKEN 对仓库内容只有读取权限;它不代表 job 看不到已经检出的源码,也不代表任何第三方 Action 都天然可信。
两道检查分别跑在哪里
本地的第一道门通常是 pre-commit:
- 发生在
git commit真正生成之前。 - 使用自己的 CPU、磁盘和本地依赖。
- 检查失败会直接阻止这次提交。
- 适合运行暂存区格式检查、静态规则、受影响模块编译等快速任务。
Git hook 也需要先启用。仅仅把 .githooks/pre-commit 放进仓库,新 clone 下来的项目不会自动执行它;项目通常要通过安装脚本设置 core.hooksPath=.githooks,或者把 hook 安装到 .git/hooks/。排查“为什么门禁没触发”时,这一步比先怀疑脚本内容更重要。
GitHub 上的第二道门是 Actions:
- 发生在代码 push 或创建、更新 PR 之后。
- 使用 GitHub Runner,不占本机资源。
- 适合在干净环境里重新安装依赖,运行测试、构建和跨模块检查。
- 检查失败会留下红叉,但普通 push 通常已经进入远端仓库。
所以,GitHub Actions 不会让本地 git commit 变慢。按下提交后迟迟没有返回,应该先检查本地 hook;代码已经推上去、GitHub 页面还在转圈,才是远端工作流仍在运行。如果 commit 已经结束、真正卡住的是 push,可以再按网络、SSH 与远端权限的顺序排查。
私有仓库会不会因此泄露代码
工作流不会改变仓库的可见性。私有代码、执行日志和检查结果仍只对有仓库权限的人可见。任务执行时,代码会被临时检出到 GitHub 的隔离 Runner,任务完成后运行环境被回收。
真正需要注意的是另外三件事:
- 不要在脚本里打印密码、Token、Cookie、私钥和数据库连接信息。
- 工作流令牌采用最小权限,普通检查通常只需要
contents: read。 - 只使用可信的 Action,不向 job 注入它不需要的 secrets。
- 私有仓库会消耗账号套餐内的 Actions 分钟和缓存额度,具体额度随 GitHub 套餐变化。
如果 workflow 同时监听所有 push 和 pull_request,一个已经打开 PR 的分支可能在推送后触发两次检查。个人项目跑得不频繁时影响不大;执行次数上来后,可以再按分支、路径或事件收窄触发范围。
如果工作流只是扫描源码、验证数据库初始化脚本的安全默认值,并且没有提供数据库凭据、没有执行迁移命令,它就不会连接或修改业务数据库。“检查数据库脚本”与“执行数据库变更”是两回事。
这次提交为什么特别慢
我遇到的实际情况是:本地 hook 大约运行了 30 秒,但其中 Maven 的 test-compile 不到 1 秒,主要时间花在完整后端治理脚本上。
而更早那次大重构之所以整体等待更久,是因为改动覆盖了 845 个文件,提交前还额外运行了 1042 个后端测试、246 个前端测试、打包和 schema 只读校验。这些是针对大改动的一次性全量验收,并不是每次普通提交都会执行的内容。
判断检查是否过重,不必只看总时长。先分清它是在每次 commit 都运行,还是只在大改动时人工运行;再看它是否拦住过真实回退,以及能否根据本次改动文件缩小范围。
如果一个很小的后端注释改动也要扫描全部领域,可以考虑只检查受影响模块,把全量扫描放到 GitHub。反过来,如果只是为了快就取消格式、编译和关键边界检查,问题往往会被推迟到更难处理的阶段。
检查失败后,谁会收到通知
GitHub 会把结果显示在 Actions 页面、commit 旁边的状态图标以及 PR 的 Checks 区域。邮件和站内通知是否发送,取决于个人账号的 Actions 通知设置。
需要特别注意:工作流失败不会自动撤销一次直接 push。想让“检查不通过的代码不能进入主分支”,还需要配置分支保护或 Ruleset,并把对应检查设为必需状态检查。
Codex、编辑器或本地终端通常也不会自动订阅 GitHub 的失败消息。确实需要主动提醒时,可以再接邮件、Webhook、Telegram、Slack 或其他通知渠道。对于没有多人协作、生产部署和资金风险的个人项目,没有必要一开始就把通知系统做得很重;生产私有仓库则应该按影响范围配置强提醒和责任人。
比较舒服的分层方式
我更倾向于保留三层检查:
- 本地 commit 前:几秒到几十秒,拦截格式、明显的重复实现和编译错误。
- GitHub push 或 PR 后:异步运行后端静态治理、数据库脚本安全和模块结构检查;前端运行类型、边界、测试、构建与 ESLint。
- 大重构交付前:本地补一次后端 Maven 全量测试、打包以及只读的数据结构校验。
这样既不会把每次提交都变成长时间等待,也不会把所有问题留到最后。日常 hook 如果稳定超过 20~30 秒并明显打断节奏,优先做按路径触发、按模块扫描和依赖缓存,而不是直接删除门禁。
慢的是哪一层,先看触发点
pre-commit 负责在自己的电脑上尽早拦错,GitHub Actions 负责在远端干净环境里复核。私有仓库不会因为多了 governance.yml 就变公开;真正影响体验的,是把哪些检查放在哪一层,以及失败后有没有清晰的状态和通知入口。




