Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(worker/pr): readable cron schedule #33229

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
26 changes: 24 additions & 2 deletions lib/workers/repository/update/pr/body/config-description.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,31 @@ describe('workers/repository/update/pr/body/config-description', () => {
it('renders UTC as the default timezone', () => {
const res = getPrConfigDescription({
...config,
schedule: ['* 1 * * * *'],
schedule: ['* 1 * * *'],
});
expect(res).toContain(`"* 1 * * * *" (UTC)`);
expect(res).toContain(
'Between 01:00 AM and 01:59 AM ( * 1 * * * ) (UTC)',
);
});

it('summarizes cron schedules', () => {
const res = getPrConfigDescription({
...config,
schedule: ['* 1 * * *', '* * 2 * 1'],
});
expect(res).toContain(
'Between 01:00 AM and 01:59 AM ( * 1 * * * ), On day 2 of the month, and on Monday ( * * 2 * 1 ) (UTC)',
);
});

it('displays later schedules', () => {
const res = getPrConfigDescription({
...config,
schedule: ['before 6am on Monday', 'after 3pm on Tuesday'],
});
expect(res).toContain(
'"before 6am on Monday,after 3pm on Tuesday" (UTC)',
);
});

it('renders undefined schedule', () => {
Expand Down
31 changes: 30 additions & 1 deletion lib/workers/repository/update/pr/body/config-description.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { CronPattern } from 'croner';
import cronstrue from 'cronstrue';
import { capitalize } from '../../../../../../tools/docs/utils';
import { emojify } from '../../../../../util/emoji';
import type { BranchConfig } from '../../../../types';

Expand Down Expand Up @@ -51,7 +54,8 @@ function scheduleToString(
): string {
let scheduleString = '';
if (schedule && schedule[0] !== 'at any time') {
scheduleString += `"${String(schedule)}"`;
scheduleString =
getReadableCronSchedule(schedule) ?? `"${String(schedule)}"`;
RahulGautamSingh marked this conversation as resolved.
Show resolved Hide resolved
if (timezone) {
scheduleString += ` in timezone ${timezone}`;
} else {
Expand All @@ -62,3 +66,28 @@ function scheduleToString(
}
return scheduleString;
}

/**
* Return human-readable cron schedule summary if the schedule is a valid cron
* else return null
*/
function getReadableCronSchedule(scheduleText: string[]): string | null {
// assuming if one schedule is cron the others in the array will be cron too
try {
new CronPattern(scheduleText[0]); // validate cron
return scheduleText
.map(
(cron) =>
capitalize(
cronstrue
.toString(cron, {
throwExceptionOnParseError: false,
})
.replace('Every minute, ', ''),
) + ` ( ${cron} )`,
)
.join(', ');
} catch {
return null;
}
}
Loading