nexarch 0.12.8 → 0.12.10
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.
|
@@ -95,9 +95,9 @@ export async function checkIn(args) {
|
|
|
95
95
|
}
|
|
96
96
|
if (commands.length > 0) {
|
|
97
97
|
console.log("\nPending application-target commands (preview only; nothing claimed):");
|
|
98
|
-
console.log(`
|
|
98
|
+
console.log(`Workspace scope is resolved server-side from companyId=${creds.companyId}.`);
|
|
99
99
|
if (identity.companyId && identity.companyId !== creds.companyId) {
|
|
100
|
-
console.log(`Note: local identity
|
|
100
|
+
console.log(`Note: local identity workspace ${identity.companyId} differs from the credentials in use (${creds.companyId}).`);
|
|
101
101
|
}
|
|
102
102
|
for (const cmd of commands) {
|
|
103
103
|
const claimable = cmd.claimable ? "yes" : "no";
|
|
@@ -25,6 +25,36 @@ async function confirm(question) {
|
|
|
25
25
|
rl.close();
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* The ingest runs that still have to happen, one per root module.
|
|
30
|
+
*
|
|
31
|
+
* Registration records the repository; it does not record the estate. Only
|
|
32
|
+
* state does that, and state is per root module — seven of them here, each
|
|
33
|
+
* needing its own Terraform run. Naming this as a list of commands rather than
|
|
34
|
+
* a paragraph of advice is the difference between an agent finishing the job
|
|
35
|
+
* and an agent reporting "skeleton_only" and stopping, which is exactly what
|
|
36
|
+
* happened when the handoff lived only in prose at the end of a real run.
|
|
37
|
+
*/
|
|
38
|
+
function nextStepsFor(projectRef, detection) {
|
|
39
|
+
return detection.rootModules.map((root) => ({
|
|
40
|
+
rootModule: root.relative,
|
|
41
|
+
environment: root.environmentHint,
|
|
42
|
+
initialised: root.initialised,
|
|
43
|
+
command: `nexarch ingest-infra --dir ${root.relative} --project-ref ${projectRef}`,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
/** Prints the per-root ingest commands, the part that actually populates the graph. */
|
|
47
|
+
function printNextSteps(steps, registered) {
|
|
48
|
+
if (steps.length === 0)
|
|
49
|
+
return;
|
|
50
|
+
console.log(`\n${registered ? "Registered" : "Would register"} the repository — the estate itself is not in the graph yet.`);
|
|
51
|
+
console.log(`Each of the ${steps.length} root modules holds its own state and needs its own ingest:\n`);
|
|
52
|
+
for (const step of steps) {
|
|
53
|
+
const notes = [step.environment ? `${step.environment} environment` : "shared stack", step.initialised ? "initialised" : "run `terraform init` here first"].join(", ");
|
|
54
|
+
console.log(` # ${step.rootModule} — ${notes}`);
|
|
55
|
+
console.log(` ${step.command}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
28
58
|
/**
|
|
29
59
|
* Shows what a real run would write.
|
|
30
60
|
*
|
|
@@ -35,8 +65,19 @@ async function confirm(question) {
|
|
|
35
65
|
*/
|
|
36
66
|
function reportDryRun(params) {
|
|
37
67
|
const { asJson, projectRef, detection, entities, relationships } = params;
|
|
68
|
+
const nextSteps = nextStepsFor(projectRef, detection);
|
|
38
69
|
if (asJson) {
|
|
39
|
-
process.stdout.write(`${JSON.stringify({
|
|
70
|
+
process.stdout.write(`${JSON.stringify({
|
|
71
|
+
ok: true,
|
|
72
|
+
dryRun: true,
|
|
73
|
+
wrote: false,
|
|
74
|
+
projectRef,
|
|
75
|
+
registrationStatus: "skeleton_only",
|
|
76
|
+
enrichmentCompleted: false,
|
|
77
|
+
detection,
|
|
78
|
+
plan: { entities, relationships },
|
|
79
|
+
nextSteps,
|
|
80
|
+
}, null, 2)}\n`);
|
|
40
81
|
return;
|
|
41
82
|
}
|
|
42
83
|
console.log(`\nWould write ${entities.length} entit${entities.length === 1 ? "y" : "ies"}:`);
|
|
@@ -47,7 +88,11 @@ function reportDryRun(params) {
|
|
|
47
88
|
for (const rel of relationships)
|
|
48
89
|
console.log(` ${rel.fromEntityRef} --${rel.relationshipTypeCode}--> ${rel.toEntityRef}`);
|
|
49
90
|
}
|
|
50
|
-
|
|
91
|
+
// The dry run used to stop here, which made registration look like the whole
|
|
92
|
+
// job: a reader saw four entities and no hint that seven ingest runs were the
|
|
93
|
+
// actual work. A preview has to preview the handoff too.
|
|
94
|
+
printNextSteps(nextSteps, false);
|
|
95
|
+
console.log(`\nNothing was written. Re-run without --dry-run to register, then run the commands above.`);
|
|
51
96
|
}
|
|
52
97
|
export async function runInfrastructureOnboarding(options, detection) {
|
|
53
98
|
const { dir, nameOverride, asJson, nonInteractive, skipIngest, dryRun } = options;
|
|
@@ -132,15 +177,9 @@ export async function runInfrastructureOnboarding(options, detection) {
|
|
|
132
177
|
// the map up front — rather than letting the caller discover it through a
|
|
133
178
|
// failure — is what lets an agent finish the job unaided.
|
|
134
179
|
const roots = detection.rootModules;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
for (const root of roots) {
|
|
139
|
-
const notes = [root.environmentHint ? `${root.environmentHint} environment` : "shared stack", root.initialised ? "initialised" : "run `terraform init` here first"].join(", ");
|
|
140
|
-
console.log(` # ${root.relative} — ${notes}`);
|
|
141
|
-
console.log(` nexarch ingest-infra --dir ${root.relative} --project-ref ${projectRef}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
180
|
+
const nextSteps = nextStepsFor(projectRef, detection);
|
|
181
|
+
if (!asJson && roots.length > 1)
|
|
182
|
+
printNextSteps(nextSteps, true);
|
|
144
183
|
let ingested = false;
|
|
145
184
|
if (!skipIngest && roots.length <= 1) {
|
|
146
185
|
const shouldIngest = nonInteractive ? false : await confirm("\nRead the current state and populate the graph now?");
|
|
@@ -156,9 +195,23 @@ export async function runInfrastructureOnboarding(options, detection) {
|
|
|
156
195
|
}
|
|
157
196
|
}
|
|
158
197
|
}
|
|
198
|
+
// Registration alone is a skeleton, and saying so in the payload keeps the
|
|
199
|
+
// caller's report honest: the numbers it needs to decide "am I finished?"
|
|
200
|
+
// come from the command that did the work, not from a convention it half
|
|
201
|
+
// remembers.
|
|
202
|
+
const outstanding = ingested ? nextSteps.filter((step) => step.rootModule !== "." && roots.length > 1) : nextSteps;
|
|
159
203
|
const { file, snippet } = ciSnippetFor(detection.ciSystem, detection.ciFile);
|
|
160
204
|
if (asJson) {
|
|
161
|
-
process.stdout.write(`${JSON.stringify({
|
|
205
|
+
process.stdout.write(`${JSON.stringify({
|
|
206
|
+
ok: true,
|
|
207
|
+
projectRef,
|
|
208
|
+
registrationStatus: outstanding.length > 0 ? "skeleton_only" : "enriched",
|
|
209
|
+
enrichmentCompleted: outstanding.length === 0,
|
|
210
|
+
detection,
|
|
211
|
+
ingested,
|
|
212
|
+
nextSteps: outstanding,
|
|
213
|
+
ci: { file, snippet },
|
|
214
|
+
}, null, 2)}\n`);
|
|
162
215
|
return;
|
|
163
216
|
}
|
|
164
217
|
console.log(`\nInfrastructure changes continuously, so ingestion belongs in the pipeline, not in someone's memory.`);
|
|
@@ -166,5 +219,9 @@ export async function runInfrastructureOnboarding(options, detection) {
|
|
|
166
219
|
console.log(snippet);
|
|
167
220
|
console.log(`\nNEXARCH_TOKEN is a service credential — create one in the workspace under`);
|
|
168
221
|
console.log(`Discovery → Agents, then store it as a masked CI variable.`);
|
|
222
|
+
if (outstanding.length > 0) {
|
|
223
|
+
console.log(`\nThis run registered the repository only. Until the ${outstanding.length} ingest command${outstanding.length === 1 ? "" : "s"} above`);
|
|
224
|
+
console.log(`have run, the graph knows the repo exists but nothing it provisions.`);
|
|
225
|
+
}
|
|
169
226
|
}
|
|
170
227
|
export { detectInfrastructureProject };
|