feat(lanes): add ccam lanes sync-base CLI (E2)
This commit is contained in:
+71
-1
@@ -1900,6 +1900,71 @@ async function cmdLanesRuntime(sub, args) {
|
||||
`lane #${laneId} running hook ${name} — follow it with: ccam lanes logs ${laneId} ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
if (sub === "sync-base") {
|
||||
const mode = laneArgs.includes("--check")
|
||||
? "check"
|
||||
: laneArgs.includes("--continue")
|
||||
? "continue"
|
||||
: "merge";
|
||||
const branch = laneArgs.find((arg) => !arg.startsWith("--"));
|
||||
const result = await post(
|
||||
`/api/lanes/${laneId}/sync-base`,
|
||||
{ mode, branch },
|
||||
{ allowError: true }
|
||||
);
|
||||
if (result.status) {
|
||||
console.error(`✖ sync-base → ${result.data?.error?.message || result.status}`);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.code === 5) {
|
||||
console.error(`✖ lane #${laneId} — MIGRATION NUMBER COLLISION (nothing merged):`);
|
||||
for (const c of result.collisions) {
|
||||
console.error(` ${c.file} collides with ${c.collidesWith} — rename to ${c.suggestion}`);
|
||||
}
|
||||
process.exitCode = 5;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.code === 4) {
|
||||
console.error(`✖ lane #${laneId} — MERGE CONFLICT (left in place).`);
|
||||
console.error(` conflicted: ${result.conflictedFiles.join(", ")}`);
|
||||
console.error(" resolve, then: git add <resolved files> && git commit --no-edit");
|
||||
console.error(
|
||||
` then: ccam lanes sync-base --continue ${branch ? branch + " " : ""}${laneId}`
|
||||
);
|
||||
process.exitCode = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === "check") {
|
||||
if (result.devDelta === null) {
|
||||
console.log("DEV_DELTA: unknown (no merge-base with origin/development)");
|
||||
} else {
|
||||
console.log(
|
||||
`DEV_DELTA: ${result.devDelta.length} file(s) changed on origin/development since merge-base`
|
||||
);
|
||||
for (const f of result.devDelta) console.log(` ${f}`);
|
||||
if (result.overlap.length) {
|
||||
console.log(
|
||||
`DEV_OVERLAP: ${result.overlap.length} file(s) — the upstream delta touches the feature's files:`
|
||||
);
|
||||
for (const f of result.overlap) console.log(` ${f}`);
|
||||
} else {
|
||||
console.log("DEV_OVERLAP: none");
|
||||
}
|
||||
}
|
||||
console.log(`lane #${laneId} preflight vs origin/development: OK`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`lane #${laneId} — synced with origin/development (re-enter the pipeline at the gates)`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2266,6 +2331,11 @@ const COMMAND_GROUPS = [
|
||||
["lanes runtime", "[<id>]", "Slot, ports, service health and the last boot error"],
|
||||
["lanes logs", "[<id>] <svc> [--tail N]", "Tail one of the lane's hook or service logs"],
|
||||
["lanes hook", "[<id>] <name> [args…]", "Run a profile hook (ci-gate, e2e, migrate, …)"],
|
||||
[
|
||||
"lanes sync-base",
|
||||
"[<id>] [--check|--continue] [branch]",
|
||||
"Fetch + migration-collision preflight, or merge origin/development into the feature branch (--check: read-only; --continue: finish after a resolved conflict; bare: merge, branch defaults to the lane's current branch)",
|
||||
],
|
||||
[
|
||||
"lanes proof-link",
|
||||
"[<id>]",
|
||||
@@ -3085,7 +3155,7 @@ async function runCommand(argv) {
|
||||
if (["reset", "remove", "purge"].includes(rest[0])) {
|
||||
return cmdLanesLifecycle(rest[0], rest.slice(1));
|
||||
}
|
||||
if (["up", "down", "runtime", "logs", "hook"].includes(rest[0])) {
|
||||
if (["up", "down", "runtime", "logs", "hook", "sync-base"].includes(rest[0])) {
|
||||
return cmdLanesRuntime(rest[0], rest.slice(1));
|
||||
}
|
||||
if (rest[0] === "proof-link") return cmdLanesProofLink(rest.slice(1));
|
||||
|
||||
Reference in New Issue
Block a user