Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Fill in:
- `triager`: the GitHub login that owns author-side steps of Dependabot and outside-contributor PRs. They must also be in `users`, or nobody gets tagged for those PRs.
- `repos`: every tracked repo, `owner/name`.
- `enabled`: leave `false` until the [production cutover](#production-cutover-checklist).
- Optional tuning (defaults in `src/features/pr_management/config.ts`): `reminders` (thresholds and message templates), `drafts` (nudge and report ages), `report` (time and time zone, default 09:30 `America/New_York`), `botAuthors`, `wipTitlePattern`.
- Optional tuning (defaults in `src/features/pr_management/config.ts`): `reminders` (thresholds and message templates), `drafts` (nudge and report ages), `report` (`enabled`, time and time zone, default on at 09:30 `America/New_York`), `botAuthors`, `wipTitlePattern`.
- `environments.staging`: `dryRun: true` and `testChannel` (a channel such as `#nathan-test`). In dry run everything Nathan would post, in any channel or DM, goes to the test channel instead.

Staging's overlay can enable `pr_management` on its own (`environments.staging.features.pr_management.enabled: true`), so it can be tested while production stays off.
Expand Down
2 changes: 2 additions & 0 deletions nathan.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default defineConfig({
repos: ["Kiln-AI/Kiln", "Kiln-AI/kiln_server"],
channel: "C0996APVD9R", // #prs
triager: "chiang-daniel",
// Daily report to #prs is off; `/nathan pr_report` still DMs it on demand.
report: { enabled: false },
},
},

Expand Down
2 changes: 2 additions & 0 deletions src/features/pr_management/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ const draftsSchema = z.strictObject({
});

const reportSchema = z.strictObject({
/** Whether the daily report is posted to the PR channel. `/nathan pr_report` works either way. */
enabled: z.boolean().default(true),
/** Local time (24h "HH:MM") the daily report is posted on weekdays. */
at: z
.string()
Expand Down
12 changes: 7 additions & 5 deletions src/features/pr_management/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ export const prManagement = defineFeature({
for (const event of GITHUB_EVENTS) registrar.github.on(event, onWebhook);

registrar.schedule({ name: "sweep", when: { everyHour: true }, run: () => sweep(ctx) });
registrar.schedule({
name: "daily_report",
when: reportSchedule(config.report),
run: ({ firedAt }) => postDailyReport(ctx, firedAt),
});
if (config.report.enabled) {
registrar.schedule({
name: "daily_report",
when: reportSchedule(config.report),
run: ({ firedAt }) => postDailyReport(ctx, firedAt),
});
}

registerRequestPR(registrar, ctx);
registerPersonalQueue(registrar, ctx);
Expand Down
2 changes: 1 addition & 1 deletion test/features/pr_management/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("pr_management config", () => {
templates: DEFAULT_REMINDER_TEMPLATES,
},
drafts: { nudgeAfterDays: 14, nudgeEveryDays: 7, reportAfterDays: 30 },
report: { at: "09:30", timezone: "America/New_York" },
report: { enabled: true, at: "09:30", timezone: "America/New_York" },
});
});

Expand Down
8 changes: 8 additions & 0 deletions test/features/pr_management/report.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,14 @@ describe("the daily report task", () => {
]);
});

it("posts nothing when the report is disabled", async () => {
const h = prApp({ config: prConfig({ report: { enabled: false } }) });
h.github.upsert(aPR({ pendingReviewers: ["bob"] }));

await tickAt(h, "2026-10-09T13:30:00Z");
expect(reports(h)).toEqual([]);
});

it("covers the time since the last report and shows the change in open PRs", async () => {
const h = prApp();
h.github.upsert(aPR({ number: 1, createdAt: at("2026-10-08T10:00:00Z") }));
Expand Down
Loading