fix(latex): narrow the lock file maintenance window to one job - #158
Conversation
Lock file maintenance is not an item that a job can exhaust. It is the difference between the committed lock file and the registry, so merging it restores that difference within hours and the next job inside the two-day window has something to create again. Across 2026-08-27 to 08-29 that produced nine pull requests over three repositories -- three in texlive-ja-textlint, four in ai-academic-paper-reviewer and two here -- one of them opened thirty-six seconds after its predecessor merged, each carrying a single transitive package where one weekly pull request would have carried all of them. Take the shape of Renovate's own default (one day, before dawn) and move only the day. Five hours still exceeds the four-hour job interval, so this window cannot fall between two jobs the way the Sunday evening one did. Nothing urgent rides on the cadence: osvVulnerabilityAlerts in the default preset bypasses every schedule. Refs #157
| "The hourly cap decides how much of the queue escapes the window. Mend runs a repository's job every four hours, so the inherited limit of two pull requests per hour is really two per run, and a window holds about a dozen runs: a backlog larger than that never drains inside one, and what is left waits on the dependency dashboard until the next. Renovate sorts majors last, so they are what stays behind, week after week. Let the schedule alone bound the noise.", | ||
| "The concurrent-PR cap throttles the same queue from the other end. Majors are never auto-merged, so they stay open until they are reviewed; under the inherited cap of ten they hold the quota and the auto-merged minor/patch lane stops being refilled -- the same starvation as above, at a different valve. The window is the only throttle either limit needs to leave in place.", | ||
| "Refresh lock files on the same weekly cadence. Bumping direct dependencies never rewrites the rest of the tree, so advisories in transitive packages accumulate unseen -- the eleven advisories found in ai-academic-paper-reviewer were almost all transitive. Lock file maintenance carries its own schedule that the top-level one does not override, so the window is repeated here; leaving it out would fall back to Renovate's Monday-early default and split the week into two update waves. This lives in the latex preset rather than the npm one because the window is defined here, and it is a no-op for repositories that have no lock file." | ||
| "Refresh lock files weekly, in a narrow window on the first day of the one above. Bumping direct dependencies never rewrites the rest of the tree, so advisories in transitive packages accumulate unseen -- the eleven advisories found in ai-academic-paper-reviewer were almost all transitive. Lock file maintenance carries its own schedule that the top-level one does not override, so a window has to be named here; leaving it out would fall back to Renovate's Monday-early default and split the week into two update waves. Take the shape of that default -- one day, before dawn -- and move only the day, because the two-day window above is wrong for this update in the way it is right for the others. A version update is an item that a job can exhaust; lock file maintenance is the difference between the committed lock file and the registry, and merging it restores that difference within hours, so the next job inside the window has something to create again. Across 2026-08-27 to 08-29 that produced three pull requests in texlive-ja-textlint, four in ai-academic-paper-reviewer and two here, one of them opened thirty-six seconds after its predecessor merged, each carrying a single transitive package where one weekly pull request would have carried all of them. Five hours still exceeds the four-hour job interval, so this window cannot fall between two jobs the way the Sunday evening one did. Nothing urgent rides on the cadence: osvVulnerabilityAlerts in the default preset bypasses every schedule, which leaves lock file maintenance a routine refresh rather than the security net. This lives in the latex preset rather than the npm one because the window is defined here, and it is a no-op for repositories that have no lock file." |
There was a problem hiding this comment.
ℹ️ [LOW] description の第5段落が非常に長くなっています(現在約600文字の1文)。将来の読者がこの設定を理解・変更しようとする際に、1文で全ての根拠を読み解くのは認知負荷が高くなります。
例えば以下のように複数の文に分割することを検討してください:
"Refresh lock files weekly, in a narrow window on the first day of the one above. ... Take the shape of that default -- one day, before dawn -- and move only the day."
"A version update is an item that a job can exhaust; lock file maintenance is the difference between the committed lock file and the registry, and merging it restores that difference within hours, so the next job inside the window has something to create again."
"Five hours still exceeds the four-hour job interval, so this window cannot fall between two jobs the way the Sunday evening one did."
設定ファイルのコメントとして残す情報量としては適切ですが、文の区切りを増やすだけで可読性が大きく向上します。
There was a problem hiding this comment.
分割しました(0ba4b95)。
ご指摘のとおり突出していました。既存段落が 373 / 461 / 503 / 840 文字なのに対し、この要素だけ 1738 文字で 2 倍以上です。
「窓が何をするか」と「なぜ上の 2 日窓より狭いか」の 2 要素に分け、751 / 953 文字になりました。あわせて観測 PR のリポジトリ別内訳(texlive-ja-textlint 3 本、ai-academic-paper-reviewer 4 本、.github 2 本)は #157 に記録があるので、description からは「9 pull requests over three repositories」に圧縮しています。
一点だけ補足すると、「約600文字の1文」は実測と異なります。実際は 1738 文字・約 9 文で、600 文字強なのは変更前の同要素(634 文字)でした。ただ長すぎるという結論自体は正しかったので、そのまま対応しています。
| "lockFileMaintenance": { | ||
| "enabled": true, | ||
| "schedule": ["on friday and saturday"] | ||
| "schedule": ["before 5am on friday"] |
There was a problem hiding this comment.
ℹ️ [LOW] "before 5am on friday" の5時間窓はMendのjob間隔(4時間)を上回るため、窓内に少なくとも1つのjobが入ることは保証されます。ただし、窓の開始直後にjobが実行され、automergeが完了する前に次のjob(最大4時間後)が走った場合、2本目のPRが作られる可能性はPR本文でも言及されています。
確実に1本にしたい場合は窓を4時間未満にする必要がありますが、PR本文の通りそれは「jobが1つも入らない」リスクを伴うため、現在のトレードオフ判断(3〜4本→1〜2本)は合理的です。将来的に観測データが蓄積された際に、窓の幅を再調整する余地があることをコメントやissueで記録しておくと、次の担当者が判断しやすくなります。
There was a problem hiding this comment.
記録として #157 に検証手順と判定基準を追記しました。この PR がマージされても #157 はクローズしません。
ご指摘のとおり本 PR は根治ではなくトレードオフなので、観測で確かめるまで判断を閉じない形にしています。#157 に置いたのは次の 3 点です。
- 次の窓(2026-09-04 金〜09-05 土)を通過させて本数を数える手順(
v1の手動移動が前提になることを含む) - 今回の実測(ai-academic-paper-reviewer 4 本 / texlive-ja-textlint 3 本 / .github 2 本)を比較対象とした判定基準
- 3 本以上残った場合の次の一手 — 窓幅ではなく automerge の完了タイミングが支配的ということなので、
lockFileMaintenanceにautomerge: falseを与える案を再検討する(ただし「Renovate が checks して Renovate が merge する」方針に逆行するため、本数の実害と天秤にかけます) - 0 本だった場合の疑い方 — 窓が狭すぎて job が入らなかったケースなので、各 dependency dashboard に
Awaiting Scheduleが残っていないかを見る
preset の description に書き足すことも検討しましたが、もう一方のスレッドで長さを指摘されて分割したばかりなので見送りました。窓幅の再調整余地は観測次第で変わる運用情報なので、バージョン管理された preset の説明文より issue のほうが置き場所として適切だと判断しています。
レビュー対応LOW 2 件、いずれも対応済みです。CI は 1. description の長さ(discussion_r3886366211)→ 修正
周囲の要素が 373 / 461 / 503 / 840 文字なので、1738 は 2 倍以上の突出でした。「窓が何をするか」と「なぜ上の 2 日窓より狭いか」で切り、観測 PR のリポジトリ別内訳は #157 にあるため 指摘中の「約600文字の1文」は実測と異なり(実際は 1738 文字・約 9 文、634 文字なのは変更前の同要素)、その点だけスレッドで補足しました。結論は正しかったのでそのまま対応しています。 2. 窓幅の再調整余地を記録すべき(discussion_r3886372995)→ #157 に記録、コード変更なしこの PR をマージしても #157 はクローズしません。 本 PR は根治ではなくトレードオフ(3〜4 本 → 1〜2 本狙い)なので、観測で確かめるまで判断を閉じない形にしました。 #157 のコメントに、次の窓(2026-09-04 〜 09-05)での検証手順、今回の実測を比較対象とした判定基準、3 本以上残った場合と 0 本だった場合それぞれの次の一手を置いています。 preset の マージ後に必要なこと
gh api -X PATCH /repos/smkwlab/.github/git/refs/tags/v1 -f sha=<full-sha> -F force=true#149(trufflehog v3.97.1)も同じく |
#157 の対応。
変更
"lockFileMaintenance": { "enabled": true, - "schedule": ["on friday and saturday"] + "schedule": ["before 5am on friday"] },description の第 5 段落も、窓を狭めた理由に合わせて書き換えています。実質の差分は 2 行です。
なぜ
latex.jsonが窓を金・土の 2 日に広げた根拠は description に書いてあるとおり「最初の job がキューを空にし、後続の job は作るものを見つけない」でした。lockFileMaintenanceだけがこの前提を満たしません。バージョン更新は job が汲み尽くせる項目ですが、lock file maintenance は「コミットされた lockfile と registry の差」です。マージすれば差はゼロになっても registry 側が数時間で動くので、窓の中の次の job には再び作るものがある。自分がマージした結果を材料に次を作る構造です。
観測(2026-08-27 〜 08-29 の窓)
3 リポジトリで 9 本。
ai-academic-paper-reviewer #77 は #76 のマージ 36 秒後に作られています。 同一 job が「マージ → 直後に再作成」を実行した跡です。
texlive-ja-textlint の 3 本は合計 15 行で、内容は transitive パッケージが 1 つずつ。週 1 本なら同じ 15 行を 1 本で運べました。CI は 1 PR あたり Docker ビルド 3 種(うち alpine は 33 分)なので、9 回が 3 回になります。
なぜ
before 5am on fridayかRenovate の
lockFileMaintenanceデフォルトはbefore 5am on mondayです。「1 日 + 夜明け前」という狭い形は、まさにこの再作成ループを避けるための設計だと思われます。description が書いているとおり、ここで窓を名指しする必要があるのは、トップレベルの schedule が
lockFileMaintenanceを上書きしないためです。ただしその際に幅までトップレベルからコピーしてしまったのがズレの原因でした。修正はデフォルトの形を保ったまま曜日だけ金曜に移すことになります。5 時間は Mend の job 間隔 4 時間より広いので、
Avoid schedules like "Run Renovate for an hour each Sunday"の失敗モード(窓が job 間隔より狭く、2 つの job の間に丸ごと落ちる)には戻りません。:elixirが日曜夜の窓で 3 週間空回りした、あの失敗です。残る挙動
窓の頭で PR が作られ、automerge がまだ窓内の次の job で完了すれば、2 本目が作られる可能性は残ります。確実に 1 本にするには窓を 4 時間未満に詰める必要がありますが、それは job が 1 つも入らない側の失敗(更新が静かに止まる)に落ちるため取っていません。3〜4 本が 1〜2 本になれば十分と判断しました。
安全性
頻度を落としても脆弱性の検知は遅れません。
default.jsonのosvVulnerabilityAlerts: trueがschedule: []/prCreation: "immediate"で窓を迂回するため(#120)、lockFileMaintenanceは安全網ではなく予防的なリフレッシュです。検証
マージ後
v1を移動すれば、次の窓(9/4–9/5)で本数を確認できます。