@kici-dev/orchestrator 0.20.0 → 0.21.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/cli/api-client.d.ts +2 -0
- package/dist/cli/commands/runs.d.ts +3 -1
- package/dist/cli/commands/shared/run-ref.d.ts +4 -0
- package/dist/cli/commands/source.d.ts +1 -1
- package/dist/cli.js +834 -687
- package/dist/db/migrations/160_execution_jobs_workflow_name.d.ts +16 -0
- package/dist/db/types.d.ts +6 -0
- package/dist/index.js +1 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +9 -1
- package/dist/pipeline/invoke-gate.d.ts +1 -1
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +3 -1
- package/dist/pipeline/test-pipeline.d.ts +23 -1
- package/dist/provenance/backfill-run.d.ts +2 -0
- package/dist/reporting/check-run-reporter.d.ts +2 -0
- package/dist/reporting/check-run-summary.d.ts +12 -0
- package/dist/reporting/execution-tracker.d.ts +30 -2
- package/dist/reporting/run-aggregator.d.ts +8 -0
- package/dist/reporting/run-workflow-names.d.ts +30 -0
- package/dist/reporting/step-display-order.d.ts +9 -5
- package/dist/server.js +51833 -51469
- package/dist/standalone.js +8612 -8289
- package/dist/ws/job-status-forward-frame.d.ts +2 -0
- package/dist/ws/test-relay-handlers.d.ts +8 -0
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +53 -53
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* `execution_jobs.workflow_name`: the workflow that defines the job. A fixture
|
|
4
|
+
* run with no `--workflow` runs every matched workflow under one run id, so
|
|
5
|
+
* `execution_runs.workflow_name` (the first matched workflow) does not say
|
|
6
|
+
* which workflow a job belongs to.
|
|
7
|
+
*
|
|
8
|
+
* Nullable, with no backfill: a row written before this column reads as
|
|
9
|
+
* unknown, and the readers fall back to the run's workflow for a run that can
|
|
10
|
+
* span only one.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent.
|
|
13
|
+
*/
|
|
14
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
15
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=160_execution_jobs_workflow_name.d.ts.map
|
package/dist/db/types.d.ts
CHANGED
|
@@ -651,6 +651,12 @@ export interface ExecutionJobTable {
|
|
|
651
651
|
job_id: string;
|
|
652
652
|
/** Job name (e.g. "test", "test[node-18]") */
|
|
653
653
|
job_name: string;
|
|
654
|
+
/**
|
|
655
|
+
* The workflow that defines the job. A run can span several workflows (an older `kici`'s shared
|
|
656
|
+
* fixture run), so the run's own
|
|
657
|
+
* `workflow_name` does not name it. NULL on a row written before the column existed.
|
|
658
|
+
*/
|
|
659
|
+
workflow_name: ColumnType<string | null, string | null | undefined, string | null>;
|
|
654
660
|
/** Job status: an `ExecutionJobStatus` value (engine). */
|
|
655
661
|
status: Generated<string>;
|
|
656
662
|
/**
|
package/dist/index.js
CHANGED
|
@@ -198,6 +198,13 @@ export interface WorkflowDispatchContext {
|
|
|
198
198
|
* explicitly rather than leave it `pending` forever.
|
|
199
199
|
*/
|
|
200
200
|
runRegisteredBeforeDispatch?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Called each time this dispatch registers the run with the tracker. An older `kici`'s shared
|
|
203
|
+
* fixture run dispatches several
|
|
204
|
+
* workflows under one run id, and holds the run open from the first
|
|
205
|
+
* registration until every workflow has registered.
|
|
206
|
+
*/
|
|
207
|
+
onRunRegistered?: () => void;
|
|
201
208
|
/**
|
|
202
209
|
* Set once `setupDispatchContext` posted the queued `kici/<workflow>` check
|
|
203
210
|
* and one `kici/<workflow>/job/<name>` per static job. They go up BEFORE the
|
|
@@ -427,7 +434,8 @@ interface JobEnvEvalResult {
|
|
|
427
434
|
* Synthetic job-id prefix every needs-gate site stamps on a held-back job. The
|
|
428
435
|
* release path (`dispatchReadyJob` → `findSyntheticJobId` → `addJobsToRun`)
|
|
429
436
|
* keys on it, so it soundly recovers the gated set without threading a parallel
|
|
430
|
-
* list through both the single-orch and cluster paths. Owned by `db/synthetic-job-ids.ts` so the
|
|
437
|
+
* list through both the single-orch and cluster paths. Owned by `db/synthetic-job-ids.ts` so the
|
|
438
|
+
* `contexts/`
|
|
431
439
|
* concurrency sweep need not import this module.
|
|
432
440
|
*/
|
|
433
441
|
export { NEEDS_PENDING_JOB_ID_PREFIX };
|
|
@@ -20,7 +20,7 @@ import { ExecutionJobStatus } from '@kici-dev/engine';
|
|
|
20
20
|
import type { LockInvoke, LockJob } from '@kici-dev/engine';
|
|
21
21
|
import type { Kysely } from 'kysely';
|
|
22
22
|
import type { Database } from '../db/types.js';
|
|
23
|
-
import type
|
|
23
|
+
import { type ExecutionTracker } from '../reporting/execution-tracker.js';
|
|
24
24
|
/**
|
|
25
25
|
* The invoke parameters carried from a gate's lock job to its (possibly deferred)
|
|
26
26
|
* execution. Persisted on the pending job context so a gate released later — or
|
|
@@ -9,7 +9,7 @@ import type { LockJob, MaterializedJob } from '@kici-dev/engine';
|
|
|
9
9
|
import type { JobKind } from '../db/types.js';
|
|
10
10
|
import type { RunContext, RunCoordinator } from '../cluster/coordinator.js';
|
|
11
11
|
import type { Dispatcher } from '../agent/dispatcher.js';
|
|
12
|
-
import type
|
|
12
|
+
import { type ExecutionTracker } from '../reporting/execution-tracker.js';
|
|
13
13
|
export interface DispatchedJobEntry {
|
|
14
14
|
jobId: string;
|
|
15
15
|
jobName: string;
|
|
@@ -73,6 +73,8 @@ export declare function routeOrDispatchJobs(opts: RouteOrDispatchOptions): Promi
|
|
|
73
73
|
}>;
|
|
74
74
|
export interface RegisterDispatchedJobsOptions {
|
|
75
75
|
newRunId: string;
|
|
76
|
+
/** The workflow the jobs belong to, recorded on each job row. */
|
|
77
|
+
workflowName: string;
|
|
76
78
|
dispatchedJobs: DispatchedJobEntry[];
|
|
77
79
|
rejectedJobs: RejectedJobEntry[];
|
|
78
80
|
executionTracker: ExecutionTracker;
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
* decorating secret resolver), and the fixture's `secrets` context mapping
|
|
21
21
|
* resolves into namespaced secrets;
|
|
22
22
|
* - direct workflow execution (bypass trigger matching) is supported.
|
|
23
|
+
*
|
|
24
|
+
* Like a webhook, it creates one run per matched workflow. A caller that
|
|
25
|
+
* follows a single run (no `acceptsMultipleRuns`) gets one shared run instead,
|
|
26
|
+
* and only when the workflows' job names cannot collide in it.
|
|
23
27
|
*/
|
|
24
28
|
import { type ProcessingDeps } from './processor.js';
|
|
25
29
|
import { type ActorPrincipal } from '@kici-dev/engine';
|
|
@@ -38,6 +42,8 @@ export interface TestTriggerInput {
|
|
|
38
42
|
routingKey: string;
|
|
39
43
|
/** Uploaded tarball reference. */
|
|
40
44
|
uploadId?: string;
|
|
45
|
+
/** The commit the uploaded overlay was built from, as its upload recorded it. */
|
|
46
|
+
uploadSha?: string;
|
|
41
47
|
/** Fixture secret context mappings `{ contextName: envName }`. */
|
|
42
48
|
secrets?: Record<string, string>;
|
|
43
49
|
/** Base64 X25519+AES-GCM blob of the developer's local secrets ({flat, contexts}). */
|
|
@@ -77,9 +83,18 @@ export interface TestTriggerInput {
|
|
|
77
83
|
* here against the matched workflow's lock dispatch descriptor.
|
|
78
84
|
*/
|
|
79
85
|
dispatchInputs?: Record<string, string>;
|
|
86
|
+
/**
|
|
87
|
+
* The caller follows every run in the result's `runs`. Without it, several
|
|
88
|
+
* matched workflows share one run, or the trigger is refused when their job
|
|
89
|
+
* names collide.
|
|
90
|
+
*/
|
|
91
|
+
acceptsMultipleRuns?: boolean;
|
|
80
92
|
}
|
|
81
93
|
interface TestTriggerResult {
|
|
94
|
+
/** The first run's id: the only run when the caller follows one. */
|
|
82
95
|
runId: string;
|
|
96
|
+
/** One entry per run, each executing one matched workflow. Absent for a shared run. */
|
|
97
|
+
runs?: TestTriggeredRun[];
|
|
83
98
|
status: 'accepted' | 'rejected';
|
|
84
99
|
reason?: string;
|
|
85
100
|
jobIds: string[];
|
|
@@ -98,9 +113,16 @@ export declare function repoIdentityFromInlineInput(input: TestTriggerInput): {
|
|
|
98
113
|
repoIdentifier: string;
|
|
99
114
|
provider: string;
|
|
100
115
|
};
|
|
116
|
+
/** One run the trigger created, with the matched workflow it executes. */
|
|
117
|
+
export interface TestTriggeredRun {
|
|
118
|
+
runId: string;
|
|
119
|
+
workflowName: string;
|
|
120
|
+
jobIds: string[];
|
|
121
|
+
}
|
|
101
122
|
/**
|
|
102
123
|
* Process a test trigger through the shared dispatch core: one
|
|
103
|
-
* `WorkflowDispatchContext` per matched workflow, into `dispatchMatchedWorkflow
|
|
124
|
+
* `WorkflowDispatchContext` per matched workflow, into `dispatchMatchedWorkflow`,
|
|
125
|
+
* each under its own run id.
|
|
104
126
|
*/
|
|
105
127
|
export declare function processTestTrigger(input: TestTriggerInput, deps: ProcessingDeps): Promise<TestTriggerResult>;
|
|
106
128
|
export {};
|
|
@@ -31,6 +31,8 @@ export interface BackfillJobRow {
|
|
|
31
31
|
run_id: string;
|
|
32
32
|
job_id: string;
|
|
33
33
|
job_name: string;
|
|
34
|
+
/** Optional: a loader that does not select it forwards no workflow. */
|
|
35
|
+
workflow_name?: string | null;
|
|
34
36
|
status: string;
|
|
35
37
|
started_at: Date | null;
|
|
36
38
|
completed_at: Date | null;
|
|
@@ -192,6 +192,8 @@ interface UpdateStepProgressOptions {
|
|
|
192
192
|
jobName: string;
|
|
193
193
|
stepIndex: number;
|
|
194
194
|
stepName: string;
|
|
195
|
+
/** The step's `step_type`, when the agent sent one. */
|
|
196
|
+
stepType?: string;
|
|
195
197
|
state: 'running' | 'success' | 'failed' | 'skipped' | 'cancelled';
|
|
196
198
|
durationMs?: number;
|
|
197
199
|
installationId?: number;
|
|
@@ -42,7 +42,19 @@ export interface StepProgressEntry {
|
|
|
42
42
|
name: string;
|
|
43
43
|
status: 'pending' | 'running' | 'success' | 'failed' | 'skipped' | 'cancelled';
|
|
44
44
|
durationMs?: number;
|
|
45
|
+
/** The step's stored index. An entry without one is read by its position (defensive). */
|
|
46
|
+
stepIndex?: number;
|
|
47
|
+
/** The step's `step_type`; places setup and init pseudo-steps first. */
|
|
48
|
+
stepType?: string;
|
|
45
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Record one step's progress: replace the entry for its index, or add it in display
|
|
52
|
+
* order. Pseudo-steps have high indices (init at 1_000_000 + n), so the list is keyed
|
|
53
|
+
* by index rather than position; a positional list would pad every gap up to it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function applyStepProgress(steps: StepProgressEntry[], entry: StepProgressEntry & {
|
|
56
|
+
stepIndex: number;
|
|
57
|
+
}): StepProgressEntry[];
|
|
46
58
|
interface BuildCheckRunSummaryOptions {
|
|
47
59
|
jobName: string;
|
|
48
60
|
stepResults: StepResultData[];
|
|
@@ -206,7 +206,9 @@ export interface ExecutionTrackerDeps {
|
|
|
206
206
|
*/
|
|
207
207
|
initFailure?: InitFailure,
|
|
208
208
|
/** Ordered bound deployment-context names for this job (multi-env jobs). */
|
|
209
|
-
contexts?: string[]
|
|
209
|
+
contexts?: string[],
|
|
210
|
+
/** The workflow that defines the job, when recorded. */
|
|
211
|
+
workflowName?: string) => void;
|
|
210
212
|
/**
|
|
211
213
|
* Optional callback to emit run.event messages to Platform.
|
|
212
214
|
* Fires at orchestrator lifecycle points (dispatch, agent assignment, job start/complete).
|
|
@@ -282,6 +284,13 @@ export interface ExecutionTrackerDeps {
|
|
|
282
284
|
export interface TrackedJobRow {
|
|
283
285
|
jobId: string;
|
|
284
286
|
jobName: string;
|
|
287
|
+
/**
|
|
288
|
+
* The workflow that defines the job. An older `kici`'s shared fixture run holds every matched
|
|
289
|
+
* workflow, so the run's own workflow
|
|
290
|
+
* does not name it. `onExecutionStarted` stamps its own workflow on a job without one;
|
|
291
|
+
* `addJobsToRun` inherits it from the placeholder the job replaces.
|
|
292
|
+
*/
|
|
293
|
+
workflowName?: string;
|
|
285
294
|
matrixValues?: Record<string, unknown>;
|
|
286
295
|
runsOnLabels?: string[];
|
|
287
296
|
baseJobName?: string;
|
|
@@ -307,6 +316,8 @@ export interface TrackedJobRow {
|
|
|
307
316
|
/** For a gate job, its wall-clock timeout in ms (orchestrator-swept). */
|
|
308
317
|
timeoutMs?: number;
|
|
309
318
|
}
|
|
319
|
+
/** Stamp each job with `workflowName`, keeping a workflow a job already names. */
|
|
320
|
+
export declare function jobsOfWorkflow<T extends TrackedJobRow>(workflowName: string, jobs: T[]): T[];
|
|
310
321
|
export declare class ExecutionTracker {
|
|
311
322
|
private readonly db;
|
|
312
323
|
private readonly observerRegistry?;
|
|
@@ -538,6 +549,11 @@ export declare class ExecutionTracker {
|
|
|
538
549
|
/** Synthetic job ID to replace (e.g. needs-pending-deploy-{uuid}). */
|
|
539
550
|
replaceSyntheticId?: string): Promise<void>;
|
|
540
551
|
private addJobsToRunImpl;
|
|
552
|
+
/**
|
|
553
|
+
* The workflow of the placeholder a job replaces: from memory, or from its
|
|
554
|
+
* row when another peer registered it.
|
|
555
|
+
*/
|
|
556
|
+
private placeholderWorkflowName;
|
|
541
557
|
/** Mark a run as a test run for observer broadcasting (called by the test pipeline). */
|
|
542
558
|
markTestRun(runId: string): void;
|
|
543
559
|
isTestRun(runId: string): boolean;
|
|
@@ -814,6 +830,13 @@ export declare class ExecutionTracker {
|
|
|
814
830
|
dispatchedByFailureLifecycle?: boolean;
|
|
815
831
|
/** Re-run lineage, when this run re-runs another. */
|
|
816
832
|
rerunLineage?: RerunLineage;
|
|
833
|
+
/**
|
|
834
|
+
* Set for a `kici run` test run, so its init failure stays readable on the
|
|
835
|
+
* test-run status and log routes, which serve only test runs.
|
|
836
|
+
*/
|
|
837
|
+
testRun?: {
|
|
838
|
+
fixtureId: string;
|
|
839
|
+
};
|
|
817
840
|
}): Promise<void>;
|
|
818
841
|
/**
|
|
819
842
|
* Write one `failed` execution_runs row for a global eval round that never
|
|
@@ -930,6 +953,10 @@ export declare class ExecutionTracker {
|
|
|
930
953
|
* {@link ExecutionTracker.recordGlobalEvalRoundFailureRun}).
|
|
931
954
|
*/
|
|
932
955
|
dispatchRoutingKey?: string;
|
|
956
|
+
/** Set for a `kici run` test run, as on {@link ExecutionTracker.recordInitFailureRun}. */
|
|
957
|
+
testRun?: {
|
|
958
|
+
fixtureId: string;
|
|
959
|
+
};
|
|
933
960
|
}): Promise<void>;
|
|
934
961
|
/**
|
|
935
962
|
* Claim a held global evaluation round for release (`held` → `pending`).
|
|
@@ -1089,7 +1116,7 @@ export declare class ExecutionTracker {
|
|
|
1089
1116
|
* worker's first status update creates the `execution_jobs` row. An existing
|
|
1090
1117
|
* entry is never clobbered, so a later terminal status survives.
|
|
1091
1118
|
*/
|
|
1092
|
-
registerJobName(runId: string, jobId: string, jobName: string): void;
|
|
1119
|
+
registerJobName(runId: string, jobId: string, jobName: string, workflowName?: string): void;
|
|
1093
1120
|
/**
|
|
1094
1121
|
* The in-memory run owning a dispatched jobId, so `getExecutionContext`
|
|
1095
1122
|
* resolves for a job-scoped agent `event.emit`. In-memory only, like
|
|
@@ -1169,6 +1196,7 @@ export declare class ExecutionTracker {
|
|
|
1169
1196
|
jobs: Array<{
|
|
1170
1197
|
jobId: string;
|
|
1171
1198
|
jobName: string;
|
|
1199
|
+
workflowName?: string;
|
|
1172
1200
|
status: string;
|
|
1173
1201
|
startedAt?: number;
|
|
1174
1202
|
completedAt?: number;
|
|
@@ -39,6 +39,8 @@ export declare function mapRunDetailStep(step: RunDetailStepRow): {
|
|
|
39
39
|
export interface RunDetailJobRow {
|
|
40
40
|
job_id: string;
|
|
41
41
|
job_name: string;
|
|
42
|
+
/** Absent from an archived row written before the column existed. */
|
|
43
|
+
workflow_name?: string | null;
|
|
42
44
|
status: string;
|
|
43
45
|
matrix_values: unknown;
|
|
44
46
|
base_job_name: string | null;
|
|
@@ -67,6 +69,11 @@ export interface RunDetailJobLookups {
|
|
|
67
69
|
upstreamName: string;
|
|
68
70
|
runOn: ExecutionJobStatus[];
|
|
69
71
|
}>>;
|
|
72
|
+
/** The run's own workflow, naming a job row that records none; see {@link jobWorkflowName}. */
|
|
73
|
+
runWorkflow?: {
|
|
74
|
+
workflow_name: string;
|
|
75
|
+
is_test_run: boolean;
|
|
76
|
+
};
|
|
70
77
|
}
|
|
71
78
|
/**
|
|
72
79
|
* The routing reason as a reader should see it: only while the job is `pending`/`queued`.
|
|
@@ -82,6 +89,7 @@ export declare function visibleRoutingReason(status: string, routingReason: stri
|
|
|
82
89
|
export declare function buildRunDetailJobs(jobs: RunDetailJobRow[], lookups: RunDetailJobLookups): {
|
|
83
90
|
jobId: string;
|
|
84
91
|
jobName: string;
|
|
92
|
+
workflowName: string | null;
|
|
85
93
|
status: string;
|
|
86
94
|
matrixValues: Record<string, unknown> | null;
|
|
87
95
|
baseJobName: string | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workflows a run spans, read from its job rows.
|
|
3
|
+
*
|
|
4
|
+
* An older `kici`'s shared fixture run holds every
|
|
5
|
+
* matched workflow. `execution_runs.workflow_name` holds the first of them; each job row
|
|
6
|
+
* records its own in `execution_jobs.workflow_name`.
|
|
7
|
+
*/
|
|
8
|
+
import type { Kysely } from 'kysely';
|
|
9
|
+
import type { Database } from '../db/types.js';
|
|
10
|
+
/** The run fields the readers below need. */
|
|
11
|
+
export interface RunWorkflowRef {
|
|
12
|
+
run_id: string;
|
|
13
|
+
workflow_name: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Every workflow each run spans, the run's own workflow first and the rest in
|
|
17
|
+
* the order their first job registered. A run whose job rows name no workflow
|
|
18
|
+
* (written before the column existed) lists its own workflow alone.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadRunWorkflowNames(db: Kysely<Database>, runs: readonly RunWorkflowRef[]): Promise<Map<string, string[]>>;
|
|
21
|
+
/**
|
|
22
|
+
* The workflow a job row belongs to. A row written before the column existed
|
|
23
|
+
* records none: a run that is not a fixture run spans one workflow, so the
|
|
24
|
+
* run's own names it; a fixture run may span several, so it stays unknown.
|
|
25
|
+
*/
|
|
26
|
+
export declare function jobWorkflowName(jobWorkflow: string | null, run: {
|
|
27
|
+
workflow_name: string;
|
|
28
|
+
is_test_run: boolean;
|
|
29
|
+
}): string | null;
|
|
30
|
+
//# sourceMappingURL=run-workflow-names.d.ts.map
|
|
@@ -3,26 +3,28 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Sorting `execution_steps` by `step_index` alone puts a pseudo-step where its index landed,
|
|
5
5
|
* not where it ran. That suits the cache pseudo-steps (indices above the real steps, mostly
|
|
6
|
-
* bracketing the work), but a job's image build
|
|
6
|
+
* bracketing the work), but a job's image build and its init commands run strictly FIRST.
|
|
7
7
|
*
|
|
8
8
|
* The index cannot express this: `step.status` rejects a negative index (an agent sending one
|
|
9
9
|
* to an older orchestrator is disconnected mid-job), and the check-run reporter
|
|
10
10
|
* (`steps[stepIndex]`) and the dashboard (log fetching gated on `stepIndex >= 0`) treat a
|
|
11
|
-
* negative index as absent. So the ordering is expressed by TYPE,
|
|
11
|
+
* negative index as absent. So the ordering is expressed by TYPE, as the engine's
|
|
12
|
+
* `StepPhase`, here, once.
|
|
12
13
|
*/
|
|
13
14
|
import { type Expression } from 'kysely';
|
|
14
15
|
/**
|
|
15
|
-
* Sort key placing setup pseudo-steps
|
|
16
|
-
* the `step_index` sort:
|
|
16
|
+
* Sort key placing steps by `StepPhase`: setup pseudo-steps, then init commands, then the
|
|
17
|
+
* job's steps. Apply BEFORE the `step_index` sort:
|
|
17
18
|
*
|
|
18
19
|
* ```ts
|
|
19
20
|
* qb.orderBy(setupStepsFirst()).orderBy('step_index', 'asc')
|
|
20
21
|
* ```
|
|
21
22
|
*
|
|
22
23
|
* Untyped steps and every real step share one key, so `step_index` alone orders each group.
|
|
24
|
+
* The init pattern matches `initStepIndex`: the prefix followed by digits only.
|
|
23
25
|
*/
|
|
24
26
|
export declare function setupStepsFirst(): Expression<number>;
|
|
25
|
-
/** In-memory equivalent, kept beside the SQL so the two agree on
|
|
27
|
+
/** In-memory equivalent over DB rows, kept beside the SQL so the two agree on the phases. */
|
|
26
28
|
export declare function compareStepsForDisplay(a: {
|
|
27
29
|
step_type?: string | null;
|
|
28
30
|
step_index: number;
|
|
@@ -30,4 +32,6 @@ export declare function compareStepsForDisplay(a: {
|
|
|
30
32
|
step_type?: string | null;
|
|
31
33
|
step_index: number;
|
|
32
34
|
}): number;
|
|
35
|
+
/** {@link compareStepsForDisplay} over untyped rows, such as cold-store rows read back from S3. */
|
|
36
|
+
export declare function compareStepRowsForDisplay(a: Record<string, unknown>, b: Record<string, unknown>): number;
|
|
33
37
|
//# sourceMappingURL=step-display-order.d.ts.map
|