From aabf1638d1a39fa675d2eecc7a23076b378c1f28 Mon Sep 17 00:00:00 2001
From: RahulGautamSingh <rahultesnik@gmail.com>
Date: Sun, 8 Dec 2024 13:37:53 +0530
Subject: [PATCH] fix(schedule): use and logic to handle dow+dom (#32903)

Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
---
 docs/usage/configuration-options.md           |  5 +++++
 .../repository/update/branch/schedule.spec.ts | 22 ++++++++++++-------
 .../repository/update/branch/schedule.ts      |  1 +
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index 5fa92c7faf..003eb19459 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -3853,6 +3853,11 @@ You could then configure a schedule like this at the repository level:
 This would mean that Renovate can run for 7 hours each night, plus all the time on weekends.
 Note how the above example makes use of the "OR" logic of combining multiple schedules in the array.
 
+<!-- prettier-ignore -->
+!!! note
+    If both the day of the week _and_ the day of the month are restricted in the schedule, then Renovate only runs when both the day of the month _and_ day of the week match!
+    For example: `* * 1-7 * 4` means Renovate only runs on the _first_ Thursday of the month.
+
 It's common to use `schedule` in combination with [`timezone`](#timezone).
 You should configure [`updateNotScheduled=false`](#updatenotscheduled) if you want the schedule more strictly enforced so that _updates_ to existing branches aren't pushed out of schedule.
 You can also configure [`automergeSchedule`](#automergeschedule) to limit the hours in which branches/PRs are _automerged_ (if [`automerge`](#automerge) is configured).
diff --git a/lib/workers/repository/update/branch/schedule.spec.ts b/lib/workers/repository/update/branch/schedule.spec.ts
index d310c4090b..4dacb99da8 100644
--- a/lib/workers/repository/update/branch/schedule.spec.ts
+++ b/lib/workers/repository/update/branch/schedule.spec.ts
@@ -299,15 +299,17 @@ describe('workers/repository/update/branch/schedule', () => {
       });
     });
 
-    describe('complex cron schedules', () => {
+    describe('handles schedule with Day Of Month and Day Of Week using AND logic', () => {
       it.each`
-        sched            | datetime                          | expected
-        ${'* * 1-7 * 0'} | ${'2024-10-04T10:50:00.000+0900'} | ${true}
-        ${'* * 1-7 * 0'} | ${'2024-10-13T10:50:00.000+0900'} | ${true}
-        ${'* * 1-7 * 0'} | ${'2024-10-16T10:50:00.000+0900'} | ${false}
-      `('$sched, $tz, $datetime', ({ sched, tz, datetime, expected }) => {
-        config.schedule = [sched];
-        config.timezone = 'Asia/Tokyo';
+        datetime                     | expected
+        ${'2017-06-01T01:00:00.000'} | ${true}
+        ${'2017-06-15T01:01:00.000'} | ${true}
+        ${'2017-06-16T03:00:00.000'} | ${false}
+        ${'2017-06-04T04:01:00.000'} | ${false}
+        ${'2017-06-08T04:01:00.000'} | ${false}
+        ${'2017-06-29T04:01:00.000'} | ${false}
+      `('$sched, $tz, $datetime', ({ datetime, expected }) => {
+        config.schedule = ['* 0-5 1-7,15-22 * 4'];
         jest.setSystemTime(new Date(datetime));
         expect(schedule.isScheduledNow(config)).toBe(expected);
       });
@@ -320,6 +322,10 @@ describe('workers/repository/update/branch/schedule', () => {
         ${'after 4pm'}            | ${'Asia/Singapore'} | ${'2017-06-30T16:01:00.000+0800'} | ${true}
         ${'before 4am on Monday'} | ${'Asia/Tokyo'}     | ${'2017-06-26T03:59:00.000+0900'} | ${true}
         ${'before 4am on Monday'} | ${'Asia/Tokyo'}     | ${'2017-06-26T04:01:00.000+0900'} | ${false}
+        ${'* 16-23 * * *'}        | ${'Asia/Singapore'} | ${'2017-06-30T15:59:00.000+0800'} | ${false}
+        ${'* 16-23 * * *'}        | ${'Asia/Singapore'} | ${'2017-06-30T16:01:00.000+0800'} | ${true}
+        ${'* 0-3 * * 1'}          | ${'Asia/Tokyo'}     | ${'2017-06-26T03:58:00.000+0900'} | ${true}
+        ${'* 0-3 * * 1'}          | ${'Asia/Tokyo'}     | ${'2017-06-26T04:01:00.000+0900'} | ${false}
       `('$sched, $tz, $datetime', ({ sched, tz, datetime, expected }) => {
         config.schedule = [sched];
         config.timezone = tz;
diff --git a/lib/workers/repository/update/branch/schedule.ts b/lib/workers/repository/update/branch/schedule.ts
index 73c68b278b..7789ebcc4c 100644
--- a/lib/workers/repository/update/branch/schedule.ts
+++ b/lib/workers/repository/update/branch/schedule.ts
@@ -96,6 +96,7 @@ export function cronMatches(
 ): boolean {
   const parsedCron: Cron = new Cron(cron, {
     ...(timezone && { timezone }),
+    legacyMode: false,
   });
   // it will always parse because it is checked beforehand
   // istanbul ignore if
-- 
GitLab