feat(lanes): let Add Lane choose the pipeline template
Creation is the only point the UI could ever set a lane's template, and it never offered the choice — so every lane added from "+ Add lane" was born on `default` and rendered an 8-node map for a 16-node workflow, with no screen able to change it afterwards. That is the defect that made the ship-feature template unreachable from the browser. The modal now shows a *Pipeline template* select fed by `GET /api/lanes/pipelines`, labelled with each template's node count so the consequence of the choice is visible. A failed fetch degrades to a `default` option rather than blocking lane creation. `pipeline` was already accepted by `POST /api/lanes` but silently dropped by `/ensure` and `/worktree`, which build their own createLane payloads; both now pass it through, and both map `EBADPIPELINE` to 400 like `EBADCWD`.
This commit is contained in:
@@ -161,11 +161,15 @@ router.post("/ensure", sameOriginGuard, (req, res) => {
|
||||
const owner = lanesLib.resolveLaneByCwd(body.cwd);
|
||||
if (owner) return res.json({ lane: payload(owner), created: false });
|
||||
try {
|
||||
const lane = lanesLib.createLane({ cwd: body.cwd, title: body.title || "" });
|
||||
const lane = lanesLib.createLane({
|
||||
cwd: body.cwd,
|
||||
title: body.title || "",
|
||||
...(body.pipeline ? { pipeline: body.pipeline } : {}),
|
||||
});
|
||||
broadcastLane(lane.id);
|
||||
return res.status(201).json({ lane: payload(lane), created: true });
|
||||
} catch (err) {
|
||||
if (err.code === "EBADCWD") {
|
||||
if (err.code === "EBADCWD" || err.code === "EBADPIPELINE") {
|
||||
return res.status(400).json({ error: { code: err.code, message: err.message } });
|
||||
}
|
||||
// The cwd UNIQUE constraint is the arbiter: someone else won the race, so
|
||||
@@ -248,7 +252,7 @@ router.post("/", sameOriginGuard, (req, res) => {
|
||||
broadcastLane(lane.id);
|
||||
res.status(201).json({ lane: payload(lane) });
|
||||
} catch (err) {
|
||||
if (err.code === "EBADCWD") {
|
||||
if (err.code === "EBADCWD" || err.code === "EBADPIPELINE" || err.code === "EBADKIND") {
|
||||
return res.status(400).json({ error: { code: err.code, message: err.message } });
|
||||
}
|
||||
if (err.code === "SQLITE_CONSTRAINT_UNIQUE" || String(err.message).includes("UNIQUE")) {
|
||||
@@ -569,6 +573,7 @@ router.post("/worktree", sameOriginGuard, async (req, res) => {
|
||||
source_repo: resolvedSourceRepo,
|
||||
base_branch: body.base || null,
|
||||
slug,
|
||||
...(body.pipeline ? { pipeline: body.pipeline } : {}),
|
||||
});
|
||||
lane = lanesLib.updateLane(lane.id, { status: "provisioning" });
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user