@aifabrix/builder 2.44.5 → 2.45.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/cli-layout.mdc +8 -4
- package/.cursor/rules/project-rules.mdc +1 -1
- package/README.md +15 -23
- package/integration/hubspot-test/README.md +2 -0
- package/integration/hubspot-test/test.js +5 -3
- package/jest.projects.js +104 -2
- package/lib/api/controller-health.api.js +49 -0
- package/lib/api/dimension-values.api.js +82 -0
- package/lib/api/dimensions.api.js +114 -0
- package/lib/api/external-systems.api.js +1 -0
- package/lib/api/integration-clients.api.js +168 -0
- package/lib/api/types/dimension-values.types.js +28 -0
- package/lib/api/types/dimensions.types.js +31 -0
- package/lib/api/types/integration-clients.types.js +45 -0
- package/lib/api/validation-runner.js +46 -25
- package/lib/app/deploy-config.js +11 -1
- package/lib/app/deploy-status-display.js +3 -3
- package/lib/app/deploy.js +36 -14
- package/lib/app/display.js +15 -11
- package/lib/app/helpers.js +3 -3
- package/lib/app/index.js +3 -3
- package/lib/app/push.js +46 -23
- package/lib/app/register.js +7 -6
- package/lib/app/restart-display.js +126 -0
- package/lib/app/rotate-secret.js +7 -6
- package/lib/app/run-container-start.js +12 -6
- package/lib/app/run-env-compose.js +30 -1
- package/lib/app/run-helpers.js +58 -19
- package/lib/app/run-reload-sync.js +148 -0
- package/lib/app/run-resolve-image.js +51 -1
- package/lib/app/run.js +148 -74
- package/lib/app/show-display.js +7 -0
- package/lib/app/show.js +87 -5
- package/lib/build/index.js +83 -49
- package/lib/cli/doctor-check.js +117 -0
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided.js +460 -0
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.js +31 -3
- package/lib/cli/setup-auth.js +98 -27
- package/lib/cli/setup-dev-path-commands.js +50 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
- package/lib/cli/setup-infra-up-platform-action.js +131 -0
- package/lib/cli/setup-infra.js +132 -118
- package/lib/cli/setup-integration-client.js +182 -0
- package/lib/cli/setup-parameters.js +21 -2
- package/lib/cli/setup-platform.js +102 -0
- package/lib/cli/setup-secrets.js +18 -6
- package/lib/cli/setup-utility-resolve.js +132 -0
- package/lib/cli/setup-utility.js +143 -84
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- package/lib/commands/datasource-capability-dimension-cli.js +128 -0
- package/lib/commands/datasource-capability-output.js +29 -0
- package/lib/commands/datasource-capability-relate-cli.js +140 -0
- package/lib/commands/datasource-capability.js +411 -0
- package/lib/commands/datasource-unified-test-cli.options.js +1 -1
- package/lib/commands/datasource.js +53 -13
- package/lib/commands/dev-down.js +3 -3
- package/lib/commands/dev-infra-gate.js +32 -0
- package/lib/commands/dev-init.js +13 -7
- package/lib/commands/dimension-value.js +179 -0
- package/lib/commands/dimension.js +330 -0
- package/lib/commands/integration-client.js +430 -0
- package/lib/commands/login-device.js +65 -30
- package/lib/commands/login.js +21 -10
- package/lib/commands/parameters-validate.js +78 -13
- package/lib/commands/repair-datasource-auto-rbac.js +166 -0
- package/lib/commands/repair-datasource-keys.js +10 -5
- package/lib/commands/repair-datasource.js +19 -7
- package/lib/commands/repair-env-template.js +4 -1
- package/lib/commands/repair-openapi-sync.js +172 -0
- package/lib/commands/repair-persist.js +102 -0
- package/lib/commands/repair-rbac-extract.js +27 -0
- package/lib/commands/repair-rbac-migrate.js +186 -0
- package/lib/commands/repair-rbac.js +214 -31
- package/lib/commands/repair-system-alignment.js +246 -0
- package/lib/commands/repair-system-permissions.js +168 -0
- package/lib/commands/repair.js +120 -338
- package/lib/commands/secure.js +1 -1
- package/lib/commands/setup-modes.js +468 -0
- package/lib/commands/setup-prompts.js +421 -0
- package/lib/commands/setup.js +254 -0
- package/lib/commands/teardown.js +277 -0
- package/lib/commands/up-common.js +113 -19
- package/lib/commands/up-dataplane.js +44 -19
- package/lib/commands/up-miso.js +18 -18
- package/lib/commands/upload.js +111 -23
- package/lib/commands/wizard-core-helpers.js +14 -11
- package/lib/commands/wizard-core.js +6 -5
- package/lib/commands/wizard-dataplane.js +2 -2
- package/lib/commands/wizard-entity-selection.js +4 -3
- package/lib/commands/wizard-headless.js +2 -1
- package/lib/commands/wizard.js +2 -1
- package/lib/constants/infra-compose-service-names.js +40 -0
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -0
- package/lib/core/config-normalize.js +60 -0
- package/lib/core/config-registered-controller-urls.js +54 -0
- package/lib/core/config.js +33 -50
- package/lib/core/env-reader.js +16 -3
- package/lib/core/secrets-admin-env.js +101 -0
- package/lib/core/secrets-ensure-infra.js +34 -1
- package/lib/core/secrets-ensure.js +88 -66
- package/lib/core/secrets-env-content.js +428 -0
- package/lib/core/secrets-env-declarative-expand.js +170 -0
- package/lib/core/secrets-env-write.js +29 -1
- package/lib/core/secrets-load.js +252 -0
- package/lib/core/secrets-names.js +32 -0
- package/lib/core/secrets.js +17 -757
- package/lib/datasource/capability/basic-exposure.js +76 -0
- package/lib/datasource/capability/capability-diff-slice.js +41 -0
- package/lib/datasource/capability/capability-key.js +34 -0
- package/lib/datasource/capability/capability-resolve.js +172 -0
- package/lib/datasource/capability/capability-storage-keys.js +22 -0
- package/lib/datasource/capability/copy-operations.js +348 -0
- package/lib/datasource/capability/copy-test-payload.js +139 -0
- package/lib/datasource/capability/create-operations.js +235 -0
- package/lib/datasource/capability/dimension-operations.js +151 -0
- package/lib/datasource/capability/dimension-validate.js +219 -0
- package/lib/datasource/capability/json-pointer.js +31 -0
- package/lib/datasource/capability/reference-rewrite.js +51 -0
- package/lib/datasource/capability/relate-operations.js +325 -0
- package/lib/datasource/capability/relate-validate.js +219 -0
- package/lib/datasource/capability/remove-operations.js +275 -0
- package/lib/datasource/capability/run-capability-copy.js +152 -0
- package/lib/datasource/capability/run-capability-diff.js +135 -0
- package/lib/datasource/capability/run-capability-dimension.js +291 -0
- package/lib/datasource/capability/run-capability-edit.js +377 -0
- package/lib/datasource/capability/run-capability-relate.js +193 -0
- package/lib/datasource/capability/run-capability-remove.js +105 -0
- package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
- package/lib/datasource/capability/validate-capability-slice.js +35 -0
- package/lib/datasource/list.js +136 -23
- package/lib/datasource/log-viewer.js +2 -4
- package/lib/datasource/unified-validation-run.js +51 -16
- package/lib/datasource/validate.js +53 -1
- package/lib/deployment/deploy-poll-ui.js +60 -0
- package/lib/deployment/deployer-status.js +29 -3
- package/lib/deployment/deployer.js +48 -30
- package/lib/deployment/environment.js +7 -2
- package/lib/deployment/poll-interval.js +72 -0
- package/lib/deployment/push.js +11 -9
- package/lib/external-system/deploy.js +9 -2
- package/lib/external-system/download.js +61 -32
- package/lib/external-system/sync-deploy-manifest.js +33 -0
- package/lib/infrastructure/index.js +49 -19
- package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
- package/lib/internal/node-fs.js +2 -0
- package/lib/parameters/infra-kv-discovery.js +29 -4
- package/lib/parameters/infra-parameter-catalog.js +6 -3
- package/lib/parameters/infra-parameter-validate.js +67 -19
- package/lib/resolvers/datasource-resolver.js +53 -0
- package/lib/resolvers/dimension-file.js +52 -0
- package/lib/resolvers/manifest-resolver.js +133 -0
- package/lib/schema/application-schema.json +4 -0
- package/lib/schema/external-datasource.schema.json +183 -53
- package/lib/schema/external-system.schema.json +23 -10
- package/lib/schema/infra.parameter.yaml +26 -1
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/aifabrix-config-dir-walk.js +40 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
- package/lib/utils/app-config-resolver.js +24 -1
- package/lib/utils/app-run-containers.js +2 -2
- package/lib/utils/applications-config-defaults.js +206 -0
- package/lib/utils/auth-config-validator.js +2 -12
- package/lib/utils/bash-secret-env.js +59 -0
- package/lib/utils/cli-secrets-error-format.js +78 -0
- package/lib/utils/cli-test-layout-chalk.js +31 -9
- package/lib/utils/cli-utils.js +4 -36
- package/lib/utils/compose-generate-docker-compose.js +111 -6
- package/lib/utils/compose-generator.js +17 -8
- package/lib/utils/controller-url.js +50 -7
- package/lib/utils/datasource-test-run-display.js +8 -0
- package/lib/utils/dev-hosts-helper.js +3 -2
- package/lib/utils/dev-init-ssh-merge.js +2 -1
- package/lib/utils/docker-build.js +17 -9
- package/lib/utils/docker-reload-mount.js +127 -0
- package/lib/utils/env-copy.js +99 -14
- package/lib/utils/env-template.js +5 -1
- package/lib/utils/external-readme.js +71 -2
- package/lib/utils/external-system-local-test-tty.js +3 -2
- package/lib/utils/external-system-readiness-core.js +45 -12
- package/lib/utils/external-system-readiness-deploy-display.js +3 -3
- package/lib/utils/external-system-readiness-display-internals.js +33 -3
- package/lib/utils/external-system-readiness-display.js +10 -1
- package/lib/utils/file-upload.js +40 -3
- package/lib/utils/health-check-db-init.js +107 -0
- package/lib/utils/health-check-public-warn.js +69 -0
- package/lib/utils/health-check-url.js +28 -10
- package/lib/utils/health-check.js +139 -107
- package/lib/utils/help-builder.js +5 -1
- package/lib/utils/image-name.js +34 -7
- package/lib/utils/infra-optional-service-flags.js +69 -0
- package/lib/utils/installation-log-core.js +282 -0
- package/lib/utils/installation-log-record.js +237 -0
- package/lib/utils/installation-log.js +123 -0
- package/lib/utils/integration-file-backup.js +74 -0
- package/lib/utils/log-redaction.js +105 -0
- package/lib/utils/manifest-location.js +164 -0
- package/lib/utils/manifest-source-emit.js +162 -0
- package/lib/utils/mutagen-install.js +30 -3
- package/lib/utils/paths.js +308 -76
- package/lib/utils/postgres-wipe.js +212 -0
- package/lib/utils/register-aifabrix-shell-env.js +15 -0
- package/lib/utils/remote-dev-auth.js +21 -5
- package/lib/utils/remote-docker-env.js +9 -1
- package/lib/utils/remote-secrets-loader.js +49 -4
- package/lib/utils/resolve-docker-image-ref.js +9 -3
- package/lib/utils/run-cli-flags.js +29 -0
- package/lib/utils/secrets-ancestor-paths.js +47 -0
- package/lib/utils/secrets-canonical.js +10 -3
- package/lib/utils/secrets-helpers.js +17 -10
- package/lib/utils/secrets-kv-refs.js +42 -0
- package/lib/utils/secrets-kv-scope.js +19 -2
- package/lib/utils/secrets-materialize-local.js +134 -0
- package/lib/utils/secrets-path.js +26 -13
- package/lib/utils/secrets-utils.js +20 -10
- package/lib/utils/system-builder-root.js +42 -0
- package/lib/utils/url-declarative-public-base.js +80 -12
- package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
- package/lib/utils/url-declarative-resolve-build.js +24 -388
- package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
- package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
- package/lib/utils/url-declarative-resolve.js +47 -7
- package/lib/utils/url-declarative-runtime-base-path.js +52 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
- package/lib/utils/urls-local-registry-scan.js +103 -0
- package/lib/utils/urls-local-registry.js +158 -76
- package/lib/utils/validation-poll-ui.js +81 -0
- package/lib/utils/validation-run-poll.js +29 -5
- package/lib/utils/with-muted-logger.js +53 -0
- package/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +5 -1
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/env.template +8 -6
- package/templates/applications/miso-controller/application.yaml +9 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/templates/applications/miso-controller/rbac.yaml +9 -9
- package/templates/external-system/README.md.hbs +83 -123
- package/.npmrc.token +0 -1
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/lib/api/service-users.api.js +0 -150
- package/lib/api/types/service-users.types.js +0 -65
- package/lib/cli/setup-service-user.js +0 -187
- package/lib/commands/service-user.js +0 -429
package/lib/app/show.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const logger = require('../utils/logger');
|
|
17
|
-
const { detectAppType, resolveApplicationConfigPath } = require('../utils/paths');
|
|
17
|
+
const { detectAppType, resolveApplicationConfigPath, getBuilderPath } = require('../utils/paths');
|
|
18
18
|
const { loadConfigFile } = require('../utils/config-format');
|
|
19
19
|
const generator = require('../generator');
|
|
20
20
|
const { getConfig, normalizeControllerUrl } = require('../core/config');
|
|
@@ -38,6 +38,58 @@ const {
|
|
|
38
38
|
sanitizeCertificationForJson
|
|
39
39
|
} = require('./certification-show-enrich');
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Attach `runReloadDefault` / `runProxyDefault` from ~/.aifabrix `applications.<appKey>`.
|
|
43
|
+
* @param {Object} summary
|
|
44
|
+
* @param {string} appKey
|
|
45
|
+
* @param {Object} userCfg
|
|
46
|
+
*/
|
|
47
|
+
function attachRunDefaultsFromUserConfig(summary, appKey, userCfg) {
|
|
48
|
+
const { isApplicationsReloadDefaultOn, getApplicationsRunProxyHint } = require('../utils/applications-config-defaults');
|
|
49
|
+
if (isApplicationsReloadDefaultOn(userCfg, appKey)) {
|
|
50
|
+
summary.runReloadDefault = true;
|
|
51
|
+
}
|
|
52
|
+
summary.runProxyDefault = getApplicationsRunProxyHint(userCfg, appKey);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Overlay `application.url` / `application.internalUrl` from declarative url:// rules (same profile as run `.env`, default `docker`).
|
|
57
|
+
* Used for offline and **online** show so controller metadata does not stale local proxy/TLS hints.
|
|
58
|
+
* @param {Object} summary
|
|
59
|
+
* @param {string} appKey
|
|
60
|
+
*/
|
|
61
|
+
async function attachDeclarativeUrlsToShowApplication(summary, appKey) {
|
|
62
|
+
if (!summary || summary.isExternal) return;
|
|
63
|
+
const t = summary.application && summary.application.type;
|
|
64
|
+
if (String(t || 'webapp').toLowerCase() === 'external') return;
|
|
65
|
+
try {
|
|
66
|
+
const { resolveDeclarativeShowUrlsForApp } = require('../core/secrets-env-declarative-expand');
|
|
67
|
+
const appPath = getBuilderPath(appKey);
|
|
68
|
+
const variablesPath = resolveApplicationConfigPath(appPath);
|
|
69
|
+
const urls = await resolveDeclarativeShowUrlsForApp(appKey, appPath, variablesPath, 'docker');
|
|
70
|
+
if (!urls) return;
|
|
71
|
+
summary.application.url = urls.publicUrl;
|
|
72
|
+
summary.application.internalUrl = urls.internalUrl;
|
|
73
|
+
} catch {
|
|
74
|
+
/* display-only */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Local manifest provenance for `--json` (plan 141); null when the app is not on disk locally.
|
|
80
|
+
* @param {string} appKey
|
|
81
|
+
* @returns {Promise<{ tier: string, tierLabel: string, configPath: string }|null>}
|
|
82
|
+
*/
|
|
83
|
+
async function tryGetLocalManifestSourceForJson(appKey) {
|
|
84
|
+
try {
|
|
85
|
+
const { getManifestSourcePayload } = require('../utils/manifest-source-emit');
|
|
86
|
+
const { appPath } = await detectAppType(appKey);
|
|
87
|
+
return getManifestSourcePayload(appKey, appPath);
|
|
88
|
+
} catch {
|
|
89
|
+
return { tier: 'unknown', tierLabel: 'unknown', configPath: '' };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
41
93
|
/** Truncate deployment key for display */
|
|
42
94
|
const DEPLOYMENT_KEY_TRUNCATE_LEN = 12;
|
|
43
95
|
|
|
@@ -651,16 +703,34 @@ async function loadOfflineShowSummary(appKey) {
|
|
|
651
703
|
}
|
|
652
704
|
}
|
|
653
705
|
|
|
706
|
+
async function emitShowOfflineManifestLine(appKey, json) {
|
|
707
|
+
if (json) return;
|
|
708
|
+
try {
|
|
709
|
+
const { detectAppType } = require('../utils/paths');
|
|
710
|
+
const { emitManifestMetadataLineIfTTY } = require('../utils/manifest-source-emit');
|
|
711
|
+
const { appPath } = await detectAppType(appKey);
|
|
712
|
+
emitManifestMetadataLineIfTTY(logger, { appKey, appPath, envOnly: false, json: false });
|
|
713
|
+
} catch {
|
|
714
|
+
/* ignore */
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
654
718
|
async function runOffline(appKey, json, permissionsOnly, verifyCert = false) {
|
|
655
719
|
const summary = await loadOfflineShowSummary(appKey);
|
|
720
|
+
await emitShowOfflineManifestLine(appKey, json);
|
|
721
|
+
const userCfg = await getConfig();
|
|
722
|
+
attachRunDefaultsFromUserConfig(summary, appKey, userCfg);
|
|
723
|
+
await attachDeclarativeUrlsToShowApplication(summary, appKey);
|
|
656
724
|
|
|
657
725
|
if (json) {
|
|
726
|
+
const manifestSource = await tryGetLocalManifestSourceForJson(appKey);
|
|
658
727
|
if (permissionsOnly) {
|
|
659
728
|
const out = {
|
|
660
729
|
source: summary.source,
|
|
661
730
|
path: summary.path,
|
|
662
731
|
appKey: summary.appKey,
|
|
663
|
-
permissions: summary.permissions || []
|
|
732
|
+
permissions: summary.permissions || [],
|
|
733
|
+
manifestSource
|
|
664
734
|
};
|
|
665
735
|
logger.log(JSON.stringify(out, null, 2));
|
|
666
736
|
return;
|
|
@@ -669,6 +739,9 @@ async function runOffline(appKey, json, permissionsOnly, verifyCert = false) {
|
|
|
669
739
|
source: summary.source,
|
|
670
740
|
path: summary.path,
|
|
671
741
|
appKey: summary.appKey,
|
|
742
|
+
runReloadDefault: Boolean(summary.runReloadDefault),
|
|
743
|
+
runProxyDefault: Boolean(summary.runProxyDefault),
|
|
744
|
+
manifestSource,
|
|
672
745
|
application: {
|
|
673
746
|
...summary.application,
|
|
674
747
|
roles: summary.roles,
|
|
@@ -717,13 +790,14 @@ async function fetchExternalSystemForOnline(controllerUrl, appKey, authConfig) {
|
|
|
717
790
|
}
|
|
718
791
|
}
|
|
719
792
|
|
|
720
|
-
function outputOnlineJson(summary, permissionsOnly) {
|
|
793
|
+
function outputOnlineJson(summary, permissionsOnly, manifestSource) {
|
|
721
794
|
if (permissionsOnly) {
|
|
722
795
|
const out = {
|
|
723
796
|
source: summary.source,
|
|
724
797
|
controllerUrl: summary.controllerUrl,
|
|
725
798
|
appKey: summary.appKey,
|
|
726
|
-
permissions: summary.permissions || []
|
|
799
|
+
permissions: summary.permissions || [],
|
|
800
|
+
manifestSource
|
|
727
801
|
};
|
|
728
802
|
logger.log(JSON.stringify(out, null, 2));
|
|
729
803
|
return;
|
|
@@ -733,6 +807,7 @@ function outputOnlineJson(summary, permissionsOnly) {
|
|
|
733
807
|
source: summary.source,
|
|
734
808
|
controllerUrl: summary.controllerUrl,
|
|
735
809
|
appKey: summary.appKey,
|
|
810
|
+
manifestSource,
|
|
736
811
|
application: {
|
|
737
812
|
key: app.key,
|
|
738
813
|
displayName: app.displayName,
|
|
@@ -751,6 +826,10 @@ function outputOnlineJson(summary, permissionsOnly) {
|
|
|
751
826
|
}
|
|
752
827
|
};
|
|
753
828
|
if (app.version !== undefined && app.version !== null) out.application.version = app.version;
|
|
829
|
+
if (summary.runReloadDefault) {
|
|
830
|
+
out.runReloadDefault = true;
|
|
831
|
+
}
|
|
832
|
+
out.runProxyDefault = Boolean(summary.runProxyDefault);
|
|
754
833
|
if (summary.externalSystem !== undefined && summary.externalSystem !== null) {
|
|
755
834
|
out.externalSystem = summary.externalSystem && summary.externalSystem.error
|
|
756
835
|
? { error: summary.externalSystem.error }
|
|
@@ -787,8 +866,11 @@ async function runOnline(appKey, json, permissionsOnly, verifyCert = false) {
|
|
|
787
866
|
token: authConfig.token,
|
|
788
867
|
controllerUrl: authResult.actualControllerUrl
|
|
789
868
|
});
|
|
869
|
+
attachRunDefaultsFromUserConfig(summary, appKey, await getConfig());
|
|
870
|
+
await attachDeclarativeUrlsToShowApplication(summary, appKey);
|
|
790
871
|
if (json) {
|
|
791
|
-
|
|
872
|
+
const manifestSource = await tryGetLocalManifestSourceForJson(appKey);
|
|
873
|
+
outputOnlineJson(summary, permissionsOnly, manifestSource);
|
|
792
874
|
return;
|
|
793
875
|
}
|
|
794
876
|
displayShow(summary, { permissionsOnly: !!permissionsOnly });
|
package/lib/build/index.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const {
|
|
2
|
+
formatSuccessLine,
|
|
3
|
+
formatSuccessParagraph,
|
|
4
|
+
formatProgress,
|
|
5
|
+
formatWarningLine,
|
|
6
|
+
sectionTitle,
|
|
7
|
+
headerKeyValue,
|
|
8
|
+
metadata,
|
|
9
|
+
formatNextActions
|
|
10
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
2
11
|
/**
|
|
3
12
|
* AI Fabrix Builder Build Functions
|
|
4
13
|
*
|
|
@@ -18,7 +27,6 @@ const paths = require('../utils/paths');
|
|
|
18
27
|
const { detectAppType, getProjectRoot } = require('../utils/paths');
|
|
19
28
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
20
29
|
const { loadConfigFile } = require('../utils/config-format');
|
|
21
|
-
const chalk = require('chalk');
|
|
22
30
|
const secrets = require('../core/secrets');
|
|
23
31
|
const config = require('../core/config');
|
|
24
32
|
const logger = require('../utils/logger');
|
|
@@ -28,6 +36,7 @@ const buildCopy = require('../utils/build-copy');
|
|
|
28
36
|
const { buildDevImageName } = require('../utils/image-name');
|
|
29
37
|
const buildHelpers = require('../utils/build-helpers');
|
|
30
38
|
const secretsEnvWrite = require('../core/secrets-env-write');
|
|
39
|
+
const { ensureRunSecretsForApp } = require('../app/run-env-compose');
|
|
31
40
|
|
|
32
41
|
/**
|
|
33
42
|
* Loads application config for an application
|
|
@@ -187,12 +196,13 @@ async function generateDockerfile(appNameOrPath, language, config, buildConfig =
|
|
|
187
196
|
|
|
188
197
|
async function postBuildTasks(appName, buildConfig) {
|
|
189
198
|
try {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
//
|
|
193
|
-
|
|
199
|
+
// Validate that env.template + secrets resolve cleanly, but never write <appPath>/.env or
|
|
200
|
+
// envOutputPath. Build args still flow through resolveAndGetEnvMap (in-memory). Run
|
|
201
|
+
// `aifabrix resolve <app>` to materialize an on-disk .env.
|
|
202
|
+
await secrets.generateEnvFile(appName, buildConfig.secrets, 'docker', false, { noWrite: true });
|
|
203
|
+
logger.log(formatSuccessLine('Env resolution validated (in-memory only; run "aifabrix resolve ' + appName + '" for on-disk .env)'));
|
|
194
204
|
} catch (error) {
|
|
195
|
-
logger.log(
|
|
205
|
+
logger.log(formatWarningLine(`Could not resolve env: ${error.message}`));
|
|
196
206
|
}
|
|
197
207
|
}
|
|
198
208
|
|
|
@@ -205,8 +215,11 @@ async function postBuildTasks(appName, buildConfig) {
|
|
|
205
215
|
async function checkExternalAppType(appName) {
|
|
206
216
|
const variables = await loadVariablesYaml(appName);
|
|
207
217
|
if (variables.app && variables.app.type === 'external') {
|
|
208
|
-
logger.log(
|
|
209
|
-
logger.log(
|
|
218
|
+
logger.log('');
|
|
219
|
+
logger.log(sectionTitle('External integration'));
|
|
220
|
+
logger.log(headerKeyValue('Application:', appName));
|
|
221
|
+
logger.log(metadata('No Docker image is built for external systems.'));
|
|
222
|
+
logger.log(formatNextActions([`aifabrix json ${appName}`]));
|
|
210
223
|
return true;
|
|
211
224
|
}
|
|
212
225
|
return false;
|
|
@@ -269,9 +282,9 @@ async function prepareDevDirectory(appName, buildConfig, options) {
|
|
|
269
282
|
const developerId = await config.getDeveloperId();
|
|
270
283
|
const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
|
|
271
284
|
const directoryName = idNum === 0 ? 'applications' : `dev-${developerId}`;
|
|
272
|
-
logger.log(
|
|
285
|
+
logger.log(formatProgress(`Copying workspace (${directoryName})…`));
|
|
273
286
|
const devDir = await buildCopy.copyBuilderToDevDirectory(appName, developerId);
|
|
274
|
-
logger.log(formatSuccessLine(`
|
|
287
|
+
logger.log(formatSuccessLine(`Workspace ready: ${devDir}`));
|
|
275
288
|
|
|
276
289
|
const { config: appConfig, imageName } = await buildHelpers.loadAndValidateConfig(appName);
|
|
277
290
|
const effectiveImageName = buildDevImageName(imageName, developerId);
|
|
@@ -297,8 +310,11 @@ function prepareBuildContext(buildConfig, devDir) {
|
|
|
297
310
|
// Check if context is using old format (../appName) - these are incompatible with dev directory structure
|
|
298
311
|
if (buildConfig.context && buildConfig.context.startsWith('../') && buildConfig.context !== '../..') {
|
|
299
312
|
// Old format detected - always use devDir instead
|
|
300
|
-
logger.log(
|
|
301
|
-
|
|
313
|
+
logger.log(
|
|
314
|
+
formatWarningLine(
|
|
315
|
+
`Build context uses legacy path (${buildConfig.context}). Using dev workspace: ${devDir}`
|
|
316
|
+
)
|
|
317
|
+
);
|
|
302
318
|
contextPath = devDir;
|
|
303
319
|
} else if (buildConfig.context && buildConfig.context !== '../..') {
|
|
304
320
|
// Resolve relative context path from dev directory
|
|
@@ -370,6 +386,56 @@ async function handleDockerfileGeneration(appName, params, options, buildHelpers
|
|
|
370
386
|
}, generateDockerfile);
|
|
371
387
|
}
|
|
372
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Resolve Docker build-args from resolved env map and merged BASH_* secrets.
|
|
391
|
+
* @param {string} appName
|
|
392
|
+
* @returns {Promise<Object.<string, string>>}
|
|
393
|
+
*/
|
|
394
|
+
async function resolveDockerBuildArgsForApp(appName) {
|
|
395
|
+
const envMap = await secretsEnvWrite.resolveAndGetEnvMap(appName, { environment: 'docker' });
|
|
396
|
+
const { getBashPrefixedProcessEnvOverlay } = require('../utils/bash-secret-env');
|
|
397
|
+
const bashOverlay = await getBashPrefixedProcessEnvOverlay(null, appName);
|
|
398
|
+
const buildArgs = {};
|
|
399
|
+
if (envMap.NPM_TOKEN) buildArgs.NPM_TOKEN = envMap.NPM_TOKEN;
|
|
400
|
+
if (envMap.PYPI_TOKEN) buildArgs.PYPI_TOKEN = envMap.PYPI_TOKEN;
|
|
401
|
+
for (const [k, v] of Object.entries(bashOverlay)) {
|
|
402
|
+
if (v && buildArgs[k] === undefined) buildArgs[k] = v;
|
|
403
|
+
}
|
|
404
|
+
return buildArgs;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Standard Docker build path after CLI header is printed (non-external apps).
|
|
409
|
+
* @param {string} appName
|
|
410
|
+
* @param {Object} options
|
|
411
|
+
* @returns {Promise<string>} Built image ref e.g. name:tag
|
|
412
|
+
*/
|
|
413
|
+
async function runStandardDockerBuild(appName, options) {
|
|
414
|
+
const { buildConfig } = await buildHelpers.loadAndValidateConfig(appName);
|
|
415
|
+
const { emitManifestMetadataLineIfTTY } = require('../utils/manifest-source-emit');
|
|
416
|
+
const { appPath } = await detectAppType(appName);
|
|
417
|
+
emitManifestMetadataLineIfTTY(logger, { appKey: appName, appPath, envOnly: false, json: false });
|
|
418
|
+
const { devDir, effectiveImageName, imageName, appConfig } = await prepareDevDirectory(appName, buildConfig, options);
|
|
419
|
+
const contextPath = prepareBuildContext(buildConfig, devDir);
|
|
420
|
+
const dockerfilePath = await handleDockerfileGeneration(appName, {
|
|
421
|
+
devDir,
|
|
422
|
+
buildConfig,
|
|
423
|
+
contextPath,
|
|
424
|
+
appConfig
|
|
425
|
+
}, options, buildHelpers);
|
|
426
|
+
await ensureRunSecretsForApp(appName);
|
|
427
|
+
const buildArgs = await resolveDockerBuildArgsForApp(appName);
|
|
428
|
+
const buildOptions = { ...options, buildArgs };
|
|
429
|
+
const tag = options.tag || 'latest';
|
|
430
|
+
if (typeof tag === 'string' && tag.includes(',')) {
|
|
431
|
+
throw new Error('Use a single image tag per build (comma-separated multiple tags are not supported).');
|
|
432
|
+
}
|
|
433
|
+
await dockerBuild.executeDockerBuildWithTag(effectiveImageName, imageName, dockerfilePath, contextPath, tag, buildOptions);
|
|
434
|
+
await postBuildTasks(appName, buildConfig);
|
|
435
|
+
logger.log(formatSuccessParagraph('Build completed successfully!'));
|
|
436
|
+
return `${effectiveImageName}:${tag}`;
|
|
437
|
+
}
|
|
438
|
+
|
|
373
439
|
/**
|
|
374
440
|
* Builds a container image for the specified application
|
|
375
441
|
* Auto-detects runtime and generates Dockerfile if needed
|
|
@@ -395,42 +461,10 @@ async function buildApp(appName, options = {}) {
|
|
|
395
461
|
}
|
|
396
462
|
|
|
397
463
|
try {
|
|
398
|
-
logger.log(
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
// 2. Prepare dev directory and copy files
|
|
404
|
-
const { devDir, effectiveImageName, imageName, appConfig } = await prepareDevDirectory(appName, buildConfig, options);
|
|
405
|
-
|
|
406
|
-
// 3. Prepare build context
|
|
407
|
-
const contextPath = prepareBuildContext(buildConfig, devDir);
|
|
408
|
-
|
|
409
|
-
// 4. Handle Dockerfile generation
|
|
410
|
-
const dockerfilePath = await handleDockerfileGeneration(appName, {
|
|
411
|
-
devDir,
|
|
412
|
-
buildConfig,
|
|
413
|
-
contextPath,
|
|
414
|
-
appConfig
|
|
415
|
-
}, options, buildHelpers);
|
|
416
|
-
|
|
417
|
-
// 5. Resolve NPM_TOKEN/PYPI_TOKEN for private registries and pass as build-args
|
|
418
|
-
const envMap = await secretsEnvWrite.resolveAndGetEnvMap(appName, { environment: 'docker' });
|
|
419
|
-
const buildArgs = {};
|
|
420
|
-
if (envMap.NPM_TOKEN) buildArgs.NPM_TOKEN = envMap.NPM_TOKEN;
|
|
421
|
-
if (envMap.PYPI_TOKEN) buildArgs.PYPI_TOKEN = envMap.PYPI_TOKEN;
|
|
422
|
-
const buildOptions = { ...options, buildArgs };
|
|
423
|
-
|
|
424
|
-
// 6. Execute Docker build
|
|
425
|
-
const tag = options.tag || 'latest';
|
|
426
|
-
await dockerBuild.executeDockerBuildWithTag(effectiveImageName, imageName, dockerfilePath, contextPath, tag, buildOptions);
|
|
427
|
-
|
|
428
|
-
// 7. Post-build tasks
|
|
429
|
-
await postBuildTasks(appName, buildConfig);
|
|
430
|
-
|
|
431
|
-
logger.log(formatSuccessParagraph('Build completed successfully!'));
|
|
432
|
-
return `${imageName}:${tag}`;
|
|
433
|
-
|
|
464
|
+
logger.log('');
|
|
465
|
+
logger.log(sectionTitle('Build'));
|
|
466
|
+
logger.log(headerKeyValue('Application:', appName));
|
|
467
|
+
return await runStandardDockerBuild(appName, options);
|
|
434
468
|
} catch (error) {
|
|
435
469
|
throw new Error(`Build failed: ${error.message}`);
|
|
436
470
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `aifabrix doctor` action: environment validation + optional infra health.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const {
|
|
9
|
+
sectionTitle,
|
|
10
|
+
formatBulletSection,
|
|
11
|
+
formatDatasourceListRow,
|
|
12
|
+
formatWarningLine,
|
|
13
|
+
metadata
|
|
14
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
15
|
+
const validator = require('../validation/validator');
|
|
16
|
+
const config = require('../core/config');
|
|
17
|
+
const infra = require('../infrastructure');
|
|
18
|
+
const logger = require('../utils/logger');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} label
|
|
22
|
+
* @param {'ok'|'warning'|'fail'} variant
|
|
23
|
+
* @param {{ ok?: string, warn?: string, fail?: string }} text
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
function formatDoctorEnvSummaryLine(label, variant, text) {
|
|
27
|
+
const base = chalk.gray(`${label}:`);
|
|
28
|
+
if (variant === 'ok') return `${base} ${chalk.green('✔')} ${chalk.white(text.ok || '')}`;
|
|
29
|
+
if (variant === 'warning') return `${base} ${chalk.yellow('⚠')} ${chalk.white(text.warn || '')}`;
|
|
30
|
+
return `${base} ${chalk.red('✖')} ${chalk.white(text.fail || '')}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {string} statusRaw
|
|
35
|
+
* @returns {'ok'|'warn'|'fail'}
|
|
36
|
+
*/
|
|
37
|
+
function doctorInfraRowAggregate(statusRaw) {
|
|
38
|
+
const s = String(statusRaw).trim().toLowerCase();
|
|
39
|
+
if (s === 'healthy') return 'ok';
|
|
40
|
+
if (s === 'unknown') return 'warn';
|
|
41
|
+
return 'fail';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {Object} result - `validator.checkEnvironment()` payload
|
|
46
|
+
*/
|
|
47
|
+
function logDoctorEnvironmentSection(result) {
|
|
48
|
+
logger.log('');
|
|
49
|
+
logger.log(sectionTitle('Environment check'));
|
|
50
|
+
logger.log('');
|
|
51
|
+
logger.log(
|
|
52
|
+
formatDoctorEnvSummaryLine(
|
|
53
|
+
'Docker',
|
|
54
|
+
result.docker === 'ok' ? 'ok' : 'fail',
|
|
55
|
+
{ ok: 'Running', fail: 'Not available' }
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
logger.log(
|
|
59
|
+
formatDoctorEnvSummaryLine(
|
|
60
|
+
'Ports',
|
|
61
|
+
result.ports === 'ok' ? 'ok' : 'warning',
|
|
62
|
+
{ ok: 'Available', warn: 'Some ports in use' }
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
logger.log(
|
|
66
|
+
formatDoctorEnvSummaryLine(
|
|
67
|
+
'Secrets',
|
|
68
|
+
result.secrets === 'ok' ? 'ok' : 'fail',
|
|
69
|
+
{ ok: 'Configured', fail: 'Missing' }
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
if (result.recommendations.length > 0) {
|
|
73
|
+
logger.log('');
|
|
74
|
+
logger.log(formatBulletSection('Recommendations:', result.recommendations));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Object} result - `validator.checkEnvironment()` payload
|
|
80
|
+
*/
|
|
81
|
+
async function logDoctorInfraHealthSection(result) {
|
|
82
|
+
if (result.docker !== 'ok') {
|
|
83
|
+
logger.log('');
|
|
84
|
+
logger.log(metadata('Infrastructure health skipped (Docker not available).'));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const cfg = await config.getConfig();
|
|
89
|
+
const health = await infra.checkInfraHealth(null, {
|
|
90
|
+
pgadmin: cfg.pgadmin !== false,
|
|
91
|
+
redisCommander: cfg.redisCommander !== false,
|
|
92
|
+
traefik: !!cfg.traefik
|
|
93
|
+
});
|
|
94
|
+
logger.log('');
|
|
95
|
+
logger.log(sectionTitle('Infrastructure health'));
|
|
96
|
+
Object.entries(health).forEach(([service, status]) => {
|
|
97
|
+
const agg = doctorInfraRowAggregate(status);
|
|
98
|
+
logger.log(formatDatasourceListRow(agg, `${service}: ${status}`, null));
|
|
99
|
+
});
|
|
100
|
+
} catch (_err) {
|
|
101
|
+
logger.log('');
|
|
102
|
+
logger.log(formatWarningLine('Infrastructure is not running or health could not be read.'));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Runs the doctor checks and prints the TTY summary.
|
|
108
|
+
* @returns {Promise<void>}
|
|
109
|
+
*/
|
|
110
|
+
async function runDoctorCheck() {
|
|
111
|
+
const result = await validator.checkEnvironment();
|
|
112
|
+
logDoctorEnvironmentSection(result);
|
|
113
|
+
await logDoctorInfraHealthSection(result);
|
|
114
|
+
logger.log('');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = { runDoctorCheck };
|
package/lib/cli/index.js
CHANGED
|
@@ -21,8 +21,11 @@ const { setupParametersCommands } = require('./setup-parameters');
|
|
|
21
21
|
const { setupExternalSystemCommands } = require('./setup-external-system');
|
|
22
22
|
const { setupAppCommands: setupAppManagementCommands } = require('../commands/app');
|
|
23
23
|
const { setupDatasourceCommands } = require('../commands/datasource');
|
|
24
|
+
const { setupDimensionCommands } = require('../commands/dimension');
|
|
25
|
+
const { setupDimensionValueCommands } = require('../commands/dimension-value');
|
|
24
26
|
const { setupCredentialDeploymentCommands } = require('./setup-credential-deployment');
|
|
25
|
-
const {
|
|
27
|
+
const { setupIntegrationClientCommands } = require('./setup-integration-client');
|
|
28
|
+
const { setupPlatformCommands } = require('./setup-platform');
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
31
|
* Sets up all CLI commands on the Commander program instance
|
|
@@ -35,13 +38,16 @@ function setupCommands(program) {
|
|
|
35
38
|
setupEnvironmentCommands(program);
|
|
36
39
|
setupAppManagementCommands(program);
|
|
37
40
|
setupDatasourceCommands(program);
|
|
41
|
+
setupDimensionCommands(program);
|
|
42
|
+
setupDimensionValueCommands(program);
|
|
38
43
|
setupUtilityCommands(program);
|
|
39
44
|
setupCredentialDeploymentCommands(program);
|
|
40
|
-
|
|
45
|
+
setupIntegrationClientCommands(program);
|
|
41
46
|
setupExternalSystemCommands(program);
|
|
42
47
|
setupDevCommands(program);
|
|
43
48
|
setupSecretsCommands(program);
|
|
44
49
|
setupParametersCommands(program);
|
|
50
|
+
setupPlatformCommands(program);
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
module.exports = {
|