@aifabrix/builder 2.43.0 → 2.44.1

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.
Files changed (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -1,3 +1,4 @@
1
+ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * CLI utility command setup (resolve, json, split-json, show, validate, diff).
3
4
  *
@@ -15,6 +16,20 @@ const logger = require('../utils/logger');
15
16
  const { handleCommandError, logOfflinePathWhenType } = require('../utils/cli-utils');
16
17
  const { detectAppType, getDeployJsonPath, getResolveAppPath } = require('../utils/paths');
17
18
 
19
+ const JSON_HELP_AFTER = `
20
+ Example:
21
+ $ aifabrix json myapp
22
+ Generates *-deploy.json (or application-schema.json) for commit before deploy.
23
+ `;
24
+
25
+ const VALIDATE_HELP_AFTER = `
26
+ Examples:
27
+ $ aifabrix validate myapp
28
+ $ aifabrix validate myapp --cert-sync
29
+ $ aifabrix validate --integration
30
+ $ aifabrix validate --builder
31
+ `;
32
+
18
33
  /**
19
34
  * Resolve app path and type for split-json (integration first, then builder).
20
35
  *
@@ -67,7 +82,7 @@ async function handleSplitJsonCommand(appName, options) {
67
82
  * @returns {void}
68
83
  */
69
84
  function logSplitJsonResult(result) {
70
- logger.log(chalk.green('\n✓ Successfully split deployment JSON into component files:'));
85
+ logger.log(formatSuccessParagraph('Successfully split deployment JSON into component files:'));
71
86
  logger.log(` • env.template: ${result.envTemplate}`);
72
87
  logger.log(` • application.yaml: ${result.variables}`);
73
88
  if (result.systemFile) {
@@ -88,7 +103,7 @@ function logSplitJsonResult(result) {
88
103
 
89
104
  function setupResolveCommand(program) {
90
105
  program.command('resolve <app>')
91
- .description('Generate .env file from template and validate application files')
106
+ .description('Generate .env from template; optional validate after')
92
107
  .option('-f, --force', 'Generate missing secret keys in secrets file')
93
108
  .option('--skip-validation', 'Skip file validation after generating .env')
94
109
  .action(async(appName, options) => {
@@ -101,7 +116,7 @@ function setupResolveCommand(program) {
101
116
  options.force,
102
117
  { appPath, envOnly, skipOutputPath: false, preserveFromPath: null }
103
118
  );
104
- logger.log(`✓ Generated .env file: ${envPath}`);
119
+ logger.log(`✔ Generated .env file: ${envPath}`);
105
120
  if (envOnly) {
106
121
  logger.log(chalk.gray(' (env-only mode: validation skipped; no application.yaml)'));
107
122
  } else if (!options.skipValidation) {
@@ -109,7 +124,7 @@ function setupResolveCommand(program) {
109
124
  const result = await validate.validateAppOrFile(appName);
110
125
  validate.displayValidationResults(result);
111
126
  if (!result.valid) {
112
- logger.log(chalk.yellow('\n⚠️ Validation found errors. Fix them before deploying.'));
127
+ logger.log(chalk.yellow('\n Validation found errors. Fix them before deploying.'));
113
128
  process.exit(1);
114
129
  }
115
130
  }
@@ -122,19 +137,20 @@ function setupResolveCommand(program) {
122
137
 
123
138
  function setupJsonCommand(program) {
124
139
  program.command('json <app>')
125
- .description('Generate deployment JSON to disk (<app>-deploy.json). Use before commit so version control has the correct file.')
140
+ .description('Write deployment JSON to disk for version control')
141
+ .addHelpText('after', JSON_HELP_AFTER)
126
142
  .action(async(appName, options) => {
127
143
  try {
128
144
  const result = await generator.generateDeployJsonWithValidation(appName, options);
129
145
  if (result.success) {
130
146
  const fileName = result.path.includes('application-schema.json') ? 'application-schema.json' : 'deployment JSON';
131
- logger.log(`✓ Generated ${fileName}: ${result.path}`);
147
+ logger.log(`✔ Generated ${fileName}: ${result.path}`);
132
148
  if (result.validation.warnings && result.validation.warnings.length > 0) {
133
- logger.log('\n⚠️ Warnings:');
149
+ logger.log('\n Warnings:');
134
150
  result.validation.warnings.forEach(w => logger.log(` • ${w}`));
135
151
  }
136
152
  } else {
137
- logger.log(' Validation failed:');
153
+ logger.log(' Validation failed:');
138
154
  (result.validation.errors || []).forEach(e => logger.log(` • ${e}`));
139
155
  process.exit(1);
140
156
  }
@@ -147,7 +163,7 @@ function setupJsonCommand(program) {
147
163
 
148
164
  function setupSplitJsonCommand(program) {
149
165
  program.command('split-json <app>')
150
- .description('Split deployment JSON into component files (env.template, application.yaml, rbac.yml, README.md)')
166
+ .description('Split deploy JSON into env.template, application.yaml, rbac, README, …')
151
167
  .option('-o, --output <dir>', 'Output directory for component files (defaults to same directory as JSON)')
152
168
  .action(async(appName, options) => {
153
169
  try {
@@ -160,13 +176,13 @@ function setupSplitJsonCommand(program) {
160
176
  }
161
177
 
162
178
  function setupRepairCommand(program) {
163
- program.command('repair <app>')
164
- .description('Repair external integration config: fix drift (file lists, app key, datasource alignment, rbac, manifest)')
179
+ program.command('repair <systemKey>')
180
+ .description('Fix external integration drift (files, RBAC, manifest, )')
165
181
  .option('--auth <method>', 'Set authentication method (oauth2, aad, apikey, basic, queryParam, oidc, hmac, none); updates system file and env.template')
166
182
  .option('--doc', 'Regenerate README.md from deployment manifest')
167
183
  .option('--dry-run', 'Report changes only; do not write')
168
184
  .option('--rbac', 'Ensure RBAC permissions per datasource and add default Admin/Reader roles if none exist')
169
- .option('--expose', 'Set exposed.attributes on each datasource to all fieldMappings.attributes keys')
185
+ .option('--expose', 'Set exposed.schema on each datasource from all fieldMappings.attributes keys (metadata.<key>); removes deprecated exposed.attributes if present')
170
186
  .option('--sync', 'Add default sync section to datasources that lack it')
171
187
  .option('--test', 'Generate testPayload.payloadTemplate and testPayload.expectedResult from attributes')
172
188
  .action(async(appName, options) => {
@@ -196,9 +212,9 @@ function setupRepairCommand(program) {
196
212
  logger.log(chalk.yellow('\nWould apply:'));
197
213
  result.changes.forEach(c => logger.log(chalk.gray(` ${c}`)));
198
214
  } else if (result.updated) {
199
- logger.log(chalk.green('\n✓ Repaired external integration config.'));
215
+ logger.log(formatSuccessParagraph('Repaired external integration config.'));
200
216
  } else if (result.readmeRegenerated) {
201
- logger.log(chalk.green('\n✓ Regenerated README.md from deployment manifest.'));
217
+ logger.log(formatSuccessParagraph('Regenerated README.md from deployment manifest.'));
202
218
  } else {
203
219
  logger.log(chalk.gray('No changes needed; config already matches files on disk.'));
204
220
  }
@@ -211,7 +227,7 @@ function setupRepairCommand(program) {
211
227
 
212
228
  function setupConvertCommand(program) {
213
229
  program.command('convert <app>')
214
- .description('Convert integration/external system and datasource config files between JSON and YAML')
230
+ .description('Convert integration config files between JSON and YAML')
215
231
  .option('--format <format>', 'Target format: json | yaml (required unless config format is set)')
216
232
  .option('-f, --force', 'Skip confirmation prompt')
217
233
  .action(async(appName, options) => {
@@ -229,7 +245,7 @@ function setupConvertCommand(program) {
229
245
  }
230
246
  const { runConvert } = require('../commands/convert');
231
247
  const { converted, deleted } = await runConvert(appName, { format: normalized, force: options.force });
232
- logger.log(chalk.green('\n✓ Convert complete.'));
248
+ logger.log(formatSuccessParagraph('Convert complete.'));
233
249
  converted.forEach(p => logger.log(` • ${p}`));
234
250
  if (deleted.length > 0) {
235
251
  logger.log(chalk.gray(' Removed old files:'));
@@ -243,14 +259,22 @@ function setupConvertCommand(program) {
243
259
  }
244
260
 
245
261
  function setupShowCommand(program) {
246
- program.command('show <appKey>')
247
- .description('Show application info from local builder/ or integration/ (offline) or from controller (--online)')
262
+ program.command('show <app>')
263
+ .description('Show app from local tree (default) or controller (--online)')
248
264
  .option('--online', 'Fetch application data from the controller')
249
265
  .option('--json', 'Output as JSON')
266
+ .option(
267
+ '--verify-cert',
268
+ 'For external integrations, verify trust state on the dataplane when logged in (with --online uses current session; offline attempts the same if a controller URL is configured)'
269
+ )
250
270
  .action(async(appKey, options) => {
251
271
  try {
252
272
  const { showApp } = require('../app/show');
253
- await showApp(appKey, { online: options.online, json: options.json });
273
+ await showApp(appKey, {
274
+ online: options.online,
275
+ json: options.json,
276
+ verifyCert: options.verifyCert === true
277
+ });
254
278
  } catch (error) {
255
279
  logger.error(chalk.red(`Error: ${error.message}`));
256
280
  process.exit(1);
@@ -292,7 +316,10 @@ async function runValidateCommand(appOrFile, options) {
292
316
  process.exit(1);
293
317
  }
294
318
 
295
- const result = await validate.validateAppOrFile(appOrFile, opts);
319
+ const result = await validate.validateAppOrFile(appOrFile, {
320
+ ...opts,
321
+ certSync: opts.certSync === true
322
+ });
296
323
  if (outFormat === 'json') {
297
324
  logger.log(JSON.stringify(result, null, 2));
298
325
  } else {
@@ -303,10 +330,15 @@ async function runValidateCommand(appOrFile, options) {
303
330
 
304
331
  function setupValidateDiffCommands(program) {
305
332
  program.command('validate [appOrFile]')
306
- .description('Validate application or external integration file; use --integration or --builder to validate all apps')
333
+ .description('Validate one app/file or all under integration/ or builder/')
334
+ .addHelpText('after', VALIDATE_HELP_AFTER)
307
335
  .option('--format <format>', 'Output format: json | default (human-readable)')
308
336
  .option('--integration', 'Validate all applications under integration/')
309
337
  .option('--builder', 'Validate all applications under builder/')
338
+ .option(
339
+ '--cert-sync',
340
+ 'After successful validation of an external integration, refresh the system file certification block from the dataplane (requires login)'
341
+ )
310
342
  .action((appOrFile, options) => {
311
343
  runValidateCommand(appOrFile, options).catch((error) => {
312
344
  handleCommandError(error, 'validate');
@@ -315,7 +347,7 @@ function setupValidateDiffCommands(program) {
315
347
  });
316
348
 
317
349
  program.command('diff <file1> <file2>')
318
- .description('Compare two configuration files (for deployment pipeline)')
350
+ .description('Diff two config files (optional schema validate)')
319
351
  .option('--no-validate', 'Skip schema validation (type check still applied)')
320
352
  .action(async(file1, file2, cmd) => {
321
353
  try {
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * Down-app command – stop container, optionally volumes, then remove image if unused
3
4
  *
@@ -7,14 +8,11 @@
7
8
  */
8
9
 
9
10
  const chalk = require('chalk');
10
- const { exec } = require('child_process');
11
- const { promisify } = require('util');
12
11
  const logger = require('../utils/logger');
13
12
  const config = require('../core/config');
14
13
  const containerHelpers = require('../utils/app-run-containers');
15
14
  const { downApp } = require('../app/down');
16
-
17
- const execAsync = promisify(exec);
15
+ const { execWithDockerEnv } = require('../utils/docker-exec');
18
16
 
19
17
  /**
20
18
  * Get image ID of a running container (sha or name:tag)
@@ -24,7 +22,7 @@ const execAsync = promisify(exec);
24
22
  */
25
23
  async function getContainerImageId(containerName) {
26
24
  try {
27
- const { stdout } = await execAsync(
25
+ const { stdout } = await execWithDockerEnv(
28
26
  `docker inspect --format='{{.Image}}' ${containerName}`,
29
27
  { encoding: 'utf8' }
30
28
  );
@@ -43,8 +41,8 @@ async function getContainerImageId(containerName) {
43
41
  async function removeImageIfUnused(imageId) {
44
42
  if (!imageId) return;
45
43
  try {
46
- await execAsync(`docker rmi ${imageId}`);
47
- logger.log(chalk.green(`✓ Image ${imageId} removed`));
44
+ await execWithDockerEnv(`docker rmi ${imageId}`);
45
+ logger.log(formatSuccessLine(`Image ${imageId} removed`));
48
46
  } catch (err) {
49
47
  const msg = (err && err.message) || '';
50
48
  if (msg.includes('in use') || msg.includes('is being used')) {
@@ -1,3 +1,4 @@
1
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
1
2
  /**
2
3
  * Install command – run install (dependencies) inside app container (dev: running; tst: ephemeral with .env).
3
4
  *
@@ -81,7 +82,7 @@ async function runInstallInDev(appName, developerId, installCmd) {
81
82
  logger.log(chalk.blue(`Running install in container ${containerName}: ${installCmd}\n`));
82
83
  const cmd = installCommandForReadOnlyApp(installCmd);
83
84
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
84
- return runDockerExec(containerName, cmd, envFilePath);
85
+ return await runDockerExec(containerName, cmd, envFilePath);
85
86
  }
86
87
 
87
88
  /**
@@ -92,7 +93,9 @@ async function runInstallInDev(appName, developerId, installCmd) {
92
93
  * @param {string|null} [envFilePath] - Path to resolved .env for --env-file (optional; when set, install has registry tokens)
93
94
  * @returns {Promise<number>} Exit code
94
95
  */
95
- function runDockerExec(containerName, cmd, envFilePath = null) {
96
+ async function runDockerExec(containerName, cmd, envFilePath = null) {
97
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
98
+ const dockerEnv = await getDockerExecEnv();
96
99
  return new Promise((resolve) => {
97
100
  const args = [
98
101
  'exec',
@@ -106,7 +109,8 @@ function runDockerExec(containerName, cmd, envFilePath = null) {
106
109
  args.push(containerName, 'sh', '-c', cmd);
107
110
  const proc = spawn('docker', args, {
108
111
  stdio: 'inherit',
109
- shell: false
112
+ shell: false,
113
+ env: dockerEnv
110
114
  });
111
115
  proc.on('close', code => resolve(code !== null ? code : 1));
112
116
  proc.on('error', () => resolve(1));
@@ -120,7 +124,9 @@ function runDockerExec(containerName, cmd, envFilePath = null) {
120
124
  * @param {string|null} [envFilePath] - Path to .env file for --env-file (optional)
121
125
  * @returns {Promise<number>} Exit code
122
126
  */
123
- function runDockerRunEphemeral(fullImage, cmd, envFilePath = null) {
127
+ async function runDockerRunEphemeral(fullImage, cmd, envFilePath = null) {
128
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
129
+ const dockerEnv = await getDockerExecEnv();
124
130
  return new Promise((resolve) => {
125
131
  const args = ['run', '--rm', '-e', `TMPDIR=${TMPDIR_VALUE}`, '-e', `npm_config_store_dir=${PNPM_STORE_DIR}`, '-e', 'CI=true'];
126
132
  if (envFilePath) {
@@ -129,7 +135,8 @@ function runDockerRunEphemeral(fullImage, cmd, envFilePath = null) {
129
135
  args.push(fullImage, 'sh', '-c', cmd);
130
136
  const proc = spawn('docker', args, {
131
137
  stdio: 'inherit',
132
- shell: false
138
+ shell: false,
139
+ env: dockerEnv
133
140
  });
134
141
  proc.on('close', code => resolve(code !== null ? code : 1));
135
142
  proc.on('error', () => resolve(1));
@@ -157,7 +164,7 @@ async function runAppInstall(appName, options = {}) {
157
164
  if (env === 'dev') {
158
165
  const code = await runInstallInDev(appName, developerId, installCmd);
159
166
  if (code !== 0) process.exit(code);
160
- logger.log(chalk.green('Install completed'));
167
+ logger.log(formatSuccessLine('Install completed'));
161
168
  return;
162
169
  }
163
170
 
@@ -166,7 +173,7 @@ async function runAppInstall(appName, options = {}) {
166
173
  const cmd = installCommandForReadOnlyApp(installCmd);
167
174
  const code = await runDockerRunEphemeral(fullImage, cmd, envFilePath);
168
175
  if (code !== 0) process.exit(code);
169
- logger.log(chalk.green('Install completed'));
176
+ logger.log(formatSuccessLine('Install completed'));
170
177
  }
171
178
 
172
179
  module.exports = { runAppInstall, getInstallCommand };
@@ -7,15 +7,14 @@
7
7
  */
8
8
 
9
9
  const chalk = require('chalk');
10
- const { exec, spawn } = require('child_process');
10
+ const { spawn } = require('child_process');
11
11
  const readline = require('readline');
12
- const { promisify } = require('util');
13
12
  const logger = require('../utils/logger');
14
13
  const config = require('../core/config');
15
14
  const containerHelpers = require('../utils/app-run-containers');
16
15
  const { validateAppName } = require('../app/push');
17
16
 
18
- const execAsync = promisify(exec);
17
+ const { execWithDockerEnv } = require('../utils/docker-exec');
19
18
 
20
19
  /** Default number of log lines */
21
20
  const DEFAULT_TAIL_LINES = 100;
@@ -132,7 +131,7 @@ function passesLevelFilter(lineLevel, minLevel) {
132
131
  */
133
132
  async function dumpMaskedEnv(containerName) {
134
133
  try {
135
- const { stdout } = await execAsync(`docker exec ${containerName} env`, { encoding: 'utf8', timeout: 5000 });
134
+ const { stdout } = await execWithDockerEnv(`docker exec ${containerName} env`, { encoding: 'utf8', timeout: 5000 });
136
135
  const lines = stdout.split('\n').filter((l) => l.trim());
137
136
  if (lines.length === 0) return;
138
137
  logger.log(chalk.bold('\n--- Environment (sensitive values masked) ---\n'));
@@ -156,6 +155,8 @@ async function dumpMaskedEnv(containerName) {
156
155
  * @returns {Promise<void>}
157
156
  */
158
157
  async function runDockerLogs(containerName, options) {
158
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
159
+ const dockerEnv = await getDockerExecEnv();
159
160
  const args = options.tail === 0 ? ['logs', containerName] : ['logs', '--tail', String(options.tail), containerName];
160
161
  const minLevel =
161
162
  options.level !== undefined && options.level !== null && options.level !== ''
@@ -164,14 +165,14 @@ async function runDockerLogs(containerName, options) {
164
165
 
165
166
  if (minLevel === null || minLevel === undefined || !LOG_LEVELS.includes(minLevel)) {
166
167
  return new Promise((resolve, reject) => {
167
- const proc = spawn('docker', args, { stdio: 'inherit' });
168
+ const proc = spawn('docker', args, { stdio: 'inherit', env: dockerEnv });
168
169
  proc.on('error', reject);
169
170
  proc.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`docker logs exited with ${code}`))));
170
171
  });
171
172
  }
172
173
 
173
174
  return new Promise((resolve, reject) => {
174
- const proc = spawn('docker', args, { stdio: ['inherit', 'pipe', 'pipe'] });
175
+ const proc = spawn('docker', args, { stdio: ['inherit', 'pipe', 'pipe'], env: dockerEnv });
175
176
  proc.on('error', reject);
176
177
 
177
178
  function onLine(line) {
@@ -213,7 +214,9 @@ async function runDockerLogs(containerName, options) {
213
214
  * @param {number} [tail] - Lines to show (0 = full, omit --tail)
214
215
  * @param {string|null} [minLevel] - Minimum log level to show (debug|info|warn|error)
215
216
  */
216
- function runDockerLogsFollow(containerName, tail, minLevel) {
217
+ async function runDockerLogsFollow(containerName, tail, minLevel) {
218
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
219
+ const dockerEnv = await getDockerExecEnv();
217
220
  const args = tail === 0 ? ['logs', '-f', containerName] : ['logs', '-f', '--tail', String(tail), containerName];
218
221
  const level =
219
222
  minLevel !== undefined && minLevel !== null && minLevel !== ''
@@ -222,7 +225,7 @@ function runDockerLogsFollow(containerName, tail, minLevel) {
222
225
  const useFilter = level !== null && level !== undefined && LOG_LEVELS.includes(level);
223
226
 
224
227
  if (!useFilter) {
225
- const proc = spawn('docker', args, { stdio: 'inherit' });
228
+ const proc = spawn('docker', args, { stdio: 'inherit', env: dockerEnv });
226
229
  proc.on('error', (err) => {
227
230
  logger.log(chalk.red(`Error: ${err.message}`));
228
231
  process.exit(1);
@@ -233,7 +236,7 @@ function runDockerLogsFollow(containerName, tail, minLevel) {
233
236
  return;
234
237
  }
235
238
 
236
- const proc = spawn('docker', args, { stdio: ['inherit', 'pipe', 'pipe'] });
239
+ const proc = spawn('docker', args, { stdio: ['inherit', 'pipe', 'pipe'], env: dockerEnv });
237
240
  proc.on('error', (err) => {
238
241
  logger.log(chalk.red(`Error: ${err.message}`));
239
242
  process.exit(1);
@@ -286,7 +289,7 @@ async function runAppLogs(appKey, options = {}) {
286
289
  }
287
290
 
288
291
  if (follow) {
289
- runDockerLogsFollow(containerName, tail, level);
292
+ await runDockerLogsFollow(containerName, tail, level);
290
293
  return;
291
294
  }
292
295
 
@@ -48,6 +48,8 @@ async function runAppShell(appName, _options = {}) {
48
48
 
49
49
  logger.log(chalk.blue(`Opening shell in ${containerName} (exit with 'exit' or Ctrl+D)...\n`));
50
50
 
51
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
52
+ const dockerEnv = await getDockerExecEnv();
51
53
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
52
54
  const proc = spawn('docker', [
53
55
  'exec', '-it',
@@ -57,7 +59,8 @@ async function runAppShell(appName, _options = {}) {
57
59
  'sh'
58
60
  ], {
59
61
  stdio: 'inherit',
60
- shell: false
62
+ shell: false,
63
+ env: dockerEnv
61
64
  });
62
65
 
63
66
  return new Promise((resolve, reject) => {
@@ -7,8 +7,8 @@
7
7
  */
8
8
 
9
9
  const { spawn } = require('child_process');
10
- const chalk = require('chalk');
11
10
  const logger = require('../utils/logger');
11
+ const { infoLine, formatSuccessLine } = require('../utils/cli-test-layout-chalk');
12
12
  const config = require('../core/config');
13
13
  const containerHelpers = require('../utils/app-run-containers');
14
14
  const composeGenerator = require('../utils/compose-generator');
@@ -97,9 +97,9 @@ async function runTestsInDev(appName, developerId, testCmd) {
97
97
  `Container ${containerName} is not running.\nRun 'aifabrix run ${appName}' first.`
98
98
  );
99
99
  }
100
- logger.log(chalk.blue(`Running tests in container ${containerName}: ${testCmd}\n`));
100
+ logger.log(infoLine(`ℹ Running tests in container ${containerName}: ${testCmd}\n`));
101
101
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
102
- return runDockerExec(containerName, testCmd, envFilePath);
102
+ return await runDockerExec(containerName, testCmd, envFilePath);
103
103
  }
104
104
 
105
105
  /**
@@ -123,14 +123,14 @@ async function runAppTest(appName, options = {}) {
123
123
  if (env === 'dev') {
124
124
  const code = await runTestsInDev(appName, developerId, testCmd);
125
125
  if (code !== 0) process.exit(code);
126
- logger.log(chalk.green('Tests completed'));
126
+ logger.log(formatSuccessLine('Tests completed.'));
127
127
  return;
128
128
  }
129
- logger.log(chalk.blue(`Running tests in ephemeral container (${fullImage}): ${testCmd}\n`));
129
+ logger.log(infoLine(`ℹ Running tests in ephemeral container (${fullImage}): ${testCmd}\n`));
130
130
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
131
131
  const code = await runDockerRunEphemeral(fullImage, testCmd, envFilePath);
132
132
  if (code !== 0) process.exit(code);
133
- logger.log(chalk.green('Tests completed'));
133
+ logger.log(formatSuccessLine('Tests completed.'));
134
134
  }
135
135
 
136
136
  /**
@@ -141,14 +141,17 @@ async function runAppTest(appName, options = {}) {
141
141
  * @param {string|null} [envFilePath] - Path to resolved .env for --env-file (optional)
142
142
  * @returns {Promise<number>} Exit code
143
143
  */
144
- function runDockerExec(containerName, testCmd, envFilePath = null) {
144
+ async function runDockerExec(containerName, testCmd, envFilePath = null) {
145
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
146
+ const dockerEnv = await getDockerExecEnv();
145
147
  return new Promise((resolve) => {
146
148
  const args = ['exec'];
147
149
  if (envFilePath) args.push('--env-file', envFilePath);
148
150
  args.push(containerName, 'sh', '-c', testCmd);
149
151
  const proc = spawn('docker', args, {
150
152
  stdio: 'inherit',
151
- shell: false
153
+ shell: false,
154
+ env: dockerEnv
152
155
  });
153
156
  proc.on('close', code => resolve(code !== null ? code : 1));
154
157
  proc.on('error', () => resolve(1));
@@ -162,14 +165,17 @@ function runDockerExec(containerName, testCmd, envFilePath = null) {
162
165
  * @param {string|null} [envFilePath] - Path to .env for docker run --env-file (optional)
163
166
  * @returns {Promise<number>} Exit code
164
167
  */
165
- function runDockerRunEphemeral(fullImage, testCmd, envFilePath = null) {
168
+ async function runDockerRunEphemeral(fullImage, testCmd, envFilePath = null) {
169
+ const { getDockerExecEnv } = require('../utils/remote-docker-env');
170
+ const dockerEnv = await getDockerExecEnv();
166
171
  return new Promise((resolve) => {
167
172
  const args = ['run', '--rm'];
168
173
  if (envFilePath) args.push('--env-file', envFilePath);
169
174
  args.push(fullImage, 'sh', '-c', testCmd);
170
175
  const proc = spawn('docker', args, {
171
176
  stdio: 'inherit',
172
- shell: false
177
+ shell: false,
178
+ env: dockerEnv
173
179
  });
174
180
  proc.on('close', code => resolve(code !== null ? code : 1));
175
181
  proc.on('error', () => resolve(1));
@@ -197,14 +203,14 @@ async function runAppTestE2e(appName, options = {}) {
197
203
  if (env === 'dev') {
198
204
  const code = await runTestsInDev(appName, developerId, cmd);
199
205
  if (code !== 0) process.exit(code);
200
- logger.log(chalk.green('Test-e2e completed'));
206
+ logger.log(formatSuccessLine('Test-e2e completed.'));
201
207
  return;
202
208
  }
203
- logger.log(chalk.blue(`Running test-e2e in ephemeral container (${fullImage}): ${cmd}\n`));
209
+ logger.log(infoLine(`ℹ Running test-e2e in ephemeral container (${fullImage}): ${cmd}\n`));
204
210
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
205
211
  const code = await runDockerRunEphemeral(fullImage, cmd, envFilePath);
206
212
  if (code !== 0) process.exit(code);
207
- logger.log(chalk.green('Test-e2e completed'));
213
+ logger.log(formatSuccessLine('Test-e2e completed.'));
208
214
  }
209
215
 
210
216
  /**
@@ -229,14 +235,14 @@ async function runAppTestIntegration(appName, options = {}) {
229
235
  if (env === 'dev') {
230
236
  const code = await runTestsInDev(appName, developerId, cmd);
231
237
  if (code !== 0) process.exit(code);
232
- logger.log(chalk.green('Test-integration completed'));
238
+ logger.log(formatSuccessLine('Test-integration completed.'));
233
239
  return;
234
240
  }
235
- logger.log(chalk.blue(`Running test-integration in ephemeral container (${fullImage}): ${cmd}\n`));
241
+ logger.log(infoLine(`ℹ Running test-integration in ephemeral container (${fullImage}): ${cmd}\n`));
236
242
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
237
243
  const code = await runDockerRunEphemeral(fullImage, cmd, envFilePath);
238
244
  if (code !== 0) process.exit(code);
239
- logger.log(chalk.green('Test-integration completed'));
245
+ logger.log(formatSuccessLine('Test-integration completed.'));
240
246
  }
241
247
 
242
248
  /**
@@ -260,14 +266,14 @@ async function runAppLint(appName, options = {}) {
260
266
  if (env === 'dev') {
261
267
  const code = await runTestsInDev(appName, developerId, cmd);
262
268
  if (code !== 0) process.exit(code);
263
- logger.log(chalk.green('Lint completed'));
269
+ logger.log(formatSuccessLine('Lint completed.'));
264
270
  return;
265
271
  }
266
- logger.log(chalk.blue(`Running lint in ephemeral container (${fullImage}): ${cmd}\n`));
272
+ logger.log(infoLine(`ℹ Running lint in ephemeral container (${fullImage}): ${cmd}\n`));
267
273
  const envFilePath = await secretsEnvWrite.resolveAndWriteEnvFile(appName, {});
268
274
  const code = await runDockerRunEphemeral(fullImage, cmd, envFilePath);
269
275
  if (code !== 0) process.exit(code);
270
- logger.log(chalk.green('Lint completed'));
276
+ logger.log(formatSuccessLine('Lint completed.'));
271
277
  }
272
278
 
273
279
  module.exports = {