Knowledge

GitHub Actions 配额管控实战:从配额耗尽到规范化 CI/CD

GitHub Actions 配额管控实战:从配额耗尽到规范化 CI/CD

独立开发者最怕的不是 Bug,而是某天收到配额超限邮件,流水线瞬间停摆。这篇文章拆解 GitHub Actions 的配额规则,分享一套经过实战检验的管控方案,让你在不花一分钱的情况下跑满整月。

如果你在用 GitHub Actions 为私有仓库构建、打包、发布应用,你可能已经注意到:一切运行良好,直到某天收到一封配额超限邮件,所有流水线瞬间停摆。

GitHub 托管运行器对私有仓库提供免费额度,但存在两项硬性约束:每月 2000 分钟运行时长500MB 制品存储容量。此前我编写的 Workflow 缺少存储管控逻辑,仅仅一周时间就触发了存储配额溢出报错(见下图),直接耗尽当月全部存储额度,整条 CI/CD 流水线被锁定无法执行,只能等待月度账单周期重置配额后恢复。

GitHub Actions 存储配额超限报错

这篇文章会拆解这两项配额的具体规则,分享一套经过实战检验的管控方案,以及如何将规范固化到 AI 生成流水线的流程中,让「配额耗尽」成为历史。

配额规则即设计约束

理解 GitHub Actions 的时长和存储计费模型,是写出不会超限的 Workflow 的前提。

运行时长配额

统计对象为 GitHub 云端托管机器的实际运行耗时,不同操作系统拥有不同的扣费倍率:

操作系统 扣费倍率 说明
Linux 1 倍 标准消耗
Windows 2 倍 同等时长双倍扣除
macOS 10 倍 极高消耗,应谨慎使用

运行分钟额度固定每月月初清零重置。这意味着如果频繁使用 macOS 运行器,免费分钟额度会极速耗尽。

制品存储配额

存储配额的计算方式并非是简单的「500MB 用满即止」,而是采用 GB-Hour(GB·小时) 计费模型:

公式: 占用存储空间 × 文件留存时长

免费额度换算:0.5 GB × 30 天 × 24 小时 = 360 GB-Hour/月

制品默认留存 90 天,这意味着一个 100MB 的构建制品如果不清除,90 天内会持续消耗存储额度。多个构建版本叠加,存储配额会迅速超限。

关键陷阱: 由于配额是按 GB-Hour 累计计费,额度耗尽后即使立即删除已有制品,已消耗的 GB-Hour 也不会回退。配额只能等月度账单周期重置后恢复,删除操作只能防止后续进一步消耗,无法挽回已超限的额度。

管控方案:流水线编写的三个关键约束

1. 即时清理 + 兜底清理

单次流水线维度: 每次执行完成后,立即清理临时制品文件。在 Workflow 末尾添加 actions/upload-artifact 的清理步骤,或使用 if: always() 确保即使任务失败也执行清理。

兜底维度: 额外搭建定时清理 Workflow,每天运行一次,批量清理过期制品与无效归档资源。这能处理任务异常中断遗留的垃圾文件。

2. 合理设置制品留存期限

上传制品时配置 retention-days 参数,从源头降低存储占用时长:

- uses: actions/upload-artifact@v4
  with:
    name: release-build
    path: ./build/
    retention-days: 1

将默认的 90 天留存缩短到 1 天(GitHub 允许设置的最小值),存储占用直接降低 99%。

3. 缓存策略的权衡取舍

缓存仅配置项目核心依赖模块(如 node_modules~/.cache/pip~/.m2 等)。完全移除缓存虽然编译打包流程依旧可运行,但构建耗时会大幅上涨,快速消耗运行分钟额度。

核心权衡:构建效率 vs 时长配额消耗。合理配置缓存能减少 50%-70% 的构建时间,但缓存本身不占用存储配额(Cache 与 Artifact 是独立的存储空间)。

优化方案:三管齐下

方案一:Workflow 编写约束清单

制定一套标准化的 Workflow 编写约束清单,作为 AI 生成流水线配置的专属规范:

约束清单(核心条款):
1. 所有 upload-artifact 步骤必须指定 retention-days ≤ 1
2. 所有流水线末尾必须包含制品清理步骤
3. 缓存仅配置核心依赖,scope 要精确到 lockfile
4. 避免在 macOS 运行器上运行非必要任务
5. 构建产物路径必须使用临时目录,避免残留

不允许无限制自由编写配置,AI 必须严格遵循既定规范输出合法可用的 Workflow 内容。

方案二:定时清理 Workflow

单独开发一套定时清理 Workflow,使用 GitHub Actions 内置的 actions/delete-artifact 或调用 GitHub API 批量清理过期制品:

name: Cleanup Old Artifacts
on:
  schedule:
    - cron: '0 6 * * *'  # 每天 UTC 6:00 执行

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - name: Delete artifacts older than 1 day
        uses: actions/github-script@v7
        with:
          script: |
            const { data: artifacts } = await github.rest.actions.listArtifactsForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
            });
            const now = Date.now();
            const cutoff = 1 * 24 * 60 * 60 * 1000;
            for (const artifact of artifacts.artifacts) {
              if (now - new Date(artifact.created_at).getTime() > cutoff) {
                await github.rest.actions.deleteArtifact({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  artifact_id: artifact.id,
                });
              }
            }

方案三:封装为 AI 技能

将约束清单和定时清理 Workflow 封装为一套独立 AI 技能,后续所有项目统一调用该 AI 技能生成对应的流水线配置文件。这样即使团队成员不了解配额细节,生成的配置也天然合规。

替代方案:自托管 Runner

部署本地自托管 Runner 能够彻底避开 GitHub 官方的时长、存储双重限制。但对于个人开发者而言,搭建、维护多异构平台运行环境(Linux、Windows、macOS)成本偏高,日常使用性价比很低。

适用场景判断:

效果与收益

采用上述管控方案后:

可复用清单

总结

  1. GitHub Actions 免费额度足够个人项目使用,但需要主动管理存储配额,而非放任不管。
  2. 制品留存策略 + 定时清理 + 合理缓存配置,三者构成完整的配额管控体系。
  3. 将规范以约束清单形式固化到 AI 生成流程中,是保持长期合规的最低成本方案。

如果你也在用 GitHub Actions 做 CI/CD,不妨从今天的清理 Workflow 开始,花 10 分钟部署一套定时清理任务,就能避免未来某天遭遇配额锁死的尴尬。

完整配置文件我放在了 GitHub 仓库,下一篇准备写《GitHub Actions 缓存策略深度优化》,RSS 订阅不迷路 📡。

你在使用 GitHub Actions 时踩过什么特别的坑?欢迎评论区聊聊 🙌。

📖 Read in English

← Back to all articles