nx 23.3.0-beta.7 → 23.3.0-beta.9
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/README.md +1 -1
- package/dist/nx-cloud-internals.d.ts +1 -1
- package/dist/nx-cloud-internals.js +4 -4
- package/dist/src/command-line/affected/affected.js +20 -1
- package/dist/src/command-line/affected/command-object.js +1 -1
- package/dist/src/command-line/migrate/agentic/master/run-master-session.d.ts +6 -2
- package/dist/src/command-line/migrate/agentic/master/run-master-session.js +88 -14
- package/dist/src/command-line/migrate/command-object.d.ts +1 -0
- package/dist/src/command-line/migrate/command-object.js +6 -1
- package/dist/src/command-line/migrate/migrate-analytics.d.ts +34 -9
- package/dist/src/command-line/migrate/migrate-analytics.js +71 -10
- package/dist/src/command-line/migrate/migrate-config.d.ts +5 -2
- package/dist/src/command-line/migrate/migrate-config.js +19 -11
- package/dist/src/command-line/migrate/migrate.d.ts +2 -0
- package/dist/src/command-line/migrate/migrate.js +152 -45
- package/dist/src/command-line/migrate/resolve-package-version.js +2 -19
- package/dist/src/command-line/migrate/run/broker.d.ts +14 -2
- package/dist/src/command-line/migrate/run/broker.js +95 -34
- package/dist/src/command-line/migrate/run/existing-run-report.d.ts +55 -0
- package/dist/src/command-line/migrate/run/existing-run-report.js +225 -0
- package/dist/src/command-line/migrate/run/give-up.d.ts +41 -0
- package/dist/src/command-line/migrate/run/give-up.js +148 -0
- package/dist/src/command-line/migrate/run/index.d.ts +6 -4
- package/dist/src/command-line/migrate/run/index.js +15 -2
- package/dist/src/command-line/migrate/run/issues.d.ts +14 -0
- package/dist/src/command-line/migrate/run/issues.js +59 -0
- package/dist/src/command-line/migrate/run/orchestrator.d.ts +40 -1
- package/dist/src/command-line/migrate/run/orchestrator.js +509 -160
- package/dist/src/command-line/migrate/run/run-id.d.ts +0 -8
- package/dist/src/command-line/migrate/run/run-id.js +0 -30
- package/dist/src/command-line/migrate/run/run-state.d.ts +11 -9
- package/dist/src/command-line/migrate/run/run-state.js +25 -12
- package/dist/src/command-line/migrate/run/runbook.js +9 -4
- package/dist/src/command-line/migrate/run/state-lock.d.ts +31 -0
- package/dist/src/command-line/migrate/run/state-lock.js +126 -0
- package/dist/src/command-line/migrate/run/state-machine.d.ts +15 -0
- package/dist/src/command-line/migrate/run/state-machine.js +137 -10
- package/dist/src/command-line/migrate/run/util.d.ts +1 -0
- package/dist/src/command-line/migrate/run/util.js +21 -0
- package/dist/src/command-line/migrate/run/worker.js +3 -0
- package/dist/src/command-line/migrate/step-actions.d.ts +1 -1
- package/dist/src/command-line/migrate/step-actions.js +7 -1
- package/dist/src/command-line/migrate/text.d.ts +6 -0
- package/dist/src/command-line/migrate/text.js +25 -0
- package/dist/src/command-line/release/utils/release-graph.js +1 -1
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +2 -5
- package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +2 -2
- package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.js +4 -5
- package/dist/src/command-line/release/version/version-actions.d.ts +3 -0
- package/dist/src/command-line/reset/reset.js +10 -4
- package/dist/src/command-line/show/command-object.js +1 -1
- package/dist/src/command-line/show/projects.js +22 -0
- package/dist/src/command-line/yargs-utils/shared-options.d.ts +4 -0
- package/dist/src/command-line/yargs-utils/shared-options.js +16 -0
- package/dist/src/config/task-graph.d.ts +1 -1
- package/dist/src/config/workspace-json-project-json.d.ts +4 -4
- package/dist/src/daemon/client/client.d.ts +3 -3
- package/dist/src/daemon/client/client.js +4 -4
- package/dist/src/daemon/message-types/select-affected-tasks.d.ts +3 -0
- package/dist/src/daemon/message-types/ultracache-configuration-version.d.ts +8 -0
- package/dist/src/daemon/server/handle-hash-tasks.d.ts +2 -2
- package/dist/src/daemon/server/handle-hash-tasks.js +3 -3
- package/dist/src/daemon/server/handle-select-affected-tasks.js +5 -2
- package/dist/src/daemon/server/ultracache-configuration-state.d.ts +7 -0
- package/dist/src/daemon/server/{io-snapshots-state.js → ultracache-configuration-state.js} +5 -4
- package/dist/src/devkit-internals.d.ts +3 -1
- package/dist/src/devkit-internals.js +8 -3
- package/dist/src/hasher/create-task-hasher.d.ts +3 -3
- package/dist/src/hasher/create-task-hasher.js +6 -6
- package/dist/src/hasher/hash-task.d.ts +2 -2
- package/dist/src/hasher/hash-task.js +6 -5
- package/dist/src/hasher/native-task-hasher-impl.d.ts +7 -7
- package/dist/src/hasher/native-task-hasher-impl.js +19 -19
- package/dist/src/hasher/task-hasher.d.ts +14 -14
- package/dist/src/hasher/task-hasher.js +13 -13
- package/dist/src/native/index.d.ts +151 -102
- package/dist/src/native/native-bindings.js +4 -5
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +15 -8
- package/dist/src/nx-cloud/update-manager.d.ts +3 -3
- package/dist/src/nx-cloud/update-manager.js +19 -13
- package/dist/src/nx-cloud/utilities/client.d.ts +1 -1
- package/dist/src/nx-cloud/utilities/client.js +1 -1
- package/dist/src/nx-cloud/utilities/is-workspace-claimed.js +2 -1
- package/dist/src/nx-cloud/utilities/nx-cloud-http-client.d.ts +5 -0
- package/dist/src/nx-cloud/utilities/nx-cloud-http-client.js +16 -0
- package/dist/src/nx-cloud/utilities/url-shorten.js +17 -10
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +22 -18
- package/dist/src/plugins/js/utils/register.js +11 -3
- package/dist/src/project-graph/affected/affected-reasons.d.ts +116 -0
- package/dist/src/project-graph/affected/affected-reasons.js +459 -0
- package/dist/src/project-graph/affected/affected-tasks.d.ts +23 -10
- package/dist/src/project-graph/affected/affected-tasks.js +203 -31
- package/dist/src/project-graph/affected/print-explanation.d.ts +11 -0
- package/dist/src/project-graph/affected/print-explanation.js +44 -0
- package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
- package/dist/src/tasks-runner/init-tasks-runner.d.ts +5 -5
- package/dist/src/tasks-runner/init-tasks-runner.js +8 -15
- package/dist/src/tasks-runner/run-command.d.ts +7 -7
- package/dist/src/tasks-runner/run-command.js +19 -23
- package/dist/src/tasks-runner/task-orchestrator.d.ts +7 -3
- package/dist/src/tasks-runner/task-orchestrator.js +9 -8
- package/dist/src/tasks-runner/tasks-runner.d.ts +2 -0
- package/dist/src/ultracache/config.d.ts +21 -0
- package/dist/src/ultracache/config.js +29 -0
- package/dist/src/ultracache/fetch.d.ts +21 -0
- package/dist/src/{io-snapshots → ultracache}/fetch.js +9 -9
- package/dist/src/ultracache/overrides.d.ts +17 -0
- package/dist/src/{io-snapshots → ultracache}/overrides.js +14 -13
- package/dist/src/ultracache/report.d.ts +13 -0
- package/dist/src/{io-snapshots → ultracache}/report.js +15 -21
- package/dist/src/ultracache/store.d.ts +40 -0
- package/dist/src/{io-snapshots → ultracache}/store.js +45 -45
- package/dist/src/utils/ab-testing.js +11 -12
- package/dist/src/utils/command-line-utils.d.ts +1 -0
- package/dist/src/utils/create-cli-options.d.ts +6 -0
- package/dist/src/utils/create-cli-options.js +29 -0
- package/dist/src/utils/db-connection.d.ts +1 -0
- package/dist/src/utils/db-connection.js +1 -0
- package/dist/src/utils/git-utils.d.ts +7 -0
- package/dist/src/utils/git-utils.js +21 -9
- package/dist/src/utils/http-client.d.ts +27 -0
- package/dist/src/utils/http-client.js +193 -0
- package/package.json +12 -38
- package/dist/src/daemon/message-types/io-snapshot-version.d.ts +0 -5
- package/dist/src/daemon/server/io-snapshots-state.d.ts +0 -7
- package/dist/src/io-snapshots/config.d.ts +0 -23
- package/dist/src/io-snapshots/config.js +0 -32
- package/dist/src/io-snapshots/fetch.d.ts +0 -21
- package/dist/src/io-snapshots/outputs.d.ts +0 -12
- package/dist/src/io-snapshots/outputs.js +0 -33
- package/dist/src/io-snapshots/overrides.d.ts +0 -17
- package/dist/src/io-snapshots/report.d.ts +0 -13
- package/dist/src/io-snapshots/store.d.ts +0 -37
- package/dist/src/nx-cloud/utilities/axios.d.ts +0 -4
- package/dist/src/nx-cloud/utilities/axios.js +0 -17
- /package/dist/src/daemon/message-types/{io-snapshot-version.js → ultracache-configuration-version.js} +0 -0
|
@@ -6,11 +6,3 @@ export declare const RUN_ID_SAFE: RegExp;
|
|
|
6
6
|
* mid-run.
|
|
7
7
|
*/
|
|
8
8
|
export declare function createRunId(): string;
|
|
9
|
-
/**
|
|
10
|
-
* Hashes a migrations.json plan so a resumed run can detect whether the plan
|
|
11
|
-
* changed since a round was recorded. `nx-console` is stripped first since
|
|
12
|
-
* editors write to it without changing the plan; object keys are sorted
|
|
13
|
-
* recursively (arrays keep their order) so key reordering from a different
|
|
14
|
-
* JSON serializer doesn't change the hash.
|
|
15
|
-
*/
|
|
16
|
-
export declare function computePlanHash(migrationsJsonContent: string | object): string;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RUN_ID_SAFE = void 0;
|
|
4
4
|
exports.createRunId = createRunId;
|
|
5
|
-
exports.computePlanHash = computePlanHash;
|
|
6
5
|
const crypto_1 = require("crypto");
|
|
7
6
|
// Orchestrator-generated run ids always match; anything else could smuggle
|
|
8
7
|
// shell metacharacters into dispensed commands or a path out of the runs dir
|
|
@@ -25,32 +24,3 @@ function compactUtcTimestamp(date) {
|
|
|
25
24
|
.replace(/[-:]/g, '')
|
|
26
25
|
.replace(/\.\d+Z$/, '');
|
|
27
26
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Hashes a migrations.json plan so a resumed run can detect whether the plan
|
|
30
|
-
* changed since a round was recorded. `nx-console` is stripped first since
|
|
31
|
-
* editors write to it without changing the plan; object keys are sorted
|
|
32
|
-
* recursively (arrays keep their order) so key reordering from a different
|
|
33
|
-
* JSON serializer doesn't change the hash.
|
|
34
|
-
*/
|
|
35
|
-
function computePlanHash(migrationsJsonContent) {
|
|
36
|
-
const parsed = (typeof migrationsJsonContent === 'string'
|
|
37
|
-
? JSON.parse(migrationsJsonContent)
|
|
38
|
-
: migrationsJsonContent);
|
|
39
|
-
const withoutNxConsole = Object.fromEntries(Object.entries(parsed).filter(([key]) => key !== 'nx-console'));
|
|
40
|
-
return (0, crypto_1.createHash)('sha256')
|
|
41
|
-
.update(JSON.stringify(canonicalize(withoutNxConsole)))
|
|
42
|
-
.digest('hex');
|
|
43
|
-
}
|
|
44
|
-
function canonicalize(value) {
|
|
45
|
-
if (Array.isArray(value)) {
|
|
46
|
-
return value.map(canonicalize);
|
|
47
|
-
}
|
|
48
|
-
if (value !== null && typeof value === 'object') {
|
|
49
|
-
const sorted = {};
|
|
50
|
-
for (const key of Object.keys(value).sort()) {
|
|
51
|
-
sorted[key] = canonicalize(value[key]);
|
|
52
|
-
}
|
|
53
|
-
return sorted;
|
|
54
|
-
}
|
|
55
|
-
return value;
|
|
56
|
-
}
|
|
@@ -14,10 +14,9 @@ declare const MIGRATE_RUN_STATUSES: readonly ['active', 'completed'];
|
|
|
14
14
|
export type MigrateRunStatus = (typeof MIGRATE_RUN_STATUSES)[number];
|
|
15
15
|
export interface MigrateRunRound {
|
|
16
16
|
index: number;
|
|
17
|
-
planHash: string;
|
|
18
17
|
planSnapshot: string;
|
|
19
18
|
}
|
|
20
|
-
declare const MIGRATE_STEP_STATUSES: readonly ['pending', 'dispensed', 'running', 'awaiting-prompt-outcome', 'succeeded', 'failed', 'skipped', 'died'];
|
|
19
|
+
declare const MIGRATE_STEP_STATUSES: readonly ['pending', 'dispensed', 'running', 'awaiting-prompt-outcome', 'succeeded', 'failed', 'skipped', 'died', 'unresolved'];
|
|
21
20
|
export type MigrateStepStatus = (typeof MIGRATE_STEP_STATUSES)[number];
|
|
22
21
|
export declare const TERMINAL_STEP_STATUSES: ReadonlySet<MigrateStepStatus>;
|
|
23
22
|
declare const PROMPT_OUTCOME_STATUSES: readonly ['completed', 'skipped', 'failed'];
|
|
@@ -50,6 +49,8 @@ export interface MigrateStep {
|
|
|
50
49
|
depsHashAtDispense?: string;
|
|
51
50
|
outcome?: MigrateStepOutcome;
|
|
52
51
|
promptOutcome?: MigrateStepPromptOutcome;
|
|
52
|
+
adopted?: boolean;
|
|
53
|
+
unresolvedIssueId?: string;
|
|
53
54
|
awaitingKind?: MigrateStepAwaitingKind;
|
|
54
55
|
commitLedgerIndex?: number;
|
|
55
56
|
commitStarted?: boolean;
|
|
@@ -112,6 +113,7 @@ export interface MigrateRunState {
|
|
|
112
113
|
skipInstall?: boolean;
|
|
113
114
|
validate?: boolean;
|
|
114
115
|
runbookPath?: string;
|
|
116
|
+
branch?: string;
|
|
115
117
|
rounds: MigrateRunRound[];
|
|
116
118
|
steps: MigrateStep[];
|
|
117
119
|
commits: MigrateCommitLedgerEntry[];
|
|
@@ -121,7 +123,7 @@ export interface MigrateRunState {
|
|
|
121
123
|
treeOperation?: MigrateTreeOperation;
|
|
122
124
|
analytics: MigrateRunAnalytics;
|
|
123
125
|
}
|
|
124
|
-
export declare const TREE_OPERATION_KINDS: readonly ['commit', 'install', 'fold-install', 'action-install', 'reset', 'checkpoint'];
|
|
126
|
+
export declare const TREE_OPERATION_KINDS: readonly ['commit', 'install', 'fold-install', 'action-install', 'reset', 'give-up', 'checkpoint'];
|
|
125
127
|
export type MigrateTreeOperationKind = (typeof TREE_OPERATION_KINDS)[number];
|
|
126
128
|
export interface MigrateTreeOperation {
|
|
127
129
|
kind: MigrateTreeOperationKind;
|
|
@@ -135,15 +137,14 @@ export declare function runDir(root: string, runId: string): string;
|
|
|
135
137
|
/** See `HANDOFFS_DIR_NAME` for why the subtree exists. */
|
|
136
138
|
export declare function runHandoffsDir(runDirPath: string): string;
|
|
137
139
|
/**
|
|
138
|
-
* Thrown
|
|
140
|
+
* Thrown for a run.json whose `formatVersion` is newer than this Nx
|
|
139
141
|
* understands. Callers must not treat such a run as absent: an older Nx
|
|
140
142
|
* ignoring a newer active run would start a competing run on top of it.
|
|
141
143
|
*
|
|
142
|
-
* Adding a member to
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* fails) instead of refusing with this error's ask for a newer Nx.
|
|
144
|
+
* Adding a member to a persisted closed set needs a
|
|
145
|
+
* `CURRENT_RUN_STATE_FORMAT_VERSION` bump only once a released Nx can read the
|
|
146
|
+
* run, or that Nx rejects the new value as corruption instead of asking for a
|
|
147
|
+
* newer Nx.
|
|
147
148
|
*/
|
|
148
149
|
export declare class NewerRunStateFormatError extends Error {
|
|
149
150
|
constructor(message: string);
|
|
@@ -191,6 +192,7 @@ export declare function findActiveRun(root: string): {
|
|
|
191
192
|
runId: string;
|
|
192
193
|
state: MigrateRunState;
|
|
193
194
|
} | null;
|
|
195
|
+
activeRunIds: string[];
|
|
194
196
|
uninterpretable: UninterpretableRunDir[];
|
|
195
197
|
};
|
|
196
198
|
/**
|
|
@@ -82,12 +82,13 @@ const MIGRATE_STEP_STATUSES = [
|
|
|
82
82
|
'failed',
|
|
83
83
|
'skipped',
|
|
84
84
|
'died',
|
|
85
|
+
'unresolved',
|
|
85
86
|
];
|
|
86
|
-
// 'failed' and 'died'
|
|
87
|
-
// attempt.
|
|
87
|
+
// 'failed' and 'died' can be re-armed; 'unresolved' cannot.
|
|
88
88
|
exports.TERMINAL_STEP_STATUSES = new Set([
|
|
89
89
|
'succeeded',
|
|
90
90
|
'skipped',
|
|
91
|
+
'unresolved',
|
|
91
92
|
]);
|
|
92
93
|
const PROMPT_OUTCOME_STATUSES = ['completed', 'skipped', 'failed'];
|
|
93
94
|
const MIGRATE_STEP_AWAITING_KINDS = [
|
|
@@ -118,6 +119,7 @@ exports.TREE_OPERATION_KINDS = [
|
|
|
118
119
|
'fold-install',
|
|
119
120
|
'action-install',
|
|
120
121
|
'reset',
|
|
122
|
+
'give-up',
|
|
121
123
|
'checkpoint',
|
|
122
124
|
];
|
|
123
125
|
const REQUIRED_TOP_LEVEL_FIELDS = [
|
|
@@ -192,7 +194,6 @@ function isStepIdArray(value) {
|
|
|
192
194
|
function isRoundShape(value) {
|
|
193
195
|
return (isPlainObject(value) &&
|
|
194
196
|
typeof value.index === 'number' &&
|
|
195
|
-
typeof value.planHash === 'string' &&
|
|
196
197
|
typeof value.planSnapshot === 'string' &&
|
|
197
198
|
PLAN_SNAPSHOT_NAME.test(value.planSnapshot));
|
|
198
199
|
}
|
|
@@ -251,6 +252,11 @@ function isStepShape(value) {
|
|
|
251
252
|
isOptionalBoolean(value.validationOwed) &&
|
|
252
253
|
isOptionalBoolean(value.generatorMadeChanges) &&
|
|
253
254
|
isOptionalBoolean(value.installFailed) &&
|
|
255
|
+
isOptionalBoolean(value.adopted) &&
|
|
256
|
+
isOptionalMatching(exports.ISSUE_ID, value.unresolvedIssueId) &&
|
|
257
|
+
// Minted by the same write that gives the step up, so it never names a
|
|
258
|
+
// step in any other status.
|
|
259
|
+
(value.unresolvedIssueId === undefined || value.status === 'unresolved') &&
|
|
254
260
|
// A cross-field invariant the rest of the loop relies on: a running step
|
|
255
261
|
// without a pid is never reclassified as died and no step action targets
|
|
256
262
|
// it, so it stalls the run forever.
|
|
@@ -385,6 +391,7 @@ function hasValidRunStateShape(parsed) {
|
|
|
385
391
|
isOptionalBoolean(parsed.skipInstall) &&
|
|
386
392
|
isOptionalBoolean(parsed.validate) &&
|
|
387
393
|
isOptionalMatching(RUNBOOK_NAME, parsed.runbookPath) &&
|
|
394
|
+
isOptionalString(parsed.branch) &&
|
|
388
395
|
parsed.rounds.every(isRoundShape) &&
|
|
389
396
|
parsed.steps.every(isStepShape) &&
|
|
390
397
|
hasUniqueStepIds(parsed.steps) &&
|
|
@@ -398,24 +405,28 @@ function hasValidRunStateShape(parsed) {
|
|
|
398
405
|
// Written only for issues that already existed: a dangling id could make a
|
|
399
406
|
// future issue's resolution look carried by a commit that predates it.
|
|
400
407
|
parsed.commits.every((c) => c.issueIds === undefined ||
|
|
401
|
-
c.issueIds.every((id) => (parsed
|
|
408
|
+
c.issueIds.every((id) => hasIssueWithId(parsed, id))) &&
|
|
409
|
+
parsed.steps.every((s) => s.unresolvedIssueId === undefined ||
|
|
410
|
+
hasIssueWithId(parsed, s.unresolvedIssueId)) &&
|
|
402
411
|
isNoProgressShape(parsed.noProgress) &&
|
|
403
412
|
isTreeOperationShape(parsed.treeOperation) &&
|
|
404
413
|
isAnalyticsShape(parsed.analytics));
|
|
405
414
|
}
|
|
415
|
+
function hasIssueWithId(parsed, id) {
|
|
416
|
+
return (parsed.issues ?? []).some((i) => i.id === id);
|
|
417
|
+
}
|
|
406
418
|
function corruptRunStateError(filePath, reason) {
|
|
407
419
|
return new Error(`Corrupt run state at ${filePath}: ${reason}`);
|
|
408
420
|
}
|
|
409
421
|
/**
|
|
410
|
-
* Thrown
|
|
422
|
+
* Thrown for a run.json whose `formatVersion` is newer than this Nx
|
|
411
423
|
* understands. Callers must not treat such a run as absent: an older Nx
|
|
412
424
|
* ignoring a newer active run would start a competing run on top of it.
|
|
413
425
|
*
|
|
414
|
-
* Adding a member to
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
* fails) instead of refusing with this error's ask for a newer Nx.
|
|
426
|
+
* Adding a member to a persisted closed set needs a
|
|
427
|
+
* `CURRENT_RUN_STATE_FORMAT_VERSION` bump only once a released Nx can read the
|
|
428
|
+
* run, or that Nx rejects the new value as corruption instead of asking for a
|
|
429
|
+
* newer Nx.
|
|
419
430
|
*/
|
|
420
431
|
class NewerRunStateFormatError extends Error {
|
|
421
432
|
constructor(message) {
|
|
@@ -458,7 +469,7 @@ function readRunState(runDirPath) {
|
|
|
458
469
|
const createdBy = typeof parsed.nxVersion === 'string'
|
|
459
470
|
? `Nx ${(0, text_1.singleLine)(parsed.nxVersion)}`
|
|
460
471
|
: 'a newer version of Nx';
|
|
461
|
-
throw new NewerRunStateFormatError(`This migrate run was created with ${createdBy} (run state format v${parsed.formatVersion}), which is newer than the Nx version currently running, ${versions_1.nxVersion} (run state format v${exports.CURRENT_RUN_STATE_FORMAT_VERSION}). Re-run your migrate command with ${createdBy} or later
|
|
472
|
+
throw new NewerRunStateFormatError(`This migrate run was created with ${createdBy} (run state format v${parsed.formatVersion}), which is newer than the Nx version currently running, ${versions_1.nxVersion} (run state format v${exports.CURRENT_RUN_STATE_FORMAT_VERSION}). Re-run your migrate command with ${createdBy} or later.`);
|
|
462
473
|
}
|
|
463
474
|
if (REQUIRED_TOP_LEVEL_FIELDS.some((field) => !(field in parsed)) ||
|
|
464
475
|
!hasValidRunStateShape(parsed)) {
|
|
@@ -541,6 +552,7 @@ function readRunDirState(candidateDir) {
|
|
|
541
552
|
*/
|
|
542
553
|
function findActiveRun(root) {
|
|
543
554
|
let newest = null;
|
|
555
|
+
const activeRunIds = [];
|
|
544
556
|
const uninterpretable = [];
|
|
545
557
|
for (const entry of readDirEntries(migrateRunsDir(root))) {
|
|
546
558
|
if (!entry.isDirectory())
|
|
@@ -574,11 +586,12 @@ function findActiveRun(root) {
|
|
|
574
586
|
});
|
|
575
587
|
continue;
|
|
576
588
|
}
|
|
589
|
+
activeRunIds.push(entry.name);
|
|
577
590
|
if (!newest || state.createdAt > newest.state.createdAt) {
|
|
578
591
|
newest = { runId: entry.name, state };
|
|
579
592
|
}
|
|
580
593
|
}
|
|
581
|
-
return { active: newest, uninterpretable };
|
|
594
|
+
return { active: newest, activeRunIds, uninterpretable };
|
|
582
595
|
}
|
|
583
596
|
/**
|
|
584
597
|
* Creates a new run directory and writes its initial state, then prunes old
|
|
@@ -8,8 +8,9 @@ exports.renderRunbook = renderRunbook;
|
|
|
8
8
|
const fragments_1 = require("../agentic/prompts/fragments");
|
|
9
9
|
const types_1 = require("../agentic/types");
|
|
10
10
|
const text_1 = require("../text");
|
|
11
|
-
// A
|
|
12
|
-
//
|
|
11
|
+
// A run's reconciles and workers skip the nx.json overlay and a continue takes
|
|
12
|
+
// only `agentic` from it, but the next init reads the whole section: an edit
|
|
13
|
+
// mid-run changes what a start-fresh or a later run does.
|
|
13
14
|
const NX_JSON_MIGRATE_RULE = ` - Do not edit the \`migrate\` section of nx.json.`;
|
|
14
15
|
exports.RUNBOOK_FILE_NAME = 'RUNBOOK.md';
|
|
15
16
|
/**
|
|
@@ -71,6 +72,10 @@ function renderRunbook(ctx) {
|
|
|
71
72
|
`repeated instructions or report the blocker to the user; re-running the`,
|
|
72
73
|
`reconcile command alone changes nothing.`,
|
|
73
74
|
``,
|
|
75
|
+
`An \`existing-run\` action means no run was started because one is`,
|
|
76
|
+
`already active. Show its report to the user and let them choose between`,
|
|
77
|
+
`the two commands it lists; do not choose for them.`,
|
|
78
|
+
``,
|
|
74
79
|
`## Agent work`,
|
|
75
80
|
``,
|
|
76
81
|
`Some steps hand work back to you:`,
|
|
@@ -89,13 +94,13 @@ function renderRunbook(ctx) {
|
|
|
89
94
|
if (ctx.validate) {
|
|
90
95
|
lines.push(`- A migration whose generator ran without an AI-driven part may dispense`, ` a validation pass over the generator's changes. Scope rules for that`, ` work:`, ...(0, fragments_1.renderValidationScopeRuleLines)().map((line) => ` ${line}`), NX_JSON_MIGRATE_RULE);
|
|
91
96
|
}
|
|
92
|
-
lines.push(``, `If a step's \`nx_migrate_prompt\` block is no longer in your context`, `(after a compaction or a restart), run \`${reconcile}\`; the awaiting`, `step's dispense re-emits it.`, ``, `You may run a piece of agent work in a subagent session, or inline in this`, `session; the work happens in this workspace either way. Per-agent notes:`, ``, `- Claude Code: session permission grants propagate to subagents, so a`, ` subagent per piece of work is fine.`, `- Codex: subagents inherit the live sandbox and approval settings.`, `- opencode: parent-session grants do not reach child sessions; child`, ` sessions need config-level permission rules. Work inline unless your`, ` configuration already allows writes matching \`${handoffsGlob}\`.`, ``, `### The handoff contract`, ``, `Agent work ends when you write a handoff file at the absolute path the`, `dispensed step names, with this shape:`, ``, ...(0, fragments_1.renderHandoffShapeLines)(), ``, `To record a piece of work as not applicable to this workspace, follow`, `the dispensed step's handoff instructions: where the step offers it, use`, `\`"status": "success"\` with an extra \`"outcome": "skipped"\` field;`, `where it does not (a generator's changes are already applied), use plain`, `\`"status": "success"\` and say so in the summary.`, ``, `How to end a piece of agent work:`, ``, `1. Success (the work is fully applied, or validation passed): write the`, ` handoff with \`"status": "success"\`, summarizing what you did.`, `2. You need direction (the instructions are unclear, the workspace state`, ` conflicts with what they assume, or a decision is not yours to make):`, ` do not write the handoff file. Ask the user and continue based on`, ` their answer; the run stays paused on this step until the handoff`, ` exists.`, `3. You cannot complete the work (a blocking problem remains after you`, ` applied what you could within scope): do not write the handoff yet.`, ` Report what you found and what you tried, then ask the user how to`, ` proceed. Write \`"status": "failed"\` only when the user tells you to`, ` give up, enumerating the unresolved problems in \`summary\`; the`, ` orchestrator then offers
|
|
97
|
+
lines.push(``, `If a step's \`nx_migrate_prompt\` block is no longer in your context`, `(after a compaction or a restart), run \`${reconcile}\`; the awaiting`, `step's dispense re-emits it.`, ``, `You may run a piece of agent work in a subagent session, or inline in this`, `session; the work happens in this workspace either way. Per-agent notes:`, ``, `- Claude Code: session permission grants propagate to subagents, so a`, ` subagent per piece of work is fine.`, `- Codex: subagents inherit the live sandbox and approval settings.`, `- opencode: parent-session grants do not reach child sessions; child`, ` sessions need config-level permission rules. Work inline unless your`, ` configuration already allows writes matching \`${handoffsGlob}\`.`, ``, `### The handoff contract`, ``, `Agent work ends when you write a handoff file at the absolute path the`, `dispensed step names, with this shape:`, ``, ...(0, fragments_1.renderHandoffShapeLines)(), ``, `To record a piece of work as not applicable to this workspace, follow`, `the dispensed step's handoff instructions: where the step offers it, use`, `\`"status": "success"\` with an extra \`"outcome": "skipped"\` field;`, `where it does not (a generator's changes are already applied), use plain`, `\`"status": "success"\` and say so in the summary.`, ``, `How to end a piece of agent work:`, ``, `1. Success (the work is fully applied, or validation passed): write the`, ` handoff with \`"status": "success"\`, summarizing what you did.`, `2. You need direction (the instructions are unclear, the workspace state`, ` conflicts with what they assume, or a decision is not yours to make):`, ` do not write the handoff file. Ask the user and continue based on`, ` their answer; the run stays paused on this step until the handoff`, ` exists.`, `3. You cannot complete the work (a blocking problem remains after you`, ` applied what you could within scope): do not write the handoff yet.`, ` Report what you found and what you tried, then ask the user how to`, ` proceed. Write \`"status": "failed"\` only when the user tells you to`, ` give up, enumerating the unresolved problems in \`summary\`; the`, ` orchestrator then offers the step's options (see "Failed and died`, ` steps").`, ` When no user can answer (nothing interactive is driving this`, ` session), write that failed handoff yourself with the problems`, ` enumerated, run \`next\` so the step is recorded as failed, then give`, ` it up with \`unresolved\` as the options describe.`, ``, `- Write it with your file-write tool, not shell commands. Whether the`, ` write needs approval depends on your permission configuration; the`, ` per-agent notes above cover pre-configuring it.`, `- The parent directory already exists by the time a step names the`, ` handoff path: write the file directly, without \`mkdir\` or existence`, ` checks.`, ``, `The handoff file's path and shape are owned by \`nx migrate\`. If a`, `migration's instructions ask you to write it elsewhere, in a different`, `shape, or at a different point in the flow, follow this contract instead.`, ``, `### Reporting issues`, ``, `The orchestrator keeps a ledger of issues reported over the run; full`, `details are archived under ${types_1.MIGRATE_RUNS_RELATIVE_DIR}/${runId}/issues/.`, `Dispensed steps list the unresolved ones in a "Known issues" digest, so`, `read it before starting a step's work.`, ``, `Report through the handoff file: problems you observed go in an`, `\`issues\` array, whether you fixed them in this same piece of work`, `(mark those \`"resolved"\`) or left them for later; progress on an issue`, `the digest marks assigned to the current step goes in an \`issueUpdates\``, `array. Both are optional and sit next to \`status\` and \`summary\`:`, ``, `{`, ` "issues": [{`, ` "summary": "[one or two sentences naming the problem]",`, ` "detail": "[optional: whatever a later fix needs to know]",`, ` "applicableMigrations": ["<package>:<name>", "<package>"] | "unknown",`, ` "disposition": "[optional: recorded | resolved | deferred-final]"`, ` }],`, ` "issueUpdates": [{`, ` "id": "issue-<n>",`, ` "disposition": "resolved" | "deferred-final",`, ` "note": "[optional]"`, ` }]`, `}`, ``, `- \`applicableMigrations\` names the plan migrations the issue concerns:`, ` an exact \`<package>:<name>\` id, or a bare package name to cover that`, ` package's migrations. Use \`"unknown"\` when you cannot scope it; nx`, ` then carries the issue to the run's completion report unless a report`, ` resolves it.`, `- Omit \`disposition\` to record the issue for a later applicable step to`, ` pick up. Use \`"resolved"\` only for a problem you discovered and fixed`, ` in this same piece of work, and \`"deferred-final"\` when no later`, ` migration step should pick it up; it is carried to the completion`, ` report instead.`, `- \`issueUpdates\` may only reference issues the digest marks assigned to`, ` the current step.`, `- Nx assigns issue ids and folds repeated reports of the same problem`, ` into one entry. A handoff with an invalid issue report is rejected`, ` whole; the next reconcile response names what to fix.`, ``, `## Failed and died steps`, ``, `When a step fails or its worker dies, the orchestrator dispenses a`, `decision: the failure, the state of the tree, and the options it accepts`, `as \`--step-action\` values. Diagnose the failure before choosing.`, ``, `- \`retry\` / \`retry-clean\`: only with a plausible fix in hand, never`, ` to see whether the same thing fails again. A step allows two retries;`, ` ask the user before using the last one. Past that, no retry is`, ` accepted.`, `- \`adopt\`: the migration's result is already in the working tree (you`, ` or the user applied it by hand, or a died worker's changes landed);`, ` record it as applied.`, `- \`skip\`: the migration does not apply to this workspace.`, `- \`unresolved\`: give the migration up. Nx records the failure as a run`, ` issue, settles the tree as the option describes, and moves on. The`, ` completion report lists it, and a session Nx started for this run`, ` exits non-zero; when you drive the loop yourself, the completion`, ` block's unresolved tally and warnings are what say work remains.`, ` Withheld, with \`skip\`, when a commit of this migration's changes`, ` landed, or was started and never recorded; the dispense then offers`, ` \`adopt\` in their place.`, ``, `Present the options to the user unless the choice is clearly yours to`, `make. When no user can answer (nothing interactive is driving this`, `session), give the step up with \`unresolved\` and continue the run`, `rather than stalling on it. Where the dispense withholds it, a commit of`, `the migration may already be in history: \`adopt\` only once you have`, `inspected the tree and finished the migration; otherwise stop and`, `report.`, ``, `## Commits`, ``);
|
|
93
98
|
if (ctx.createCommits) {
|
|
94
99
|
lines.push(`Nx commits each migration's changes itself. Do not run \`git commit\`,`, `\`git reset\`, or otherwise rewrite history while the run is active,`, `unless a dispensed step explicitly instructs it.`);
|
|
95
100
|
}
|
|
96
101
|
else {
|
|
97
102
|
lines.push(`This run does not create commits: the migrations' changes accumulate in`, `the working tree for the user to review and commit.`);
|
|
98
103
|
}
|
|
99
|
-
lines.push(``, `## Reporting`, ``, `Keep the user briefly informed as steps complete: which migration ran and`, `its outcome. When the
|
|
104
|
+
lines.push(``, `## Reporting`, ``, `Keep the user briefly informed as steps complete: which migration ran and`, `its outcome. When the run is reported complete, summarize the outcome for`, `the user: what was applied, adopted, skipped, or left unresolved, and any`, `warnings the completion carries.`, ``);
|
|
100
105
|
return lines.join('\n');
|
|
101
106
|
}
|
|
@@ -23,3 +23,34 @@ export declare function withRunCreationLock<T>(root: string, fn: () => T): T;
|
|
|
23
23
|
* corrupt or newer-format run.json propagates from the read.
|
|
24
24
|
*/
|
|
25
25
|
export declare function updateRunState(runDirPath: string, apply: (fresh: MigrateRunState) => MigrateRunState | null): MigrateRunState;
|
|
26
|
+
/**
|
|
27
|
+
* Marks this process as acting on the run until it exits or releases the
|
|
28
|
+
* hold, so a `--start-fresh` elsewhere refuses to delete it. One lock file per
|
|
29
|
+
* process and run, taken under the creation lock that deletion probes under.
|
|
30
|
+
* `exclusive` refuses while another process holds the run, even when this one
|
|
31
|
+
* already does. No-op under WASM, which has no native lock.
|
|
32
|
+
*/
|
|
33
|
+
export declare function holdRunActivity(root: string, runId: string, exclusive?: boolean): void;
|
|
34
|
+
export declare function heldRunError(action: 'continuing' | 'deleting', runId: string, holders: number[] | 'unknown'): Error;
|
|
35
|
+
export declare function describeHolders(holders: number[]): string;
|
|
36
|
+
/**
|
|
37
|
+
* The hold without the creation lock: for the init that creates the run
|
|
38
|
+
* inside its own creation-lock section, so the run is never discoverable
|
|
39
|
+
* without a holder. Every other caller goes through holdRunActivity.
|
|
40
|
+
*/
|
|
41
|
+
export declare function registerRunActivity(dir: string): void;
|
|
42
|
+
export declare function releaseRunActivity(dir: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* The pids of the other live processes holding the run, from their lock
|
|
45
|
+
* names. This process's own hold is skipped: a deleting init may hold the run
|
|
46
|
+
* from its report or preflight, which is not competing work. Locks left by
|
|
47
|
+
* dead holders are free. 'unknown' under WASM, and when the folder cannot be
|
|
48
|
+
* listed, a lock cannot be probed, or a held lock's name carries no pid.
|
|
49
|
+
*/
|
|
50
|
+
export declare function liveRunActivityPids(dir: string): number[] | 'unknown';
|
|
51
|
+
/**
|
|
52
|
+
* Whether any live process, this one included, holds an activity lock on the
|
|
53
|
+
* run: for the init discovery that treats a held directory without run.json
|
|
54
|
+
* as a run being started, whichever process is starting it. Fails closed.
|
|
55
|
+
*/
|
|
56
|
+
export declare function hasAnyLiveRunActivity(dir: string): boolean;
|
|
@@ -16,12 +16,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
16
16
|
exports.withRunStateLock = withRunStateLock;
|
|
17
17
|
exports.withRunCreationLock = withRunCreationLock;
|
|
18
18
|
exports.updateRunState = updateRunState;
|
|
19
|
+
exports.holdRunActivity = holdRunActivity;
|
|
20
|
+
exports.heldRunError = heldRunError;
|
|
21
|
+
exports.describeHolders = describeHolders;
|
|
22
|
+
exports.registerRunActivity = registerRunActivity;
|
|
23
|
+
exports.releaseRunActivity = releaseRunActivity;
|
|
24
|
+
exports.liveRunActivityPids = liveRunActivityPids;
|
|
25
|
+
exports.hasAnyLiveRunActivity = hasAnyLiveRunActivity;
|
|
26
|
+
const crypto_1 = require("crypto");
|
|
19
27
|
const fs_1 = require("fs");
|
|
20
28
|
const path_1 = require("path");
|
|
21
29
|
const native_1 = require("../../../native");
|
|
22
30
|
const run_state_1 = require("./run-state");
|
|
23
31
|
const STATE_LOCK_FILE_NAME = 'run.json.lock';
|
|
24
32
|
const CREATION_LOCK_FILE_NAME = 'init.lock';
|
|
33
|
+
const ACTIVITY_DIR_NAME = 'activity';
|
|
25
34
|
function withFileLock(lockPath, fn) {
|
|
26
35
|
if (native_1.IS_WASM) {
|
|
27
36
|
return fn();
|
|
@@ -74,3 +83,120 @@ function updateRunState(runDirPath, apply) {
|
|
|
74
83
|
return next;
|
|
75
84
|
});
|
|
76
85
|
}
|
|
86
|
+
// The activity locks this process holds, one per run dir. Each is held until
|
|
87
|
+
// the process exits (the kernel releases it) or until this process releases
|
|
88
|
+
// it: deleting the run, or handing a continue off to the workspace-local nx.
|
|
89
|
+
const heldActivity = new Map();
|
|
90
|
+
/**
|
|
91
|
+
* Marks this process as acting on the run until it exits or releases the
|
|
92
|
+
* hold, so a `--start-fresh` elsewhere refuses to delete it. One lock file per
|
|
93
|
+
* process and run, taken under the creation lock that deletion probes under.
|
|
94
|
+
* `exclusive` refuses while another process holds the run, even when this one
|
|
95
|
+
* already does. No-op under WASM, which has no native lock.
|
|
96
|
+
*/
|
|
97
|
+
function holdRunActivity(root, runId, exclusive = false) {
|
|
98
|
+
if (native_1.IS_WASM)
|
|
99
|
+
return;
|
|
100
|
+
const dir = (0, run_state_1.runDir)(root, runId);
|
|
101
|
+
if (heldActivity.has(dir) && !exclusive)
|
|
102
|
+
return;
|
|
103
|
+
withRunCreationLock(root, () => {
|
|
104
|
+
if (!(0, run_state_1.hasRunState)(dir)) {
|
|
105
|
+
throw new Error(`Migrate run '${runId}' was deleted while this command was starting.`);
|
|
106
|
+
}
|
|
107
|
+
if (exclusive) {
|
|
108
|
+
const others = liveRunActivityPids(dir);
|
|
109
|
+
if (others === 'unknown' || others.length > 0) {
|
|
110
|
+
throw heldRunError('continuing', runId, others);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
registerRunActivity(dir);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// 'unknown' is the fail-closed case: the activity folder could not be read or
|
|
117
|
+
// a lock could not be probed.
|
|
118
|
+
function heldRunError(action, runId, holders) {
|
|
119
|
+
const refusal = `Not ${action} migrate run '${runId}'`;
|
|
120
|
+
return new Error(holders === 'unknown'
|
|
121
|
+
? `${refusal}: nx cannot tell whether another nx migrate process is still working on it.`
|
|
122
|
+
: `${refusal}: ${describeHolders(holders)} (an agent session, a reconcile, or a step). Wait for it to end, then re-run the command.`);
|
|
123
|
+
}
|
|
124
|
+
function describeHolders(holders) {
|
|
125
|
+
return holders.length === 1
|
|
126
|
+
? `process ${holders[0]} is still working on it`
|
|
127
|
+
: `processes ${holders.join(', ')} are still working on it`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The hold without the creation lock: for the init that creates the run
|
|
131
|
+
* inside its own creation-lock section, so the run is never discoverable
|
|
132
|
+
* without a holder. Every other caller goes through holdRunActivity.
|
|
133
|
+
*/
|
|
134
|
+
function registerRunActivity(dir) {
|
|
135
|
+
if (native_1.IS_WASM || heldActivity.has(dir))
|
|
136
|
+
return;
|
|
137
|
+
const name = `${process.pid}-${(0, crypto_1.randomBytes)(4).toString('hex')}.lock`;
|
|
138
|
+
const lock = new native_1.FileLock((0, path_1.join)(dir, ACTIVITY_DIR_NAME, name));
|
|
139
|
+
lock.lock();
|
|
140
|
+
heldActivity.set(dir, { lock, name });
|
|
141
|
+
}
|
|
142
|
+
function releaseRunActivity(dir) {
|
|
143
|
+
const held = heldActivity.get(dir);
|
|
144
|
+
if (held === undefined)
|
|
145
|
+
return;
|
|
146
|
+
held.lock.unlock();
|
|
147
|
+
heldActivity.delete(dir);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The pids of the other live processes holding the run, from their lock
|
|
151
|
+
* names. This process's own hold is skipped: a deleting init may hold the run
|
|
152
|
+
* from its report or preflight, which is not competing work. Locks left by
|
|
153
|
+
* dead holders are free. 'unknown' under WASM, and when the folder cannot be
|
|
154
|
+
* listed, a lock cannot be probed, or a held lock's name carries no pid.
|
|
155
|
+
*/
|
|
156
|
+
function liveRunActivityPids(dir) {
|
|
157
|
+
if (native_1.IS_WASM)
|
|
158
|
+
return 'unknown';
|
|
159
|
+
const names = liveActivityNames(dir, heldActivity.get(dir)?.name);
|
|
160
|
+
if (names === 'unknown')
|
|
161
|
+
return 'unknown';
|
|
162
|
+
const pids = names.map((name) => Number(name.split('-', 1)[0]));
|
|
163
|
+
return pids.every((pid) => Number.isInteger(pid) && pid > 0)
|
|
164
|
+
? pids
|
|
165
|
+
: 'unknown';
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Whether any live process, this one included, holds an activity lock on the
|
|
169
|
+
* run: for the init discovery that treats a held directory without run.json
|
|
170
|
+
* as a run being started, whichever process is starting it. Fails closed.
|
|
171
|
+
*/
|
|
172
|
+
function hasAnyLiveRunActivity(dir) {
|
|
173
|
+
const names = liveActivityNames(dir, undefined);
|
|
174
|
+
return names === 'unknown' || names.length > 0;
|
|
175
|
+
}
|
|
176
|
+
// The names of the held lock files other than `skip`; 'unknown' when the
|
|
177
|
+
// folder cannot be listed or a lock cannot be probed.
|
|
178
|
+
function liveActivityNames(dir, skip) {
|
|
179
|
+
let names;
|
|
180
|
+
try {
|
|
181
|
+
names = (0, fs_1.readdirSync)((0, path_1.join)(dir, ACTIVITY_DIR_NAME));
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
if (e?.code === 'ENOENT')
|
|
185
|
+
return [];
|
|
186
|
+
return 'unknown';
|
|
187
|
+
}
|
|
188
|
+
const held = [];
|
|
189
|
+
for (const name of names) {
|
|
190
|
+
if (name === skip)
|
|
191
|
+
continue;
|
|
192
|
+
try {
|
|
193
|
+
if (new native_1.FileLock((0, path_1.join)(dir, ACTIVITY_DIR_NAME, name)).check()) {
|
|
194
|
+
held.push(name);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return 'unknown';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return held;
|
|
202
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CommitResult } from '../migrate-commits';
|
|
2
2
|
import type { MigrateCommitLedgerEntry, MigrateRunState, MigrateStep, MigrateStepAwaitingKind, MigrateStepOutcome, MigrateStepPromptOutcome } from './run-state';
|
|
3
|
+
import type { MigrateOrchestratorTallies } from '../migrate-analytics';
|
|
3
4
|
import type { StepAction } from '../step-actions';
|
|
4
5
|
export type { StepAction };
|
|
5
6
|
export type StepEvent = {
|
|
@@ -59,6 +60,19 @@ export declare function applyStepEvent(state: MigrateRunState, event: StepEvent)
|
|
|
59
60
|
* commit already carries its changes.
|
|
60
61
|
*/
|
|
61
62
|
export declare function discardGeneratorRun(state: MigrateRunState, stepId: string): MigrateRunState;
|
|
63
|
+
export interface StepTally {
|
|
64
|
+
applied: number;
|
|
65
|
+
adopted: number;
|
|
66
|
+
skipped: number;
|
|
67
|
+
unresolved: MigrateStep[];
|
|
68
|
+
remaining: number;
|
|
69
|
+
stalled: number;
|
|
70
|
+
}
|
|
71
|
+
export declare function tallySteps(state: MigrateRunState): StepTally;
|
|
72
|
+
export declare function runTallies(state: MigrateRunState): MigrateOrchestratorTallies;
|
|
73
|
+
export declare function unresolvedFailureDetail(step: MigrateStep): string;
|
|
74
|
+
export declare function completionSummaryLines(state: MigrateRunState): string[];
|
|
75
|
+
export declare function unresolvedCommitName(step: MigrateStep): string;
|
|
62
76
|
/**
|
|
63
77
|
* Records that the run could not install the dependency changes a step left
|
|
64
78
|
* behind. Not a {@link StepEvent}: it annotates a step instead of moving it,
|
|
@@ -102,6 +116,7 @@ export declare function stepsToPendingMigrations(state: MigrateRunState, stepIds
|
|
|
102
116
|
package: string;
|
|
103
117
|
name: string;
|
|
104
118
|
}[];
|
|
119
|
+
export declare function gitRan(result: CommitResult): boolean;
|
|
105
120
|
/**
|
|
106
121
|
* Classifies a commit attempt into the ledger entry to record, or null when
|
|
107
122
|
* there is nothing to record ('no-changes' / 'disabled'). A landed entry
|