.gitea/workflows/renovate.yaml shipped with `cron: "15 3 * * *"`. Gitea Actions cron is UTC, and renovate.json carries schedule ["after 3am and before 6am"] with timezone America/New_York -- and THAT inner schedule is authoritative: Renovate re-checks it and declines to open PRs outside it. 03:15 UTC -> 23:15 EDT, the PREVIOUS EVENING in New York window -> 03:00-06:00 local => NOT INSIDE (3h45m early) The original comment claimed the cron sat "slightly ahead" of the window. It sat 3h45m behind it, on the previous day. Every nightly run would have started, logged "not within schedule", opened ZERO PRs and exited SUCCESSFULLY -- a green tick forever, indistinguishable from "nothing needed updating", hiding the ~30 pending updates PR #73 existed to surface. Changed to `15 8 * * *`, chosen to survive DST rather than to look tidy: EDT (UTC-4): local 03:00-06:00 == 07:00-10:00 UTC EST (UTC-5): local 03:00-06:00 == 08:00-11:00 UTC 08:15 UTC is inside BOTH (04:15 EDT / 03:15 EST), verified by computation at both extremes, so neither switchover needs an edit. A cron cannot follow DST. Also confirmed while here: RENOVATE_TOKEN now exists as a repo Actions secret, so the workflow's fail-hard preflight will pass. STILL UNRESOLVED and the likelier remaining bug: renovate.json's `enabledManagers` lists bare `regex`, where modern Renovate names the custom manager `custom.regex`. If the bare name is ignored, every inline `# renovate:` marker in the tree does nothing. Deliberately NOT changed -- guessing at a key that could fail validation and take the whole run down is worse than a question one dry run answers. See the handoff. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
4.5 KiB
date, branch, title
| date | branch | title |
|---|---|---|
| 2026-10-18 | fix/renovate-cron-window | The Renovate cron fired outside Renovate's own schedule, so it would never have opened a PR |
What changed
.gitea/workflows/renovate.yaml shipped (PR #73) with cron: "15 3 * * *". That schedule could
never have produced a single PR.
Gitea Actions cron is UTC. renovate.json carries "schedule": ["after 3am and before 6am"]
with "timezone": "America/New_York", and that inner schedule is authoritative — Renovate
re-checks it and declines to open PRs outside it. So:
cron 03:15 UTC -> 23:15 EDT, the PREVIOUS EVENING in New York
window -> 03:00-06:00 local
inside? -> NO (3h45m before the window opens)
The original comment claimed the cron was "slightly ahead of the repo window ... so a run is always in flight when the window opens". It is 3h45m behind, on the previous day. Every nightly run would have started, logged "not within schedule", opened zero PRs and exited successfully — a green tick forever, indistinguishable from "nothing needed updating". That is the same "failure-mode-is-a-green-tick" shape this repo keeps hitting, and it would have hidden the ~30 pending updates PR #73 was written to surface.
Changed to cron: "15 8 * * *", chosen to survive DST rather than to be tidy. The window's UTC
position moves:
| local window | in UTC | |
|---|---|---|
| EDT (UTC-4, Mar–Nov) | 03:00–06:00 | 07:00–10:00 |
| EST (UTC-5, Nov–Mar) | 03:00–06:00 | 08:00–11:00 |
08:15 UTC is inside both (04:15 EDT / 03:15 EST), so no edit is needed at either switchover.
A cron cannot follow DST, so this is the only way to get it right once.
What I verified
- The defect, by arithmetic rather than assertion:
datetime(2026,10,18,03,15, UTC)converted toAmerica/New_Yorkviazoneinfois2026-10-17 23:15 EDT;3 <= hour < 6is False. - The fix, at both DST extremes:
08:15 UTC→04:15 EDTin July and03:15 ESTin December, both inside03:00–06:00. Computed, not reasoned. - The inner schedule really is authoritative and really is set:
renovate.jsononmaincarriestimezone = America/New_Yorkandschedule = ['after 3am and before 6am']. RENOVATE_TOKENnow exists as a repository Actions secret (listed by name via the Gitea API alongsideSETTINGS_API_TOKEN), so the workflow's fail-hard preflight will pass. It did not exist when PR #73 was authored.- The edited workflow parses as YAML.
What I did NOT verify
- Renovate has still never executed. This fixes when it runs, not whether it works. No run has happened, so nothing here proves it extracts dependencies, authenticates to Gitea, or opens a usable PR.
enabledManagersmay silently disable the custom managers — UNRESOLVED and the likelier remaining bug.renovate.jsonlistsenabledManagers: [..., 'regex', ...]and definescustomManagers(correct modern key;regexManagersis absent, which is right). But modern Renovate names the custom managercustom.regexinenabledManagers, not bareregex. If the bare name is invalid or ignored, every inline# renovate:marker in the tree does nothing — including theexternal-snapshotternewTagpin PR #73 flagged as probably inert. I did not change it, because guessing at a config key that could fail validation and take the whole run down is worse than leaving a question that one dry run answers definitively. Thedry_run: truedispatch log settles it: look for a per-manager dependency-extraction count, and for any config validation warning namingregex.- Whether a dry run inside vs outside the window differs usefully. Renovate honours its schedule even in dry-run, so a manual dispatch outside 03:00–06:00 local will also log "not within schedule". That makes the first dispatch's output less informative than it looks; to see what Renovate would do, either dispatch inside the local window or override the schedule for that run. Not tested either way.
- No alert fires if the schedule stops firing. PR #73 recorded this gap and it is still open: a Renovate workflow that silently stops running (disabled Actions, expired token, deleted secret) produces no signal at all. Closing it needs a check on last-successful-run age, which nothing does.
- No conformance test asserts the cron falls inside
renovate.json's window, so this exact bug can return. A static check comparing the two is feasible and is not written.