@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
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Guided (non-verbose) UX for infra/platform commands.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const logger = require('../utils/logger');
|
|
9
|
+
const config = require('../core/config');
|
|
10
|
+
const devConfig = require('../utils/dev-config');
|
|
11
|
+
const pathsUtil = require('../utils/paths');
|
|
12
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
13
|
+
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
14
|
+
const { withMutedLogger } = require('../utils/with-muted-logger');
|
|
15
|
+
const { formatBlockingError, formatProgress, formatSuccessLine, successGlyph } = require('../utils/cli-test-layout-chalk');
|
|
16
|
+
const { computePublicUrlBaseString } = require('../utils/url-declarative-public-base');
|
|
17
|
+
const { joinUrlPath, normalizeFrontDoorPatternForHealth } = require('../utils/health-check-url');
|
|
18
|
+
const ora = require('ora');
|
|
19
|
+
const infra = require('../infrastructure');
|
|
20
|
+
const { execWithDockerEnv } = require('../utils/docker-exec');
|
|
21
|
+
const { getLogLevel, passesLevelFilter } = require('../commands/app-logs');
|
|
22
|
+
const { handleLogin } = require('../commands/login');
|
|
23
|
+
const healthCheck = require('../utils/health-check');
|
|
24
|
+
const { prepareUrlsLocalRegistryForUpPlatform } = require('../commands/up-common');
|
|
25
|
+
const { assertDevInfraUp } = require('../commands/dev-infra-gate');
|
|
26
|
+
const {
|
|
27
|
+
emitSystemBuilderAppManifestLineIfTTY
|
|
28
|
+
} = require('../utils/manifest-source-emit');
|
|
29
|
+
|
|
30
|
+
const SEPARATOR = '────────────────────────────────────────';
|
|
31
|
+
|
|
32
|
+
function title(text) {
|
|
33
|
+
return chalk.bold(text);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function shouldUseSpinner() {
|
|
37
|
+
return Boolean(process && process.stdout && process.stdout.isTTY);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function startSpinner(text) {
|
|
41
|
+
if (!shouldUseSpinner()) {
|
|
42
|
+
logger.log(formatProgress(text));
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return ora({ text, spinner: 'dots' }).start();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function stopSpinnerSuccess(spinner, text) {
|
|
49
|
+
if (!spinner) {
|
|
50
|
+
logger.log(formatSuccessLine(text));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
spinner.succeed(text);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function getRunningContainerNameForApp(appName) {
|
|
57
|
+
const apps = await infra.getAppStatus();
|
|
58
|
+
const hit = (apps || []).find(a => a && a.name === appName && a.container);
|
|
59
|
+
return hit ? hit.container : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function hasErrorLogs(appName, opts = {}) {
|
|
63
|
+
const tailLines = Number.isFinite(opts.tailLines) ? opts.tailLines : 200;
|
|
64
|
+
const container = await getRunningContainerNameForApp(appName);
|
|
65
|
+
if (!container) return false;
|
|
66
|
+
const { stdout } = await execWithDockerEnv(`docker logs --tail ${tailLines} ${container}`);
|
|
67
|
+
const lines = String(stdout || '').split('\n');
|
|
68
|
+
return lines.some(line => passesLevelFilter(getLogLevel(line), 'error'));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function validateAppErrorLogs(appNames) {
|
|
72
|
+
const names = Array.isArray(appNames) ? appNames : [];
|
|
73
|
+
const bad = [];
|
|
74
|
+
for (const name of names) {
|
|
75
|
+
try {
|
|
76
|
+
const hasErrors = await hasErrorLogs(name, { tailLines: 300 });
|
|
77
|
+
if (hasErrors) {
|
|
78
|
+
bad.push(name);
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// ignore per-app log failures
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (bad.length === 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
logger.log(chalk.yellow('⚠ Some services reported error logs'));
|
|
88
|
+
for (const name of bad) {
|
|
89
|
+
logger.log(chalk.gray(` Run: aifabrix logs ${name} -l error`));
|
|
90
|
+
}
|
|
91
|
+
logger.log('');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function waitForAppReady(appName, opts = {}) {
|
|
95
|
+
const timeoutSeconds = Number.isFinite(opts.timeoutSeconds) ? opts.timeoutSeconds : 90;
|
|
96
|
+
const builderPath = pathsUtil.getBuilderPath(appName);
|
|
97
|
+
const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
|
|
98
|
+
const appConfig = loadConfigFile(configPath) || {};
|
|
99
|
+
|
|
100
|
+
const apps = await infra.getAppStatus();
|
|
101
|
+
const hit = (apps || []).find(a => a && a.name === appName && typeof a.url === 'string');
|
|
102
|
+
const portMatch = hit && hit.url ? hit.url.match(/:(\d+)$/) : null;
|
|
103
|
+
const hostPort = portMatch ? parseInt(portMatch[1], 10) : null;
|
|
104
|
+
if (!hostPort) {
|
|
105
|
+
throw new Error(`Could not determine host port for ${appName}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const userCfg = await config.getConfig();
|
|
109
|
+
const healthRunOpts = { profile: 'docker' };
|
|
110
|
+
if (userCfg && userCfg.traefik === true) {
|
|
111
|
+
healthRunOpts.traefikEnabled = true;
|
|
112
|
+
}
|
|
113
|
+
await healthCheck.waitForHealthCheck(appName, timeoutSeconds, hostPort, appConfig, false, healthRunOpts);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolveInfraHost(remoteServer) {
|
|
117
|
+
const raw = String(remoteServer || '').trim().replace(/\/+$/, '');
|
|
118
|
+
if (!raw) return 'localhost';
|
|
119
|
+
try {
|
|
120
|
+
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
121
|
+
const u = new URL(withScheme);
|
|
122
|
+
return u.hostname || 'localhost';
|
|
123
|
+
} catch {
|
|
124
|
+
// Fallback for non-URL strings.
|
|
125
|
+
return raw.replace(/^https?:\/\//i, '').split('/')[0].split(':')[0] || 'localhost';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function computeAppBaseUrl(appName) {
|
|
130
|
+
const builderPath = pathsUtil.getBuilderPath(appName);
|
|
131
|
+
const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
|
|
132
|
+
const variables = loadConfigFile(configPath) || {};
|
|
133
|
+
const basePort = Number(variables.port || 3000);
|
|
134
|
+
const developerIdRaw = await config.getDeveloperId();
|
|
135
|
+
const developerIdNum = typeof developerIdRaw === 'string' ? parseInt(developerIdRaw, 10) : developerIdRaw;
|
|
136
|
+
const userCfg = await config.getConfig();
|
|
137
|
+
const remoteServer = await config.getRemoteServer();
|
|
138
|
+
const infraTlsEnabled = Boolean(userCfg && userCfg.tlsEnabled);
|
|
139
|
+
|
|
140
|
+
const fd = variables.frontDoorRouting || null;
|
|
141
|
+
const frontDoorEnabled = Boolean(fd && fd.enabled === true);
|
|
142
|
+
const traefikOn = Boolean(userCfg && userCfg.traefik);
|
|
143
|
+
const pathActive = Boolean(traefikOn && frontDoorEnabled);
|
|
144
|
+
|
|
145
|
+
const publicBase = computePublicUrlBaseString({
|
|
146
|
+
traefik: traefikOn,
|
|
147
|
+
pathActive,
|
|
148
|
+
hostTemplate: fd ? fd.host : null,
|
|
149
|
+
tls: fd ? fd.tls : true,
|
|
150
|
+
developerIdRaw,
|
|
151
|
+
remoteServer,
|
|
152
|
+
// These guided bootstrap commands start services via Docker Compose, so we want the
|
|
153
|
+
// docker-published host port (no workstation +10 offset).
|
|
154
|
+
profile: 'docker',
|
|
155
|
+
listenPort: basePort,
|
|
156
|
+
developerIdNum,
|
|
157
|
+
infraTlsEnabled
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
if (pathActive) {
|
|
161
|
+
const mount = normalizeFrontDoorPatternForHealth(fd.pattern);
|
|
162
|
+
return joinUrlPath(publicBase, mount);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// No Traefik front-door routing: publicBase is localhost + published port unless Traefik/proxy opts into remote.
|
|
166
|
+
return String(publicBase).replace(/\/+$/, '');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function logSection(label, value) {
|
|
170
|
+
logger.log(title(label));
|
|
171
|
+
logger.log(` ${value}`);
|
|
172
|
+
logger.log('');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function logFooterStart(label) {
|
|
176
|
+
logger.log('');
|
|
177
|
+
logger.log(SEPARATOR);
|
|
178
|
+
logger.log(title(label));
|
|
179
|
+
logger.log(SEPARATOR);
|
|
180
|
+
logger.log('');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function logFooterEnd() {
|
|
184
|
+
logger.log(SEPARATOR);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function logPlatformReadyFooter() {
|
|
188
|
+
const [controllerUrl, dataplaneUrl, keycloakUrl] = await Promise.all([
|
|
189
|
+
resolveControllerUrl(),
|
|
190
|
+
computeAppBaseUrl('dataplane'),
|
|
191
|
+
computeAppBaseUrl('keycloak')
|
|
192
|
+
]);
|
|
193
|
+
const cfg = await config.getConfig();
|
|
194
|
+
const env = (cfg && cfg.environment) ? cfg.environment : 'dev';
|
|
195
|
+
|
|
196
|
+
logFooterStart('Platform Ready');
|
|
197
|
+
logSection('Environment', env);
|
|
198
|
+
logSection('Miso Controller', controllerUrl);
|
|
199
|
+
logSection('Dataplane (DEV)', dataplaneUrl);
|
|
200
|
+
logSection('Keycloak', keycloakUrl);
|
|
201
|
+
logSection('API Documentation', `${dataplaneUrl}/api/docs`);
|
|
202
|
+
logSection('Knowledge Base', 'https://docs.aifabrix.ai');
|
|
203
|
+
logSection('Getting Started', 'https://docs.aifabrix.ai/get-started');
|
|
204
|
+
logFooterEnd();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function logMisoReadyFooter() {
|
|
208
|
+
const [controllerUrl, keycloakUrl] = await Promise.all([
|
|
209
|
+
resolveControllerUrl(),
|
|
210
|
+
computeAppBaseUrl('keycloak')
|
|
211
|
+
]);
|
|
212
|
+
logFooterStart('Miso Ready');
|
|
213
|
+
logSection('Miso Controller', controllerUrl);
|
|
214
|
+
logSection('Keycloak', keycloakUrl);
|
|
215
|
+
logFooterEnd();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function logDataplaneReadyFooter() {
|
|
219
|
+
const dataplaneUrl = await computeAppBaseUrl('dataplane');
|
|
220
|
+
const cfg = await config.getConfig();
|
|
221
|
+
const env = (cfg && cfg.environment) ? cfg.environment : 'dev';
|
|
222
|
+
logFooterStart('Dataplane Ready');
|
|
223
|
+
logSection('Environment', env);
|
|
224
|
+
logSection('Dataplane (DEV)', dataplaneUrl);
|
|
225
|
+
logSection('API Documentation', `${dataplaneUrl}/api/docs`);
|
|
226
|
+
logFooterEnd();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function getInfraHostAndPorts() {
|
|
230
|
+
const developerId = await config.getDeveloperId();
|
|
231
|
+
const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
|
|
232
|
+
const ports = devConfig.getDevPorts(idNum);
|
|
233
|
+
const cfg = await config.getConfig();
|
|
234
|
+
const traefikOn = Boolean(cfg && cfg.traefik === true);
|
|
235
|
+
const remoteServer = traefikOn ? await config.getRemoteServer() : null;
|
|
236
|
+
const host = resolveInfraHost(remoteServer);
|
|
237
|
+
return { idNum, ports, host };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function runGuidedUpInfra(options, runUpInfraCommand) {
|
|
241
|
+
logger.log('');
|
|
242
|
+
logger.log(title('AI Fabrix Infrastructure Setup'));
|
|
243
|
+
logger.log(SEPARATOR);
|
|
244
|
+
logger.log('');
|
|
245
|
+
const spin = startSpinner('Starting infrastructure services...');
|
|
246
|
+
await withMutedLogger(() => runUpInfraCommand(options), {
|
|
247
|
+
allow: (msg) => {
|
|
248
|
+
if (typeof msg !== 'string') return false;
|
|
249
|
+
return (
|
|
250
|
+
msg.includes('✔ Developer ID set to') ||
|
|
251
|
+
msg.includes('✔ Traefik enabled and saved to config') ||
|
|
252
|
+
msg.includes('✔ Traefik disabled and saved to config') ||
|
|
253
|
+
msg.includes('✔ pgAdmin enabled and saved to config') ||
|
|
254
|
+
msg.includes('✔ pgAdmin disabled and saved to config') ||
|
|
255
|
+
msg.includes('✔ Redis Commander enabled and saved to config') ||
|
|
256
|
+
msg.includes('✔ Redis Commander disabled and saved to config')
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
stopSpinnerSuccess(spin, 'Infrastructure ready');
|
|
261
|
+
|
|
262
|
+
const [{ idNum, ports, host }, cfg] = await Promise.all([
|
|
263
|
+
getInfraHostAndPorts(),
|
|
264
|
+
config.getConfig()
|
|
265
|
+
]);
|
|
266
|
+
|
|
267
|
+
logFooterStart('Infra Ready');
|
|
268
|
+
logSection('Developer', `dev${String(idNum).padStart(2, '0')} (id: ${idNum})`);
|
|
269
|
+
logSection('Postgres', `${host}:${ports.postgres}`);
|
|
270
|
+
logSection('Redis', `${host}:${ports.redis}`);
|
|
271
|
+
if (cfg.pgadmin !== false) logSection('pgAdmin', `http://${host}:${ports.pgadmin}`);
|
|
272
|
+
if (cfg.redisCommander !== false) logSection('Redis Commander', `http://${host}:${ports.redisCommander}`);
|
|
273
|
+
if (cfg.traefik) logSection('Traefik', `http://${host}:${ports.traefikHttp}`);
|
|
274
|
+
if (cfg.tlsEnabled === true) logSection('TLS mode', 'on');
|
|
275
|
+
logFooterEnd();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async function runGuidedUpMiso(options, handleUpMiso) {
|
|
279
|
+
logger.log('');
|
|
280
|
+
logger.log(title('AI Fabrix Platform Setup'));
|
|
281
|
+
logger.log(SEPARATOR);
|
|
282
|
+
logger.log('');
|
|
283
|
+
const kcSpin = startSpinner('Starting Keycloak...');
|
|
284
|
+
await withMutedLogger(() => handleUpMiso({ ...options, platformInstall: true }));
|
|
285
|
+
stopSpinnerSuccess(kcSpin, 'Keycloak ready');
|
|
286
|
+
logger.log('');
|
|
287
|
+
const mcSpin = startSpinner('Starting Miso Controller...');
|
|
288
|
+
await waitForAppReady('miso-controller', { timeoutSeconds: 120 });
|
|
289
|
+
stopSpinnerSuccess(mcSpin, 'Miso Controller ready');
|
|
290
|
+
await logMisoReadyFooter();
|
|
291
|
+
await validateAppErrorLogs(['miso-controller']);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function runGuidedUpDataplane(options, handleUpDataplane) {
|
|
295
|
+
logger.log('');
|
|
296
|
+
logger.log(title('AI Fabrix Dataplane Setup'));
|
|
297
|
+
logger.log(SEPARATOR);
|
|
298
|
+
logger.log('');
|
|
299
|
+
// Infra must be checked before auth: device login talks to the controller, which needs
|
|
300
|
+
// Postgres/Redis when the controller runs locally — a down infra looks like "network error".
|
|
301
|
+
const infraSpin = startSpinner('Checking infrastructure...');
|
|
302
|
+
try {
|
|
303
|
+
await assertDevInfraUp({ quietSuccess: true });
|
|
304
|
+
stopSpinnerSuccess(infraSpin, 'Infrastructure is up');
|
|
305
|
+
} catch (infraErr) {
|
|
306
|
+
// Match up-miso: one error block from handleCommandError only (no spinner.fail / extra hints).
|
|
307
|
+
if (infraSpin) infraSpin.stop();
|
|
308
|
+
throw infraErr;
|
|
309
|
+
}
|
|
310
|
+
// Avoid an outer long-running spinner here: up-dataplane has multiple internal
|
|
311
|
+
// phases and may print some output. An outer spinner causes "spinner over spinner"
|
|
312
|
+
// rendering artifacts. Instead, do the same single auth step as up-platform, then
|
|
313
|
+
// show one spinner for the dataplane install/run phase.
|
|
314
|
+
await runGuidedAuthStep(handleLogin);
|
|
315
|
+
|
|
316
|
+
logger.log('');
|
|
317
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'dataplane');
|
|
318
|
+
const dpSpin = startSpinner('Starting Dataplane...');
|
|
319
|
+
await withMutedLogger(() =>
|
|
320
|
+
handleUpDataplane({ ...options, platformInstall: true, skipInfraCheck: true })
|
|
321
|
+
);
|
|
322
|
+
stopSpinnerSuccess(dpSpin, 'Dataplane ready');
|
|
323
|
+
await validateAppErrorLogs(['dataplane']);
|
|
324
|
+
await logDataplaneReadyFooter();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Guided-mode summary after `up-platform --force` (printed under the platform header).
|
|
329
|
+
* @param {{ deviceCleared: number, clientCleared: number, environment: string, defaultControllerUrl: string }} forceSummary
|
|
330
|
+
* @param {string[]} cleanedApps
|
|
331
|
+
*/
|
|
332
|
+
function logUpPlatformForceCleanSummary(forceSummary, cleanedApps) {
|
|
333
|
+
const check = successGlyph();
|
|
334
|
+
logger.log(chalk.bold('Clean installation files'));
|
|
335
|
+
logger.log(
|
|
336
|
+
chalk.gray(
|
|
337
|
+
` ${check} Cleared ${forceSummary.deviceCleared} device token(s) and ${forceSummary.clientCleared} client token(s)`
|
|
338
|
+
)
|
|
339
|
+
);
|
|
340
|
+
logger.log(chalk.gray(` ${check} Environment set to ${forceSummary.environment}`));
|
|
341
|
+
logger.log(
|
|
342
|
+
chalk.gray(
|
|
343
|
+
` ${check} Default controller set to ${forceSummary.defaultControllerUrl} (run aifabrix login after platform is up)`
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
for (const appName of cleanedApps || []) {
|
|
347
|
+
logger.log(chalk.gray(` ${check} Cleaned builder/${appName}`));
|
|
348
|
+
}
|
|
349
|
+
logger.log('');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function logGuidedPlatformSetupHeader() {
|
|
353
|
+
logger.log('');
|
|
354
|
+
logger.log(title('AI Fabrix Platform Setup'));
|
|
355
|
+
logger.log(SEPARATOR);
|
|
356
|
+
logger.log(chalk.gray('This may take a few minutes...'));
|
|
357
|
+
logger.log('');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async function runGuidedAuthStep(handleLogin) {
|
|
361
|
+
const spin = startSpinner('Authenticating...');
|
|
362
|
+
try {
|
|
363
|
+
const controllerUrl = await resolveControllerUrl();
|
|
364
|
+
await handleLogin({ method: 'device', controller: controllerUrl, environment: 'dev', compact: true });
|
|
365
|
+
} catch (authErr) {
|
|
366
|
+
if (spin) spin.fail('Authentication failed');
|
|
367
|
+
logger.error(formatBlockingError('Authentication failed'));
|
|
368
|
+
logger.log(chalk.gray('\nRun:\n af login\n\nThen retry:\n af up-platform\n'));
|
|
369
|
+
throw authErr;
|
|
370
|
+
}
|
|
371
|
+
// Compact device-login already prints a success line; don't duplicate it.
|
|
372
|
+
if (spin) spin.stop();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
async function runGuidedKeycloakAndMisoControllerPhase(options, handleUpMiso) {
|
|
376
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'keycloak');
|
|
377
|
+
const kcSpin = startSpinner('Starting Keycloak...');
|
|
378
|
+
await withMutedLogger(() => handleUpMiso({ ...options, platformInstall: true }));
|
|
379
|
+
stopSpinnerSuccess(kcSpin, 'Keycloak ready');
|
|
380
|
+
logger.log('');
|
|
381
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'miso-controller');
|
|
382
|
+
const mcSpin = startSpinner('Starting Miso Controller...');
|
|
383
|
+
await waitForAppReady('miso-controller', { timeoutSeconds: 120 });
|
|
384
|
+
stopSpinnerSuccess(mcSpin, 'Miso Controller ready');
|
|
385
|
+
logger.log('');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function runGuidedDataplaneInstallPhase(options, handleUpDataplane) {
|
|
389
|
+
logger.log('');
|
|
390
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'dataplane');
|
|
391
|
+
const dpSpin = startSpinner('Starting Dataplane...');
|
|
392
|
+
await withMutedLogger(() =>
|
|
393
|
+
handleUpDataplane({ ...options, platformInstall: true, skipInfraCheck: true })
|
|
394
|
+
);
|
|
395
|
+
stopSpinnerSuccess(dpSpin, 'Dataplane ready');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async function runGuidedUpPlatform(options, handleUpMiso, handleUpDataplane, handleLogin, forceCleanSummary = null) {
|
|
399
|
+
logGuidedPlatformSetupHeader();
|
|
400
|
+
if (forceCleanSummary && forceCleanSummary.forceSummary) {
|
|
401
|
+
logUpPlatformForceCleanSummary(forceCleanSummary.forceSummary, forceCleanSummary.cleanedApps);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
await withMutedLogger(() => prepareUrlsLocalRegistryForUpPlatform());
|
|
405
|
+
await runGuidedKeycloakAndMisoControllerPhase(options, handleUpMiso);
|
|
406
|
+
await runGuidedAuthStep(handleLogin);
|
|
407
|
+
await runGuidedDataplaneInstallPhase(options, handleUpDataplane);
|
|
408
|
+
await validateAppErrorLogs(['miso-controller', 'dataplane']);
|
|
409
|
+
await logPlatformReadyFooter();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function logStoppedServices(cfg) {
|
|
413
|
+
logger.log(title('Stopped'));
|
|
414
|
+
logger.log(' postgres');
|
|
415
|
+
logger.log(' redis');
|
|
416
|
+
if (cfg.pgadmin !== false) logger.log(' pgadmin');
|
|
417
|
+
if (cfg.redisCommander !== false) logger.log(' redis-commander');
|
|
418
|
+
if (cfg.traefik) logger.log(' traefik');
|
|
419
|
+
logger.log('');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async function runGuidedDownInfra(appName, options, infra, appLib) {
|
|
423
|
+
logger.log('');
|
|
424
|
+
logger.log(title('AI Fabrix Shutdown'));
|
|
425
|
+
logger.log(SEPARATOR);
|
|
426
|
+
logger.log('');
|
|
427
|
+
|
|
428
|
+
const spin = startSpinner('Stopping infrastructure...');
|
|
429
|
+
await withMutedLogger(async() => {
|
|
430
|
+
if (typeof appName === 'string' && appName.trim().length > 0) {
|
|
431
|
+
await appLib.downApp(appName, { volumes: !!options.volumes });
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (options.volumes) await infra.stopInfraWithVolumes();
|
|
435
|
+
else await infra.stopInfra();
|
|
436
|
+
});
|
|
437
|
+
stopSpinnerSuccess(spin, 'Infrastructure stopped');
|
|
438
|
+
|
|
439
|
+
const developerId = await config.getDeveloperId();
|
|
440
|
+
const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
|
|
441
|
+
const cfg = await config.getConfig();
|
|
442
|
+
|
|
443
|
+
logFooterStart('Stopped');
|
|
444
|
+
logSection('Developer', `dev${String(idNum).padStart(2, '0')} (id: ${idNum})`);
|
|
445
|
+
logStoppedServices(cfg);
|
|
446
|
+
if (options.volumes) {
|
|
447
|
+
logger.log(chalk.yellow('⚠ Volumes removed: all local data deleted'));
|
|
448
|
+
logger.log('');
|
|
449
|
+
}
|
|
450
|
+
logFooterEnd();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
module.exports = {
|
|
454
|
+
runGuidedUpInfra,
|
|
455
|
+
runGuidedUpMiso,
|
|
456
|
+
runGuidedUpDataplane,
|
|
457
|
+
runGuidedUpPlatform,
|
|
458
|
+
runGuidedDownInfra
|
|
459
|
+
};
|
|
460
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared completion hook for infra/platform CLI commands (installation.log).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview installation.log CLI helper
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const config = require('../core/config');
|
|
12
|
+
const installationLog = require('../utils/installation-log');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object} params
|
|
16
|
+
* @param {string} params.command
|
|
17
|
+
* @param {Object} params.options
|
|
18
|
+
* @param {Date} params.startedAt
|
|
19
|
+
* @param {'success'|'failure'} params.outcome
|
|
20
|
+
* @param {Error} [params.error]
|
|
21
|
+
* @param {string[]} [params.platformAppList]
|
|
22
|
+
* @param {Object} [params.cleanup]
|
|
23
|
+
* @param {boolean} [params.upPlatformForce]
|
|
24
|
+
* @param {boolean} [params.omitInfraSection]
|
|
25
|
+
* @returns {Promise<void>}
|
|
26
|
+
*/
|
|
27
|
+
async function recordInfraInstallationCommand(params) {
|
|
28
|
+
const {
|
|
29
|
+
command,
|
|
30
|
+
options,
|
|
31
|
+
startedAt,
|
|
32
|
+
outcome,
|
|
33
|
+
error,
|
|
34
|
+
platformAppList,
|
|
35
|
+
cleanup,
|
|
36
|
+
upPlatformForce,
|
|
37
|
+
omitInfraSection
|
|
38
|
+
} = params;
|
|
39
|
+
|
|
40
|
+
const completedAt = new Date();
|
|
41
|
+
let cfg = {};
|
|
42
|
+
try {
|
|
43
|
+
cfg = await config.getConfig();
|
|
44
|
+
} catch {
|
|
45
|
+
cfg = {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await installationLog.appendInstallationRecord({
|
|
50
|
+
command,
|
|
51
|
+
outcome,
|
|
52
|
+
startedAt,
|
|
53
|
+
completedAt,
|
|
54
|
+
options,
|
|
55
|
+
infra: !omitInfraSection && cfg ? { cfg, options } : undefined,
|
|
56
|
+
platformAppList,
|
|
57
|
+
cleanup,
|
|
58
|
+
upPlatformForce: upPlatformForce === true,
|
|
59
|
+
configExtra: {
|
|
60
|
+
controllerUrl: await installationLog.resolveControllerUrlForLog(),
|
|
61
|
+
adminEmail: await installationLog.resolveAdminEmailPresence()
|
|
62
|
+
},
|
|
63
|
+
error,
|
|
64
|
+
errorCode: error && error.code ? String(error.code) : undefined
|
|
65
|
+
});
|
|
66
|
+
} catch {
|
|
67
|
+
// never block CLI on log failure
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
recordInfraInstallationCommand
|
|
73
|
+
};
|
package/lib/cli/setup-app.js
CHANGED
|
@@ -31,6 +31,19 @@ Example:
|
|
|
31
31
|
$ aifabrix push myapp -t v1.0.0
|
|
32
32
|
`;
|
|
33
33
|
|
|
34
|
+
const LOGS_HELP_AFTER = `
|
|
35
|
+
Examples:
|
|
36
|
+
$ aifabrix logs miso-controller -l error
|
|
37
|
+
$ aifabrix logs miso-controller -f
|
|
38
|
+
$ aifabrix logs dataplane -l warn
|
|
39
|
+
$ aifabrix logs dataplane -f -t 100
|
|
40
|
+
$ aifabrix logs keycloak -f -t 0
|
|
41
|
+
|
|
42
|
+
Notes:
|
|
43
|
+
- Platform apps use names such as miso-controller, dataplane, keycloak (see aifabrix run).
|
|
44
|
+
- Use -t 0 (--tail 0) for the full buffered log; default is 100 lines.
|
|
45
|
+
`;
|
|
46
|
+
|
|
34
47
|
/**
|
|
35
48
|
* Normalize options for external system creation
|
|
36
49
|
* @param {Object} options - Raw CLI options
|
|
@@ -188,19 +201,31 @@ See integration/hubspot-test/wizard-hubspot-e2e.yaml for an example.`;
|
|
|
188
201
|
|
|
189
202
|
function registerRunCommand(program) {
|
|
190
203
|
const runHelp = `
|
|
191
|
-
In dev: use --reload for
|
|
204
|
+
In dev: use --reload for live code in the container. Before start, the CLI prints a "Reload (dev)" section: direct bind mount when the Docker engine is on this machine, or Mutagen when the engine is remote.
|
|
192
205
|
Examples:
|
|
193
206
|
$ aifabrix run myapp
|
|
194
207
|
$ aifabrix run myapp --env tst
|
|
195
208
|
$ aifabrix run myapp --tag v1.0.0
|
|
196
|
-
$ aifabrix run myapp --
|
|
209
|
+
$ aifabrix run myapp --base
|
|
210
|
+
$ aifabrix run myapp --reload
|
|
211
|
+
$ aifabrix run myapp --no-proxy # same as --proxy false: localhost for Docker declarative public URLs; saves applications.<app>.proxy: false`;
|
|
197
212
|
program.command('run <app>')
|
|
198
213
|
.description('Run app locally or on remote Docker host')
|
|
199
214
|
.option('-p, --port <port>', 'Override local port')
|
|
200
215
|
.option('-d, --debug', 'Enable debug output with detailed container information')
|
|
201
216
|
.option('-t, --tag <tag>', 'Image tag to run (e.g. v1.0.0); overrides application.yaml image.tag')
|
|
202
217
|
.option('-e, --env <env>', 'Environment: dev (default), tst, or pro', 'dev')
|
|
203
|
-
.option('--
|
|
218
|
+
.option('--base', 'Use manifest base image only (skip local developer-scoped tag preference)')
|
|
219
|
+
.option('--reload', 'In dev: mount workspace into container (Mutagen only if docker-endpoint is a remote host)')
|
|
220
|
+
.option(
|
|
221
|
+
'--proxy',
|
|
222
|
+
'Use Traefik/front-door public URL hints when infra has Traefik and application.yaml enables frontDoorRouting (default: on)',
|
|
223
|
+
true
|
|
224
|
+
)
|
|
225
|
+
.option(
|
|
226
|
+
'--no-proxy',
|
|
227
|
+
'Docker declarative public url://* use localhost + published port (saves applications.<app>.proxy: false); overrides --proxy'
|
|
228
|
+
)
|
|
204
229
|
.addHelpText('after', runHelp)
|
|
205
230
|
.action(async(appName, options) => {
|
|
206
231
|
try {
|
|
@@ -219,6 +244,7 @@ function setupBuildRunLogsDownCommands(program) {
|
|
|
219
244
|
.option('-f, --force-template', 'Force rebuild from template')
|
|
220
245
|
.option('--no-cache', 'Full Docker rebuild (disable layer cache); use after Dockerfile or context fixes')
|
|
221
246
|
.option('-t, --tag <tag>', 'Image tag (default: latest). Set image.tag in application.yaml to match for deploy.')
|
|
247
|
+
.option('--base', 'Also tag the manifest base image name (after developer-scoped build when developer id > 0)')
|
|
222
248
|
.action(async(appName, options) => {
|
|
223
249
|
try {
|
|
224
250
|
const imageTag = await app.buildApp(appName, options);
|
|
@@ -236,6 +262,7 @@ function setupBuildRunLogsDownCommands(program) {
|
|
|
236
262
|
.option('-f', 'Follow log stream')
|
|
237
263
|
.option('-t, --tail <lines>', 'Number of lines (default: 100); 0 = full list', '100')
|
|
238
264
|
.option('-l, --level <level>', 'Show only logs at this level or above (debug|info|warn|error)')
|
|
265
|
+
.addHelpText('after', LOGS_HELP_AFTER)
|
|
239
266
|
.action(async(appName, options) => {
|
|
240
267
|
try {
|
|
241
268
|
const { runAppLogs } = require('../commands/app-logs');
|
|
@@ -328,6 +355,7 @@ function setupPushDeployDockerfileCommands(program) {
|
|
|
328
355
|
.option('--local', 'Send manifest to controller then run app locally (app: same as aifabrix run <app>; external: restart dataplane)')
|
|
329
356
|
.option('--client-id <id>', 'Client ID (overrides config)')
|
|
330
357
|
.option('--client-secret <secret>', 'Client Secret (overrides config)')
|
|
358
|
+
.option('--repository-url <url>', 'Repository URL for pipeline validation (default: application.yaml repository.repositoryUrl, else https://github.com/aifabrix/<appKey>)')
|
|
331
359
|
.option('--poll', 'Poll for deployment status', true)
|
|
332
360
|
.option('--no-poll', 'Do not poll for status')
|
|
333
361
|
.option('--probe', 'After external deploy, run dataplane runtime checks (validation/run); slower')
|