patchrelay 0.64.0 → 0.65.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
|
@@ -37,7 +37,15 @@ export class LinearSessionSync {
|
|
|
37
37
|
prUrl: syncedIssue.prUrl,
|
|
38
38
|
}
|
|
39
39
|
: syncedIssue;
|
|
40
|
-
|
|
40
|
+
const project = this.config.projects.find((p) => p.id === syncedIssue.projectId);
|
|
41
|
+
await syncActiveWorkflowState({
|
|
42
|
+
db: this.db,
|
|
43
|
+
issue: syncedIssue,
|
|
44
|
+
linear,
|
|
45
|
+
...(trackedIssue ? { trackedIssue } : {}),
|
|
46
|
+
...(options ? { options } : {}),
|
|
47
|
+
...(project ? { project } : {}),
|
|
48
|
+
});
|
|
41
49
|
await this.agentSessions.syncSessionPlan(syncedIssue, linear, options);
|
|
42
50
|
if (shouldSyncVisibleIssueComment(visibleIssue, Boolean(syncedIssue.agentSessionId))) {
|
|
43
51
|
await syncVisibleStatusComment({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { resolvePreferredQueuedLinearState, resolvePreferredCompletedLinearState, resolvePreferredDeployingLinearState, resolvePreferredHumanNeededLinearState, resolvePreferredImplementingLinearState, resolvePreferredReviewLinearState, resolvePreferredReviewingLinearState, } from "./linear-workflow.js";
|
|
1
|
+
import { resolvePreferredQueuedLinearState, resolvePreferredCompletedLinearState, resolvePreferredDeployingLinearState, resolvePreferredDeployLinearState, resolvePreferredHumanNeededLinearState, resolvePreferredImplementingLinearState, resolvePreferredReviewLinearState, resolvePreferredReviewingLinearState, } from "./linear-workflow.js";
|
|
2
|
+
import { resolveMergeQueueProtocol } from "./merge-queue-protocol.js";
|
|
2
3
|
import { isCompletedLinearState } from "./pr-state.js";
|
|
3
4
|
import { hasTrustedNoPrCompletion } from "./trusted-no-pr-completion.js";
|
|
4
5
|
export async function syncActiveWorkflowState(params) {
|
|
5
|
-
const { db, issue, linear, trackedIssue, options } = params;
|
|
6
|
+
const { db, issue, linear, trackedIssue, options, project } = params;
|
|
6
7
|
const liveIssue = await linear.getIssue(issue.linearIssueId).catch(() => undefined);
|
|
7
8
|
if (!liveIssue)
|
|
8
9
|
return;
|
|
@@ -21,6 +22,15 @@ export async function syncActiveWorkflowState(params) {
|
|
|
21
22
|
refreshCachedLinearState(db, issue, liveIssue.stateName, liveIssue.stateType);
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
25
|
+
// Plan §4.6: keep the queued-for-deploy label in sync UNCONDITIONALLY,
|
|
26
|
+
// before the state-equality early-return. When a project lacks an
|
|
27
|
+
// In Deploy state the deploying-Linear-state collapses to the same
|
|
28
|
+
// value as In Review — meaning when an awaiting_queue issue is sitting
|
|
29
|
+
// in the In Review state, the early-return below skips the state
|
|
30
|
+
// write but the label still needs to be added/removed to reflect
|
|
31
|
+
// factoryState. Running first guarantees the label tracks reality
|
|
32
|
+
// even when the state name doesn't change.
|
|
33
|
+
await syncQueuedForDeployLabel({ issue, liveIssue, linear, project }).catch(() => undefined);
|
|
24
34
|
const targetState = resolveDesiredActiveWorkflowState(issue, trackedIssue, options, liveIssue);
|
|
25
35
|
if (!targetState)
|
|
26
36
|
return;
|
|
@@ -32,6 +42,50 @@ export async function syncActiveWorkflowState(params) {
|
|
|
32
42
|
const updated = await linear.setIssueState(issue.linearIssueId, targetState);
|
|
33
43
|
refreshCachedLinearState(db, issue, updated.stateName, updated.stateType);
|
|
34
44
|
}
|
|
45
|
+
// Plan §4.6: when the issue's factoryState says it's In Deploy but the
|
|
46
|
+
// project's Linear workflow has no In Deploy-equivalent state, we want
|
|
47
|
+
// the dashboard to be able to distinguish "in review, awaiting verdict"
|
|
48
|
+
// from "in review, queued for landing". A configurable PR/Linear label
|
|
49
|
+
// (`queuedForDeployLabel`, default `queued-for-deploy`) carries that
|
|
50
|
+
// signal idempotently. The helper computes the desired present/absent
|
|
51
|
+
// state and only calls the API when there's a delta — safe to run on
|
|
52
|
+
// every sync invocation.
|
|
53
|
+
async function syncQueuedForDeployLabel(params) {
|
|
54
|
+
const { issue, liveIssue, linear, project } = params;
|
|
55
|
+
const labelName = resolveMergeQueueProtocol(project).queuedForDeployLabel;
|
|
56
|
+
const want = isQueuedForDeployFallback(issue, liveIssue);
|
|
57
|
+
const currentLabels = (liveIssue.labels ?? [])
|
|
58
|
+
.map((label) => label.name.trim().toLowerCase())
|
|
59
|
+
.filter(Boolean);
|
|
60
|
+
const have = currentLabels.includes(labelName.trim().toLowerCase());
|
|
61
|
+
if (want === have)
|
|
62
|
+
return;
|
|
63
|
+
if (want) {
|
|
64
|
+
await linear.updateIssueLabels({ issueId: issue.linearIssueId, addNames: [labelName] });
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
await linear.updateIssueLabels({ issueId: issue.linearIssueId, removeNames: [labelName] });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// True only when (a) the issue is In Deploy AND (b) the project's
|
|
71
|
+
// Linear workflow has no In Deploy-equivalent state — detected by the
|
|
72
|
+
// preferred-deploying state collapsing to the same name as the
|
|
73
|
+
// preferred-review state. When the project does have a real In Deploy
|
|
74
|
+
// state, `setIssueState` flows the issue there and the label is
|
|
75
|
+
// unnecessary.
|
|
76
|
+
function isQueuedForDeployFallback(issue, liveIssue) {
|
|
77
|
+
if (issue.factoryState !== "awaiting_queue")
|
|
78
|
+
return false;
|
|
79
|
+
const deploying = resolvePreferredDeployingLinearState(liveIssue);
|
|
80
|
+
const review = resolvePreferredReviewLinearState(liveIssue);
|
|
81
|
+
const deployUnstarted = resolvePreferredDeployLinearState(liveIssue);
|
|
82
|
+
if (!deploying || !review)
|
|
83
|
+
return false;
|
|
84
|
+
// No "deploying"/"deploy" state in the workflow → both resolve to
|
|
85
|
+
// a review state. That's the fallback condition.
|
|
86
|
+
return deploying.trim().toLowerCase() === review.trim().toLowerCase()
|
|
87
|
+
&& (deployUnstarted ?? "").trim().toLowerCase() === review.trim().toLowerCase();
|
|
88
|
+
}
|
|
35
89
|
async function syncCompletedLinearState(params) {
|
|
36
90
|
const { db, issue, linear, liveIssue } = params;
|
|
37
91
|
if (isCompletedLinearState(liveIssue.stateType, liveIssue.stateName)) {
|