patchrelay 0.59.0 → 0.60.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/build-info.json
CHANGED
|
@@ -336,6 +336,10 @@ async function evaluateGitHubIssueHealth(snapshot, config, runCommand, reviewQui
|
|
|
336
336
|
if (issue.delegatedToPatchRelay
|
|
337
337
|
&& gateCheckStatus === "failure"
|
|
338
338
|
&& issue.factoryState !== "repairing_ci"
|
|
339
|
+
// Plan §6.1 / §4.3: branch CI failures while In Deploy are
|
|
340
|
+
// metadata only — the lander's spec CI is the gate. Don't flag
|
|
341
|
+
// these as a missing-ci-repair condition.
|
|
342
|
+
&& issue.factoryState !== "awaiting_queue"
|
|
339
343
|
&& issue.activeRunId === undefined
|
|
340
344
|
&& ageMs >= RECONCILIATION_GRACE_MS) {
|
|
341
345
|
return {
|
|
@@ -430,6 +434,7 @@ function buildCiEntry(params) {
|
|
|
430
434
|
const owner = deriveCiOwner({
|
|
431
435
|
delegatedToPatchRelay,
|
|
432
436
|
gateCheckStatus,
|
|
437
|
+
activeRunId: issue.activeRunId,
|
|
433
438
|
factoryState: issue.factoryState,
|
|
434
439
|
reviewDecision,
|
|
435
440
|
reviewRequested,
|
|
@@ -461,6 +466,9 @@ function buildCiEntry(params) {
|
|
|
461
466
|
};
|
|
462
467
|
}
|
|
463
468
|
function deriveCiOwner(params) {
|
|
469
|
+
if (params.activeRunId !== undefined) {
|
|
470
|
+
return "patchrelay";
|
|
471
|
+
}
|
|
464
472
|
const headAdvancedPastBlockingReview = Boolean(params.currentHeadSha
|
|
465
473
|
&& params.latestBlockingReviewHeadSha
|
|
466
474
|
&& params.currentHeadSha !== params.latestBlockingReviewHeadSha);
|
package/dist/factory-state.js
CHANGED
|
@@ -58,9 +58,29 @@ const TRANSITION_RULES = [
|
|
|
58
58
|
{ event: "check_passed",
|
|
59
59
|
guard: (s) => s === "repairing_ci",
|
|
60
60
|
to: (_, ctx) => ctx.prReviewState === "approved" ? "awaiting_queue" : "pr_open" },
|
|
61
|
-
// CI failure when no run is active
|
|
61
|
+
// CI failure when no run is active. Plan §4.3: classification by
|
|
62
|
+
// failureSource determines whether we route to queue or branch repair.
|
|
63
|
+
// While In Deploy (`awaiting_queue`), branch CI failures are metadata
|
|
64
|
+
// only — the lander handles the spec; we don't initiate a ci_repair.
|
|
62
65
|
{ event: "check_failed",
|
|
63
|
-
guard: (s, ctx) => isOpen(s)
|
|
66
|
+
guard: (s, ctx) => isOpen(s)
|
|
67
|
+
&& ctx.activeRunId === undefined
|
|
68
|
+
&& ctx.failureSource === "queue_eviction",
|
|
69
|
+
to: "repairing_queue" },
|
|
70
|
+
{ event: "check_failed",
|
|
71
|
+
guard: (s, ctx) => isOpen(s)
|
|
72
|
+
&& ctx.activeRunId === undefined
|
|
73
|
+
&& ctx.failureSource === "branch_ci"
|
|
74
|
+
&& s !== "awaiting_queue",
|
|
75
|
+
to: "repairing_ci" },
|
|
76
|
+
// Backward-compat fallback for callers that haven't classified the
|
|
77
|
+
// failure (older code paths or test fixtures). Behaves like today's
|
|
78
|
+
// single rule but still skips while In Deploy.
|
|
79
|
+
{ event: "check_failed",
|
|
80
|
+
guard: (s, ctx) => isOpen(s)
|
|
81
|
+
&& ctx.activeRunId === undefined
|
|
82
|
+
&& ctx.failureSource === undefined
|
|
83
|
+
&& s !== "awaiting_queue",
|
|
64
84
|
to: "repairing_ci" },
|
|
65
85
|
// pr_synchronize: no rule → no transition (resets counters only)
|
|
66
86
|
// merge_group events: not used — merge queue is handled by external steward
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { resolveFactoryStateFromGitHub } from "./factory-state.js";
|
|
2
2
|
import { resolveMergeQueueProtocol, } from "./merge-queue-protocol.js";
|
|
3
|
-
import { isIssueTerminal } from "./pr-state.js";
|
|
4
3
|
const DEFAULT_GATE_CHECK_NAMES = ["verify", "tests"];
|
|
5
4
|
/**
|
|
6
5
|
* GitHub sends both check_run and check_suite completion events.
|
|
@@ -84,16 +83,16 @@ export function resolveGitHubFactoryStateForEvent(issue, event, project) {
|
|
|
84
83
|
&& (event.prState === "open" || event.prNumber !== undefined)
|
|
85
84
|
? "pr_open"
|
|
86
85
|
: issue.factoryState;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
86
|
+
// Classify check_failed events so the rule table can route them.
|
|
87
|
+
// The duplicate short-circuit that lived here before is gone — the
|
|
88
|
+
// table now handles queue_eviction via failureSource (plan §4.3).
|
|
89
|
+
const failureSource = event.triggerEvent === "check_failed"
|
|
90
|
+
? (isQueueEvictionFailure(issue, event, project) ? "queue_eviction" : "branch_ci")
|
|
91
|
+
: undefined;
|
|
94
92
|
const resolved = resolveFactoryStateFromGitHub(event.triggerEvent, effectiveCurrentState, {
|
|
95
93
|
prReviewState: issue.prReviewState,
|
|
96
94
|
activeRunId: issue.activeRunId,
|
|
95
|
+
failureSource,
|
|
97
96
|
});
|
|
98
97
|
if (resolved !== undefined) {
|
|
99
98
|
return resolved;
|
|
@@ -49,6 +49,22 @@ export async function maybeEnqueueGitHubReactiveRun(params) {
|
|
|
49
49
|
}
|
|
50
50
|
async function handleCheckFailedEvent(params) {
|
|
51
51
|
const { db, logger, feed, enqueueIssue, issue, event, project, failureContextResolver } = params;
|
|
52
|
+
// Plan §4.3: while In Deploy (`awaiting_queue`), branch CI is metadata
|
|
53
|
+
// only — the lander owns admission, and its spec CI on the integration
|
|
54
|
+
// tree is the gate. Queue eviction failures still flow through (they're
|
|
55
|
+
// how the lander signals a real integration regression).
|
|
56
|
+
if (issue.factoryState === "awaiting_queue" && !isQueueEvictionFailure(issue, event, project)) {
|
|
57
|
+
feed?.publish({
|
|
58
|
+
level: "info",
|
|
59
|
+
kind: "github",
|
|
60
|
+
issueKey: issue.issueKey,
|
|
61
|
+
projectId: issue.projectId,
|
|
62
|
+
stage: issue.factoryState,
|
|
63
|
+
status: "branch_ci_metadata_in_deploy",
|
|
64
|
+
summary: `Ignored ${event.checkName ?? "branch CI"} failure while In Deploy; lander owns admission`,
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
52
68
|
if (isQueueEvictionFailure(issue, event, project)) {
|
|
53
69
|
const queueRepairContext = buildQueueRepairContextFromEvent(event);
|
|
54
70
|
const failureContext = buildGitHubQueueFailureContext(event, project, queueRepairContext);
|
|
@@ -84,6 +84,13 @@ export class InterruptedRunRecovery {
|
|
|
84
84
|
queueRepairAttempts: issue.queueRepairAttempts - 1,
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
+
else if (isRequestedChangesRunType(run.runType) && issue.reviewFixAttempts > 0) {
|
|
88
|
+
this.db.issueSessions.upsertIssueWithLease(lease, {
|
|
89
|
+
projectId: issue.projectId,
|
|
90
|
+
linearIssueId: issue.linearIssueId,
|
|
91
|
+
reviewFixAttempts: issue.reviewFixAttempts - 1,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
87
94
|
if (run.runType === "ci_repair" || run.runType === "queue_repair") {
|
|
88
95
|
this.db.issueSessions.upsertIssueWithLease(lease, {
|
|
89
96
|
projectId: issue.projectId,
|