@numa-tech/numa 1.13.4 → 1.14.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/README.md +140 -26
- package/dist/application-onboarding/client.d.ts +1 -0
- package/dist/application-onboarding/commands.d.ts +2 -0
- package/dist/application-onboarding/commands.js +41 -16
- package/dist/application-onboarding/commands.js.map +1 -1
- package/dist/application-onboarding/errors.js +1 -1
- package/dist/application-onboarding/errors.js.map +1 -1
- package/dist/application-onboarding/schemas.d.ts +8 -0
- package/dist/application-onboarding/schemas.js +4 -2
- package/dist/application-onboarding/schemas.js.map +1 -1
- package/dist/application-onboarding/scm-credentials.d.ts +5 -2
- package/dist/application-onboarding/scm-credentials.js +64 -13
- package/dist/application-onboarding/scm-credentials.js.map +1 -1
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.js +252 -15
- package/dist/command-catalog.js.map +1 -1
- package/dist/integration-bootstrap/client.d.ts +23 -0
- package/dist/integration-bootstrap/client.js +124 -0
- package/dist/integration-bootstrap/client.js.map +1 -0
- package/dist/integration-bootstrap/commands.d.ts +20 -0
- package/dist/integration-bootstrap/commands.js +129 -0
- package/dist/integration-bootstrap/commands.js.map +1 -0
- package/dist/integration-bootstrap/schemas.d.ts +422 -0
- package/dist/integration-bootstrap/schemas.js +216 -0
- package/dist/integration-bootstrap/schemas.js.map +1 -0
- package/dist/jenkins/commands.d.ts +10 -0
- package/dist/jenkins/commands.js +15 -0
- package/dist/jenkins/commands.js.map +1 -0
- package/dist/jenkins-jobs/client.d.ts +12 -12
- package/dist/jenkins-jobs/schemas.d.ts +96 -8
- package/dist/jenkins-jobs/schemas.js +2 -2
- package/dist/jenkins-jobs/schemas.js.map +1 -1
- package/dist/pipeline/client.d.ts +5 -0
- package/dist/pipeline/commands.js +2 -0
- package/dist/pipeline/commands.js.map +1 -1
- package/dist/pipeline/schemas.d.ts +6 -0
- package/dist/pipeline/schemas.js +2 -0
- package/dist/pipeline/schemas.js.map +1 -1
- package/dist/platform-build-job-replans/client.d.ts +283 -0
- package/dist/platform-build-job-replans/client.js +148 -0
- package/dist/platform-build-job-replans/client.js.map +1 -0
- package/dist/platform-build-job-replans/commands.d.ts +6 -0
- package/dist/platform-build-job-replans/commands.js +371 -0
- package/dist/platform-build-job-replans/commands.js.map +1 -0
- package/dist/platform-build-job-replans/schemas.d.ts +145 -0
- package/dist/platform-build-job-replans/schemas.js +150 -0
- package/dist/platform-build-job-replans/schemas.js.map +1 -0
- package/dist/platform-build-rollouts/client.d.ts +346 -0
- package/dist/platform-build-rollouts/client.js +153 -0
- package/dist/platform-build-rollouts/client.js.map +1 -0
- package/dist/platform-build-rollouts/commands.d.ts +98 -0
- package/dist/platform-build-rollouts/commands.js +465 -0
- package/dist/platform-build-rollouts/commands.js.map +1 -0
- package/dist/platform-build-rollouts/schemas.d.ts +348 -0
- package/dist/platform-build-rollouts/schemas.js +257 -0
- package/dist/platform-build-rollouts/schemas.js.map +1 -0
- package/dist/platform-builds/client.d.ts +147 -0
- package/dist/platform-builds/client.js +115 -0
- package/dist/platform-builds/client.js.map +1 -0
- package/dist/platform-builds/commands.d.ts +7 -0
- package/dist/platform-builds/commands.js +226 -0
- package/dist/platform-builds/commands.js.map +1 -0
- package/dist/platform-builds/schemas.d.ts +127 -0
- package/dist/platform-builds/schemas.js +66 -0
- package/dist/platform-builds/schemas.js.map +1 -0
- package/dist/publications/client.d.ts +30 -0
- package/dist/publications/client.js +6 -1
- package/dist/publications/client.js.map +1 -1
- package/dist/publications/commands.d.ts +2 -0
- package/dist/publications/commands.js +84 -5
- package/dist/publications/commands.js.map +1 -1
- package/dist/repositories/client.d.ts +6 -0
- package/dist/repositories/commands.d.ts +3 -1
- package/dist/repositories/commands.js +22 -8
- package/dist/repositories/commands.js.map +1 -1
- package/dist/repositories/errors.d.ts +2 -1
- package/dist/repositories/errors.js +4 -2
- package/dist/repositories/errors.js.map +1 -1
- package/dist/repositories/schemas.d.ts +32 -0
- package/dist/repositories/schemas.js +4 -0
- package/dist/repositories/schemas.js.map +1 -1
- package/package.json +4 -4
- package/skills/numa-create-application/SKILL.md +26 -13
- package/skills/numa-create-application/agents/openai.yaml +2 -2
- package/skills/numa-create-application/evals/evals.json +72 -12
- package/skills/numa-create-application/references/checklist.md +12 -5
- package/skills/numa-create-application/references/numa-cli.md +55 -13
- package/skills/numa-create-application/references/promote-workflows.md +63 -24
- package/skills/numa-create-application/scripts/inspect-project.mjs +1 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { resolveBackendUrl } from "../backend.js";
|
|
2
|
+
import { ensureAccessToken, fetchWithKeycloakIdentity } from "../oauth.js";
|
|
3
|
+
import { PipelineError } from "../pipeline/errors.js";
|
|
4
|
+
import { IntegrationBootstrapSessionSchema, IntegrationBootstrapStartSchema } from "./schemas.js";
|
|
5
|
+
export const INTEGRATION_BOOTSTRAP_PLAN_SESSION_ROOT = "/api/v1/admin/integration-bootstrap/jenkins-gitops-writer/plan-sessions";
|
|
6
|
+
const IDEMPOTENCY_KEY = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,199}$/u;
|
|
7
|
+
const SESSION_NO = /^ibps_[0-9a-f]{32}$/u;
|
|
8
|
+
const MAX_RESPONSE_BYTES = 1_048_576;
|
|
9
|
+
export function integrationBootstrapIdempotencyKey(value) {
|
|
10
|
+
const key = value.trim();
|
|
11
|
+
if (!IDEMPOTENCY_KEY.test(key)) {
|
|
12
|
+
throw new PipelineError("idempotency-key must be 8-200 characters, start with a letter or number, and use only letters, numbers, . _ : or -.", "INTEGRATION_BOOTSTRAP_IDEMPOTENCY_INVALID");
|
|
13
|
+
}
|
|
14
|
+
return key;
|
|
15
|
+
}
|
|
16
|
+
function sessionNo(value) {
|
|
17
|
+
const candidate = value.trim();
|
|
18
|
+
if (!SESSION_NO.test(candidate)) {
|
|
19
|
+
throw new PipelineError("Integration bootstrap session number is invalid.", "INTEGRATION_BOOTSTRAP_SESSION_INVALID");
|
|
20
|
+
}
|
|
21
|
+
return candidate;
|
|
22
|
+
}
|
|
23
|
+
function safeRequestId(response) {
|
|
24
|
+
const value = response.headers.get("x-request-id");
|
|
25
|
+
return value != null && value.length <= 256 && !/[\u0000-\u001f\u007f]/u.test(value)
|
|
26
|
+
? value
|
|
27
|
+
: undefined;
|
|
28
|
+
}
|
|
29
|
+
async function successfulBody(response) {
|
|
30
|
+
const length = response.headers.get("content-length");
|
|
31
|
+
if (length != null && Number(length) > MAX_RESPONSE_BYTES) {
|
|
32
|
+
throw new PipelineError("Integration bootstrap API response exceeded the safe CLI size limit.", "INTEGRATION_BOOTSTRAP_INVALID_RESPONSE", response.status, safeRequestId(response));
|
|
33
|
+
}
|
|
34
|
+
const text = await response.text();
|
|
35
|
+
if (Buffer.byteLength(text, "utf8") > MAX_RESPONSE_BYTES) {
|
|
36
|
+
throw new PipelineError("Integration bootstrap API response exceeded the safe CLI size limit.", "INTEGRATION_BOOTSTRAP_INVALID_RESPONSE", response.status, safeRequestId(response));
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(text);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new PipelineError("Integration bootstrap API returned non-JSON data.", "INTEGRATION_BOOTSTRAP_INVALID_RESPONSE", response.status, safeRequestId(response));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class IntegrationBootstrapClient {
|
|
46
|
+
config;
|
|
47
|
+
fetchImpl;
|
|
48
|
+
tokenProvider;
|
|
49
|
+
constructor(config, dependencies = {}) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.fetchImpl = dependencies.fetch ?? fetch;
|
|
52
|
+
this.tokenProvider = dependencies.tokenProvider ?? ensureAccessToken;
|
|
53
|
+
}
|
|
54
|
+
async authenticatedFetch(path, init = {}) {
|
|
55
|
+
const method = String(init.method ?? "GET").toUpperCase();
|
|
56
|
+
const url = resolveBackendUrl(this.config, { method, path });
|
|
57
|
+
const headers = new Headers(init.headers);
|
|
58
|
+
headers.set("Accept", "application/json");
|
|
59
|
+
if (init.body != null)
|
|
60
|
+
headers.set("Content-Type", "application/json");
|
|
61
|
+
return fetchWithKeycloakIdentity(this.config, url, () => ({ ...init, headers }), { fetch: this.fetchImpl, tokenProvider: this.tokenProvider });
|
|
62
|
+
}
|
|
63
|
+
async json(path, schema, init, expectedStatus, operation) {
|
|
64
|
+
const unknownStart = (status, requestId) => new PipelineError("Integration bootstrap start result is unknown. Do not choose a new key; rerun the same plan command with the original idempotency-key.", "INTEGRATION_BOOTSTRAP_START_RESULT_UNKNOWN", status, requestId);
|
|
65
|
+
let response;
|
|
66
|
+
try {
|
|
67
|
+
response = await this.authenticatedFetch(path, init);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof TypeError) {
|
|
71
|
+
if (operation === "start")
|
|
72
|
+
throw unknownStart();
|
|
73
|
+
throw new PipelineError("Integration bootstrap session could not be read. The plan session was not mutated; retry the same plan command and idempotency-key.", "INTEGRATION_BOOTSTRAP_READ_UNAVAILABLE");
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
if (operation === "start" && response.status >= 500) {
|
|
79
|
+
throw unknownStart(response.status, safeRequestId(response));
|
|
80
|
+
}
|
|
81
|
+
throw new PipelineError(`Integration bootstrap API HTTP ${response.status}: request failed without exposing the upstream response body.`, response.status === 401
|
|
82
|
+
? "INTEGRATION_BOOTSTRAP_AUTHENTICATION_REQUIRED"
|
|
83
|
+
: response.status === 403
|
|
84
|
+
? "INTEGRATION_BOOTSTRAP_FORBIDDEN"
|
|
85
|
+
: response.status === 409
|
|
86
|
+
? "INTEGRATION_BOOTSTRAP_CONFLICT"
|
|
87
|
+
: "INTEGRATION_BOOTSTRAP_API_ERROR", response.status, safeRequestId(response));
|
|
88
|
+
}
|
|
89
|
+
if (response.status !== expectedStatus) {
|
|
90
|
+
if (operation === "start")
|
|
91
|
+
throw unknownStart(response.status, safeRequestId(response));
|
|
92
|
+
throw new PipelineError(`Integration bootstrap API returned HTTP ${response.status}; expected ${expectedStatus}.`, "INTEGRATION_BOOTSTRAP_INVALID_RESPONSE", response.status, safeRequestId(response));
|
|
93
|
+
}
|
|
94
|
+
let body;
|
|
95
|
+
try {
|
|
96
|
+
body = await successfulBody(response);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (operation === "start" && error instanceof PipelineError) {
|
|
100
|
+
throw unknownStart(response.status, safeRequestId(response));
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
const parsed = schema.safeParse(body);
|
|
105
|
+
if (!parsed.success) {
|
|
106
|
+
if (operation === "start")
|
|
107
|
+
throw unknownStart(response.status, safeRequestId(response));
|
|
108
|
+
throw new PipelineError("Integration bootstrap API response does not match the strict secret-free plan contract.", "INTEGRATION_BOOTSTRAP_INVALID_RESPONSE", response.status, safeRequestId(response));
|
|
109
|
+
}
|
|
110
|
+
return parsed.data;
|
|
111
|
+
}
|
|
112
|
+
startPlanSession(keyValue) {
|
|
113
|
+
const key = integrationBootstrapIdempotencyKey(keyValue);
|
|
114
|
+
return this.json(INTEGRATION_BOOTSTRAP_PLAN_SESSION_ROOT, IntegrationBootstrapStartSchema, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: { "Idempotency-Key": key },
|
|
117
|
+
body: "{}"
|
|
118
|
+
}, 201, "start");
|
|
119
|
+
}
|
|
120
|
+
getPlanSession(value) {
|
|
121
|
+
return this.json(`${INTEGRATION_BOOTSTRAP_PLAN_SESSION_ROOT}/${encodeURIComponent(sessionNo(value))}`, IntegrationBootstrapSessionSchema, {}, 200, "read");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/integration-bootstrap/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAA8B,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EACL,iCAAiC,EACjC,+BAA+B,EAGhC,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,uCAAuC,GAClD,yEAAyE,CAAC;AAE5E,MAAM,eAAe,GAAG,sCAAsC,CAAC;AAC/D,MAAM,UAAU,GAAG,sBAAsB,CAAC;AAC1C,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAkBrC,MAAM,UAAU,kCAAkC,CAAC,KAAa;IAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,aAAa,CACrB,qHAAqH,EACrH,2CAA2C,CAC5C,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,aAAa,CACrB,kDAAkD,EAClD,uCAAuC,CACxC,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,QAAkB;IACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC;QAClF,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAkB;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACtD,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;QAC1D,MAAM,IAAI,aAAa,CACrB,sEAAsE,EACtE,wCAAwC,EACxC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;QACzD,MAAM,IAAI,aAAa,CACrB,sEAAsE,EACtE,wCAAwC,EACxC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,aAAa,CACrB,mDAAmD,EACnD,wCAAwC,EACxC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,0BAA0B;IAKlB,MAAM;IAJR,SAAS,CAAe;IACxB,aAAa,CAAwB;IAEtD,YACmB,MAAkB,EACnC,YAAY,GAA2C,EAAE;sBADxC,MAAM;QAGvB,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC,KAAK,IAAI,KAAK,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC,aAAa,IAAI,iBAAiB,CAAC;IACvE,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,IAAY,EAAE,IAAI,GAAgB,EAAE;QACnE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAoB,CAAC;QAC5E,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACvE,OAAO,yBAAyB,CAC9B,IAAI,CAAC,MAAM,EACX,GAAG,EACH,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,EAC5B,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAC7D,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,IAAI,CAChB,IAAY,EACZ,MAAiB,EACjB,IAAiB,EACjB,cAAsB,EACtB,SAA2B;QAE3B,MAAM,YAAY,GAAG,CAAC,MAAe,EAAE,SAAkB,EAAiB,EAAE,CAAC,IAAI,aAAa,CAC5F,wIAAwI,EACxI,4CAA4C,EAC5C,MAAM,EACN,SAAS,CACV,CAAC;QACF,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;gBAC/B,IAAI,SAAS,KAAK,OAAO;oBAAE,MAAM,YAAY,EAAE,CAAC;gBAChD,MAAM,IAAI,aAAa,CACrB,qIAAqI,EACrI,wCAAwC,CACzC,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,SAAS,KAAK,OAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBACpD,MAAM,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,IAAI,aAAa,CACrB,kCAAkC,QAAQ,CAAC,MAAM,+DAA+D,EAChH,QAAQ,CAAC,MAAM,KAAK,GAAG;gBACrB,CAAC,CAAC,+CAA+C;gBACjD,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG;oBACvB,CAAC,CAAC,iCAAiC;oBACnC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG;wBACvB,CAAC,CAAC,gCAAgC;wBAClC,CAAC,CAAC,iCAAiC,EACzC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YACvC,IAAI,SAAS,KAAK,OAAO;gBAAE,MAAM,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YACxF,MAAM,IAAI,aAAa,CACrB,2CAA2C,QAAQ,CAAC,MAAM,cAAc,cAAc,GAAG,EACzF,wCAAwC,EACxC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;QACJ,CAAC;QACD,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,SAAS,KAAK,OAAO,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBAC5D,MAAM,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,SAAS,KAAK,OAAO;gBAAE,MAAM,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YACxF,MAAM,IAAI,aAAa,CACrB,yFAAyF,EACzF,wCAAwC,EACxC,QAAQ,CAAC,MAAM,EACf,aAAa,CAAC,QAAQ,CAAC,CACxB,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,gBAAgB,CAAC,QAAgB;QAC/B,MAAM,GAAG,GAAG,kCAAkC,CAAC,QAAQ,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,IAAI,CACd,uCAAuC,EACvC,+BAA+B,EAC/B;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE;YACnC,IAAI,EAAE,IAAI;SACX,EACD,GAAG,EACH,OAAO,CACR,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,KAAa;QAC1B,OAAO,IAAI,CAAC,IAAI,CACd,GAAG,uCAAuC,IAAI,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EACpF,iCAAiC,EACjC,EAAE,EACF,GAAG,EACH,MAAM,CACP,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type IntegrationBootstrapApi } from "./client.js";
|
|
3
|
+
import type { IntegrationBootstrapSession, IntegrationBootstrapStart } from "./schemas.js";
|
|
4
|
+
export interface IntegrationBootstrapCommandDependencies {
|
|
5
|
+
clientFactory?: () => IntegrationBootstrapApi;
|
|
6
|
+
openBrowser?: (url: string) => Promise<void>;
|
|
7
|
+
sleep?: (milliseconds: number) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
interface PlanOptions {
|
|
10
|
+
idempotencyKey: string;
|
|
11
|
+
noOpen?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function stableIntegrationBootstrapOutput(value: unknown): unknown;
|
|
14
|
+
export declare function waitForIntegrationBootstrapPlan(client: Pick<IntegrationBootstrapApi, "getPlanSession">, started: IntegrationBootstrapStart, sleep?: (milliseconds: number) => Promise<void>): Promise<IntegrationBootstrapSession>;
|
|
15
|
+
export declare function executeIntegrationBootstrapPlan(api: IntegrationBootstrapApi, options: PlanOptions, openBrowser: (url: string) => Promise<void>, sleep: (milliseconds: number) => Promise<void>, notify?: (message: string) => void): Promise<{
|
|
16
|
+
started: IntegrationBootstrapStart;
|
|
17
|
+
session?: IntegrationBootstrapSession;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function registerIntegrationBootstrapCommands(program: Command, dependencies?: IntegrationBootstrapCommandDependencies): void;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import open from "open";
|
|
4
|
+
import { loadAppConfig } from "../app-config.js";
|
|
5
|
+
import { loadConfig } from "../config.js";
|
|
6
|
+
import { PipelineError, sanitizePipelineOutput } from "../pipeline/errors.js";
|
|
7
|
+
import { IntegrationBootstrapClient, integrationBootstrapIdempotencyKey } from "./client.js";
|
|
8
|
+
const TERMINAL = new Set(["SUCCEEDED", "FAILED", "EXPIRED"]);
|
|
9
|
+
function snake(key) {
|
|
10
|
+
return key.replace(/([a-z0-9])([A-Z])/gu, "$1_$2").toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
export function stableIntegrationBootstrapOutput(value) {
|
|
13
|
+
const safe = sanitizePipelineOutput(value);
|
|
14
|
+
if (Array.isArray(safe))
|
|
15
|
+
return safe.map(stableIntegrationBootstrapOutput);
|
|
16
|
+
if (safe && typeof safe === "object") {
|
|
17
|
+
return Object.fromEntries(Object.entries(safe).map(([key, item]) => [snake(key), stableIntegrationBootstrapOutput(item)]));
|
|
18
|
+
}
|
|
19
|
+
return safe;
|
|
20
|
+
}
|
|
21
|
+
async function jsonEnabled(command) {
|
|
22
|
+
return Boolean(command.optsWithGlobals().json
|
|
23
|
+
|| (await loadAppConfig()).output === "json");
|
|
24
|
+
}
|
|
25
|
+
async function output(command, payload, text) {
|
|
26
|
+
process.stdout.write(await jsonEnabled(command)
|
|
27
|
+
? `${JSON.stringify(stableIntegrationBootstrapOutput(payload), null, 2)}\n`
|
|
28
|
+
: `${String(sanitizePipelineOutput(text))}\n`);
|
|
29
|
+
}
|
|
30
|
+
function planLine(plan) {
|
|
31
|
+
const changes = plan.changes.map((change) => ` ${change.component}\t${change.action}\t${change.target}\t${change.reasonCode}`);
|
|
32
|
+
const blockers = plan.blockers.map((blocker) => ` ${blocker.component}\t${blocker.target}\t${blocker.reasonCode}`);
|
|
33
|
+
return [
|
|
34
|
+
`${plan.state}\t${plan.schemaVersion}\t${plan.profileCode}`,
|
|
35
|
+
`plan digest: ${plan.planDigest}`,
|
|
36
|
+
`review expires: ${plan.reviewExpiresAt}`,
|
|
37
|
+
"changes:",
|
|
38
|
+
...(changes.length ? changes : [" -"]),
|
|
39
|
+
"blockers:",
|
|
40
|
+
...(blockers.length ? blockers : [" -"])
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
function sessionLine(session) {
|
|
44
|
+
if (session.plan != null)
|
|
45
|
+
return planLine(session.plan);
|
|
46
|
+
const error = session.errorCode == null
|
|
47
|
+
? ""
|
|
48
|
+
: `\n${session.errorCode}: ${session.errorSummary ?? "-"}`;
|
|
49
|
+
return `${session.sessionNo}\t${session.status}${error}`;
|
|
50
|
+
}
|
|
51
|
+
function sessionSucceeded(session) {
|
|
52
|
+
return session.status === "SUCCEEDED" && session.plan?.state === "READY";
|
|
53
|
+
}
|
|
54
|
+
export async function waitForIntegrationBootstrapPlan(client, started, sleep = (milliseconds) => delay(milliseconds)) {
|
|
55
|
+
let deadline = Date.parse(started.expiresAt) + 15_000;
|
|
56
|
+
for (;;) {
|
|
57
|
+
const session = await client.getPlanSession(started.sessionNo);
|
|
58
|
+
if (TERMINAL.has(session.status))
|
|
59
|
+
return session;
|
|
60
|
+
const serverDeadline = Date.parse(session.expiresAt) + 15_000;
|
|
61
|
+
if (Number.isFinite(serverDeadline))
|
|
62
|
+
deadline = Math.max(deadline, serverDeadline);
|
|
63
|
+
if (!Number.isFinite(deadline) || Date.now() >= deadline) {
|
|
64
|
+
throw new PipelineError("Integration bootstrap plan did not finish before its fresh authorization session expired. Rerun the same plan command with the original idempotency-key to inspect the same session.", "INTEGRATION_BOOTSTRAP_SESSION_EXPIRED", 409);
|
|
65
|
+
}
|
|
66
|
+
await sleep(1_000);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function executeIntegrationBootstrapPlan(api, options, openBrowser, sleep, notify = (message) => process.stderr.write(message)) {
|
|
70
|
+
const key = integrationBootstrapIdempotencyKey(options.idempotencyKey);
|
|
71
|
+
const started = await api.startPlanSession(key);
|
|
72
|
+
if (options.noOpen && !TERMINAL.has(started.status))
|
|
73
|
+
return { started };
|
|
74
|
+
if (started.loginUrl != null) {
|
|
75
|
+
notify(`正在打开一次性 Keycloak 管理员登录(session ${started.sessionNo})…\n`);
|
|
76
|
+
try {
|
|
77
|
+
await openBrowser(started.loginUrl);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
notify(`无法自动打开浏览器,请手动打开:\n${started.loginUrl}\n`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { started, session: await waitForIntegrationBootstrapPlan(api, started, sleep) };
|
|
84
|
+
}
|
|
85
|
+
function addExamples(command, values, notes) {
|
|
86
|
+
return command.addHelpText("after", `\n说明:\n${notes.map((value) => ` - ${value}`).join("\n")}\n\nExamples:\n${values.map((value) => ` ${value}`).join("\n")}\n`);
|
|
87
|
+
}
|
|
88
|
+
export function registerIntegrationBootstrapCommands(program, dependencies = {}) {
|
|
89
|
+
const client = () => dependencies.clientFactory?.()
|
|
90
|
+
?? new IntegrationBootstrapClient(loadConfig("platform"));
|
|
91
|
+
const openBrowser = dependencies.openBrowser ?? (async (url) => { await open(url); });
|
|
92
|
+
const sleep = dependencies.sleep ?? ((milliseconds) => delay(milliseconds));
|
|
93
|
+
const integration = program.command("integration")
|
|
94
|
+
.description("审阅平台固定的外部系统集成 bootstrap 计划");
|
|
95
|
+
const bootstrap = integration.command("bootstrap")
|
|
96
|
+
.description("通过新鲜管理员网页登录生成只读、无密钥的集成计划")
|
|
97
|
+
.addHelpText("after", `
|
|
98
|
+
安全边界:
|
|
99
|
+
仅生成 jenkins-gitops-writer 的服务端固定计划;没有 apply、status、retry 或 reconcile 命令。
|
|
100
|
+
realm、client、role、Jenkins instance、credential 元数据均由服务端固定,CLI 不接受覆盖参数。
|
|
101
|
+
CLI 不接收、读取或输出管理员 token、client secret、Jenkins password 或 Secret 响应。
|
|
102
|
+
POST 结果未知时不得换键;逐字重跑同一 plan 命令和原 Idempotency-Key,只会恢复同一 session。
|
|
103
|
+
`);
|
|
104
|
+
addExamples(bootstrap.command("plan")
|
|
105
|
+
.description("新鲜登录后只读检查 Keycloak 与 Jenkins inventory,并返回可审阅摘要")
|
|
106
|
+
.requiredOption("--idempotency-key <key>", "8-200 字符稳定键;未知结果重试必须原样复用")
|
|
107
|
+
.option("--no-open", "不打开浏览器;返回一次性 login URL 和 sessionNo")
|
|
108
|
+
.action(async (options, command) => {
|
|
109
|
+
const result = await executeIntegrationBootstrapPlan(client(), { idempotencyKey: options.idempotencyKey, noOpen: options.open === false }, openBrowser, sleep);
|
|
110
|
+
if (result.session == null) {
|
|
111
|
+
const ok = !["FAILED", "EXPIRED"].includes(result.started.status);
|
|
112
|
+
await output(command, { ok, integration_bootstrap_session: result.started }, `${result.started.sessionNo}\t${result.started.status}\n请在浏览器打开: ${result.started.loginUrl ?? "-"}`);
|
|
113
|
+
if (!ok)
|
|
114
|
+
process.exitCode = 1;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const ok = sessionSucceeded(result.session);
|
|
118
|
+
await output(command, { ok, integration_bootstrap_session: result.session }, sessionLine(result.session));
|
|
119
|
+
if (!ok)
|
|
120
|
+
process.exitCode = 1;
|
|
121
|
+
}), [
|
|
122
|
+
"numa integration bootstrap plan --idempotency-key integration-plan-20260825-01 --json",
|
|
123
|
+
"numa integration bootstrap plan --idempotency-key integration-plan-20260825-01 --no-open --json"
|
|
124
|
+
], [
|
|
125
|
+
"每个新键创建一次新鲜 Keycloak 管理员浏览器会话;同键只恢复同一 session。",
|
|
126
|
+
"READY/BLOCKED 均为只读计划结果;BLOCKED 以 ok=false 返回,不触发任何修复写入。"
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/integration-bootstrap/commands.ts"],"names":[],"mappings":"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"}
|