merge-steward 0.9.4 → 0.9.5

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.
@@ -52,7 +52,7 @@ export async function reconcile(ctx) {
52
52
  });
53
53
  await cleanupSpec(ctx, entry);
54
54
  ctx.store.transition(entry.id, "preparing_head", {
55
- ...CLEAN_CI, ...CLEAN_SPEC,
55
+ ...CLEAN_CI, ...CLEAN_SPEC, retryAttempts: 0, lastFailedBaseSha: null,
56
56
  }, `stale dependency ${dep?.status ?? "removed"}`);
57
57
  continue;
58
58
  }
@@ -151,7 +151,7 @@ async function prepareEntry(ctx, entry, isHead, prevEntry) {
151
151
  // Gate: main CI must be green.
152
152
  if (ctx.ci.getMainStatus) {
153
153
  const mainStatus = await ctx.ci.getMainStatus(ctx.baseBranch);
154
- if (mainStatus === "fail") {
154
+ if (mainStatus !== "pass") {
155
155
  let mainChecks = [];
156
156
  try {
157
157
  mainChecks = await ctx.github.listChecksForRef(ref(ctx, ctx.baseBranch));
@@ -368,6 +368,15 @@ async function mergeHead(ctx, entry) {
368
368
  catch {
369
369
  // Can't verify — proceed and let push fail if needed.
370
370
  }
371
+ // Final main health check — don't push to a broken main.
372
+ if (ctx.ci.getMainStatus) {
373
+ const mainStatus = await ctx.ci.getMainStatus(ctx.baseBranch);
374
+ if (mainStatus !== "pass") {
375
+ emit(ctx, entry, "main_broken", { detail: "main unhealthy at merge time, re-preparing" });
376
+ ctx.store.transition(entry.id, "preparing_head", { ...CLEAN_CI, ...CLEAN_SPEC }, "main unhealthy at merge time");
377
+ return;
378
+ }
379
+ }
371
380
  // Push the spec branch to main (fast-forward).
372
381
  try {
373
382
  await ctx.git.push(entry.specBranch, false, ctx.baseBranch);
@@ -406,7 +415,7 @@ async function invalidateDownstream(ctx, allActive, afterIndex) {
406
415
  continue;
407
416
  emit(ctx, downstream, "invalidated", { detail: `base changed after position ${afterIndex}` });
408
417
  await cleanupSpec(ctx, downstream);
409
- ctx.store.transition(downstream.id, "preparing_head", { ...CLEAN_CI, ...CLEAN_SPEC }, "invalidated: base changed");
418
+ ctx.store.transition(downstream.id, "preparing_head", { ...CLEAN_CI, ...CLEAN_SPEC, retryAttempts: 0, lastFailedBaseSha: null }, "invalidated: base changed");
410
419
  }
411
420
  }
412
421
  async function cleanupSpec(ctx, entry) {
package/dist/service.js CHANGED
@@ -291,9 +291,13 @@ export class MergeStewardService {
291
291
  continue;
292
292
  if (TERMINAL_STATUSES.includes(downstream.status))
293
293
  continue;
294
+ if (downstream.specBranch) {
295
+ this.specBuilder.deleteSpeculative(downstream.specBranch).catch(() => { });
296
+ }
294
297
  this.store.transition(downstream.id, "preparing_head", {
295
298
  ciRunId: null, ciRetries: 0,
296
299
  specBranch: null, specSha: null, specBasedOn: null,
300
+ retryAttempts: 0, lastFailedBaseSha: null,
297
301
  }, `invalidated: entry ${removedEntry.id.slice(0, 8)} dequeued`);
298
302
  invalidated++;
299
303
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "merge-steward",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Serial merge queue for GitHub — rebase, CI-gate, and merge PRs one at a time",
5
5
  "type": "module",
6
6
  "repository": {