@aifabrix/builder 2.43.0 → 2.44.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/.cursor/rules/anchor-docs.mdc +15 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +288 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +0 -1
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +99 -0
- package/lib/api/validation-runner.js +99 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +1 -1
- package/lib/app/show.js +1 -1
- package/lib/build/index.js +13 -10
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +57 -121
- package/lib/cli/setup-app.test-commands.js +179 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +62 -22
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +106 -8
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +36 -20
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +22 -10
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +495 -0
- package/lib/commands/datasource-unified-test-cli.options.js +149 -0
- package/lib/commands/datasource-validation-cli.js +129 -0
- package/lib/commands/datasource.js +105 -98
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +138 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +84 -53
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +95 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +65 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +92 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +131 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +60 -6
- package/lib/infrastructure/helpers.js +201 -29
- package/lib/infrastructure/index.js +28 -17
- package/lib/infrastructure/services.js +21 -15
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +181 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +213 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +49 -14
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +442 -0
- package/lib/utils/datasource-test-run-exit.js +58 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +234 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +134 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +89 -0
- package/lib/utils/validation-run-post-retry.js +73 -0
- package/lib/utils/validation-run-request.js +98 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate.js +4 -13
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +7 -3
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +304 -55
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +75 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +20 -4
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for external system readiness (Tier A publish / Tier B probe).
|
|
3
|
+
* No I/O; safe for unit tests.
|
|
4
|
+
*
|
|
5
|
+
* @fileoverview Readiness classification and manifest-derived identity/credential intent
|
|
6
|
+
* @author AI Fabrix Team
|
|
7
|
+
* @version 2.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unwraps `{ success, data }` API envelope or returns object if already body.
|
|
12
|
+
* @param {*} res - ApiClient / makeApiCall response
|
|
13
|
+
* @returns {Object|null}
|
|
14
|
+
*/
|
|
15
|
+
function unwrapApiData(res) {
|
|
16
|
+
if (!res || typeof res !== 'object') return null;
|
|
17
|
+
if (res.success === false) return null;
|
|
18
|
+
if (res.data !== undefined && res.data !== null) return res.data;
|
|
19
|
+
return res;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* True if object looks like dataplane PublicationResult.
|
|
24
|
+
* @param {*} obj - Parsed JSON
|
|
25
|
+
* @returns {boolean}
|
|
26
|
+
*/
|
|
27
|
+
function isPublicationResultShape(obj) {
|
|
28
|
+
return !!(obj && typeof obj === 'object' && (obj.uploadId || obj.system) && Array.isArray(obj.datasources));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns publication payload from upload API response.
|
|
33
|
+
* @param {*} res - Response from uploadApplicationViaPipeline
|
|
34
|
+
* @returns {Object|null}
|
|
35
|
+
*/
|
|
36
|
+
function unwrapPublicationResult(res) {
|
|
37
|
+
const d = unwrapApiData(res);
|
|
38
|
+
return isPublicationResultShape(d) ? d : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Tier A: readiness from published datasource row + MCP expectation.
|
|
43
|
+
* Rules: inactive/archived → Failed; MCP expected but missing → Partial; draft → Partial; published/deployed + active → Ready.
|
|
44
|
+
* @param {Object} ds - ExternalDataSourceResponse-like
|
|
45
|
+
* @param {boolean} generateMcpContract - From application config
|
|
46
|
+
* @returns {'ready'|'partial'|'failed'}
|
|
47
|
+
*/
|
|
48
|
+
function classifyDatasourceTierA(ds, generateMcpContract) {
|
|
49
|
+
const active = ds.isActive !== false;
|
|
50
|
+
const status = String(ds.status || '').toLowerCase();
|
|
51
|
+
if (!active || status === 'archived') {
|
|
52
|
+
return 'failed';
|
|
53
|
+
}
|
|
54
|
+
if (generateMcpContract === true && !ds.mcpContract) {
|
|
55
|
+
return 'partial';
|
|
56
|
+
}
|
|
57
|
+
if (status === 'draft') {
|
|
58
|
+
return 'partial';
|
|
59
|
+
}
|
|
60
|
+
if (status === 'published' || status === 'deployed') {
|
|
61
|
+
return 'ready';
|
|
62
|
+
}
|
|
63
|
+
return 'partial';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {Array<Object>} datasources - Datasource list
|
|
68
|
+
* @param {boolean} generateMcpContract
|
|
69
|
+
* @returns {{ rows: Array<{ key: string, tier: string }>, ready: number, partial: number, failed: number }}
|
|
70
|
+
*/
|
|
71
|
+
function summarizeDatasourceTiersA(datasources, generateMcpContract) {
|
|
72
|
+
const rows = [];
|
|
73
|
+
let ready = 0;
|
|
74
|
+
let partial = 0;
|
|
75
|
+
let failed = 0;
|
|
76
|
+
for (const ds of datasources || []) {
|
|
77
|
+
const key = ds.key || ds.sourceKey || 'unknown';
|
|
78
|
+
const tier = classifyDatasourceTierA(ds, generateMcpContract);
|
|
79
|
+
rows.push({ key, tier });
|
|
80
|
+
if (tier === 'ready') ready += 1;
|
|
81
|
+
else if (tier === 'partial') partial += 1;
|
|
82
|
+
else failed += 1;
|
|
83
|
+
}
|
|
84
|
+
return { rows, ready, partial, failed };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Aggregate verdict label for system readiness line.
|
|
89
|
+
* @param {{ ready: number, partial: number, failed: number }} counts
|
|
90
|
+
* @returns {'READY'|'PARTIAL'|'FAILED'}
|
|
91
|
+
*/
|
|
92
|
+
function aggregateVerdictFromCounts(counts) {
|
|
93
|
+
const { ready, partial, failed } = counts;
|
|
94
|
+
const total = ready + partial + failed;
|
|
95
|
+
if (total === 0) return 'PARTIAL';
|
|
96
|
+
if (failed === total) return 'FAILED';
|
|
97
|
+
if (failed === 0 && partial === 0) return 'READY';
|
|
98
|
+
return 'PARTIAL';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Tier B: map validation/run per-datasource result.
|
|
103
|
+
* @param {Object} row - ExternalDataSourceTestResponse-like
|
|
104
|
+
* @returns {'ready'|'partial'|'failed'}
|
|
105
|
+
*/
|
|
106
|
+
function classifyDatasourceTierB(row) {
|
|
107
|
+
if (!row || row.skipped) return 'partial';
|
|
108
|
+
if (row.success === false) return 'failed';
|
|
109
|
+
const vr = row.validationResults || {};
|
|
110
|
+
if (vr.isValid === false) return 'failed';
|
|
111
|
+
const warnings = vr.warnings || row.fieldMappingResults?.warnings;
|
|
112
|
+
const etr = row.endpointTestResults || {};
|
|
113
|
+
if (etr.success === false || etr.endpointReachable === false) return 'failed';
|
|
114
|
+
if ((Array.isArray(warnings) && warnings.length > 0) || etr.warning) return 'partial';
|
|
115
|
+
return 'ready';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* True if body matches dataplane **DatasourceTestRun** (POST /validation/run success shape).
|
|
120
|
+
* @param {*} obj
|
|
121
|
+
* @returns {boolean}
|
|
122
|
+
*/
|
|
123
|
+
function isDatasourceTestRunEnvelope(obj) {
|
|
124
|
+
if (!obj || typeof obj !== 'object') return false;
|
|
125
|
+
const ver = obj.reportVersion;
|
|
126
|
+
return typeof ver === 'string' && ver.length > 0 && 'datasourceKey' in obj;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const CONNECTIVITY_STEP_MARKERS = ['credential', 'endpoint', 'connectivity', 'live'];
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Array<*>} issues
|
|
133
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
134
|
+
*/
|
|
135
|
+
function partitionDatasourceTestRunIssues(issues) {
|
|
136
|
+
const errors = [];
|
|
137
|
+
const warnings = [];
|
|
138
|
+
for (const i of issues) {
|
|
139
|
+
if (!i || typeof i !== 'object') continue;
|
|
140
|
+
const msg = i.message || i.code || '';
|
|
141
|
+
const sev = String(i.severity || '').toLowerCase();
|
|
142
|
+
if (sev === 'blocking') errors.push(String(msg));
|
|
143
|
+
else warnings.push(String(msg));
|
|
144
|
+
}
|
|
145
|
+
return { errors, warnings };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {Object} step
|
|
150
|
+
* @returns {boolean}
|
|
151
|
+
*/
|
|
152
|
+
function stepFailureAffectsConnectivity(step) {
|
|
153
|
+
if (!step || typeof step !== 'object' || step.success !== false) return false;
|
|
154
|
+
const n = String(step.name || '').toLowerCase();
|
|
155
|
+
return CONNECTIVITY_STEP_MARKERS.some(m => n.includes(m));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Endpoint flags from integration + root status (legacy probe row shape).
|
|
160
|
+
* @param {Object} run - DatasourceTestRun
|
|
161
|
+
* @returns {{ endpointSuccess: boolean, endpointReachable: boolean, endpointWarning: boolean, endpointMessage: string|null, rootStatus: string }}
|
|
162
|
+
*/
|
|
163
|
+
function datasourceTestRunEndpointFlags(run) {
|
|
164
|
+
let endpointSuccess = true;
|
|
165
|
+
let endpointReachable = true;
|
|
166
|
+
let endpointWarning = false;
|
|
167
|
+
let endpointMessage = null;
|
|
168
|
+
const integration = run.integration;
|
|
169
|
+
if (integration && typeof integration === 'object') {
|
|
170
|
+
const ist = String(integration.status || '').toLowerCase();
|
|
171
|
+
if (ist === 'fail') {
|
|
172
|
+
endpointSuccess = false;
|
|
173
|
+
endpointReachable = false;
|
|
174
|
+
}
|
|
175
|
+
if (ist === 'warn') endpointWarning = true;
|
|
176
|
+
if (integration.summary) endpointMessage = String(integration.summary);
|
|
177
|
+
const steps = integration.stepResults;
|
|
178
|
+
if (Array.isArray(steps) && steps.some(stepFailureAffectsConnectivity)) {
|
|
179
|
+
endpointSuccess = false;
|
|
180
|
+
endpointReachable = false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const rootStatus = run.status && typeof run.status === 'string' ? run.status.toLowerCase() : '';
|
|
184
|
+
if (rootStatus === 'fail') {
|
|
185
|
+
endpointSuccess = false;
|
|
186
|
+
}
|
|
187
|
+
return { endpointSuccess, endpointReachable, endpointWarning, endpointMessage, rootStatus };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Map canonical DatasourceTestRun JSON into a legacy probe row for {@link summarizeProbeResults}.
|
|
192
|
+
* @param {Object} run
|
|
193
|
+
* @returns {Object}
|
|
194
|
+
*/
|
|
195
|
+
function datasourceTestRunToLegacyRow(run) {
|
|
196
|
+
const v = run.validation;
|
|
197
|
+
const vStatus = v && typeof v.status === 'string' ? v.status.toLowerCase() : '';
|
|
198
|
+
const issues = Array.isArray(v?.issues) ? v.issues : [];
|
|
199
|
+
const { errors, warnings } = partitionDatasourceTestRunIssues(issues);
|
|
200
|
+
const isValid = vStatus !== 'fail' && errors.length === 0;
|
|
201
|
+
const ep = datasourceTestRunEndpointFlags(run);
|
|
202
|
+
return {
|
|
203
|
+
sourceKey: run.datasourceKey,
|
|
204
|
+
key: run.datasourceKey,
|
|
205
|
+
success: ep.rootStatus !== 'fail',
|
|
206
|
+
skipped: ep.rootStatus === 'skipped',
|
|
207
|
+
validationResults: { isValid, errors, warnings },
|
|
208
|
+
endpointTestResults: {
|
|
209
|
+
success: ep.endpointSuccess,
|
|
210
|
+
endpointReachable: ep.endpointReachable,
|
|
211
|
+
message: ep.endpointMessage,
|
|
212
|
+
warning: ep.endpointWarning
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Normalize runtime probe body for Tier B display.
|
|
219
|
+
*
|
|
220
|
+
* Mapping note (plan 127: "align examples to API"):
|
|
221
|
+
* - **Upload** uses dataplane pipeline upload and returns **PublicationResult** with:
|
|
222
|
+
* - `uploadId`, `uploadStatus`, `system`, `datasources[]`, `generateMcpContract`
|
|
223
|
+
* - **Server validation (upload --verbose)** uses pipeline validate and returns:
|
|
224
|
+
* - `warnings[]` (dry-run; no publish)
|
|
225
|
+
* - **Runtime probe (--probe)** uses validation run and returns either:
|
|
226
|
+
* - legacy `{ results: ExternalDataSourceTestResponse[] }`, or
|
|
227
|
+
* - canonical **DatasourceTestRun** envelope (single success shape) which we coerce into a legacy row
|
|
228
|
+
*
|
|
229
|
+
* This helper intentionally accepts multiple shapes so the CLI output stays truthful across dataplane versions.
|
|
230
|
+
*
|
|
231
|
+
* @param {*} probeRaw - Unwrapped API data
|
|
232
|
+
* @returns {Object[]}
|
|
233
|
+
*/
|
|
234
|
+
function coerceProbeRunToResultRows(probeRaw) {
|
|
235
|
+
if (!probeRaw || typeof probeRaw !== 'object') return [];
|
|
236
|
+
if (Array.isArray(probeRaw.results) && probeRaw.results.length > 0) return probeRaw.results;
|
|
237
|
+
if (isDatasourceTestRunEnvelope(probeRaw)) return [datasourceTestRunToLegacyRow(probeRaw)];
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @param {Array<Object>} results - ExternalSystemTestResponse.results
|
|
243
|
+
* @returns {{ rows: Array<{ key: string, tier: string }>, ready: number, partial: number, failed: number, issues: Array<{ key: string, lines: string[] }> }}
|
|
244
|
+
*/
|
|
245
|
+
function summarizeProbeResults(results) {
|
|
246
|
+
const rows = [];
|
|
247
|
+
const issues = [];
|
|
248
|
+
let ready = 0;
|
|
249
|
+
let partial = 0;
|
|
250
|
+
let failed = 0;
|
|
251
|
+
for (const r of results || []) {
|
|
252
|
+
const key = r.sourceKey || r.key || 'unknown';
|
|
253
|
+
const tier = classifyDatasourceTierB(r);
|
|
254
|
+
rows.push({ key, tier });
|
|
255
|
+
if (tier === 'ready') ready += 1;
|
|
256
|
+
else if (tier === 'partial') partial += 1;
|
|
257
|
+
else failed += 1;
|
|
258
|
+
const lines = [];
|
|
259
|
+
if (r.error) lines.push(r.error);
|
|
260
|
+
const vr = r.validationResults || {};
|
|
261
|
+
if (Array.isArray(vr.errors)) vr.errors.forEach(e => lines.push(String(e)));
|
|
262
|
+
const etr = r.endpointTestResults || {};
|
|
263
|
+
if (etr.message && (tier === 'failed' || tier === 'partial')) lines.push(String(etr.message));
|
|
264
|
+
if (lines.length) issues.push({ key, lines });
|
|
265
|
+
}
|
|
266
|
+
return { rows, ready, partial, failed, issues };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Identity summary from external system manifest `system` object.
|
|
271
|
+
* @param {Object} system - manifest.system
|
|
272
|
+
* @returns {{ mode: string, attribution: string, tokenBroker: string }}
|
|
273
|
+
*/
|
|
274
|
+
function extractIdentitySummary(system) {
|
|
275
|
+
const ip = system?.identityPropagation || {};
|
|
276
|
+
const mode = ip.mode || ip.executionMode || 'system';
|
|
277
|
+
const attr = ip.attribution;
|
|
278
|
+
let attribution = 'disabled';
|
|
279
|
+
if (attr && typeof attr === 'object' && attr.enabled === true) attribution = 'enabled';
|
|
280
|
+
else if (attr === true) attribution = 'enabled';
|
|
281
|
+
const tb = ip.tokenBroker;
|
|
282
|
+
let tokenBroker = 'not configured';
|
|
283
|
+
if (tb && typeof tb === 'object' && Object.keys(tb).length > 0) {
|
|
284
|
+
tokenBroker = 'configured';
|
|
285
|
+
}
|
|
286
|
+
return { mode: String(mode), attribution, tokenBroker };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Resolves GET test URL display from authentication.variables (apikey, oauth2, etc.).
|
|
291
|
+
* @param {Object} system - manifest.system
|
|
292
|
+
* @returns {string|null} Full URL or null
|
|
293
|
+
*/
|
|
294
|
+
function resolveCredentialTestEndpointDisplay(system) {
|
|
295
|
+
const auth = system?.authentication;
|
|
296
|
+
if (!auth || typeof auth !== 'object') return null;
|
|
297
|
+
const vars = auth.variables || {};
|
|
298
|
+
const baseUrl = typeof vars.baseUrl === 'string' ? vars.baseUrl.replace(/\/$/, '') : '';
|
|
299
|
+
const testPath = vars.testEndpoint;
|
|
300
|
+
if (!testPath) return baseUrl ? `${baseUrl}/health` : null;
|
|
301
|
+
if (/^https?:\/\//i.test(testPath)) return testPath;
|
|
302
|
+
if (!baseUrl) return testPath;
|
|
303
|
+
const path = testPath.startsWith('/') ? testPath : `/${testPath}`;
|
|
304
|
+
return `${baseUrl}${path}`;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Human-readable reason for dataplane fetch errors (no stack).
|
|
309
|
+
* @param {Error} err - Network or API error
|
|
310
|
+
* @param {string} dataplaneUrl - Base URL for context
|
|
311
|
+
* @returns {string}
|
|
312
|
+
*/
|
|
313
|
+
function formatDataplaneFetchReason(err, dataplaneUrl) {
|
|
314
|
+
const msg = err && err.message ? err.message : String(err);
|
|
315
|
+
const lower = msg.toLowerCase();
|
|
316
|
+
if (lower.includes('econnrefused') || lower.includes('connection refused')) {
|
|
317
|
+
return `connection refused (${dataplaneUrl})`;
|
|
318
|
+
}
|
|
319
|
+
if (lower.includes('enotfound') || lower.includes('getaddrinfo')) {
|
|
320
|
+
return `host not reachable (${dataplaneUrl})`;
|
|
321
|
+
}
|
|
322
|
+
if (lower.includes('401') || lower.includes('unauthorized')) {
|
|
323
|
+
return 'authentication failed (401)';
|
|
324
|
+
}
|
|
325
|
+
if (lower.includes('403') || lower.includes('forbidden')) {
|
|
326
|
+
return 'forbidden (403)';
|
|
327
|
+
}
|
|
328
|
+
if (lower.includes('404')) {
|
|
329
|
+
return 'not found (404)';
|
|
330
|
+
}
|
|
331
|
+
return msg.split('\n')[0].slice(0, 200);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Next-action hints from Tier A summary.
|
|
336
|
+
* @param {string} systemKey
|
|
337
|
+
* @param {{ rows: Array<{ key: string, tier: string }> }} summary
|
|
338
|
+
* @param {boolean} generateMcpContract
|
|
339
|
+
* @returns {string[]}
|
|
340
|
+
*/
|
|
341
|
+
function buildNextActionsTierA(systemKey, summary, generateMcpContract) {
|
|
342
|
+
const lines = [];
|
|
343
|
+
const failed = summary.rows.filter(r => r.tier === 'failed').map(r => r.key);
|
|
344
|
+
const partial = summary.rows.filter(r => r.tier === 'partial').map(r => r.key);
|
|
345
|
+
if (failed.length > 0) {
|
|
346
|
+
lines.push(`Investigate failed datasource: ${failed.join(', ')}`);
|
|
347
|
+
lines.push(`Run: aifabrix datasource test-e2e ${failed[0]} --app ${systemKey}`);
|
|
348
|
+
} else if (partial.length > 0) {
|
|
349
|
+
lines.push(`Review partial datasource(s): ${partial.join(', ')}`);
|
|
350
|
+
lines.push('Run: aifabrix upload ' + systemKey + ' --probe');
|
|
351
|
+
}
|
|
352
|
+
if (generateMcpContract && partial.length > 0) {
|
|
353
|
+
lines.push('If MCP is missing on a datasource, check generateMcpContract and datasource config.');
|
|
354
|
+
}
|
|
355
|
+
if (lines.length === 0) {
|
|
356
|
+
lines.push('Use --probe for runtime verification against the live API.');
|
|
357
|
+
}
|
|
358
|
+
return lines;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
module.exports = {
|
|
362
|
+
unwrapApiData,
|
|
363
|
+
unwrapPublicationResult,
|
|
364
|
+
isPublicationResultShape,
|
|
365
|
+
classifyDatasourceTierA,
|
|
366
|
+
summarizeDatasourceTiersA,
|
|
367
|
+
aggregateVerdictFromCounts,
|
|
368
|
+
classifyDatasourceTierB,
|
|
369
|
+
summarizeProbeResults,
|
|
370
|
+
coerceProbeRunToResultRows,
|
|
371
|
+
isDatasourceTestRunEnvelope,
|
|
372
|
+
datasourceTestRunToLegacyRow,
|
|
373
|
+
extractIdentitySummary,
|
|
374
|
+
resolveCredentialTestEndpointDisplay,
|
|
375
|
+
formatDataplaneFetchReason,
|
|
376
|
+
buildNextActionsTierA
|
|
377
|
+
};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
const { formatBlockingError, formatSuccessLine } = require('./cli-test-layout-chalk');
|
|
2
|
+
/**
|
|
3
|
+
* Deploy readiness CLI output (config / deployment / runtime layers).
|
|
4
|
+
* Kept separate from upload display to satisfy file/function size rules.
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Deploy external system readiness logging
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('./logger');
|
|
13
|
+
const {
|
|
14
|
+
summarizeDatasourceTiersA,
|
|
15
|
+
aggregateVerdictFromCounts,
|
|
16
|
+
summarizeProbeResults,
|
|
17
|
+
coerceProbeRunToResultRows,
|
|
18
|
+
formatDataplaneFetchReason,
|
|
19
|
+
buildNextActionsTierA
|
|
20
|
+
} = require('./external-system-readiness-core');
|
|
21
|
+
const {
|
|
22
|
+
logSeparator,
|
|
23
|
+
logSectionTitle,
|
|
24
|
+
logDatasourceTable,
|
|
25
|
+
verdictLine,
|
|
26
|
+
logIdentityBlock,
|
|
27
|
+
logCredentialIntentBlock,
|
|
28
|
+
logDocsBlock,
|
|
29
|
+
logNextActions
|
|
30
|
+
} = require('./external-system-readiness-display-internals');
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {Array<Object>|undefined} dsFromCtx
|
|
34
|
+
* @param {Object} manifest
|
|
35
|
+
* @returns {Object[]}
|
|
36
|
+
*/
|
|
37
|
+
function resolveDeployDatasources(dsFromCtx, manifest) {
|
|
38
|
+
let datasources = Array.isArray(dsFromCtx) ? dsFromCtx : [];
|
|
39
|
+
if (datasources.length === 0 && Array.isArray(manifest.dataSources)) {
|
|
40
|
+
datasources = manifest.dataSources.map(d => ({
|
|
41
|
+
key: d.key,
|
|
42
|
+
status: d.status || 'published',
|
|
43
|
+
isActive: d.isActive !== false,
|
|
44
|
+
mcpContract: d.mcpContract
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
return datasources;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {Object} probeData
|
|
52
|
+
*/
|
|
53
|
+
function logDeployProbeDatasourceSection(probeData) {
|
|
54
|
+
const results = coerceProbeRunToResultRows(probeData);
|
|
55
|
+
const probeSummary = summarizeProbeResults(results);
|
|
56
|
+
logSectionTitle('Runtime Readiness:');
|
|
57
|
+
logDatasourceTable(probeSummary.rows, probeSummary);
|
|
58
|
+
if (probeSummary.issues.length > 0) {
|
|
59
|
+
logSeparator();
|
|
60
|
+
logSectionTitle('Key Issues:');
|
|
61
|
+
for (const { key, lines } of probeSummary.issues) {
|
|
62
|
+
logger.log(chalk.white(key));
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
logger.log(chalk.red(`- ${line}`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
logSeparator();
|
|
69
|
+
logSectionTitle('Credential Test:');
|
|
70
|
+
const anyEndpointFail = results.some(row => row?.endpointTestResults?.success === false);
|
|
71
|
+
if (anyEndpointFail) {
|
|
72
|
+
logger.log(formatBlockingError('Failed (see Key Issues / endpoint test)'));
|
|
73
|
+
} else if (probeSummary.failed > 0) {
|
|
74
|
+
logger.log(formatBlockingError('Some datasource checks failed'));
|
|
75
|
+
} else if (probeSummary.partial > 0) {
|
|
76
|
+
logger.log(chalk.yellow('⚠ Completed with warnings'));
|
|
77
|
+
} else {
|
|
78
|
+
logger.log(formatSuccessLine('Passed'));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {Object|null} systemFromDataplane
|
|
84
|
+
* @param {boolean} genMcp
|
|
85
|
+
*/
|
|
86
|
+
function logDeployContractsSection(systemFromDataplane, genMcp) {
|
|
87
|
+
if (!systemFromDataplane) return;
|
|
88
|
+
logSeparator();
|
|
89
|
+
logSectionTitle('Contracts:');
|
|
90
|
+
const mcpOk = genMcp !== false;
|
|
91
|
+
logger.log(mcpOk ? formatSuccessLine('MCP generation enabled') : chalk.gray('○ MCP generation not enabled'));
|
|
92
|
+
if (systemFromDataplane.openApiDocsPageUrl || systemFromDataplane.apiDocumentUrl) {
|
|
93
|
+
logger.log(formatSuccessLine('OpenAPI available'));
|
|
94
|
+
} else {
|
|
95
|
+
logger.log(chalk.gray('○ OpenAPI docs URL not available'));
|
|
96
|
+
}
|
|
97
|
+
logDocsBlock(systemFromDataplane);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} systemKey
|
|
102
|
+
* @param {Object|null} probeData
|
|
103
|
+
* @param {Object} summary
|
|
104
|
+
* @param {boolean} genMcp
|
|
105
|
+
*/
|
|
106
|
+
function logDeployNextActionsSection(systemKey, probeData, summary, genMcp) {
|
|
107
|
+
logSeparator();
|
|
108
|
+
if (probeData) {
|
|
109
|
+
logNextActions(
|
|
110
|
+
['Fix API credentials or permissions if endpoint tests failed'],
|
|
111
|
+
`Run: aifabrix datasource test-e2e <datasourceKey> --app ${systemKey}`
|
|
112
|
+
);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const hints = buildNextActionsTierA(systemKey, summary, genMcp);
|
|
116
|
+
const deployHints = hints.filter(h => !h.includes('aifabrix upload'));
|
|
117
|
+
const probeCmd = `Run: aifabrix deploy ${systemKey} --probe`;
|
|
118
|
+
if (!deployHints.some(h => h.includes('--probe'))) {
|
|
119
|
+
deployHints.push(probeCmd);
|
|
120
|
+
}
|
|
121
|
+
logNextActions(deployHints.slice(0, 6));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {Object} ctx
|
|
126
|
+
* @param {string} ctx.environment
|
|
127
|
+
* @param {string} ctx.dataplaneUrl
|
|
128
|
+
* @param {string} systemKey
|
|
129
|
+
* @param {Error} fetchError
|
|
130
|
+
*/
|
|
131
|
+
function logDeployReadinessFetchError(ctx, systemKey, fetchError) {
|
|
132
|
+
const { dataplaneUrl } = ctx;
|
|
133
|
+
logSeparator();
|
|
134
|
+
logger.log(chalk.yellow('⚠ Unable to fetch system details from dataplane'));
|
|
135
|
+
logger.log(chalk.yellow(`Reason: ${formatDataplaneFetchReason(fetchError, dataplaneUrl || '')}`));
|
|
136
|
+
logger.log(chalk.white('\nDeployment succeeded, but readiness could not be verified.'));
|
|
137
|
+
logSeparator();
|
|
138
|
+
logNextActions(
|
|
139
|
+
['Verify dataplane is running', 'Check network / authentication'],
|
|
140
|
+
`Retry: aifabrix deploy ${systemKey}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {Object} systemCfg
|
|
146
|
+
* @param {boolean} deploymentOk
|
|
147
|
+
* @param {Object|null} probeData
|
|
148
|
+
* @param {Object} summary
|
|
149
|
+
* @param {Object|null} [deploymentDetail] - from parseControllerDeploymentOutcome when !deploymentOk
|
|
150
|
+
*/
|
|
151
|
+
function logDeployDeploymentSubsection(deploymentOk, deploymentDetail) {
|
|
152
|
+
logSectionTitle('Deployment:');
|
|
153
|
+
if (deploymentOk) {
|
|
154
|
+
logger.log(formatSuccessLine('Controller deployment OK'));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
logger.log(formatBlockingError('Controller deployment failed'));
|
|
158
|
+
if (!deploymentDetail) {
|
|
159
|
+
logger.log(chalk.gray(' No deployment status payload was available after polling.'));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (deploymentDetail.statusLabel) {
|
|
163
|
+
logger.log(chalk.gray(` Status: ${deploymentDetail.statusLabel}`));
|
|
164
|
+
}
|
|
165
|
+
if (deploymentDetail.error) {
|
|
166
|
+
logger.log(chalk.red(` Error: ${deploymentDetail.error}`));
|
|
167
|
+
}
|
|
168
|
+
if (deploymentDetail.message) {
|
|
169
|
+
logger.log(chalk.yellow(` Message: ${deploymentDetail.message}`));
|
|
170
|
+
}
|
|
171
|
+
if (!deploymentDetail.error && !deploymentDetail.message && !deploymentDetail.statusLabel) {
|
|
172
|
+
logger.log(chalk.gray(' No error details in the deployment status response; check controller logs.'));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function logDeployConfigDeploymentRuntime(systemCfg, deploymentOk, probeData, summary, deploymentDetail) {
|
|
177
|
+
const verdict = aggregateVerdictFromCounts(summary);
|
|
178
|
+
logSeparator();
|
|
179
|
+
logger.log(verdictLine(verdict));
|
|
180
|
+
logSectionTitle('Config:');
|
|
181
|
+
logger.log(formatSuccessLine('Manifest valid'));
|
|
182
|
+
const method = systemCfg.authentication?.method || 'unknown';
|
|
183
|
+
logger.log(formatSuccessLine(`Authentication configured (${method})`));
|
|
184
|
+
logDeployDeploymentSubsection(deploymentOk, deploymentDetail);
|
|
185
|
+
logSectionTitle('Runtime:');
|
|
186
|
+
if (!probeData) {
|
|
187
|
+
logger.log(chalk.gray('⏭ Skipped (use --probe to verify)'));
|
|
188
|
+
} else {
|
|
189
|
+
logger.log(formatSuccessLine('Runtime checks completed (--probe)'));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @param {string} environment
|
|
195
|
+
* @param {string} dataplaneUrl
|
|
196
|
+
*/
|
|
197
|
+
function logDeployEnvironmentAndDataplane(environment, dataplaneUrl) {
|
|
198
|
+
logger.log('');
|
|
199
|
+
logger.log(chalk.gray(`Environment: ${environment}`));
|
|
200
|
+
logger.log(chalk.gray(`Dataplane: ${dataplaneUrl || '(unknown)'}`));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @param {Object} systemCfg
|
|
205
|
+
* @param {boolean} withProbe
|
|
206
|
+
*/
|
|
207
|
+
function logDeployIdentityAndCredentialBlocks(systemCfg, withProbe) {
|
|
208
|
+
logSeparator();
|
|
209
|
+
logIdentityBlock(systemCfg);
|
|
210
|
+
if (!withProbe) {
|
|
211
|
+
logSeparator();
|
|
212
|
+
logCredentialIntentBlock(systemCfg, false);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @param {Object} ctx
|
|
218
|
+
* @param {string} ctx.environment
|
|
219
|
+
* @param {string} ctx.dataplaneUrl
|
|
220
|
+
* @param {Object} ctx.manifest
|
|
221
|
+
* @param {Array<Object>} [ctx.datasources]
|
|
222
|
+
* @param {Object|null} ctx.systemFromDataplane
|
|
223
|
+
* @param {Error|null} ctx.fetchError
|
|
224
|
+
* @param {boolean} ctx.deploymentOk
|
|
225
|
+
* @param {Object|null} [ctx.deploymentDetail]
|
|
226
|
+
* @param {Object|null} ctx.probeData
|
|
227
|
+
*/
|
|
228
|
+
function logDeployReadinessSummary(ctx) {
|
|
229
|
+
const {
|
|
230
|
+
environment,
|
|
231
|
+
dataplaneUrl,
|
|
232
|
+
manifest,
|
|
233
|
+
datasources: dsFromCtx,
|
|
234
|
+
systemFromDataplane,
|
|
235
|
+
fetchError,
|
|
236
|
+
deploymentOk,
|
|
237
|
+
deploymentDetail,
|
|
238
|
+
probeData
|
|
239
|
+
} = ctx;
|
|
240
|
+
const systemKey = manifest.key;
|
|
241
|
+
const systemCfg = manifest.system || {};
|
|
242
|
+
const genMcp = systemCfg.generateMcpContract !== false;
|
|
243
|
+
|
|
244
|
+
logDeployEnvironmentAndDataplane(environment, dataplaneUrl);
|
|
245
|
+
|
|
246
|
+
if (fetchError) {
|
|
247
|
+
logDeployReadinessFetchError(ctx, systemKey, fetchError);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const datasources = resolveDeployDatasources(dsFromCtx, manifest);
|
|
252
|
+
const summary = summarizeDatasourceTiersA(datasources, genMcp);
|
|
253
|
+
logDeployConfigDeploymentRuntime(systemCfg, deploymentOk, probeData, summary, deploymentDetail || null);
|
|
254
|
+
|
|
255
|
+
logSeparator();
|
|
256
|
+
if (probeData) {
|
|
257
|
+
logDeployProbeDatasourceSection(probeData);
|
|
258
|
+
} else {
|
|
259
|
+
logDatasourceTable(summary.rows, summary);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
logDeployIdentityAndCredentialBlocks(systemCfg, !!probeData);
|
|
263
|
+
|
|
264
|
+
logDeployContractsSection(systemFromDataplane, genMcp);
|
|
265
|
+
logDeployNextActionsSection(systemKey, probeData, summary, genMcp);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
module.exports = {
|
|
269
|
+
logDeployReadinessSummary
|
|
270
|
+
};
|