feat(gsd): create draft PR on milestone completion when git.auto_pr enabled (#1627)
Adds createDraftPR() to git-service.ts and hooks it into the milestone transition block in auto-loop.ts. Best-effort, non-fatal on failure. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
70cf14f72d
commit
1d3e3ee46b
2 changed files with 79 additions and 0 deletions
|
|
@ -840,6 +840,25 @@ export async function autoLoop(
|
|||
|
||||
// Worktree lifecycle on milestone transition — merge current, enter next
|
||||
deps.resolver.mergeAndExit(s.currentMilestoneId!, ctx.ui);
|
||||
|
||||
// Opt-in: create draft PR on milestone completion
|
||||
if (prefs?.git?.auto_pr) {
|
||||
try {
|
||||
const { createDraftPR } = await import("./git-service.js");
|
||||
const prUrl = createDraftPR(
|
||||
s.basePath,
|
||||
s.currentMilestoneId!,
|
||||
`[GSD] ${s.currentMilestoneId} complete`,
|
||||
`Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
|
||||
);
|
||||
if (prUrl) {
|
||||
ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
|
||||
}
|
||||
} catch {
|
||||
// Non-fatal — PR creation is best-effort
|
||||
}
|
||||
}
|
||||
|
||||
deps.invalidateAllCaches();
|
||||
|
||||
state = await deps.deriveState(s.basePath);
|
||||
|
|
@ -893,6 +912,24 @@ export async function autoLoop(
|
|||
// All milestones complete — merge milestone branch before stopping
|
||||
if (s.currentMilestoneId) {
|
||||
deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
|
||||
|
||||
// Opt-in: create draft PR on milestone completion
|
||||
if (prefs?.git?.auto_pr) {
|
||||
try {
|
||||
const { createDraftPR } = await import("./git-service.js");
|
||||
const prUrl = createDraftPR(
|
||||
s.basePath,
|
||||
s.currentMilestoneId,
|
||||
`[GSD] ${s.currentMilestoneId} complete`,
|
||||
`Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
|
||||
);
|
||||
if (prUrl) {
|
||||
ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
|
||||
}
|
||||
} catch {
|
||||
// Non-fatal — PR creation is best-effort
|
||||
}
|
||||
}
|
||||
}
|
||||
deps.sendDesktopNotification(
|
||||
"GSD",
|
||||
|
|
@ -974,6 +1011,24 @@ export async function autoLoop(
|
|||
// Milestone merge on complete (before closeout so branch state is clean)
|
||||
if (s.currentMilestoneId) {
|
||||
deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
|
||||
|
||||
// Opt-in: create draft PR on milestone completion
|
||||
if (prefs?.git?.auto_pr) {
|
||||
try {
|
||||
const { createDraftPR } = await import("./git-service.js");
|
||||
const prUrl = createDraftPR(
|
||||
s.basePath,
|
||||
s.currentMilestoneId,
|
||||
`[GSD] ${s.currentMilestoneId} complete`,
|
||||
`Milestone ${s.currentMilestoneId} completed by GSD auto-mode.\n\nSee .gsd/${s.currentMilestoneId}/ for details.`,
|
||||
);
|
||||
if (prUrl) {
|
||||
ctx.ui.notify(`Draft PR created: ${prUrl}`, "info");
|
||||
}
|
||||
} catch {
|
||||
// Non-fatal — PR creation is best-effort
|
||||
}
|
||||
}
|
||||
}
|
||||
deps.sendDesktopNotification(
|
||||
"GSD",
|
||||
|
|
|
|||
|
|
@ -584,6 +584,30 @@ export class GitServiceImpl {
|
|||
|
||||
}
|
||||
|
||||
// ─── Draft PR Creation ─────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Create a draft pull request for a completed milestone using `gh pr create`.
|
||||
* Returns the PR URL on success, or null on failure.
|
||||
* Non-fatal: callers should treat failure as best-effort.
|
||||
*/
|
||||
export function createDraftPR(
|
||||
basePath: string,
|
||||
milestoneId: string,
|
||||
title: string,
|
||||
body: string,
|
||||
): string | null {
|
||||
try {
|
||||
const result = execSync(
|
||||
`gh pr create --draft --title ${JSON.stringify(title)} --body ${JSON.stringify(body)}`,
|
||||
{ cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV },
|
||||
);
|
||||
return result.trim();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Factory ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** Create a GitServiceImpl with the current effective git preferences. */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue