@botbuddy/cli 1.6.1 → 1.6.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/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schema_version":1,"source_version":"1.6.1","source_identity":"9cc6a78baeb0da589214386daad729a2e8909936a2407da801777f9902e8667f"}
|
package/src/wait-core.mjs
CHANGED
|
@@ -228,6 +228,35 @@ const VALIDATORS = {
|
|
|
228
228
|
}
|
|
229
229
|
return { repo };
|
|
230
230
|
},
|
|
231
|
+
// BOT-1458 — staging-release: wake when the first staging release train whose
|
|
232
|
+
// head commit CONTAINS this PR's merge commit reaches a terminal conclusion
|
|
233
|
+
// (success OR failure). Unlike `staging-green` this is PR-scoped and reports
|
|
234
|
+
// the train's outcome, never a health verdict. Inclusion is decided server-side
|
|
235
|
+
// by git ancestry (GitHub compare API), never by wall-clock ordering, so the
|
|
236
|
+
// condition only names the repo + PR; the relay stamps the resolved
|
|
237
|
+
// merge_commit_sha and workspace at registration. Optional
|
|
238
|
+
// `after_run=<run_id>[:<attempt>]` lets a wait re-armed from a failure receipt
|
|
239
|
+
// skip the run it already saw and park for the NEXT train.
|
|
240
|
+
"staging-release"(p) {
|
|
241
|
+
const { repo, number } = parsePrTarget(p, "staging-release");
|
|
242
|
+
if (number == null) {
|
|
243
|
+
throw new Error("staging-release needs pr=<number> (or pr=<owner/repo#number>)");
|
|
244
|
+
}
|
|
245
|
+
const out = { repo, pr: number };
|
|
246
|
+
if (p.after_run !== undefined) {
|
|
247
|
+
const raw = String(p.after_run).trim();
|
|
248
|
+
const m = /^(\d+)(?::(\d+))?$/.exec(raw);
|
|
249
|
+
if (!m) throw new Error("staging-release after_run must be <run_id>[:<attempt>]");
|
|
250
|
+
out.afterRunId = m[1];
|
|
251
|
+
if (m[2] !== undefined) out.afterRunAttempt = Number(m[2]);
|
|
252
|
+
}
|
|
253
|
+
const allowed = new Set(["repo", "pr", "number", "after_run"]);
|
|
254
|
+
const extras = Object.keys(p).filter((key) => !allowed.has(key));
|
|
255
|
+
if (extras.length > 0) {
|
|
256
|
+
throw new Error(`staging-release accepts only repo=<owner/repo>, pr=<number>, after_run=<run_id>[:<attempt>] (got: ${extras.join(", ")})`);
|
|
257
|
+
}
|
|
258
|
+
return out;
|
|
259
|
+
},
|
|
231
260
|
// BOT-1247 — unblocked: wake when a ticket's LAST open blocker clears (its
|
|
232
261
|
// open-blocker count transitions >0 → 0). Level-triggered: a ticket already
|
|
233
262
|
// unblocked (or never blocked) at registration is granted immediately with
|
|
@@ -666,6 +695,27 @@ function conditionMatchesSignal(condition, signal, waitSessionId) {
|
|
|
666
695
|
payload.gate_open === false &&
|
|
667
696
|
payload.operational_status === "healthy";
|
|
668
697
|
}
|
|
698
|
+
case "staging-release": {
|
|
699
|
+
// BOT-1458: a PR-scoped staging release train reached a terminal conclusion
|
|
700
|
+
// and its head commit contains this PR's merge (`includes_pr:true`, decided
|
|
701
|
+
// server-side by ancestry). The signal is tenant-scoped, so the central
|
|
702
|
+
// guard already fenced foreign workspaces. Subject is `<owner/repo>#<pr>`.
|
|
703
|
+
if (signal.signal_type !== "staging_release") return false;
|
|
704
|
+
const payload = signal.payload ?? {};
|
|
705
|
+
const subject = typeof signal.subject_key === "string" ? signal.subject_key.toLowerCase() : "";
|
|
706
|
+
if (subject !== `${params.repo}#${params.pr}`.toLowerCase()) return false;
|
|
707
|
+
if (payload.includes_pr !== true) return false;
|
|
708
|
+
// AC-9: a wait re-armed with after_run ignores the run it already saw — that
|
|
709
|
+
// run id, and (when an attempt was named) that attempt or lower — so a
|
|
710
|
+
// re-registration after a failure receipt parks for the NEXT train instead
|
|
711
|
+
// of instantly replaying the same failure via `--since`.
|
|
712
|
+
if (params.afterRunId != null && String(payload.workflow_run_id) === String(params.afterRunId)) {
|
|
713
|
+
if (params.afterRunAttempt == null) return false;
|
|
714
|
+
const attempt = Number(payload.workflow_run_attempt);
|
|
715
|
+
if (Number.isFinite(attempt) && attempt <= params.afterRunAttempt) return false;
|
|
716
|
+
}
|
|
717
|
+
return true;
|
|
718
|
+
}
|
|
669
719
|
case "unblocked": {
|
|
670
720
|
// Wakes on the ticket_unblocked spine signal for this ticket (the server emits both
|
|
671
721
|
// the genuine >0→0 transition and the level-triggered `already_unblocked` echo).
|