利用 CF Workers 解决 GitHub Actions 不按时触发问题
问题描述
“注意:schedule 事件在 GitHub Actions 工作流运行期间负载过高时可能会延迟。 高负载时间包括每小时的开始时间。 如果负载足够高,可能会删除一些排队作业。 为了降低延迟的可能性,将您的工作流程安排在不同时间运行。”
本站采用 Upptime 来监控站点服务状态,它基于 GitHub Actions 的 schedule 事件定时触发,其中 Uptime CI 默认配置如下:
name: Uptime CIon: schedule: - cron: "*/5 * * * *" repository_dispatch: types: [uptime] workflow_dispatch:...触发运行的 Cron 表达式为每 5 分钟运行一次,但实际部署后发现存在高达一个小时的运行间隔(可能中间这几次全被吞了),非常不稳定。高达,哪里有高达
在 Upptime 仓库的 issue 中也有人报告这一点:Uptime CI not running every 5 minutes · upptime · Discussion #112
其中提到一种解决方法是,采用 repository_dispatch 事件,使用其他环境来运行 Cron 作业,并通过它触发 Uptime CI。
解决方案
这里提供一种基于 Cloudflare Workers 来触发 GitHub Actions 的方案(以本站的 Upptime 为例):
1. 创建 GitHub Personal Access Token
建议使用 Fine-grained tokens
Repository access 仅选择对应的仓库
Permissions 仅授予 Contents 的 Read and write 权限(不需要 Actions 权限,非常反直觉)
生成后请记住保存好 Token
2. 创建 Cloudflare Worker
在 Cloudflare Dashboard 创建一个新的 Worker,粘贴以下代码:
export default { async scheduled(event, env, ctx) { const GITHUB_TOKEN = env.GH_TOKEN; // 从环境变量读取 const REPO_OWNER = "你的 GitHub 用户名"; // 记得修改 const REPO_NAME = "你的仓库名"; // 记得修改
const url = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/dispatches`;
const response = await fetch(url, { method: 'POST', headers: { 'Authorization': `Bearer ${GITHUB_TOKEN}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'User-Agent': 'Cloudflare-Worker-Trigger' }, body: JSON.stringify({ event_type: 'cf-worker-trigger' // 对应 Action 里的类型 }) });
if (response.ok) { console.log("已成功触发 GitHub Actions"); } else { console.error("触发 GitHub Actions 失败:", await response.text()); } },};别忘记修改代码中你的 GitHub 用户名和仓库名喵!
event_type 这里的 cf-worker-trigger 可以任意修改,只要和下一步对上就行
3. 配置 Worker 环境变量与定时器
- 在 Worker 的 设置 -> 变量和机密 点击添加,类型选择
密钥,变量名称为GH_TOKEN,值填入最开始获取的 Token - 在 设置 -> 触发事件 点击添加,选择Cron 触发器,设置为你需要的间隔(我这里填
*/5 * * * *,代表每 5 分钟触发一次)
Cloudflare 提供了可视化的 Cron 编辑菜单,这里必须好评
4. 修改 GitHub Actions 配置
在你的 GitHub 仓库中,编辑 .github/workflows/<你的工作流文件>.yml,在 on 下面添加 repository_dispatch 事件:
on: schedule: - cron: "*/5 * * * *" # 原有的保留作为兜底,你也可以直接删掉 repository_dispatch: types: [cf-worker-trigger] # 这里要和 Worker 里的 event_type 一致...大功告成!
好啦!以后每次 Cloudflare Worker 触发定时任务时,GitHub Actions 就会自动运行啦! 通过这种方式似乎还能绕过 GitHub Action 的定时触发间隔最低 5 分钟的限制,也许可以自己探索一下
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!