feat(cli): add branch push check before PR creation
This commit is contained in:
@@ -23,6 +23,8 @@ import type { Config } from "./src/types";
|
|||||||
import {
|
import {
|
||||||
getDefaultBranch,
|
getDefaultBranch,
|
||||||
getBranchName,
|
getBranchName,
|
||||||
|
getBranchPushStatus,
|
||||||
|
pushCurrentBranch,
|
||||||
getBranchCommits,
|
getBranchCommits,
|
||||||
getBranchDiff,
|
getBranchDiff,
|
||||||
detectPlatform,
|
detectPlatform,
|
||||||
@@ -524,6 +526,30 @@ async function handlePR(draft: boolean): Promise<void> {
|
|||||||
` ${commits.length} commit${commits.length > 1 ? "s" : ""} on this branch`,
|
` ${commits.length} commit${commits.length > 1 ? "s" : ""} on this branch`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const pushStatus = await getBranchPushStatus();
|
||||||
|
if (!pushStatus.pushed) {
|
||||||
|
const target = pushStatus.upstream ?? `origin/${branchName}`;
|
||||||
|
const answer = await ask(
|
||||||
|
` Branch is not pushed to ${CYAN}${target}${RESET}. Push now? [${GREEN}Y${RESET}/n] `,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (answer.toLowerCase() === "n") {
|
||||||
|
console.log(" Aborted.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(` Pushing ${CYAN}${branchName}${RESET}...`);
|
||||||
|
try {
|
||||||
|
await pushCurrentBranch(branchName, pushStatus.upstream);
|
||||||
|
console.log(` ${GREEN}Pushed ${branchName}.${RESET}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
` ${RED}Push failed: ${err instanceof Error ? err.message : err}${RESET}`,
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const diff = await getBranchDiff(baseBranch);
|
const diff = await getBranchDiff(baseBranch);
|
||||||
if (!diff) {
|
if (!diff) {
|
||||||
console.error(` ${RED}Error: No diff from base branch.${RESET}`);
|
console.error(` ${RED}Error: No diff from base branch.${RESET}`);
|
||||||
|
|||||||
@@ -25,6 +25,38 @@ export async function getBranchName(): Promise<string> {
|
|||||||
return result.trim();
|
return result.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getBranchPushStatus(): Promise<{
|
||||||
|
pushed: boolean;
|
||||||
|
upstream: string | null;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
const upstream = (await Bun.$`git rev-parse --abbrev-ref --symbolic-full-name @{u}`.quiet().text()).trim();
|
||||||
|
const localHead = (await Bun.$`git rev-parse HEAD`.quiet().text()).trim();
|
||||||
|
const remoteHead = (await Bun.$`git rev-parse @{u}`.quiet().text()).trim();
|
||||||
|
return { pushed: localHead === remoteHead, upstream };
|
||||||
|
} catch {
|
||||||
|
return { pushed: false, upstream: null };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function pushCurrentBranch(branch: string, upstream: string | null): Promise<void> {
|
||||||
|
const args = upstream
|
||||||
|
? ["push"]
|
||||||
|
: ["push", "-u", "origin", branch];
|
||||||
|
|
||||||
|
const proc = Bun.spawn(["git", ...args], {
|
||||||
|
stdout: "pipe",
|
||||||
|
stderr: "pipe",
|
||||||
|
});
|
||||||
|
const exitCode = await proc.exited;
|
||||||
|
const stdout = await new Response(proc.stdout).text();
|
||||||
|
const stderr = await new Response(proc.stderr).text();
|
||||||
|
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
throw new Error(stderr.trim() || stdout.trim() || `git push failed (exit code ${exitCode})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getBranchCommits(base: string): Promise<string[]> {
|
export async function getBranchCommits(base: string): Promise<string[]> {
|
||||||
try {
|
try {
|
||||||
const result =
|
const result =
|
||||||
|
|||||||
Reference in New Issue
Block a user