- NO.
- 042
- DATE
- READ
- ~7 min
- KIND
- 笔记
- STATUS
- 原文
GitHub Actions 免费分钟耗尽:博客部署为何停了
私有博客的 GitHub Actions 部署在启动前被拒。通过真实账单厘清原始消耗、免费抵扣和实际费用,解释公开仓库与 macOS 测试的计费差异,并评估预算、测试频率和迁移成本。
10 月 13 日,一个部署到 Cloudflare Workers 的私人博客没有随着代码提交更新。GitHub Actions 的 Deploy 作业在开始后几秒就失败了,没有进入安装依赖或构建阶段。运行页给出的提示是:
recent account payments have failed or your spending limit needs to be increased
这条提示提供了两个可能方向:付款问题,或者支出限制。但它不能单独证明账户欠费,更不能说明网站代码出了错。
接着核对 Billing 页面,发现账户当月的免费 Actions 分钟数是 2,000 / 2,000,Actions 预算为 $0,且开启了达到预算时停止使用。账户当时没有配置付款方式。问题发生在 GitHub 的任务调度和计费边界,构建流程本身根本没有机会运行。
以下隐去了账号及仓库名称,保留账单数值和工作流类型;规则与价格按 2026-10-13 查到的 GitHub 官方文档整理。
$16.44 消耗,不等于欠了 $16.44
账单概览并排显示了两个数:
| 账单字段 | 当时显示 | 应该怎么理解 |
|---|---|---|
| Current metered usage | $16.44 | 按资源用量计算的原始金额 |
| Current included usage | $16.44 | 包含额度和适用优惠带来的抵扣 |
| Billable usage | $0.00 | 本次查看时显示的实际可计费金额 |
| Next payment due | — | 页面没有显示一笔待支付金额 |
GitHub 的用量报表提供三个有用的字段:gross_amount 是抵扣前金额,discount_amount 是抵扣额,net_amount 是扣除优惠后实际计费额。判断账单不能只看第一列。
而且账单里按仓库排列的 Gross amount 也会混入本来就免费的运行。比如这次截图中有一个公开仓库显示 $3.55 原始消耗,但它运行的是标准 Ubuntu / Windows GitHub 托管 Runner,按官方规则免费。那 $3.55 不能直接算成这个公开仓库的应付账单,也不应该归入私有仓库的 2,000 分钟消耗。
真正需要追问的是:哪些仓库、哪些作业消耗了私有仓库的免费额度?
同一个账号:便宜的部署被昂贵的测试挤掉
GitHub Free 每个账户每月包含 2,000 分钟标准托管 Runner 用量。私有仓库共享这份额度;公开仓库使用标准 Runner 不消耗这份额度。高规格 Larger Runner 则另有计费规则。
当时三个值得比较的仓库,在 Gross amount 中分别是:
| 仓库类型(已匿名) | 原始计量金额 | 对排障的意义 |
|---|---|---|
| 私有前端工具 | $10.38 | 首先检查高频、跨系统的 CI |
| 公开开发工具 | $3.55 | 标准 Runner 免费,不能把原始金额当成实际支出 |
| 私有博客 | $1.62 | 单独成本不高,却可能因为账户额度耗尽而无法部署 |
前端工具里有两组真正需要 macOS 环境的 Safari 相关测试。它们不是无用测试:此前就发现过键盘焦点、中文导出编码及拖拽反馈等浏览器差异。但每次普通提交都完整运行,带来的增量覆盖不一定与成本相称。
GitHub 当前给出的标准 Runner 参考单价是:
| Runner | 超额分钟参考价格 |
|---|---|
| Linux 2-core | $0.006 |
| Windows 2-core | $0.010 |
| macOS 标准版 | $0.062 |
macOS 单价约为 Linux 的十倍。GitHub 对每个 Job 的执行分钟向上取整,因此看账单时还要分清 Job 数量、运行时长、平台倍率和免费额度;不能拿一个工作流页面显示的总时长直接换算整月费用。
这里的结构性问题是:同一账户下,非关键测试和生产部署共用一个有限资源池。前者提前消耗配额,后者即使很便宜,也会一同被拦住。
为什么把预算从 $0 改成 $3,还不一定能恢复?
原来 Actions 预算是 $0,Stop usage 为 Yes;后来调整成每月 $3,保留停止使用开关。这个预算针对超出包含额度之后的付费使用,不是充值,也不是每月固定订阅费。
还有一个不能跳过的条件:GitHub 官方明确写明,没有有效付款方式时,包含额度用尽后,额外使用仍会被阻止。仅修改预算数字,不等于完成了付费条件,更不能仅凭预算页面判断部署已经恢复。
如果已有有效付款方式,假设免费额度完全用尽,$3 按目前 Linux 2-core 的 $0.006/分钟算,理论上能覆盖约 500 个超额计费分钟。实际会受不同 Runner、按 Job 取整和其他任务影响,这只是成本预算,不是运行次数保证。
这次部署失败的正确恢复顺序是先检查 Billing 的 Included usage、Billable usage、Budgets and alerts、Payment information,再尝试新的 Deploy,最后到生产网址核对页面。不能把“预算保存成功”当成“网站上线成功”。
最终改的是测试节奏,不是站点平台
排查时比较过几个方向:升级 GitHub Pro,把博客构建搬到 Cloudflare,在服务器上自托管 Runner,或者把私有仓库改成公开仓库。最终优先改的是造成配额压力的触发规则。
私人前端工具中,Safari 相关测试调整为手动运行,在重要发布前执行;普通变更继续跑成本更低的常规检查。只改说明文档的提交也不再触发整套 CI。仓库运维记录中,调整后的首次 CI 已显示 Safari 作业跳过,其余测试仍照常运行。
博客的部署工作流没有为这次账单问题而换平台。它本来用 Ubuntu 构建并部署到 Cloudflare,还负责生成分享图片和验证生产路由。把承载网站的平台换掉,也不一定能解决 GitHub 账户里 macOS 测试消耗过高的问题。
保留私有仓库同样是一个明确约束:核心代码暂时不准备公开。因此,虽然公开仓库的标准 Actions 免费,也不能为了省额度就把源码公开。把私有仓库来回转移到其他账户,也会增加权限、密钥和维护负担,不是优先解法。
从成本看,应该优化哪一步?
这次决策可以拆成三种成本。
第一是边际成本。免费额度用尽后,增加一次 10 分钟的 Linux 构建,按当前单价约 $0.06;同样时长的 macOS 作业约 $0.62。优先减少不必要的 macOS 运行,比削减博客发布频率更有效。
第二是机会成本。平台迁移除了账面价格,还需要适配构建环境、验证密钥权限、恢复定时任务、准备回滚路径。为了每月可能只有几美元的超额费用花好几个小时重建部署链路,需要明确回本周期。
第三是失败成本。删掉 Safari 测试确实可以省钱,却会失去跨浏览器的回归信号。把它改为每周、手动或发布前执行,可以保留检测能力,同时减少低价值的重复运行。
所以当前选择是:保持私有仓库和现有部署架构,按风险分层运行 CI,为偶发超额设置一个很小的付费预算,并继续观察真实用量。是否需要购买更高套餐,要等新的运行节奏积累出一个完整计费周期的数据再决定。
如果你也遇到相同错误
可以按这个顺序检查:
- 在 GitHub 的 Billing & licensing → Usage → Actions 里看免费分钟是否用尽,而不是只看首页 Gross amount。
- 在 Budgets and alerts 里检查 Actions 的预算额度、范围,以及 Stop usage 是否开启;多个重叠预算可能共同限制运行。
- 在 Payment information 里检查有效付款方式。免费额度耗尽且没有付款方式时,光把预算改成正数仍不够。
- 按私有仓库和 Runner 类型拆分用量,尤其留意 macOS、Windows、高频定时任务和一次提交触发的多个 Job。
- 调整触发条件之后,实际运行一次必要的工作流;以构建、部署和生产请求的结果为准,不以“设置完成”为准。
边界
- 本次账单截图在检查时显示 $0 实际计费金额;不代表整个月最终都不会产生费用,也不能据此推断支付方式或账户状态后来是否变化。
- “更改测试触发条件后足以长期留在 2,000 分钟内”仍是预算预测,尚未经过下一个完整账期验证。
- Runner 单价、套餐额度和预算规则可能变化;具体以文末 GitHub 官方文档为准。
- 原始账单的仓库名称、私有工作流路径和凭据信息没有公开。
写作说明:GPT-6 根据对话中的账单记录、仓库文档和 GitHub 官方资料起草;作者决定发布。
评论
评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion