feat: improve cron create delivery ergonomics

Summary:
- Add Hermes-style schedule-first cron create parsing while preserving flagged create options.
- Support webhook create/edit delivery and clear stale webhook/chat delivery fields across mode changes.
- Update cron docs and schedule identity normalization tests.

Verification:
- pnpm test src/cron/schedule-identity.test.ts src/cli/cron-cli.test.ts src/cron/service.jobs.test.ts -- --reporter=verbose
- pnpm test src/cli/cron-cli.test.ts src/cron/service.jobs.test.ts -- --reporter=verbose
- pnpm check:test-types
- pnpm check:import-cycles
- pnpm check:docs
- pnpm check:changed via Crabbox run_8c44bcb158da, exit 0
- autoreview branch diff clean
This commit is contained in:
Peter Steinberger
2026-05-29 04:34:50 +01:00
committed by GitHub
parent 4b18234fc1
commit 2209faef40
12 changed files with 576 additions and 219 deletions

View File

@@ -75,7 +75,9 @@ function stableJson(value) {
}
export function sanitizeDisplayValue(value) {
return String(value).replace(/[\p{Cc}]/gu, "?").slice(0, 240);
return String(value)
.replace(/[\p{Cc}]/gu, "?")
.slice(0, 240);
}
export function markdownCode(value) {
@@ -242,10 +244,7 @@ export function renderAuthorizedDependencyComment(override) {
if (override.reason) {
lines.push(`- Reason: ${markdownCode(override.reason)}`);
}
lines.push(
"",
"A later push changes the PR head SHA and requires a fresh security approval.",
);
lines.push("", "A later push changes the PR head SHA and requires a fresh security approval.");
return lines.join("\n");
}
@@ -278,19 +277,20 @@ export function renderBlockedDependencyComment({
`- ${markdownCode(change.path)} changed ${change.fields.map(markdownCode).join(", ")}.`,
);
}
const removalSteps = lockfileChanges.length > 0
? [
"",
"To remove accidental lockfile residue, restore the lockfile changes from the target branch:",
"",
"```bash",
"git fetch origin",
`git checkout ${baseRef} -- ${lockfileChanges.map(shellQuote).join(" ")}`,
'git commit -m "Remove dependency lockfile change"',
"git push",
"```",
]
: [];
const removalSteps =
lockfileChanges.length > 0
? [
"",
"To remove accidental lockfile residue, restore the lockfile changes from the target branch:",
"",
"```bash",
"git fetch origin",
`git checkout ${baseRef} -- ${lockfileChanges.map(shellQuote).join(" ")}`,
'git commit -m "Remove dependency lockfile change"',
"git push",
"```",
]
: [];
return [
dependencyGraphGuardMarker,
"",
@@ -328,7 +328,9 @@ function githubApi(token) {
return null;
}
if (!response.ok) {
const error = new Error(`${response.status} ${response.statusText}: ${await response.text()}`);
const error = new Error(
`${response.status} ${response.statusText}: ${await response.text()}`,
);
error.status = response.status;
throw error;
}
@@ -477,39 +479,49 @@ async function main() {
if (!labelNames.has(label)) {
return;
}
await api.request(`${issuePath}/labels/${encodeURIComponent(label)}`, {
method: "DELETE",
}).catch(ignoreUnavailableWritePermission(`label "${label}" removal`));
await api
.request(`${issuePath}/labels/${encodeURIComponent(label)}`, {
method: "DELETE",
})
.catch(ignoreUnavailableWritePermission(`label "${label}" removal`));
};
const addLabelIfMissing = async (label) => {
if (labelNames.has(label)) {
return;
}
await api.request(`${issuePath}/labels`, {
method: "POST",
body: JSON.stringify({ labels: [label] }),
}).catch(ignoreUnavailableWritePermission(`label "${label}" update`));
await api
.request(`${issuePath}/labels`, {
method: "POST",
body: JSON.stringify({ labels: [label] }),
})
.catch(ignoreUnavailableWritePermission(`label "${label}" update`));
};
const deleteCommentIfPresent = async (comment) => {
if (!comment) {
return;
}
await api.request(`/repos/${owner}/${repo}/issues/comments/${comment.id}`, {
method: "DELETE",
}).catch(ignoreUnavailableWritePermission("comment deletion"));
await api
.request(`/repos/${owner}/${repo}/issues/comments/${comment.id}`, {
method: "DELETE",
})
.catch(ignoreUnavailableWritePermission("comment deletion"));
};
const upsertComment = async (comment, body) => {
if (comment) {
await api.request(`/repos/${owner}/${repo}/issues/comments/${comment.id}`, {
method: "PATCH",
body: JSON.stringify({ body }),
}).catch(ignoreUnavailableWritePermission("comment update"));
await api
.request(`/repos/${owner}/${repo}/issues/comments/${comment.id}`, {
method: "PATCH",
body: JSON.stringify({ body }),
})
.catch(ignoreUnavailableWritePermission("comment update"));
return;
}
await api.request(`${issuePath}/comments`, {
method: "POST",
body: JSON.stringify({ body }),
}).catch(ignoreUnavailableWritePermission("comment creation"));
await api
.request(`${issuePath}/comments`, {
method: "POST",
body: JSON.stringify({ body }),
})
.catch(ignoreUnavailableWritePermission("comment creation"));
};
if (dependencyGraphFiles.length === 0) {