@snappedly-tools/shipyard 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +28 -26
- package/dist/main.js.map +1 -1
- package/dist/templates/parallel-planner/main.mts +5 -1
- package/dist/templates/parallel-planner/planner-branch.mts +40 -0
- package/dist/templates/parallel-planner-with-review/main.mts +5 -1
- package/dist/templates/parallel-planner-with-review/planner-branch.mts +40 -0
- package/package.json +1 -1
|
@@ -5,7 +5,10 @@ import { existsSync } from "node:fs";
|
|
|
5
5
|
import * as shipyard from "@snappedly-tools/shipyard";
|
|
6
6
|
import { docker } from "@snappedly-tools/shipyard/sandboxes/docker";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
fastForwardPlannerBranch,
|
|
10
|
+
resolvePlannerBranch,
|
|
11
|
+
} from "./planner-branch.mjs";
|
|
9
12
|
|
|
10
13
|
if (process.loadEnvFile && existsSync(".shipyard/.env"))
|
|
11
14
|
process.loadEnvFile(".shipyard/.env");
|
|
@@ -205,6 +208,7 @@ for (let iteration = 0; iteration < 10; iteration++) {
|
|
|
205
208
|
.split(/\r?\n/)
|
|
206
209
|
.filter(Boolean);
|
|
207
210
|
const plannerBranch = await resolvePlannerBranch(localBranches);
|
|
211
|
+
fastForwardPlannerBranch(plannerBranch, targetBranch);
|
|
208
212
|
const plan = await shipyard.run({
|
|
209
213
|
hooks,
|
|
210
214
|
sandbox: sandboxProvider,
|
|
@@ -52,6 +52,46 @@ const reusablePlannerBranch = (
|
|
|
52
52
|
)?.branch;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
/** Keep a reused planner branch current without discarding its own commits. */
|
|
56
|
+
export const fastForwardPlannerBranch = (
|
|
57
|
+
plannerBranch: string,
|
|
58
|
+
targetBranch: string,
|
|
59
|
+
repoDir = process.cwd(),
|
|
60
|
+
): void => {
|
|
61
|
+
if (plannerBranch === targetBranch) return;
|
|
62
|
+
let plannerHead: string;
|
|
63
|
+
try {
|
|
64
|
+
plannerHead = execFileSync(
|
|
65
|
+
"git",
|
|
66
|
+
["rev-parse", "--verify", `refs/heads/${plannerBranch}`],
|
|
67
|
+
{ cwd: repoDir, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
68
|
+
).trim();
|
|
69
|
+
} catch {
|
|
70
|
+
return; // WorktreeManager creates a new planner branch from HEAD.
|
|
71
|
+
}
|
|
72
|
+
const targetHead = execFileSync(
|
|
73
|
+
"git",
|
|
74
|
+
["rev-parse", "--verify", `refs/heads/${targetBranch}`],
|
|
75
|
+
{ cwd: repoDir, encoding: "utf8" },
|
|
76
|
+
).trim();
|
|
77
|
+
if (plannerHead === targetHead) return;
|
|
78
|
+
try {
|
|
79
|
+
execFileSync(
|
|
80
|
+
"git",
|
|
81
|
+
["merge-base", "--is-ancestor", plannerHead, targetHead],
|
|
82
|
+
{ cwd: repoDir, stdio: "ignore" },
|
|
83
|
+
);
|
|
84
|
+
} catch {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Planner branch '${plannerBranch}' has commits outside '${targetBranch}'. Review and integrate them before restarting Shipyard.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
execFileSync("git", ["branch", "-f", plannerBranch, targetHead], {
|
|
90
|
+
cwd: repoDir,
|
|
91
|
+
stdio: "ignore",
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
55
95
|
export const resolvePlannerBranch = async (
|
|
56
96
|
localBranches: readonly string[],
|
|
57
97
|
options: {
|
|
@@ -5,7 +5,10 @@ import { existsSync } from "node:fs";
|
|
|
5
5
|
import * as shipyard from "@snappedly-tools/shipyard";
|
|
6
6
|
import { docker } from "@snappedly-tools/shipyard/sandboxes/docker";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
fastForwardPlannerBranch,
|
|
10
|
+
resolvePlannerBranch,
|
|
11
|
+
} from "./planner-branch.mjs";
|
|
9
12
|
|
|
10
13
|
if (process.loadEnvFile && existsSync(".shipyard/.env"))
|
|
11
14
|
process.loadEnvFile(".shipyard/.env");
|
|
@@ -228,6 +231,7 @@ for (let iteration = 0; iteration < 10; iteration++) {
|
|
|
228
231
|
.split(/\r?\n/)
|
|
229
232
|
.filter(Boolean);
|
|
230
233
|
const plannerBranch = await resolvePlannerBranch(localBranches);
|
|
234
|
+
fastForwardPlannerBranch(plannerBranch, targetBranch);
|
|
231
235
|
const plan = await shipyard.run({
|
|
232
236
|
hooks,
|
|
233
237
|
sandbox: sandboxProvider,
|
|
@@ -52,6 +52,46 @@ const reusablePlannerBranch = (
|
|
|
52
52
|
)?.branch;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
/** Keep a reused planner branch current without discarding its own commits. */
|
|
56
|
+
export const fastForwardPlannerBranch = (
|
|
57
|
+
plannerBranch: string,
|
|
58
|
+
targetBranch: string,
|
|
59
|
+
repoDir = process.cwd(),
|
|
60
|
+
): void => {
|
|
61
|
+
if (plannerBranch === targetBranch) return;
|
|
62
|
+
let plannerHead: string;
|
|
63
|
+
try {
|
|
64
|
+
plannerHead = execFileSync(
|
|
65
|
+
"git",
|
|
66
|
+
["rev-parse", "--verify", `refs/heads/${plannerBranch}`],
|
|
67
|
+
{ cwd: repoDir, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
68
|
+
).trim();
|
|
69
|
+
} catch {
|
|
70
|
+
return; // WorktreeManager creates a new planner branch from HEAD.
|
|
71
|
+
}
|
|
72
|
+
const targetHead = execFileSync(
|
|
73
|
+
"git",
|
|
74
|
+
["rev-parse", "--verify", `refs/heads/${targetBranch}`],
|
|
75
|
+
{ cwd: repoDir, encoding: "utf8" },
|
|
76
|
+
).trim();
|
|
77
|
+
if (plannerHead === targetHead) return;
|
|
78
|
+
try {
|
|
79
|
+
execFileSync(
|
|
80
|
+
"git",
|
|
81
|
+
["merge-base", "--is-ancestor", plannerHead, targetHead],
|
|
82
|
+
{ cwd: repoDir, stdio: "ignore" },
|
|
83
|
+
);
|
|
84
|
+
} catch {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Planner branch '${plannerBranch}' has commits outside '${targetBranch}'. Review and integrate them before restarting Shipyard.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
execFileSync("git", ["branch", "-f", plannerBranch, targetHead], {
|
|
90
|
+
cwd: repoDir,
|
|
91
|
+
stdio: "ignore",
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
55
95
|
export const resolvePlannerBranch = async (
|
|
56
96
|
localBranches: readonly string[],
|
|
57
97
|
options: {
|