Renovate 调度(Scheduling)配置指南:精确控制依赖更新的时间窗口
【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate
本文围绕 Renovate 的调度机制展开,讲解如何通过timezone、schedule、automergeSchedule等配置选项,把依赖更新(创建分支、自动合并)限制在指定的时间窗口内,并结合源码剖析调度判定的底层原理。读完本文,你将掌握 cron 调度语法的正确写法、内置调度预设的使用方法,以及如何为特定包或包组单独定制更新节奏,从而有效降低 PR 噪音、避开业务高峰时段。
Renovate 调度的定位与默认行为
Renovate 何时运行:由后端配置决定
Renovate 本身是一个周期性运行的 CLI 程序,"什么时候跑"由运行它的后端(backend)管理方决定,而不是由仓库配置文件决定。例如管理员可以把 Renovate 配置为每小时运行一次、每天运行一次,或仅在下班时间运行。
每个仓库实际被处理的频率取决于多个因素:
- 后端配置的运行频率(例如每小时、每天);
- 组织或账号下已 onboarding 的仓库总数;
- 每个仓库里待处理的工作量(依赖数量、待更新分支数等)。
这里有一个关键限制:如果后端配置导致每个仓库大约每 X 小时才被调度一次,那么仓库级配置无法把间隔缩短到小于 X,也无法强制 Renovate 在某个精确时刻处理特定仓库。仓库配置只能在"Renovate 程序已经运行起来"这个前提下,决定"这次运行是否允许为某些依赖创建/更新分支"。
默认时区:UTC
默认情况下,Renovate 的所有调度均按UTC 时区解释。如果需要按本地时间调度,可以通过timezone配置选项设置自己的时区(详见下文"设置时区"一节)。
调度运行耗时:依赖数与仓库数的影响
Renovate 处理单个仓库的耗时随依赖数量、仓库数量的增长而增长。官方文档给出了如下量级参考:
| 待更新依赖数 | 拥有这些依赖的仓库数 | 运行耗时 |
|---|---|---|
| 1 | 1 | 非常快 |
| 1 | 10 | 快 |
| 1 | 100 | 慢 |
| 50 | 1 | 慢 |
| 100 | 100 | 非常慢 |
这意味着在后端硬件上应预留足够的处理时间,避免把调度窗口设置得过于局促(例如"每周日只跑一小时")——后面"仓库级调度配置"一节会再次强调这一点。
全局调度与具体调度
从宏观上看,Renovate 有两种调度方式,作用完全不同:
| 调度方式 | 作用 | 说明 |
|---|---|---|
| 全局调度(Global) | 决定 Renovate 程序何时运行 | 通常由组织管理员控制;对于 Mend Renovate App,由 Mend 决定 Renovate 何时运行 |
| 具体调度(Specific) | 当 Renovate 运行时,检查调度以决定是否应为某个依赖查找更新 | 通常写在renovate.json或类似的配置文件中 |
因此,一个依赖只有在两个条件同时成立时才会被更新:
- Renovate 程序正在运行(在你的硬件上,或 Mend 的硬件上);
- Renovate 配置文件中的调度允许 Renovate 查找该依赖的更新。
管理更新频率
Renovate 默认"始终开启、发现更新立即开 PR",这会让用户被源源不断的"新 PR"通知淹没。合理使用调度可以显著改善体验,典型做法包括:
- 在仓库的 Renovate 配置文件中,把检查更新的频率限制为每周一次;
- 为某个包或某个包组单独设置更新调度(见下文"为特定依赖设置调度")。
从源码看,schedule配置项在 lib/config/options/index.ts 中的定义为:"限制在一天或一周中的这些时间段创建分支",类型为字符串数组,默认值为['at any time'],同时支持allowString(即可以写成单个字符串,但官方建议使用数组语法)。
调度使用场景
调度工具可以帮你实现以下目标:
- 在非办公时段运行 Renovate,把持续集成资源释放给开发人员;
- 让某些包按固定周期更新,而不是一有新版就立刻更新;
- 减少白天收到的 Renovate PR 通知。
一句话概括:调度解决的是"什么时候允许 Renovate 动手"的问题,而不是"要不要更新"的问题。
自定义调度
自定义调度只需掌握两个核心配置项:timezone(时区)与schedule(调度)。整体步骤如下:
- 告诉 Renovate 你想使用哪个
timezone; - 学习调度语法(推荐 cron);
- 可选:设置"仓库级调度";
- 可选:通过
packageRules为某个包或包组设置自定义schedule。
设置时区(timezone)
默认情况下 Renovate 的调度按 UTC 解释。若希望按本地时间调度,使用timezone配置项,其值必须是有效的 IANA 时区名称(IANA Time Zone Database 中的合法名称)。例如:
{ "timezone": "America/Los_Angeles" }配置项定义同样位于 lib/config/options/index.ts,类型为字符串,说明中明确要求符合 IANA 时区格式。
从源码来看,时区合法性校验在 lib/workers/repository/update/branch/schedule.ts 的hasValidTimezone函数中完成:它用 Luxon 的DateTime.local().setZone(timezone).isValid判断时区是否有效,无效时返回Invalid schedule: Unsupported timezone ...错误信息。测试用例 lib/workers/repository/update/branch/schedule.spec.ts 中同时覆盖了有效时区(返回 true)与无效时区(返回 false)两种场景。
调度语法
设置好时区后,就可以定义"一周中的哪些天"或"一天中的哪些小时"允许 Renovate 执行变更操作。
推荐的 cron 语法
官方强烈推荐使用标准cron 语法。常用写法对照:
| 描述 | Cron 语法 |
|---|---|
| 每个周末 | * * * * 0,6 |
| 凌晨 5 点前 | * 0-4 * * * |
| 每个工作日的晚上 10 点到次日凌晨 5 点 | * 22-23,0-4 * * 1-5 |
| 周五和周六 | * * * * 5,6 |
| 每季度(每 3 个月)的 1 号 | * * 1 */3 * |
使用 cron 语法时有两点硬性约束:
- 分钟位置必须使用
*通配符:Renovate 不支持分钟级粒度,因此30 0 * * *这类写法是无效的; - cron 表达式必须包含五个部分(分、时、日、月、周)。
上述校验逻辑在源码中可以直接验证:hasValidSchedule函数(lib/workers/repository/update/branch/schedule.ts)先用croner的CronPattern尝试解析;如果解析成功且分钟位置包含非*的值,或表达式不是以*开头,就会报错Invalid schedule: ... doesn't have * as minutes。
已废弃的 breejs/later 语法
Renovate 还支持(但已废弃)基于@breejs/later库的自然语言文本语法。官方计划在未来的大版本中移除@breejs/later库(前提是找到把所有合法调度迁移到 cron 语法的方案),因此强烈建议所有用户改用 cron 调度,新配置不要再使用 later 语法。
@breejs/later库负责解释every、before、after、on等关键词,以及"天""time_before""time_after"等语义。合法但已废弃的 later 写法与 cron 写法对照:
| 合法但已废弃的 later 语法 | Cron 语法 |
|---|---|
| every weekend | * * * * 0,6 |
| before 5:00am | * 0-4 * * * |
| after 10pm and before 5am every weekday | * 22-23,0-4 * * 1-5 |
| on friday and saturday | * * * * 5,6 |
| every 3 months on the first day of the month | * * 1 */3 * |
再次强调:Renovate 不支持"精确到分钟"或"指定精确时刻"的粒度,粒度最小必须是一小时。
源码层面,later 语法的兼容路径同样在hasValidSchedule中:当 cron 解析失败时,会调用later.parse.text()解析文本,并检查解析结果——若出错、或指定了分钟(s.m)、或既没有月份/星期/时刻限制,都会判定为无效调度。另外,isScheduledNow(lib/workers/repository/update/branch/schedule.ts)会先尝试 cron 解析,成功则走cronMatches判断;否则退回 later 语法的later.schedule(parsedSchedule).isValid()判断。两条路径并存,正是当前"cron 为主、later 兼容"的实现写照。
仓库级调度配置
需要注意:Renovate 进程何时运行通常由管理员控制(例如通过系统cron工具)。对于 Mend Renovate App,Mend 维护者控制进程运行节奏,通常是每小时一次。
如果你自行掌控 Renovate 所运行的硬件,官方建议:
- 在硬件上为 Renovate 预留足够的处理时间,确保能处理完所有仓库;
- 避免"每周日运行一小时"这类过于局促的调度,否则一定会遇到问题(仓库可能处理不完,更新被反复跳过)。
仓库级配置示例:
{ "description": "Schedule daily before 4 AM", "schedule": ["* 0-3 * * *"] }{ "description": "Schedule during typical non-office hours on weekdays (i.e., 10 PM - 5 AM) and anytime on weekends", "schedule": ["* 0-4,22-23 * * 1-5", "* * * * 0,6"] }调度预设(Schedule presets)
Renovate 内置了常见调度场景的预设(preset),例如"每周一次""非办公时段"等。在自建调度之前,先检查内置预设是否满足需求——这样可以少写代码、少踩坑。这些预设只决定 Renovate 何时查找更新,不影响任何具体依赖/包。
内置预设定义在 lib/config/presets/internal/schedule.preset.ts 中,可以直接在配置里通过"extends": ["schedule:xxx"]引用,例如:
| 预设名 | 含义 | 对应 cron |
|---|---|---|
schedule:daily | 每天凌晨 4 点前 | * 0-3 * * * |
schedule:earlyMondays | 每周一凌晨 4 点前 | * 0-3 * * 1 |
schedule:weekly | 每周一次(继承schedule:earlyMondays) | — |
schedule:monthly | 每月 1 号凌晨 4 点前 | * 0-3 1 * * |
schedule:quarterly | 每季度 1 号 | * * 1 */3 * |
schedule:yearly | 每年 1 月 1 日 | * * 1 */12 * |
schedule:nonOfficeHours | 工作日 22 点-次日 5 点 + 周末全天 | * 0-4,22-23 * * 1-5,* * * * 0,6 |
schedule:officeHours | 工作日 8-17 点 | * 8-17 * * 1-5 |
schedule:weekdays | 工作日 | * * * * 1-5 |
schedule:weekends | 周末 | * * * * 0,6 |
此外还有一组schedule:automerge*预设(automergeDaily、automergeEarlyMondays、automergeMonthly、automergeNonOfficeHours、automergeOfficeHours、automergeQuarterly、automergeWeekly、automergeWeekends、automergeYearly),它们作用于automergeSchedule而不是schedule,用于限制自动合并的时间窗口。
为特定依赖设置调度
利用packageRules搭配schedule,可以为特定包或包组定制更新节奏,从而"限制频繁更新依赖带来的噪音"。以 AWS SDK 为例,把它限制为每周日晚上更新:
{ "packageRules": [ { "description": "Schedule AWS SDK updates on Sunday nights (9 PM - 12 AM)", "matchPackageNames": ["@aws-sdk/*"], "schedule": ["* 21-23 * * 0"] } ] }使用"schedule"属性时的关键要点:
- 始终使用数组语法
[],即使只设置一个调度; - 多个条目之间用逗号分隔,如
["cron for schedule 1", "cron for schedule 2"]; - 数组中的多个条目按布尔 OR 逻辑解释——只要命中其中任意一个时间窗口,就算在调度内。
与调度配合使用的其他配置项
automergeSchedule:单独限制自动合并时间
如果开启了automerge,可以再用automergeSchedule单独限定"自动合并分支/PR"的时段,与schedule(创建分支的时段)互不影响。该配置定义在 lib/config/options/index.ts,默认同为['at any time']。从 lib/workers/repository/update/branch/automerge.ts 可以看到,自动合并判定调用的是isScheduledNow(config, 'automergeSchedule'),即复用同一套调度判定逻辑、只是传入不同的配置键。
需要注意:当platformAutomerge开启时,Renovate 在 PR 创建时就把平台自动合并入队,此时automergeSchedule无法生效;如果必须严格限定自动合并时段,需要把platformAutomerge设为false,改用 Renovate 自身的自动合并。
updateNotScheduled:是否在调度外更新已有分支
schedule默认只约束"创建分支",而updateNotScheduled(lib/config/options/index.ts)控制是否在非调度时段更新已有分支,默认值为true。若希望调度被更严格地执行——即调度窗口外连已有分支的更新也不推送——需要显式设置:
{ "updateNotScheduled": false }从 lib/workers/repository/update/branch/index.spec.ts 的测试用例(如第 340、191 行附近的用例)可以看到,updateNotScheduled为false且isScheduledNow返回 false 时,分支更新会被跳过;反之则允许在调度外继续更新已有分支。
调度判定流程与最佳实践
底层判定流程(isScheduledNow)
综合源码 lib/workers/repository/update/branch/schedule.ts,Renovate 判断"当前是否在调度内"的完整流程是:
- 读取
schedule(或automergeSchedule)配置;若为空、"at any time"则直接放行; - 校验调度合法性(
hasValidSchedule),非法时记录 warning 并放行(fail-open 策略); - 若配置了
timezone,校验其合法性并用它把当前时间now转换到时区;无效时同样放行; - 逐个尝试 cron 解析:成功则用
croner的Cron(domAndDow: true模式)计算"上一个整分钟之后的下一次运行时刻",与当前分钟比对(cronMatches);失败则回退到@breejs/later的later.schedule().isValid(); - 只要命中任意一个调度条目(OR 逻辑),即认为"在调度内"。
值得注意的实现细节:cron 匹配把当前时刻与"下一次 cron 触发时刻"按分钟对齐比较(nextMinute.toMillis() === nowMinute.toMillis()),本质上以小时为最小粒度判断当前是否处于允许窗口内,与"不支持分钟粒度"的约束一致。
时间窗口与边界条件建议
- 调度窗口建议至少留 3-4 小时:如果调度过于严苛,而 Renovate 恰好在窗口外运行的概率又高,依赖更新会被反复跳过;
- 日与月同时受限时是 AND 逻辑:
schedule中如果同时限制"日(day of month)"与"星期(day of week)",Renovate 只有在两者同时命中时才运行。例如* * 1-7 * 4表示仅每月第一个星期四运行; - 已有旧式 later 语法的处理:Renovate 的配置迁移机制(见 lib/config/migrations/custom/schedule-migration.ts)会自动把
after 10pm and before 5am这类跨天写法拆成两条调度、把on the last day of the month规范化为on the first day of the month、把every weekday等文本统一格式,逐步引导配置向 cron 迁移; - 区分"创建分支"与"更新分支":默认情况下
schedule只约束新分支的创建,已有分支在调度外仍可能被更新;需要严格模式时记得配置updateNotScheduled=false。
小结
Renovate 的调度体系可以概括为"两层控制":后端决定程序何时运行,仓库配置决定程序运行时是否允许动某个依赖。仓库侧的核心工具是timezone+schedule,推荐统一使用五段式 cron 语法(分钟位固定为*),善用内置的schedule:*预设减少重复配置,再配合automergeSchedule与updateNotScheduled精确控制自动合并与分支更新的边界。把握住"最小粒度一小时、数组 OR 逻辑、日与月 AND 逻辑、窗口至少 3-4 小时"这几个要点,就能为团队设计出既安静又不漏更新的依赖自动化策略。
【免费下载链接】renovateHome of the Renovate CLI: Cross-platform Dependency Automation by Mend.io项目地址: https://gitcode.com/GitHub_Trending/re/renovate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考