@h-rig/core 0.0.6-alpha.155 → 0.0.6-alpha.156
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/src/config.d.ts +1 -1
- package/dist/src/config.js +4 -91
- package/dist/src/define-plugin.d.ts +11 -7
- package/dist/src/define-plugin.js +4 -91
- package/dist/src/index.d.ts +1 -11
- package/dist/src/index.js +33 -3704
- package/dist/src/plugin-host.d.ts +25 -18
- package/dist/src/plugin-host.js +28 -149
- package/dist/src/plugin-runtime.d.ts +82 -51
- package/dist/src/project-plugins.d.ts +66 -0
- package/dist/src/project-plugins.js +596 -0
- package/dist/src/task-io.d.ts +54 -0
- package/dist/src/task-io.js +707 -0
- package/package.json +8 -20
- package/dist/src/dependencyGraph.d.ts +0 -43
- package/dist/src/dependencyGraph.js +0 -703
- package/dist/src/engineReadModelReducer.d.ts +0 -12
- package/dist/src/engineReadModelReducer.js +0 -1784
- package/dist/src/rig-init-builder.d.ts +0 -30
- package/dist/src/rig-init-builder.js +0 -61
- package/dist/src/rigSelectors.d.ts +0 -220
- package/dist/src/rigSelectors.js +0 -414
- package/dist/src/rollups.d.ts +0 -6
- package/dist/src/rollups.js +0 -377
- package/dist/src/stageResolve.d.ts +0 -77
- package/dist/src/stageResolve.js +0 -361
- package/dist/src/taskGraph.d.ts +0 -64
- package/dist/src/taskGraph.js +0 -377
- package/dist/src/taskGraphCodes.d.ts +0 -3
- package/dist/src/taskGraphCodes.js +0 -26
- package/dist/src/taskGraphLayout.d.ts +0 -61
- package/dist/src/taskGraphLayout.js +0 -397
- package/dist/src/taskScore.d.ts +0 -17
- package/dist/src/taskScore.js +0 -49
package/dist/src/rollups.js
DELETED
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// packages/core/src/rollups.ts
|
|
3
|
-
import { isOperatorActiveRunStatus } from "@rig/contracts";
|
|
4
|
-
|
|
5
|
-
// packages/core/src/rigSelectors.ts
|
|
6
|
-
function isObjectRecord(value) {
|
|
7
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
-
}
|
|
9
|
-
function normalizeLogin(value) {
|
|
10
|
-
return value.trim().replace(/^@+/, "").toLowerCase();
|
|
11
|
-
}
|
|
12
|
-
function assigneeLoginsFromValue(value) {
|
|
13
|
-
if (!Array.isArray(value))
|
|
14
|
-
return [];
|
|
15
|
-
return value.flatMap((entry) => {
|
|
16
|
-
if (typeof entry === "string" && entry.trim())
|
|
17
|
-
return [normalizeLogin(entry)];
|
|
18
|
-
if (isObjectRecord(entry) && typeof entry.login === "string" && entry.login.trim()) {
|
|
19
|
-
return [normalizeLogin(entry.login)];
|
|
20
|
-
}
|
|
21
|
-
return [];
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function readTaskAssigneeLogins(task) {
|
|
25
|
-
const taskRecord = task;
|
|
26
|
-
const metadata = isObjectRecord(task.metadata) ? task.metadata : null;
|
|
27
|
-
const raw = isObjectRecord(metadata?.raw) ? metadata.raw : null;
|
|
28
|
-
return Array.from(new Set([
|
|
29
|
-
...assigneeLoginsFromValue(taskRecord.assignees),
|
|
30
|
-
...assigneeLoginsFromValue(metadata?.assignees),
|
|
31
|
-
...assigneeLoginsFromValue(raw?.assignees)
|
|
32
|
-
]));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// packages/core/src/taskGraph.ts
|
|
36
|
-
function isObjectRecord2(value) {
|
|
37
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38
|
-
}
|
|
39
|
-
function readStringList(value) {
|
|
40
|
-
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.length > 0) : [];
|
|
41
|
-
}
|
|
42
|
-
function unique(values) {
|
|
43
|
-
return Array.from(new Set(values));
|
|
44
|
-
}
|
|
45
|
-
function readTaskMetadataStringList(task, key) {
|
|
46
|
-
const taskRecord = task;
|
|
47
|
-
const topLevel = readStringList(taskRecord[key]);
|
|
48
|
-
if (topLevel.length > 0)
|
|
49
|
-
return topLevel;
|
|
50
|
-
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
51
|
-
const metadataList = readStringList(metadata?.[key]);
|
|
52
|
-
if (metadataList.length > 0)
|
|
53
|
-
return metadataList;
|
|
54
|
-
if (key === "dependencies") {
|
|
55
|
-
return readStringList(metadata?.deps);
|
|
56
|
-
}
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
function readTaskBlockingDependencyRefs(task) {
|
|
60
|
-
return readTaskMetadataStringList(task, "dependencies");
|
|
61
|
-
}
|
|
62
|
-
function readTaskSourceIssueId(task) {
|
|
63
|
-
if (typeof task.sourceIssueId === "string" && task.sourceIssueId.length > 0) {
|
|
64
|
-
return task.sourceIssueId;
|
|
65
|
-
}
|
|
66
|
-
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
67
|
-
if (typeof metadata?.sourceIssueId === "string" && metadata.sourceIssueId.length > 0) {
|
|
68
|
-
return metadata.sourceIssueId;
|
|
69
|
-
}
|
|
70
|
-
const rigMetadata = isObjectRecord2(metadata?._rig) ? metadata._rig : null;
|
|
71
|
-
return typeof rigMetadata?.sourceIssueId === "string" && rigMetadata.sourceIssueId.length > 0 ? rigMetadata.sourceIssueId : null;
|
|
72
|
-
}
|
|
73
|
-
function resolveTaskReference(ref, tasksById, taskIdByExternalRef, taskIdBySourceIssueId) {
|
|
74
|
-
if (tasksById.has(ref))
|
|
75
|
-
return ref;
|
|
76
|
-
return taskIdBySourceIssueId.get(ref) ?? taskIdByExternalRef.get(ref) ?? null;
|
|
77
|
-
}
|
|
78
|
-
function buildTaskReferenceIndex(tasks) {
|
|
79
|
-
return {
|
|
80
|
-
tasksById: new Map(tasks.map((task) => [task.id, task])),
|
|
81
|
-
taskIdByExternalRef: new Map(tasks.flatMap((task) => task.externalId ? [[task.externalId, task.id]] : [])),
|
|
82
|
-
taskIdBySourceIssueId: new Map(tasks.flatMap((task) => {
|
|
83
|
-
const sourceIssueId = readTaskSourceIssueId(task);
|
|
84
|
-
return sourceIssueId ? [[sourceIssueId, task.id]] : [];
|
|
85
|
-
}))
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function computeTaskBlockingDepths(tasks) {
|
|
89
|
-
const { tasksById, taskIdByExternalRef, taskIdBySourceIssueId } = buildTaskReferenceIndex(tasks);
|
|
90
|
-
const memo = new Map;
|
|
91
|
-
const visit = (taskId, stack) => {
|
|
92
|
-
const cached = memo.get(taskId);
|
|
93
|
-
if (cached !== undefined)
|
|
94
|
-
return cached;
|
|
95
|
-
if (stack.has(taskId))
|
|
96
|
-
return 0;
|
|
97
|
-
const task = tasksById.get(taskId);
|
|
98
|
-
if (!task)
|
|
99
|
-
return 0;
|
|
100
|
-
stack.add(taskId);
|
|
101
|
-
const blockers = readTaskBlockingDependencyRefs(task).map((ref) => resolveTaskReference(ref, tasksById, taskIdByExternalRef, taskIdBySourceIssueId)).filter((ref) => ref !== null && ref !== taskId);
|
|
102
|
-
const depth = blockers.length === 0 ? 0 : Math.max(...blockers.map((blockerId) => visit(blockerId, stack) + 1));
|
|
103
|
-
stack.delete(taskId);
|
|
104
|
-
memo.set(taskId, depth);
|
|
105
|
-
return depth;
|
|
106
|
-
};
|
|
107
|
-
for (const task of tasks) {
|
|
108
|
-
visit(task.id, new Set);
|
|
109
|
-
}
|
|
110
|
-
return memo;
|
|
111
|
-
}
|
|
112
|
-
function isTaskTerminalStatus(status) {
|
|
113
|
-
switch (status) {
|
|
114
|
-
case "closed":
|
|
115
|
-
case "completed":
|
|
116
|
-
case "done":
|
|
117
|
-
case "cancelled":
|
|
118
|
-
case "canceled":
|
|
119
|
-
return true;
|
|
120
|
-
default:
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function isTaskBlockedStatus(status) {
|
|
125
|
-
return status === "blocked";
|
|
126
|
-
}
|
|
127
|
-
function isTaskRunnableStatus(status) {
|
|
128
|
-
if (status === null || status === undefined || status === "")
|
|
129
|
-
return true;
|
|
130
|
-
if (isTaskTerminalStatus(status) || isTaskBlockedStatus(status))
|
|
131
|
-
return false;
|
|
132
|
-
switch (status) {
|
|
133
|
-
case "ready":
|
|
134
|
-
case "open":
|
|
135
|
-
case "failed":
|
|
136
|
-
return true;
|
|
137
|
-
default:
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
function computeTaskDependencyBadges(tasks) {
|
|
142
|
-
const index = buildTaskReferenceIndex(tasks);
|
|
143
|
-
const blockingDepths = computeTaskBlockingDepths(tasks);
|
|
144
|
-
const dependencyIdsByTask = new Map;
|
|
145
|
-
const unresolvedRefsByTask = new Map;
|
|
146
|
-
const blocksByTask = new Map;
|
|
147
|
-
for (const task of tasks) {
|
|
148
|
-
const dependencyIds = [];
|
|
149
|
-
const unresolvedRefs = [];
|
|
150
|
-
for (const ref of readTaskBlockingDependencyRefs(task)) {
|
|
151
|
-
const dependencyId = resolveTaskReference(ref, index.tasksById, index.taskIdByExternalRef, index.taskIdBySourceIssueId);
|
|
152
|
-
if (dependencyId && dependencyId !== task.id) {
|
|
153
|
-
dependencyIds.push(dependencyId);
|
|
154
|
-
const blocks = blocksByTask.get(dependencyId);
|
|
155
|
-
if (blocks) {
|
|
156
|
-
blocks.push(task.id);
|
|
157
|
-
} else {
|
|
158
|
-
blocksByTask.set(dependencyId, [task.id]);
|
|
159
|
-
}
|
|
160
|
-
} else {
|
|
161
|
-
unresolvedRefs.push(ref);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
dependencyIdsByTask.set(task.id, unique(dependencyIds));
|
|
165
|
-
unresolvedRefsByTask.set(task.id, unique(unresolvedRefs));
|
|
166
|
-
}
|
|
167
|
-
const summaries = new Map;
|
|
168
|
-
for (const task of tasks) {
|
|
169
|
-
const dependencyIds = dependencyIdsByTask.get(task.id) ?? [];
|
|
170
|
-
const unresolvedDependencyRefs = unresolvedRefsByTask.get(task.id) ?? [];
|
|
171
|
-
const blockedBy = dependencyIds.filter((dependencyId) => {
|
|
172
|
-
const dependency = index.tasksById.get(dependencyId);
|
|
173
|
-
return dependency ? !isTaskTerminalStatus(dependency.status) : false;
|
|
174
|
-
});
|
|
175
|
-
const blocks = unique(blocksByTask.get(task.id) ?? []);
|
|
176
|
-
const blocked = isTaskBlockedStatus(task.status) || blockedBy.length > 0;
|
|
177
|
-
const ready = isTaskRunnableStatus(task.status) && !blocked;
|
|
178
|
-
const badges = [];
|
|
179
|
-
if (blocked) {
|
|
180
|
-
badges.push({
|
|
181
|
-
kind: "blocked",
|
|
182
|
-
label: blockedBy.length > 0 ? `blocked \xD7${blockedBy.length}` : "blocked",
|
|
183
|
-
description: blockedBy.length > 0 ? `Waiting on ${blockedBy.join(", ")}.` : "Task source marks this task blocked.",
|
|
184
|
-
...blockedBy.length > 0 ? { count: blockedBy.length } : {},
|
|
185
|
-
taskIds: blockedBy
|
|
186
|
-
});
|
|
187
|
-
} else if (ready) {
|
|
188
|
-
badges.push({
|
|
189
|
-
kind: "ready",
|
|
190
|
-
label: "ready",
|
|
191
|
-
description: "No open dependencies block this task."
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
if (dependencyIds.length > 0 || blocks.length > 0 || unresolvedDependencyRefs.length > 0) {
|
|
195
|
-
badges.push({
|
|
196
|
-
kind: "dependency",
|
|
197
|
-
label: `deps ${dependencyIds.length}/${blocks.length}`,
|
|
198
|
-
description: [
|
|
199
|
-
dependencyIds.length > 0 ? `Depends on ${dependencyIds.join(", ")}.` : null,
|
|
200
|
-
blocks.length > 0 ? `Blocks ${blocks.join(", ")}.` : null,
|
|
201
|
-
unresolvedDependencyRefs.length > 0 ? `Unresolved refs: ${unresolvedDependencyRefs.join(", ")}.` : null
|
|
202
|
-
].filter((part) => part !== null).join(" "),
|
|
203
|
-
count: dependencyIds.length + blocks.length,
|
|
204
|
-
taskIds: unique([...dependencyIds, ...blocks])
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
summaries.set(task.id, {
|
|
208
|
-
taskId: task.id,
|
|
209
|
-
blockingDepth: blockingDepths.get(task.id) ?? 0,
|
|
210
|
-
dependencyIds,
|
|
211
|
-
unresolvedDependencyRefs,
|
|
212
|
-
blockedBy,
|
|
213
|
-
blocks,
|
|
214
|
-
blocked,
|
|
215
|
-
ready,
|
|
216
|
-
dependencyCount: dependencyIds.length,
|
|
217
|
-
dependentCount: blocks.length,
|
|
218
|
-
badges
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
return summaries;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// packages/core/src/taskGraphCodes.ts
|
|
225
|
-
var TASK_CODE_RE = /^\[([A-Z0-9]+(?:-[A-Z0-9]+)*)\]\s*/;
|
|
226
|
-
function extractTaskCode(title) {
|
|
227
|
-
const match = title.match(TASK_CODE_RE);
|
|
228
|
-
return match?.[1] ?? null;
|
|
229
|
-
}
|
|
230
|
-
function extractTaskGroupKey(title) {
|
|
231
|
-
const code = extractTaskCode(title);
|
|
232
|
-
if (!code)
|
|
233
|
-
return null;
|
|
234
|
-
const parts = code.split("-");
|
|
235
|
-
const suffix = parts.at(-1) ?? "";
|
|
236
|
-
if (/^\d+$/.test(suffix)) {
|
|
237
|
-
return parts.slice(0, -1).join("-");
|
|
238
|
-
}
|
|
239
|
-
return parts[0] ?? code;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// packages/core/src/rollups.ts
|
|
243
|
-
var UNASSIGNED_EPIC = "(unassigned-epic)";
|
|
244
|
-
var UNASSIGNED_ASSIGNEE = "(unassigned)";
|
|
245
|
-
var HUMAN_BLOCKER_CLASSES = {
|
|
246
|
-
"human-decision": true,
|
|
247
|
-
"human-approval": true,
|
|
248
|
-
"external-input": true,
|
|
249
|
-
unknown: true
|
|
250
|
-
};
|
|
251
|
-
function isObjectRecord3(value) {
|
|
252
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
253
|
-
}
|
|
254
|
-
function readIssueType(task) {
|
|
255
|
-
const metadata = isObjectRecord3(task.metadata) ? task.metadata : null;
|
|
256
|
-
const raw = isObjectRecord3(metadata?.raw) ? metadata.raw : null;
|
|
257
|
-
const value = raw?.issueType ?? metadata?.issueType;
|
|
258
|
-
return typeof value === "string" && value.trim() ? value.trim().toLowerCase() : null;
|
|
259
|
-
}
|
|
260
|
-
function isEpicTask(task) {
|
|
261
|
-
return readIssueType(task) === "epic";
|
|
262
|
-
}
|
|
263
|
-
function isInFlightTaskStatus(status) {
|
|
264
|
-
switch (status) {
|
|
265
|
-
case "queued":
|
|
266
|
-
case "running":
|
|
267
|
-
case "in_progress":
|
|
268
|
-
case "under_review":
|
|
269
|
-
return true;
|
|
270
|
-
default:
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function epicKeyForTask(task, tasksById, resolve) {
|
|
275
|
-
const parentRef = readTaskMetadataStringList(task, "parentChildDeps")[0];
|
|
276
|
-
const parentId = parentRef ? resolve(parentRef) : null;
|
|
277
|
-
const parent = parentId ? tasksById.get(parentId) : null;
|
|
278
|
-
if (parent)
|
|
279
|
-
return extractTaskGroupKey(parent.title) ?? parent.title ?? parent.id;
|
|
280
|
-
return extractTaskGroupKey(task.title) ?? UNASSIGNED_EPIC;
|
|
281
|
-
}
|
|
282
|
-
function rollupByEpic(tasks, classifications = new Map) {
|
|
283
|
-
const index = buildTaskReferenceIndex(tasks);
|
|
284
|
-
const badges = computeTaskDependencyBadges(tasks);
|
|
285
|
-
const resolve = (ref) => resolveTaskReference(ref, index.tasksById, index.taskIdByExternalRef, index.taskIdBySourceIssueId);
|
|
286
|
-
const buckets = new Map;
|
|
287
|
-
for (const task of tasks) {
|
|
288
|
-
if (isEpicTask(task))
|
|
289
|
-
continue;
|
|
290
|
-
const epicKey = epicKeyForTask(task, index.tasksById, resolve);
|
|
291
|
-
const current = buckets.get(epicKey) ?? {
|
|
292
|
-
total: 0,
|
|
293
|
-
completed: 0,
|
|
294
|
-
blockedCount: 0,
|
|
295
|
-
humanBlockedCount: 0,
|
|
296
|
-
inFlightCount: 0,
|
|
297
|
-
byStatus: {}
|
|
298
|
-
};
|
|
299
|
-
current.total += 1;
|
|
300
|
-
if (isTaskTerminalStatus(task.status))
|
|
301
|
-
current.completed += 1;
|
|
302
|
-
if (badges.get(task.id)?.blocked === true)
|
|
303
|
-
current.blockedCount += 1;
|
|
304
|
-
if (isInFlightTaskStatus(task.status))
|
|
305
|
-
current.inFlightCount += 1;
|
|
306
|
-
const classification = classifications.get(task.id);
|
|
307
|
-
if (classification && HUMAN_BLOCKER_CLASSES[classification])
|
|
308
|
-
current.humanBlockedCount += 1;
|
|
309
|
-
current.byStatus[task.status] = (current.byStatus[task.status] ?? 0) + 1;
|
|
310
|
-
buckets.set(epicKey, current);
|
|
311
|
-
}
|
|
312
|
-
return [...buckets.entries()].map(([epicKey, bucket]) => ({
|
|
313
|
-
epicKey,
|
|
314
|
-
total: bucket.total,
|
|
315
|
-
percentComplete: bucket.total === 0 ? 0 : Math.round(100 * bucket.completed / bucket.total),
|
|
316
|
-
blockedCount: bucket.blockedCount,
|
|
317
|
-
humanBlockedCount: bucket.humanBlockedCount,
|
|
318
|
-
inFlightCount: bucket.inFlightCount,
|
|
319
|
-
byStatus: Object.fromEntries(Object.entries(bucket.byStatus).sort(([left], [right]) => left.localeCompare(right)))
|
|
320
|
-
})).toSorted((left, right) => left.epicKey.localeCompare(right.epicKey));
|
|
321
|
-
}
|
|
322
|
-
function assigneesForTask(task) {
|
|
323
|
-
const assignees = readTaskAssigneeLogins(task);
|
|
324
|
-
return assignees.length > 0 ? assignees : [UNASSIGNED_ASSIGNEE];
|
|
325
|
-
}
|
|
326
|
-
function rollupByAssignee(tasks, runs) {
|
|
327
|
-
const tasksById = new Map(tasks.map((task) => [String(task.id), task]));
|
|
328
|
-
const badges = computeTaskDependencyBadges(tasks);
|
|
329
|
-
const buckets = new Map;
|
|
330
|
-
const ensureBucket = (assignee) => {
|
|
331
|
-
const existing = buckets.get(assignee);
|
|
332
|
-
if (existing)
|
|
333
|
-
return existing;
|
|
334
|
-
const created = { openTaskCount: 0, inFlightRunIds: new Set, prsAwaitingReview: 0, blockers: new Set };
|
|
335
|
-
buckets.set(assignee, created);
|
|
336
|
-
return created;
|
|
337
|
-
};
|
|
338
|
-
for (const task of tasks) {
|
|
339
|
-
if (isEpicTask(task))
|
|
340
|
-
continue;
|
|
341
|
-
for (const assignee of assigneesForTask(task)) {
|
|
342
|
-
const bucket = ensureBucket(assignee);
|
|
343
|
-
if (!isTaskTerminalStatus(task.status))
|
|
344
|
-
bucket.openTaskCount += 1;
|
|
345
|
-
if (badges.get(task.id)?.blocked === true)
|
|
346
|
-
bucket.blockers.add(task.id);
|
|
347
|
-
if (task.status === "under_review")
|
|
348
|
-
bucket.prsAwaitingReview += 1;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
for (const run of runs) {
|
|
352
|
-
const taskId = run.record.taskId;
|
|
353
|
-
const task = taskId ? tasksById.get(taskId) : null;
|
|
354
|
-
if (!task)
|
|
355
|
-
continue;
|
|
356
|
-
if (isEpicTask(task))
|
|
357
|
-
continue;
|
|
358
|
-
for (const assignee of assigneesForTask(task)) {
|
|
359
|
-
const bucket = ensureBucket(assignee);
|
|
360
|
-
if (run.status && isOperatorActiveRunStatus(run.status))
|
|
361
|
-
bucket.inFlightRunIds.add(run.record.runId ?? `${String(task.id)}:${run.lastSeq}`);
|
|
362
|
-
if (run.status === "reviewing" && run.record.prUrl)
|
|
363
|
-
bucket.prsAwaitingReview += 1;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return [...buckets.entries()].map(([assignee, bucket]) => ({
|
|
367
|
-
assignee,
|
|
368
|
-
openTaskCount: bucket.openTaskCount,
|
|
369
|
-
inFlightRunCount: bucket.inFlightRunIds.size,
|
|
370
|
-
prsAwaitingReview: bucket.prsAwaitingReview,
|
|
371
|
-
blockers: [...bucket.blockers].toSorted((left, right) => String(left).localeCompare(String(right)))
|
|
372
|
-
})).toSorted((left, right) => left.assignee.localeCompare(right.assignee));
|
|
373
|
-
}
|
|
374
|
-
export {
|
|
375
|
-
rollupByEpic,
|
|
376
|
-
rollupByAssignee
|
|
377
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export type StageKind = "transform" | "gate" | "observe";
|
|
2
|
-
export type StageMutationOp = "insert" | "remove" | "replace" | "wrap" | "reorder";
|
|
3
|
-
export interface ResolvableStage {
|
|
4
|
-
readonly id: string;
|
|
5
|
-
readonly kind?: StageKind | string;
|
|
6
|
-
readonly before?: readonly string[];
|
|
7
|
-
readonly after?: readonly string[];
|
|
8
|
-
readonly priority?: number;
|
|
9
|
-
readonly protected?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export interface StageWrapper<TStage extends ResolvableStage = ResolvableStage> {
|
|
12
|
-
readonly id?: string;
|
|
13
|
-
readonly priority?: number;
|
|
14
|
-
readonly apply?: (stage: TStage) => TStage;
|
|
15
|
-
}
|
|
16
|
-
export type StageMutation<TStage extends ResolvableStage = ResolvableStage> = Readonly<{
|
|
17
|
-
op: "insert";
|
|
18
|
-
stage: TStage;
|
|
19
|
-
contributedBy?: string;
|
|
20
|
-
}> | Readonly<{
|
|
21
|
-
op: "remove";
|
|
22
|
-
id: string;
|
|
23
|
-
contributedBy?: string;
|
|
24
|
-
}> | Readonly<{
|
|
25
|
-
op: "replace";
|
|
26
|
-
id: string;
|
|
27
|
-
stage: TStage;
|
|
28
|
-
contributedBy?: string;
|
|
29
|
-
}> | Readonly<{
|
|
30
|
-
op: "wrap";
|
|
31
|
-
id: string;
|
|
32
|
-
wrapper: StageWrapper<TStage>;
|
|
33
|
-
contributedBy?: string;
|
|
34
|
-
}> | Readonly<{
|
|
35
|
-
op: "wrap";
|
|
36
|
-
id: string;
|
|
37
|
-
around: StageWrapper<TStage>;
|
|
38
|
-
contributedBy?: string;
|
|
39
|
-
}> | Readonly<{
|
|
40
|
-
op: "reorder";
|
|
41
|
-
id: string;
|
|
42
|
-
before?: readonly string[];
|
|
43
|
-
after?: readonly string[];
|
|
44
|
-
contributedBy?: string;
|
|
45
|
-
}>;
|
|
46
|
-
export interface ResolveStagePipelineInput<TStage extends ResolvableStage = ResolvableStage> {
|
|
47
|
-
readonly defaultStages: readonly TStage[];
|
|
48
|
-
readonly mutations?: readonly StageMutation<TStage>[];
|
|
49
|
-
}
|
|
50
|
-
export interface DroppedStageAnchor {
|
|
51
|
-
readonly stageId: string;
|
|
52
|
-
readonly anchor: string;
|
|
53
|
-
readonly direction: "before" | "after";
|
|
54
|
-
readonly reason: "removed" | "missing";
|
|
55
|
-
readonly removedBy?: string;
|
|
56
|
-
}
|
|
57
|
-
export interface StageResolutionRecordEntry {
|
|
58
|
-
readonly stageId: string;
|
|
59
|
-
readonly contributedBy: string;
|
|
60
|
-
readonly removedBy?: string;
|
|
61
|
-
readonly replacedBy?: string;
|
|
62
|
-
readonly wrappedBy?: readonly string[];
|
|
63
|
-
readonly droppedAnchors?: readonly DroppedStageAnchor[];
|
|
64
|
-
readonly isProtected: boolean;
|
|
65
|
-
}
|
|
66
|
-
export interface ResolvedStagePipeline<TStage extends ResolvableStage = ResolvableStage> {
|
|
67
|
-
readonly stages: readonly TStage[];
|
|
68
|
-
readonly order: readonly string[];
|
|
69
|
-
readonly record: readonly StageResolutionRecordEntry[];
|
|
70
|
-
readonly cycles: readonly (readonly string[])[];
|
|
71
|
-
}
|
|
72
|
-
export declare class PipelineUnresolvableError extends Error {
|
|
73
|
-
readonly cycles: readonly (readonly string[])[];
|
|
74
|
-
readonly contributors: readonly string[];
|
|
75
|
-
constructor(message: string, cycles: readonly (readonly string[])[], contributors: readonly string[]);
|
|
76
|
-
}
|
|
77
|
-
export declare function resolveStagePipeline<TStage extends ResolvableStage>(input: ResolveStagePipelineInput<TStage>): ResolvedStagePipeline<TStage>;
|