@tablation/crew 0.75.6 → 0.76.0
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/cli.js +47 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3997,6 +3997,9 @@ function sweepStaleReleaseRoots(tmp, now = Date.now(), maxAgeMs = 60 * 60 * 1e3)
|
|
|
3997
3997
|
function pushBranch(cwd, remote, branch, dst = branch) {
|
|
3998
3998
|
git(cwd, ["push", remote, `${branch}:${dst}`]);
|
|
3999
3999
|
}
|
|
4000
|
+
function pushBranchUpstream(cwd, remote, branch, dst = branch) {
|
|
4001
|
+
git(cwd, ["push", "--set-upstream", remote, `${branch}:${dst}`]);
|
|
4002
|
+
}
|
|
4000
4003
|
function worktrees(cwd) {
|
|
4001
4004
|
const out = gitOk(cwd, ["worktree", "list", "--porcelain"]) ?? "";
|
|
4002
4005
|
const list = [];
|
|
@@ -6989,7 +6992,15 @@ function inspectHandoff(dir, cfg, ticket, role) {
|
|
|
6989
6992
|
}
|
|
6990
6993
|
return { kind: "pushed", branch, sha: origin, remote };
|
|
6991
6994
|
}
|
|
6992
|
-
function
|
|
6995
|
+
function pushableBounce(dir, v) {
|
|
6996
|
+
if (!v.branch || !v.local) return false;
|
|
6997
|
+
return !v.origin || isAncestor(dir, v.origin, v.local);
|
|
6998
|
+
}
|
|
6999
|
+
function describeHandoffPush(dir, cfg, ticket, role) {
|
|
7000
|
+
const v = inspectHandoff(dir, cfg, ticket, role);
|
|
7001
|
+
return v.kind === "bounce" && pushableBounce(dir, v) ? `would push ${v.branch} to ${v.remote}` : null;
|
|
7002
|
+
}
|
|
7003
|
+
function bounceComment(v, shipName2, pushError) {
|
|
6993
7004
|
return `${HANDOFF_BOUNCED_MARKER}
|
|
6994
7005
|
|
|
6995
7006
|
**Hand-off bounced: the branch is not on \`${v.remote}\` at the tip this ticket was built to.**
|
|
@@ -6998,7 +7009,7 @@ ${shipName2 ? `Ship: ${shipName2}
|
|
|
6998
7009
|
` : ""}Local HEAD: ${v.local ? `\`${v.local}\`` : "(no local branch)"}
|
|
6999
7010
|
\`${v.remote}\`: ${v.origin ? `\`${v.origin}\`` : v.branch ? "(branch missing)" : "(no branch to look for)"}
|
|
7000
7011
|
|
|
7001
|
-
${v.reason[0].toUpperCase()}${v.reason.slice(1)}. Set back to \`in_progress\`, still held by this ship; push with a plain \`git push --set-upstream ${v.remote} <branch>\` (never \`--force\`) and set \`fixed\` again. Your brief authorizes this push: it is the hand-off, not a release, so do it now rather than asking for permission.`;
|
|
7012
|
+
${v.reason[0].toUpperCase()}${v.reason.slice(1)}. ${pushError ? ` The runner tried a plain push and git refused it: \`${pushError}\`.` : ""} Set back to \`in_progress\`, still held by this ship; push with a plain \`git push --set-upstream ${v.remote} <branch>\` (never \`--force\`) and set \`fixed\` again. Your brief authorizes this push: it is the hand-off, not a release, so do it now rather than asking for permission.`;
|
|
7002
7013
|
}
|
|
7003
7014
|
async function takenOverSince(i, ticketRow) {
|
|
7004
7015
|
if (!i.since || !i.writer.events) return false;
|
|
@@ -7048,12 +7059,35 @@ async function enforceHandoff(i) {
|
|
|
7048
7059
|
i.log.warn(`${t.issue_id} has no local branch on this ship, so it is not this ship's hand-off to bounce: ${v.reason}`, log);
|
|
7049
7060
|
return { kind: "unverified", why: "no local branch on this ship" };
|
|
7050
7061
|
}
|
|
7062
|
+
let pushError;
|
|
7063
|
+
if (pushableBounce(i.dir, v)) {
|
|
7064
|
+
const wt = worktrees(i.dir).find((w) => w.branch === v.branch);
|
|
7065
|
+
try {
|
|
7066
|
+
pushBranchUpstream(wt?.path ?? i.dir, v.remote, v.branch);
|
|
7067
|
+
const again = inspectHandoff(i.dir, i.cfg, t, i.role);
|
|
7068
|
+
if (again.kind === "pushed") {
|
|
7069
|
+
await i.writer.postEvent(t.id, pushedEventBody(again.sha, again.remote, again.branch), i.seatId, "pushed");
|
|
7070
|
+
await i.writer.postEvent(
|
|
7071
|
+
t.id,
|
|
7072
|
+
`The runner pushed \`${again.branch}\` to \`${again.remote}\` on ${i.shipName ? `${i.shipName}'s` : "this ship's"} behalf: the ${i.role} seat set \`${i.contract.statuses.handoff}\` without pushing. Plain fast-forward push.${i.cfg.hooks.ci_status ? " The repo's `ci_status` hook was NOT run by the hand-off guard, so CI was not checked by the builder." : ""}`,
|
|
7073
|
+
i.seatId,
|
|
7074
|
+
"pushed_by_runner"
|
|
7075
|
+
).catch(() => i.log.warn("pushed, but the note failed to post", log));
|
|
7076
|
+
i.log.emit(`${t.issue_id}: pushed ${again.branch} to ${again.remote} on the seat's behalf at ${again.sha.slice(0, 7)} \u2014 handed on to QA`, log);
|
|
7077
|
+
return { kind: "pushed", sha: again.sha };
|
|
7078
|
+
}
|
|
7079
|
+
pushError = `the push succeeded but ${again.kind === "bounce" ? again.reason : again.why}`;
|
|
7080
|
+
} catch (e) {
|
|
7081
|
+
pushError = e.message;
|
|
7082
|
+
}
|
|
7083
|
+
i.log.warn(`${t.issue_id}: the runner's own push failed: ${pushError}`, log);
|
|
7084
|
+
}
|
|
7051
7085
|
await i.writer.updateTicket(t.id, {
|
|
7052
7086
|
status: i.contract.statuses.building,
|
|
7053
7087
|
...t.assignee_id ? {} : { assignee_id: i.seatId },
|
|
7054
7088
|
...i.hold && !heldBy ? { [i.hold.column]: i.hold.shipId } : {}
|
|
7055
7089
|
});
|
|
7056
|
-
await i.writer.postEvent(t.id, bounceComment(v, i.shipName), i.seatId, "bounced").catch(() => {
|
|
7090
|
+
await i.writer.postEvent(t.id, bounceComment(v, i.shipName, pushError), i.seatId, "bounced").catch(() => {
|
|
7057
7091
|
i.log.warn("bounced, but the note failed to post", log);
|
|
7058
7092
|
});
|
|
7059
7093
|
i.log.warn(`${t.issue_id} bounced back to ${i.contract.statuses.building}: ${v.reason}`, log);
|
|
@@ -18250,6 +18284,16 @@ ${changed2.map((c) => ` - ${c}
|
|
|
18250
18284
|
if (dryRun) {
|
|
18251
18285
|
process.stdout.write(`${describePlan(plan)}
|
|
18252
18286
|
`);
|
|
18287
|
+
if (workingId && (current === "dev" || current === "design")) {
|
|
18288
|
+
try {
|
|
18289
|
+
const t = await tracker2.ticket(workingId);
|
|
18290
|
+
const r = repoConfigFor(route, t);
|
|
18291
|
+
const would = r && describeHandoffPush(r.target.dir, r.cfg, t, current);
|
|
18292
|
+
if (would) process.stdout.write(`${would}
|
|
18293
|
+
`);
|
|
18294
|
+
} catch {
|
|
18295
|
+
}
|
|
18296
|
+
}
|
|
18253
18297
|
break;
|
|
18254
18298
|
}
|
|
18255
18299
|
const before = snapshot(await tracker2.openTickets());
|
package/package.json
CHANGED