@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
package/lib/app/rotate-secret.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatBlockingError, formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
3
|
* AI Fabrix Builder - App Rotate Secret Command
|
|
3
4
|
*
|
|
@@ -70,7 +71,7 @@ function validateEnvironment(environment) {
|
|
|
70
71
|
async function resolveControllerAndEnvironment() {
|
|
71
72
|
const controllerUrl = await resolveControllerUrl();
|
|
72
73
|
if (!controllerUrl) {
|
|
73
|
-
logger.error(
|
|
74
|
+
logger.error(formatBlockingError('Controller URL is required. Run "aifabrix login" to set the controller URL in config.yaml'));
|
|
74
75
|
process.exit(1);
|
|
75
76
|
}
|
|
76
77
|
const environment = await resolveEnvironment();
|
|
@@ -135,7 +136,7 @@ function extractCredentials(response) {
|
|
|
135
136
|
*/
|
|
136
137
|
function validateResponse(response) {
|
|
137
138
|
if (!response.data || typeof response.data !== 'object') {
|
|
138
|
-
logger.error(
|
|
139
|
+
logger.error(formatBlockingError('Invalid response: missing data'));
|
|
139
140
|
logger.error(chalk.gray('\nAPI response type:'), typeof response.data);
|
|
140
141
|
logger.error(chalk.gray('API response:'), JSON.stringify(response.data, null, 2));
|
|
141
142
|
logger.error(chalk.gray('\nFull response for debugging:'));
|
|
@@ -146,7 +147,7 @@ function validateResponse(response) {
|
|
|
146
147
|
const result = extractCredentials(response);
|
|
147
148
|
|
|
148
149
|
if (!result) {
|
|
149
|
-
logger.error(
|
|
150
|
+
logger.error(formatBlockingError('Invalid response: missing or invalid credentials'));
|
|
150
151
|
logger.error(chalk.gray('\nAPI response type:'), typeof response.data);
|
|
151
152
|
logger.error(chalk.gray('API response:'), JSON.stringify(response.data, null, 2));
|
|
152
153
|
logger.error(chalk.gray('\nFull response for debugging:'));
|
|
@@ -166,7 +167,7 @@ function validateResponse(response) {
|
|
|
166
167
|
* @param {string} [message] - Optional message from API
|
|
167
168
|
*/
|
|
168
169
|
function displayRotationResults(appKey, environment, credentials, apiUrl, message) {
|
|
169
|
-
logger.log(
|
|
170
|
+
logger.log(formatSuccessLine('Secret rotated successfully!\n'));
|
|
170
171
|
logger.log(chalk.bold('📋 Application Details:'));
|
|
171
172
|
logger.log(` Key: ${appKey}`);
|
|
172
173
|
logger.log(` Environment: ${environment}`);
|
|
@@ -206,7 +207,7 @@ async function getTokenFromUrl(controllerUrl) {
|
|
|
206
207
|
};
|
|
207
208
|
}
|
|
208
209
|
} catch (error) {
|
|
209
|
-
logger.error(
|
|
210
|
+
logger.error(formatBlockingError(`Failed to authenticate with controller: ${controllerUrl}`));
|
|
210
211
|
logger.error(chalk.gray(`Error: ${error.message}`));
|
|
211
212
|
process.exit(1);
|
|
212
213
|
}
|
|
@@ -287,18 +288,18 @@ async function saveCredentialsLocally(appKey, credentials, actualControllerUrl)
|
|
|
287
288
|
// Regenerate .env file with updated credentials
|
|
288
289
|
try {
|
|
289
290
|
await generateEnvFile(appKey, null, 'local');
|
|
290
|
-
logger.log(
|
|
291
|
+
logger.log(formatSuccessLine('.env file updated with new credentials'));
|
|
291
292
|
} catch (error) {
|
|
292
|
-
logger.warn(chalk.yellow(
|
|
293
|
+
logger.warn(chalk.yellow(`⚠ Could not regenerate .env file: ${error.message}`));
|
|
293
294
|
}
|
|
294
295
|
|
|
295
|
-
logger.log(
|
|
296
|
-
logger.log(
|
|
296
|
+
logger.log(formatSuccessParagraph('Credentials saved to ~/.aifabrix/secrets.local.yaml'));
|
|
297
|
+
logger.log(formatSuccessLine('env.template updated with MISO_CLIENTID, MISO_CLIENTSECRET, and MISO_CONTROLLER_URL\n'));
|
|
297
298
|
} else {
|
|
298
|
-
logger.log(
|
|
299
|
+
logger.log(formatSuccessParagraph('Credentials saved to ~/.aifabrix/secrets.local.yaml\n'));
|
|
299
300
|
}
|
|
300
301
|
} catch (error) {
|
|
301
|
-
logger.warn(chalk.yellow(
|
|
302
|
+
logger.warn(chalk.yellow(`⚠ Could not save credentials locally: ${error.message}`));
|
|
302
303
|
}
|
|
303
304
|
}
|
|
304
305
|
|
|
@@ -337,7 +338,7 @@ async function executeRotation(appKey, actualControllerUrl, environment, token)
|
|
|
337
338
|
* @throws {Error} If rotation fails
|
|
338
339
|
*/
|
|
339
340
|
async function rotateSecret(appKey, _options = {}) {
|
|
340
|
-
logger.log(chalk.yellow('
|
|
341
|
+
logger.log(chalk.yellow('⚠ This will invalidate the old ClientSecret!\n'));
|
|
341
342
|
|
|
342
343
|
const { ensureSecretsEncryptionKey } = require('../core/config');
|
|
343
344
|
await ensureSecretsEncryptionKey();
|
|
@@ -349,7 +350,7 @@ async function rotateSecret(appKey, _options = {}) {
|
|
|
349
350
|
try {
|
|
350
351
|
await executeRotation(appKey, actualControllerUrl, environment, token);
|
|
351
352
|
} catch (error) {
|
|
352
|
-
logger.error(
|
|
353
|
+
logger.error(formatBlockingError(`Failed to rotate secret via controller: ${actualControllerUrl}`));
|
|
353
354
|
logger.error(chalk.gray(`Error: ${error.message}`));
|
|
354
355
|
process.exit(1);
|
|
355
356
|
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker Compose up and docker-run fallback for `aifabrix run`.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Extracted from run-helpers to keep file size within limits
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
9
|
+
|
|
10
|
+
const fs = require('fs').promises;
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const { exec } = require('child_process');
|
|
13
|
+
const { promisify } = require('util');
|
|
14
|
+
const logger = require('../utils/logger');
|
|
15
|
+
const dockerUtils = require('../utils/docker');
|
|
16
|
+
const containerHelpers = require('../utils/app-run-containers');
|
|
17
|
+
const healthCheck = require('../utils/health-check');
|
|
18
|
+
const runDockerFallback = require('./run-docker-fallback');
|
|
19
|
+
const { resolveRunImage } = require('./run-resolve-image');
|
|
20
|
+
|
|
21
|
+
const execAsync = promisify(exec);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Logs and runs docker when Compose CLI is missing (narrow eligibility).
|
|
25
|
+
* @async
|
|
26
|
+
* @param {string} appName
|
|
27
|
+
* @param {Object} appConfig
|
|
28
|
+
* @param {number} port
|
|
29
|
+
* @param {Object} opts
|
|
30
|
+
*/
|
|
31
|
+
async function emitAndRunDockerFallback(appName, appConfig, port, opts) {
|
|
32
|
+
const { debug, runEnvPath, runOptions, misoEnvironment } = opts;
|
|
33
|
+
logger.log(
|
|
34
|
+
chalk.yellow(
|
|
35
|
+
'Docker Compose not found; using docker run (apps without database/redis only). ' +
|
|
36
|
+
'Install docker-compose-plugin for full compose support.'
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
const { imageName, imageTag } = resolveRunImage(appName, appConfig, runOptions);
|
|
40
|
+
await runDockerFallback.executeDockerRunUp({
|
|
41
|
+
appName,
|
|
42
|
+
appConfig,
|
|
43
|
+
hostPort: port,
|
|
44
|
+
fullImage: `${imageName}:${imageTag}`,
|
|
45
|
+
runEnvPath,
|
|
46
|
+
misoEnvironment,
|
|
47
|
+
debug
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Prepares env for docker compose child process (UID/GID + remote docker).
|
|
53
|
+
* @async
|
|
54
|
+
* @param {boolean} debug
|
|
55
|
+
* @returns {Promise<Object>}
|
|
56
|
+
*/
|
|
57
|
+
async function prepareContainerEnv(debug) {
|
|
58
|
+
const { getDockerExecEnv } = require('../utils/remote-docker-env');
|
|
59
|
+
const env = await getDockerExecEnv();
|
|
60
|
+
|
|
61
|
+
if (typeof process.getuid === 'function' && typeof process.getgid === 'function') {
|
|
62
|
+
env.AIFABRIX_UID = String(process.getuid());
|
|
63
|
+
env.AIFABRIX_GID = String(process.getgid());
|
|
64
|
+
} else {
|
|
65
|
+
env.AIFABRIX_UID = '1000';
|
|
66
|
+
env.AIFABRIX_GID = '1000';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (debug) {
|
|
70
|
+
logger.log(chalk.gray('[DEBUG] Container env prepared (secrets via env_file)'));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return env;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @async
|
|
78
|
+
* @param {string} composeCmdBase
|
|
79
|
+
* @param {string} composePath
|
|
80
|
+
* @param {Object} env
|
|
81
|
+
* @param {boolean} debug
|
|
82
|
+
*/
|
|
83
|
+
async function executeComposeUp(composeCmdBase, composePath, env, debug) {
|
|
84
|
+
const composeCmd = `${composeCmdBase} -f "${composePath}" up -d`;
|
|
85
|
+
if (debug) {
|
|
86
|
+
logger.log(chalk.gray(`[DEBUG] Executing: ${composeCmd}`));
|
|
87
|
+
logger.log(chalk.gray(`[DEBUG] Compose file: ${composePath}`));
|
|
88
|
+
}
|
|
89
|
+
await execAsync(composeCmd, { env });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Log status, wait for HTTP health, delete run .env files.
|
|
94
|
+
* @async
|
|
95
|
+
* @param {string} appName
|
|
96
|
+
* @param {number} port
|
|
97
|
+
* @param {Object} appConfig
|
|
98
|
+
* @param {{ debug: boolean, runEnvPath: string|null, runEnvAdminPath: string|null }} o
|
|
99
|
+
*/
|
|
100
|
+
async function waitForHealthyAndCleanupEnvFiles(appName, port, appConfig, o) {
|
|
101
|
+
const { debug, runEnvPath, runEnvAdminPath, runOptions = {} } = o;
|
|
102
|
+
const ro = runOptions || {};
|
|
103
|
+
const scopeOpts =
|
|
104
|
+
ro.effectiveEnvironmentScopedResources === true && ro.env
|
|
105
|
+
? { effectiveEnvironmentScopedResources: true, env: String(ro.env).toLowerCase() }
|
|
106
|
+
: null;
|
|
107
|
+
const containerName = containerHelpers.getContainerName(appName, appConfig.developerId, scopeOpts);
|
|
108
|
+
logger.log(formatSuccessLine(`Container ${containerName} started`));
|
|
109
|
+
await containerHelpers.logContainerStatus(containerName, debug);
|
|
110
|
+
|
|
111
|
+
const healthCheckPath = appConfig?.healthCheck?.path || '/health';
|
|
112
|
+
const healthUrl = (typeof healthCheck.computeHealthCheckUrl === 'function')
|
|
113
|
+
? await healthCheck.computeHealthCheckUrl(appName, port, appConfig, { runOptions: ro })
|
|
114
|
+
: null;
|
|
115
|
+
// Keep a stable fallback in the message if URL computation fails for any reason.
|
|
116
|
+
const displayUrl = (healthUrl && typeof healthUrl === 'string')
|
|
117
|
+
? healthUrl
|
|
118
|
+
: `http://localhost:${port}${healthCheckPath}`;
|
|
119
|
+
logger.log(chalk.blue(`Waiting for application to be healthy at ${displayUrl}...`));
|
|
120
|
+
await healthCheck.waitForHealthCheck(appName, 90, port, appConfig, debug, ro);
|
|
121
|
+
|
|
122
|
+
for (const p of [runEnvPath, runEnvAdminPath]) {
|
|
123
|
+
if (p && typeof p === 'string') {
|
|
124
|
+
try {
|
|
125
|
+
await fs.unlink(p);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (err.code !== 'ENOENT') logger.log(chalk.yellow(`Warning: could not remove run .env: ${err.message}`));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Starts the container and waits for health check. Deletes run .env files after success (ISO 27K).
|
|
135
|
+
* @async
|
|
136
|
+
* @param {string} appName
|
|
137
|
+
* @param {string} composePath
|
|
138
|
+
* @param {number} port
|
|
139
|
+
* @param {Object} appConfig
|
|
140
|
+
* @param {Object} [opts]
|
|
141
|
+
*/
|
|
142
|
+
async function startContainer(appName, composePath, port, appConfig = null, opts = {}) {
|
|
143
|
+
const {
|
|
144
|
+
debug = false,
|
|
145
|
+
runEnvPath = null,
|
|
146
|
+
runEnvAdminPath = null,
|
|
147
|
+
runOptions = {},
|
|
148
|
+
devMountPath = null,
|
|
149
|
+
misoEnvironment = 'dev'
|
|
150
|
+
} = opts;
|
|
151
|
+
logger.log(chalk.blue(`Starting ${appName}...`));
|
|
152
|
+
|
|
153
|
+
let composeCmdBase;
|
|
154
|
+
let usedDockerRunFallback = false;
|
|
155
|
+
try {
|
|
156
|
+
composeCmdBase = await dockerUtils.ensureDockerAndCompose();
|
|
157
|
+
} catch (composeErr) {
|
|
158
|
+
if (runDockerFallback.canUseDockerRunWithoutCompose(appConfig, { devMountPath })) {
|
|
159
|
+
await emitAndRunDockerFallback(appName, appConfig, port, {
|
|
160
|
+
debug,
|
|
161
|
+
runEnvPath,
|
|
162
|
+
runOptions,
|
|
163
|
+
misoEnvironment
|
|
164
|
+
});
|
|
165
|
+
usedDockerRunFallback = true;
|
|
166
|
+
} else {
|
|
167
|
+
throw composeErr;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!usedDockerRunFallback) {
|
|
172
|
+
const env = await prepareContainerEnv(debug);
|
|
173
|
+
await executeComposeUp(composeCmdBase, composePath, env, debug);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
await waitForHealthyAndCleanupEnvFiles(appName, port, appConfig, {
|
|
177
|
+
debug,
|
|
178
|
+
runEnvPath,
|
|
179
|
+
runEnvAdminPath,
|
|
180
|
+
runOptions
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = { startContainer, prepareContainerEnv, executeComposeUp };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback `docker run` when Docker Compose CLI is missing — narrow case only.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Apps that declare no Postgres/Redis in application.yaml can start
|
|
5
|
+
* with plain Docker; same eligibility as skipping local infra health.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const logger = require('../utils/logger');
|
|
12
|
+
const { execWithDockerEnv } = require('../utils/docker-exec');
|
|
13
|
+
const { getContainerPort } = require('../utils/port-resolver');
|
|
14
|
+
const { getAppInfraRequirements } = require('./run-infra-requirements');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Shell-single-quote a string for use inside a POSIX sh -c style command.
|
|
18
|
+
* @param {string} value
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
function shellSingleQuote(value) {
|
|
22
|
+
const s = String(value);
|
|
23
|
+
return '\'' + s.replace(/'/g, '\'\\\'\'') + '\'';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Named volume for /mnt/data (must match templates/typescript/docker-compose.hbs).
|
|
28
|
+
* @param {string} appName
|
|
29
|
+
* @param {string|number} developerId
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function storageVolumeName(appName, developerId) {
|
|
33
|
+
const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
|
|
34
|
+
if (idNum === 0) {
|
|
35
|
+
return `aifabrix_${appName}_data`;
|
|
36
|
+
}
|
|
37
|
+
return `aifabrix_dev${developerId}_${appName}_data`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* True when safe to emulate compose with `docker run` if Compose is unavailable.
|
|
42
|
+
* @param {Object} appConfig
|
|
43
|
+
* @param {{ devMountPath?: string|null }} startOpts
|
|
44
|
+
* @returns {boolean}
|
|
45
|
+
*/
|
|
46
|
+
function canUseDockerRunWithoutCompose(appConfig, startOpts) {
|
|
47
|
+
const req = getAppInfraRequirements(appConfig);
|
|
48
|
+
if (!req || req.needsPostgres || req.needsRedis) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (appConfig.frontDoorRouting && appConfig.frontDoorRouting.enabled === true) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (startOpts.devMountPath) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {Object} o
|
|
62
|
+
* @param {string} o.appName
|
|
63
|
+
* @param {Object} o.appConfig
|
|
64
|
+
* @param {number} o.hostPort
|
|
65
|
+
* @param {string} o.fullImage image:tag
|
|
66
|
+
* @param {string|null} o.runEnvPath
|
|
67
|
+
* @param {string} o.misoEnvironment
|
|
68
|
+
* @param {boolean} o.debug
|
|
69
|
+
* @returns {Promise<void>}
|
|
70
|
+
*/
|
|
71
|
+
async function executeDockerRunUp(o) {
|
|
72
|
+
const { appName, appConfig, hostPort, fullImage, runEnvPath, misoEnvironment, debug } = o;
|
|
73
|
+
const idNum = typeof appConfig.developerId === 'string' ? parseInt(appConfig.developerId, 10) : appConfig.developerId;
|
|
74
|
+
const containerName = idNum === 0 ? `aifabrix-${appName}` : `aifabrix-dev${appConfig.developerId}-${appName}`;
|
|
75
|
+
const containerPort = getContainerPort(appConfig, 3000);
|
|
76
|
+
|
|
77
|
+
const needsStorage =
|
|
78
|
+
appConfig.requires?.storage === true ||
|
|
79
|
+
appConfig.services?.storage === true;
|
|
80
|
+
|
|
81
|
+
const parts = [
|
|
82
|
+
'docker run -d',
|
|
83
|
+
`--name ${shellSingleQuote(containerName)}`,
|
|
84
|
+
'--restart unless-stopped',
|
|
85
|
+
`-p ${hostPort}:${containerPort}`,
|
|
86
|
+
`-e MISO_ENVIRONMENT=${shellSingleQuote(misoEnvironment)}`
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
if (needsStorage) {
|
|
90
|
+
parts.push(`-v ${shellSingleQuote(storageVolumeName(appName, appConfig.developerId))}:/mnt/data`);
|
|
91
|
+
}
|
|
92
|
+
if (runEnvPath && typeof runEnvPath === 'string') {
|
|
93
|
+
parts.push(`--env-file ${shellSingleQuote(runEnvPath)}`);
|
|
94
|
+
}
|
|
95
|
+
parts.push(shellSingleQuote(fullImage));
|
|
96
|
+
|
|
97
|
+
const cmd = parts.join(' ');
|
|
98
|
+
if (debug) {
|
|
99
|
+
logger.log(chalk.gray(`[DEBUG] Docker run fallback: ${cmd.replace(/env-file [^ ]+/, 'env-file <redacted>')}`));
|
|
100
|
+
}
|
|
101
|
+
await execWithDockerEnv(cmd);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
canUseDockerRunWithoutCompose,
|
|
106
|
+
executeDockerRunUp,
|
|
107
|
+
storageVolumeName
|
|
108
|
+
};
|
|
@@ -16,7 +16,6 @@ const pathsUtil = require('../utils/paths');
|
|
|
16
16
|
const adminSecrets = require('../core/admin-secrets');
|
|
17
17
|
const secretsEnvWrite = require('../core/secrets-env-write');
|
|
18
18
|
const { getContainerPort } = require('../utils/port-resolver');
|
|
19
|
-
const { getInfraDirName } = require('../infrastructure/helpers');
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* Clean applications directory: remove generated docker-compose.yaml and .env.* files.
|
|
@@ -58,12 +57,20 @@ function pgUserName(dbName) {
|
|
|
58
57
|
* @param {Object} env - Merged env object (mutated)
|
|
59
58
|
* @param {Object} appConfig - Application config (requires.databases or databases array)
|
|
60
59
|
*/
|
|
61
|
-
function injectDatabaseNamesAndUsers(env, appConfig) {
|
|
60
|
+
function injectDatabaseNamesAndUsers(env, appConfig, scopeOpts = null) {
|
|
62
61
|
const databases = appConfig?.requires?.databases || appConfig?.databases;
|
|
63
62
|
if (!Array.isArray(databases) || databases.length === 0) return;
|
|
63
|
+
const prefix =
|
|
64
|
+
scopeOpts &&
|
|
65
|
+
scopeOpts.effectiveEnvironmentScopedResources &&
|
|
66
|
+
scopeOpts.runEnvKey &&
|
|
67
|
+
(scopeOpts.runEnvKey === 'dev' || scopeOpts.runEnvKey === 'tst')
|
|
68
|
+
? `${String(scopeOpts.runEnvKey).toLowerCase()}-`
|
|
69
|
+
: '';
|
|
64
70
|
for (let i = 0; i < databases.length; i++) {
|
|
65
71
|
const db = databases[i];
|
|
66
|
-
const
|
|
72
|
+
const baseName = db?.name || (appConfig?.app?.key || 'app');
|
|
73
|
+
const name = prefix ? `${prefix}${baseName}` : baseName;
|
|
67
74
|
env[`DB_${i}_NAME`] = name;
|
|
68
75
|
env[`DB_${i}_USER`] = pgUserName(name);
|
|
69
76
|
}
|
|
@@ -146,24 +153,6 @@ function buildDbInitOnlyEnv(merged) {
|
|
|
146
153
|
return dbInit;
|
|
147
154
|
}
|
|
148
155
|
|
|
149
|
-
/**
|
|
150
|
-
* Return pgpass paths under infra-dev* directories in aifabrix home (for fallback lookup).
|
|
151
|
-
* @param {string} aifabrixDir - Aifabrix home directory
|
|
152
|
-
* @returns {string[]} Paths to pgpass files
|
|
153
|
-
*/
|
|
154
|
-
function getInfraDevPgpassPaths(aifabrixDir) {
|
|
155
|
-
if (!fsSync.existsSync(aifabrixDir)) return [];
|
|
156
|
-
let entries;
|
|
157
|
-
try {
|
|
158
|
-
entries = fsSync.readdirSync(aifabrixDir).sort();
|
|
159
|
-
} catch {
|
|
160
|
-
return [];
|
|
161
|
-
}
|
|
162
|
-
return entries
|
|
163
|
-
.filter((name) => name.startsWith('infra-dev'))
|
|
164
|
-
.map((name) => path.join(aifabrixDir, name, 'pgpass'));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
156
|
/**
|
|
168
157
|
* Read first password from a pgpass file (format host:port:db:user:password).
|
|
169
158
|
* @param {string} pgpassPath - Path to pgpass file
|
|
@@ -178,34 +167,31 @@ async function readPasswordFromPgpassFile(pgpassPath) {
|
|
|
178
167
|
}
|
|
179
168
|
|
|
180
169
|
/**
|
|
181
|
-
* Read POSTGRES_PASSWORD from
|
|
182
|
-
*
|
|
170
|
+
* Read POSTGRES_PASSWORD from `pgpass` next to the active infra compose (same as `resolveInfraStatePaths()`).
|
|
171
|
+
* Does not use `getAifabrixHome()` alone, so a stale pgpass under the wrong base directory (e.g. when
|
|
172
|
+
* `aifabrix-home` points at $HOME but compose lives under the config dir) cannot override admin-secrets.
|
|
183
173
|
* @param {number|string} developerId - Developer ID
|
|
184
174
|
* @returns {Promise<string|undefined>} Password or undefined
|
|
185
175
|
*/
|
|
186
176
|
async function readPostgresPasswordFromPgpass(developerId) {
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
} catch {
|
|
199
|
-
// ignore
|
|
200
|
-
}
|
|
177
|
+
const { resolveInfraStatePaths } = require('../infrastructure/helpers');
|
|
178
|
+
const { infraDir } = resolveInfraStatePaths(developerId);
|
|
179
|
+
const pgpassPath = path.join(infraDir, 'pgpass');
|
|
180
|
+
if (!fsSync.existsSync(pgpassPath)) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const pwd = await readPasswordFromPgpassFile(pgpassPath);
|
|
185
|
+
return pwd;
|
|
186
|
+
} catch {
|
|
187
|
+
return undefined;
|
|
201
188
|
}
|
|
202
|
-
return undefined;
|
|
203
189
|
}
|
|
204
190
|
|
|
205
191
|
/**
|
|
206
192
|
* Build two run env files: .env.run (app-only, no admin secrets) and .env.run.admin (start-only, for db-init).
|
|
207
193
|
* Admin password is never set in the app container; .env.run.admin is used only for start and then deleted.
|
|
208
|
-
* When
|
|
194
|
+
* When `pgpass` exists beside the active infra compose, POSTGRES_PASSWORD is taken from it so db-init matches Postgres.
|
|
209
195
|
* @async
|
|
210
196
|
* @param {string} appName - Application name
|
|
211
197
|
* @param {Object} appConfig - Application configuration
|
|
@@ -213,24 +199,26 @@ async function readPostgresPasswordFromPgpass(developerId) {
|
|
|
213
199
|
* @param {number|string} [developerId] - Developer ID (for pgpass lookup)
|
|
214
200
|
* @returns {Promise<{ runEnvPath: string, runEnvAdminPath: string }>} Paths to .env.run and .env.run.admin
|
|
215
201
|
*/
|
|
216
|
-
async function buildMergedRunEnvAndWrite(appName, appConfig, devDir, developerId) {
|
|
202
|
+
async function buildMergedRunEnvAndWrite(appName, appConfig, devDir, developerId, scopeOpts = null) {
|
|
217
203
|
const infra = require('../infrastructure');
|
|
218
204
|
const ensureAdminSecretsFn = typeof infra.ensureAdminSecrets === 'function'
|
|
219
205
|
? infra.ensureAdminSecrets
|
|
220
206
|
: require('../infrastructure/helpers').ensureAdminSecrets;
|
|
221
207
|
await ensureAdminSecretsFn();
|
|
222
208
|
const adminObj = await adminSecrets.readAndDecryptAdminSecrets();
|
|
209
|
+
const runEnvKey = scopeOpts && scopeOpts.runEnvKey ? String(scopeOpts.runEnvKey).toLowerCase() : 'dev';
|
|
223
210
|
const appObj = await secretsEnvWrite.resolveAndGetEnvMap(appName, {
|
|
224
211
|
environment: 'docker',
|
|
225
212
|
secretsPath: null,
|
|
226
|
-
force: false
|
|
213
|
+
force: false,
|
|
214
|
+
runEnvKey
|
|
227
215
|
});
|
|
228
216
|
const merged = { ...adminObj, ...appObj };
|
|
229
217
|
if (developerId !== undefined) {
|
|
230
218
|
const pgpassPwd = await readPostgresPasswordFromPgpass(developerId);
|
|
231
219
|
if (pgpassPwd !== undefined) merged.POSTGRES_PASSWORD = pgpassPwd;
|
|
232
220
|
}
|
|
233
|
-
injectDatabaseNamesAndUsers(merged, appConfig);
|
|
221
|
+
injectDatabaseNamesAndUsers(merged, appConfig, scopeOpts);
|
|
234
222
|
injectContainerPortForRun(merged, appConfig, appName);
|
|
235
223
|
|
|
236
224
|
const runEnvPath = path.join(devDir, '.env.run');
|