@aifabrix/builder 2.45.5 → 2.47.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 +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/project-rules.mdc +1 -0
- package/.npmrc.token +1 -0
- package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
- package/.temp/validation/summary.txt +5 -0
- package/README.md +43 -17
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +146 -0
- package/jest.projects.js +65 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/dataplane-health.api.js +19 -7
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +98 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/resource-types.api.js +107 -0
- package/lib/api/runtime-configuration.api.js +72 -0
- package/lib/api/types/resource-types.types.js +45 -0
- package/lib/api/user-groups.api.js +9 -9
- package/lib/api/users.api.js +8 -8
- package/lib/api/validation-runner.js +3 -1
- package/lib/api/wizard.api.js +10 -2
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/down.js +78 -27
- package/lib/app/index.js +2 -2
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/app/run-resolve-image.js +2 -1
- package/lib/app/run-stop-containers.js +113 -0
- package/lib/app/run.js +1 -31
- package/lib/app/show-display.js +35 -0
- package/lib/app/show.js +32 -1
- package/lib/build/index.js +22 -5
- package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/channels/add-channel.js +348 -0
- package/lib/channels/channel-artifact-generator.js +141 -0
- package/lib/channels/channel-audit.js +101 -0
- package/lib/channels/channel-auth-context.js +37 -0
- package/lib/channels/channel-credential.js +200 -0
- package/lib/channels/channel-display-name.js +64 -0
- package/lib/channels/channel-external-system.js +106 -0
- package/lib/channels/channel-integration-generator.js +274 -0
- package/lib/channels/channel-probe.js +89 -0
- package/lib/channels/channel-runtime-resolver.js +152 -0
- package/lib/channels/channel-status-display.js +141 -0
- package/lib/channels/channel-targets.js +115 -0
- package/lib/cli/index.js +20 -4
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +84 -81
- package/lib/cli/setup-app.help.js +0 -31
- package/lib/cli/setup-app.js +82 -5
- package/lib/cli/setup-app.test-commands.js +5 -57
- package/lib/cli/setup-auth.js +25 -0
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +25 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
- package/lib/cli/setup-infra-up-platform-action.js +2 -1
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +25 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +44 -5
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/app-logs.js +54 -26
- package/lib/commands/app.js +41 -0
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +142 -68
- package/lib/commands/auth-status.js +43 -54
- package/lib/commands/channel.js +58 -0
- package/lib/commands/datasource-test-trust-cli.js +27 -23
- package/lib/commands/datasource-unified-test-cli.js +6 -3
- package/lib/commands/datasource-unified-test-cli.options.js +5 -1
- package/lib/commands/datasource.js +8 -8
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/identity-apply-sync.js +49 -8
- package/lib/commands/identity-group-cli.js +66 -26
- package/lib/commands/identity-membership-role-cache.js +58 -37
- package/lib/commands/identity-shared.js +22 -1
- package/lib/commands/identity-user-cli.js +80 -34
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +11 -2
- package/lib/commands/repair-auth-apply.js +153 -0
- package/lib/commands/repair-auth-config.js +8 -13
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-com-v2.js +15 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-service-contract.js +206 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +49 -64
- package/lib/commands/repair-env-template.js +76 -25
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +49 -4
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +160 -0
- package/lib/commands/repair-system-alignment.js +7 -4
- package/lib/commands/repair.js +29 -296
- package/lib/commands/resource-type.js +371 -0
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +70 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +24 -8
- package/lib/commands/test-governance-external.js +3 -24
- package/lib/commands/test-trust-external.js +48 -100
- package/lib/commands/up-common.js +57 -13
- package/lib/commands/up-dataplane.js +56 -15
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +113 -110
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +73 -0
- package/lib/commands/verify-trust-external.js +59 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +2 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +90 -0
- package/lib/datasource/agent-trust-debug-log.js +1 -1
- package/lib/datasource/agent-trust-run.js +5 -3
- package/lib/datasource/audit-evidence-extract-debug.js +30 -18
- package/lib/datasource/audit-evidence-extract.js +7 -4
- package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
- package/lib/datasource/bulk-loader-run-batches.js +15 -3
- package/lib/datasource/capability/capability-diff-slice.js +2 -2
- package/lib/datasource/capability/capability-manifest.js +254 -0
- package/lib/datasource/capability/capability-resolve.js +3 -4
- package/lib/datasource/capability/copy-operations.js +5 -3
- package/lib/datasource/capability/remove-operations.js +2 -1
- package/lib/datasource/capability/run-capability-copy.js +32 -4
- package/lib/datasource/capability/run-capability-diff.js +3 -3
- package/lib/datasource/capability/run-capability-dimension.js +2 -4
- package/lib/datasource/capability/run-capability-edit.js +4 -7
- package/lib/datasource/capability/run-capability-relate.js +2 -4
- package/lib/datasource/capability/run-capability-remove.js +2 -4
- package/lib/datasource/capability/validate-capability-slice.js +2 -1
- package/lib/datasource/datasource-identifier.js +2 -1
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/datasource-validate-display.js +1 -1
- package/lib/datasource/field-reference-validator.js +24 -3
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/orphan-profiles-validator.js +98 -0
- package/lib/datasource/test-e2e.js +4 -1
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run.js +5 -2
- package/lib/datasource/validate.js +41 -23
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download-helpers.js +87 -0
- package/lib/external-system/download.js +78 -138
- package/lib/external-system/generator.js +1 -55
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test.js +16 -21
- package/lib/generator/builders.js +11 -1
- package/lib/generator/external-controller-manifest.js +18 -0
- package/lib/generator/split.js +3 -1
- package/lib/generator/wizard.js +1 -28
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-run-display.js +215 -25
- package/lib/identity/fk-reference.js +65 -0
- package/lib/identity/identity-apply-core.js +13 -58
- package/lib/identity/identity-apply-phases.js +5 -1
- package/lib/identity/identity-display.js +243 -0
- package/lib/identity/identity-response-helpers.js +52 -0
- package/lib/identity/identity-sync-errors.js +62 -0
- package/lib/identity/resolve-user-id.js +129 -0
- package/lib/identity/username-default.js +31 -0
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display-trust.js +70 -0
- package/lib/lifecycle/report-display.js +472 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +10 -4
- package/lib/resolvers/datasource-resolver.js +2 -3
- package/lib/resolvers/resource-type-file.js +159 -0
- package/lib/schema/application-schema.json +17 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/deployment-rules.yaml +2 -1
- package/lib/schema/external-datasource.schema.json +2947 -2619
- package/lib/schema/external-system.schema.json +1418 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- package/lib/schema/type/document-storage.json +9 -5
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/app-run-containers.js +25 -2
- package/lib/utils/authentication-shape.js +224 -0
- package/lib/utils/build-copy.js +36 -5
- package/lib/utils/build-resolve-image.js +66 -12
- package/lib/utils/celery-companion-apps.js +53 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-utils.js +20 -4
- package/lib/utils/compose-celery-worker.js +23 -0
- package/lib/utils/compose-generate-docker-compose.js +13 -1
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/configuration-env-resolver.js +36 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-secrets-env-kv.js +216 -0
- package/lib/utils/credential-secrets-env.js +175 -257
- package/lib/utils/dataplane-resolver.js +18 -2
- package/lib/utils/declarative-url-ports.js +27 -4
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/docker-build.js +1 -4
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +11 -3
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/external-system-validators.js +8 -2
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +13 -8
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +2 -0
- package/lib/utils/paths.js +25 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +157 -0
- package/lib/utils/platform-kv-ref.js +57 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/runtime-configuration-download.js +189 -0
- package/lib/utils/runtime-configuration-values.js +119 -0
- package/lib/utils/schema-loader.js +19 -4
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +12 -5
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +8 -0
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/utils/worker-sidecars.js +142 -0
- package/lib/validation/external-manifest-validator.js +2 -0
- package/lib/validation/runtime-configuration-rules.js +98 -0
- package/lib/validation/validate-display-dimensions.js +154 -0
- package/lib/validation/validate-display-sections.js +276 -0
- package/lib/validation/validate-display-steps.js +67 -0
- package/lib/validation/validate-display.js +24 -402
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +7 -1
- package/templates/applications/dataplane/env.template +50 -14
- package/templates/applications/dataplane/rbac.yaml +108 -1
- package/templates/applications/miso-controller/application.yaml +2 -2
- package/templates/applications/miso-controller/env.template +53 -122
- package/templates/applications/miso-controller/rbac.yaml +28 -13
- package/templates/channels/chatgpt/install.template.md.hbs +49 -0
- package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
- package/templates/channels/slack/install.template.md.hbs +49 -0
- package/templates/channels/slack/manifest.template.json.hbs +66 -0
- package/templates/channels/teams-bot/install.template.md.hbs +49 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
- package/templates/channels/web-embed/install.template.md.hbs +49 -0
- package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +75 -18
- package/templates/typescript/docker-compose.hbs +70 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
package/lib/build/index.js
CHANGED
|
@@ -33,10 +33,11 @@ const logger = require('../utils/logger');
|
|
|
33
33
|
const dockerfileUtils = require('../utils/dockerfile-utils');
|
|
34
34
|
const dockerBuild = require('../utils/docker-build');
|
|
35
35
|
const buildCopy = require('../utils/build-copy');
|
|
36
|
-
const {
|
|
36
|
+
const { resolveBuildDockerTagNames } = require('../utils/build-resolve-image');
|
|
37
37
|
const buildHelpers = require('../utils/build-helpers');
|
|
38
38
|
const secretsEnvWrite = require('../core/secrets-env-write');
|
|
39
39
|
const { ensureRunSecretsForApp } = require('../app/run-env-compose');
|
|
40
|
+
const { assertMisoControllerNpmSdkDeps } = require('./miso-controller-npm-sdk-guard');
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* Loads application config for an application
|
|
@@ -286,8 +287,15 @@ async function prepareDevDirectory(appName, buildConfig, options) {
|
|
|
286
287
|
const devDir = await buildCopy.copyBuilderToDevDirectory(appName, developerId);
|
|
287
288
|
logger.log(formatSuccessLine(`Workspace ready: ${devDir}`));
|
|
288
289
|
|
|
289
|
-
const { config: appConfig
|
|
290
|
-
const
|
|
290
|
+
const { config: appConfig } = await buildHelpers.loadAndValidateConfig(appName);
|
|
291
|
+
const { buildImageName, compatBaseName } = await resolveBuildDockerTagNames(
|
|
292
|
+
appName,
|
|
293
|
+
appConfig,
|
|
294
|
+
developerId,
|
|
295
|
+
options
|
|
296
|
+
);
|
|
297
|
+
const effectiveImageName = buildImageName;
|
|
298
|
+
const imageName = compatBaseName || buildImageName;
|
|
291
299
|
|
|
292
300
|
// Check if application source files exist, if not copy from templates
|
|
293
301
|
const filesCopied = await copyApplicationSourceFiles(appName, devDir);
|
|
@@ -389,9 +397,10 @@ async function handleDockerfileGeneration(appName, params, options, buildHelpers
|
|
|
389
397
|
/**
|
|
390
398
|
* Resolve Docker build-args from resolved env map and merged BASH_* secrets.
|
|
391
399
|
* @param {string} appName
|
|
400
|
+
* @param {string} [contextPath] Docker build context (repo root for miso-controller)
|
|
392
401
|
* @returns {Promise<Object.<string, string>>}
|
|
393
402
|
*/
|
|
394
|
-
async function resolveDockerBuildArgsForApp(appName) {
|
|
403
|
+
async function resolveDockerBuildArgsForApp(appName, contextPath) {
|
|
395
404
|
const envMap = await secretsEnvWrite.resolveAndGetEnvMap(appName, { environment: 'docker' });
|
|
396
405
|
const { getBashPrefixedProcessEnvOverlay } = require('../utils/bash-secret-env');
|
|
397
406
|
const bashOverlay = await getBashPrefixedProcessEnvOverlay(null, appName);
|
|
@@ -401,6 +410,14 @@ async function resolveDockerBuildArgsForApp(appName) {
|
|
|
401
410
|
for (const [k, v] of Object.entries(bashOverlay)) {
|
|
402
411
|
if (v && buildArgs[k] === undefined) buildArgs[k] = v;
|
|
403
412
|
}
|
|
413
|
+
// Exported shell tokens win (local dev: export NPM_TOKEN=... before af build / docker build).
|
|
414
|
+
const shellNpm = typeof process.env.NPM_TOKEN === 'string' ? process.env.NPM_TOKEN.trim() : '';
|
|
415
|
+
const shellPypi = typeof process.env.PYPI_TOKEN === 'string' ? process.env.PYPI_TOKEN.trim() : '';
|
|
416
|
+
if (shellNpm) buildArgs.NPM_TOKEN = shellNpm;
|
|
417
|
+
if (shellPypi) buildArgs.PYPI_TOKEN = shellPypi;
|
|
418
|
+
if (appName === 'miso-controller' && contextPath) {
|
|
419
|
+
assertMisoControllerNpmSdkDeps(path.resolve(contextPath));
|
|
420
|
+
}
|
|
404
421
|
return buildArgs;
|
|
405
422
|
}
|
|
406
423
|
|
|
@@ -424,7 +441,7 @@ async function runStandardDockerBuild(appName, options) {
|
|
|
424
441
|
appConfig
|
|
425
442
|
}, options, buildHelpers);
|
|
426
443
|
await ensureRunSecretsForApp(appName);
|
|
427
|
-
const buildArgs = await resolveDockerBuildArgsForApp(appName);
|
|
444
|
+
const buildArgs = await resolveDockerBuildArgsForApp(appName, contextPath);
|
|
428
445
|
const buildOptions = { ...options, buildArgs };
|
|
429
446
|
const tag = options.tag || 'latest';
|
|
430
447
|
if (typeof tag === 'string' && tag.includes(',')) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure miso-controller SDK deps are npm semver before Docker build (no file: vendor hacks).
|
|
3
|
+
* @fileoverview miso-controller npm SDK guard for builder
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { execFileSync } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} repoRoot - aifabrix-miso repo root (Docker build context)
|
|
12
|
+
* @throws {Error} When guard script is missing or deps use file:
|
|
13
|
+
*/
|
|
14
|
+
function assertMisoControllerNpmSdkDeps(repoRoot) {
|
|
15
|
+
const script = path.join(
|
|
16
|
+
repoRoot,
|
|
17
|
+
'packages/miso-controller/scripts/assert-npm-sdk-deps.js'
|
|
18
|
+
);
|
|
19
|
+
if (!fs.existsSync(script)) {
|
|
20
|
+
throw new Error(`miso-controller SDK guard not found: ${script}`);
|
|
21
|
+
}
|
|
22
|
+
execFileSync('node', [script], { cwd: repoRoot, stdio: 'inherit' });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = { assertMisoControllerNpmSdkDeps };
|
|
@@ -211,7 +211,8 @@ async function maybeSyncSystemCertificationFromDataplane(params) {
|
|
|
211
211
|
authConfig,
|
|
212
212
|
datasourceKeys,
|
|
213
213
|
issuanceFailureHint,
|
|
214
|
-
verboseCertHints
|
|
214
|
+
verboseCertHints,
|
|
215
|
+
silent
|
|
215
216
|
} = params;
|
|
216
217
|
if (noCertSync === true) return;
|
|
217
218
|
try {
|
|
@@ -224,14 +225,20 @@ async function maybeSyncSystemCertificationFromDataplane(params) {
|
|
|
224
225
|
verboseCertHints
|
|
225
226
|
});
|
|
226
227
|
if (r.written) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
if (silent !== true) {
|
|
229
|
+
logger.log(
|
|
230
|
+
chalk.gray(`Updated certification block from dataplane${label ? ` (${label})` : ''} in system file.`)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
230
233
|
} else if (r.reason) {
|
|
231
|
-
|
|
234
|
+
if (silent !== true) {
|
|
235
|
+
logCertificationSyncNotWritten(r, label, verboseCertHints === true);
|
|
236
|
+
}
|
|
232
237
|
}
|
|
233
238
|
} catch (e) {
|
|
234
|
-
|
|
239
|
+
if (silent !== true) {
|
|
240
|
+
logger.log(chalk.yellow(`⚠ Certification sync skipped: ${e.message}`));
|
|
241
|
+
}
|
|
235
242
|
}
|
|
236
243
|
}
|
|
237
244
|
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrate aifabrix app add-channel (plan 152).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Channel install after communication external system deploy
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { getChannelTarget, getDefaultChannelDescription } = require('./channel-targets');
|
|
12
|
+
const { resolveChannelRuntimeValues } = require('./channel-runtime-resolver');
|
|
13
|
+
const { generateChannelArtifact } = require('./channel-artifact-generator');
|
|
14
|
+
const {
|
|
15
|
+
getExistingChannelExtension,
|
|
16
|
+
buildChannelExtensionBlock,
|
|
17
|
+
fetchCommunicationSystem,
|
|
18
|
+
patchChannelExtension
|
|
19
|
+
} = require('./channel-external-system');
|
|
20
|
+
const {
|
|
21
|
+
auditArtifactGenerated,
|
|
22
|
+
auditConfigPatched,
|
|
23
|
+
auditApprovalRequired,
|
|
24
|
+
auditValidated,
|
|
25
|
+
auditFailed
|
|
26
|
+
} = require('./channel-audit');
|
|
27
|
+
const { runChannelProbe } = require('./channel-probe');
|
|
28
|
+
const { resolveChannelAuthContext } = require('./channel-auth-context');
|
|
29
|
+
const { ensureChannelCredential } = require('./channel-credential');
|
|
30
|
+
const {
|
|
31
|
+
normalizeBaseChannelName,
|
|
32
|
+
resolveChannelDisplayName
|
|
33
|
+
} = require('./channel-display-name');
|
|
34
|
+
const {
|
|
35
|
+
displayExistingChannelStatus,
|
|
36
|
+
displayChannelInstallResult,
|
|
37
|
+
displayChannelError
|
|
38
|
+
} = require('./channel-status-display');
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {typeof import('./channel-targets').CHANNEL_TARGETS[string]} target
|
|
42
|
+
* @param {Object} channelExt
|
|
43
|
+
* @param {Object} [context]
|
|
44
|
+
* @returns {string|null}
|
|
45
|
+
*/
|
|
46
|
+
function resolveApprovalUrl(target, channelExt, context = {}) {
|
|
47
|
+
if (!target.approvalRequired) return null;
|
|
48
|
+
if (channelExt?.status === 'installed' || channelExt?.status === 'validated') return null;
|
|
49
|
+
if (target.key === 'slack' && context.artifactPath) {
|
|
50
|
+
return `https://api.slack.com/apps/new — upload manifest: ${context.artifactPath}`;
|
|
51
|
+
}
|
|
52
|
+
if (target.key === 'teams-bot') {
|
|
53
|
+
return 'https://admin.teams.microsoft.com/ — configure Bot Channel Registration for this tenant';
|
|
54
|
+
}
|
|
55
|
+
return `https://platform-admin.example/configure/${target.key}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {Object} target
|
|
60
|
+
* @param {Object} channelExt
|
|
61
|
+
* @param {boolean} dryRun
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
function resolveInstallStatus(target, channelExt, dryRun) {
|
|
65
|
+
if (dryRun) return 'generated';
|
|
66
|
+
if (channelExt?.status === 'approvalRequired') return 'approvalRequired';
|
|
67
|
+
if (target.approvalRequired && !channelExt) return 'approvalRequired';
|
|
68
|
+
if (target.approvalRequired && channelExt?.status !== 'installed') return 'approvalRequired';
|
|
69
|
+
return 'installed';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {Object|null} validation
|
|
74
|
+
* @returns {Object|null}
|
|
75
|
+
*/
|
|
76
|
+
function toValidationDisplay(validation) {
|
|
77
|
+
if (!validation) return null;
|
|
78
|
+
return {
|
|
79
|
+
callbackReachable: validation.callbackReachable,
|
|
80
|
+
credentialValid: validation.credentialValid,
|
|
81
|
+
assistantCatalogReachable: validation.assistantCatalogReachable,
|
|
82
|
+
inboundVerification: Object.values(validation.inboundVerification).every(Boolean)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {Object} params
|
|
88
|
+
* @returns {Object|null}
|
|
89
|
+
*/
|
|
90
|
+
function showExistingChannelStatus(params) {
|
|
91
|
+
const { existing, options, target, channelTarget, name, baseName } = params;
|
|
92
|
+
if (!existing || options.force || options.dryRun) return null;
|
|
93
|
+
const sameInstall =
|
|
94
|
+
(existing.baseName && existing.baseName === baseName) ||
|
|
95
|
+
(!existing.baseName && existing.name === name);
|
|
96
|
+
if (!sameInstall) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Channel already configured as "${existing.name}". ` +
|
|
99
|
+
`Use --force to replace with "${name}".`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
displayExistingChannelStatus({
|
|
103
|
+
channelTarget,
|
|
104
|
+
name: existing.name || name,
|
|
105
|
+
channelExt: existing,
|
|
106
|
+
approvalUrl: resolveApprovalUrl(target, existing)
|
|
107
|
+
});
|
|
108
|
+
return { skipped: true, channelExt: existing };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {string} channelTarget
|
|
113
|
+
* @param {Object} artifactParams
|
|
114
|
+
* @returns {Object}
|
|
115
|
+
*/
|
|
116
|
+
function generateArtifactWithAudit(channelTarget, artifactParams) {
|
|
117
|
+
try {
|
|
118
|
+
const artifact = generateChannelArtifact(artifactParams);
|
|
119
|
+
auditArtifactGenerated(channelTarget, {
|
|
120
|
+
artifactHash: artifact.artifactHash,
|
|
121
|
+
outputPath: artifact.outputPath,
|
|
122
|
+
dryRun: artifactParams.dryRun === true
|
|
123
|
+
});
|
|
124
|
+
return artifact;
|
|
125
|
+
} catch (err) {
|
|
126
|
+
auditFailed(channelTarget, { phase: 'artifact', error: err.message });
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {Object} ctx
|
|
133
|
+
* @param {string} channelTarget
|
|
134
|
+
* @param {Object} channelBlock
|
|
135
|
+
* @param {string} status
|
|
136
|
+
* @param {string} artifactHash
|
|
137
|
+
* @returns {Promise<void>}
|
|
138
|
+
*/
|
|
139
|
+
async function patchConfigWithAudit(ctx, channelTarget, channelBlock, status, artifactHash) {
|
|
140
|
+
try {
|
|
141
|
+
await patchChannelExtension(
|
|
142
|
+
{ dataplaneUrl: ctx.dataplaneUrl, authConfig: ctx.authConfig, channelTarget },
|
|
143
|
+
channelBlock
|
|
144
|
+
);
|
|
145
|
+
auditConfigPatched(channelTarget, { status, artifactHash });
|
|
146
|
+
} catch (err) {
|
|
147
|
+
auditFailed(channelTarget, { phase: 'patch', error: err.message });
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @param {Object} ctx
|
|
154
|
+
* @param {Object} channelBlock
|
|
155
|
+
* @param {string} channelTarget
|
|
156
|
+
* @param {boolean} probe
|
|
157
|
+
* @returns {Promise<Object|null>}
|
|
158
|
+
*/
|
|
159
|
+
async function maybeRunProbe(ctx, channelBlock, channelTarget, probe) {
|
|
160
|
+
if (!probe) return null;
|
|
161
|
+
const validation = await runChannelProbe(
|
|
162
|
+
{ dataplaneUrl: ctx.dataplaneUrl, authConfig: ctx.authConfig },
|
|
163
|
+
channelBlock
|
|
164
|
+
);
|
|
165
|
+
if (validation.passed) {
|
|
166
|
+
auditValidated(channelTarget, { probe: true });
|
|
167
|
+
} else {
|
|
168
|
+
auditFailed(channelTarget, { phase: 'probe', validation });
|
|
169
|
+
}
|
|
170
|
+
return validation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {string} channelTarget
|
|
175
|
+
* @param {Object} options
|
|
176
|
+
* @returns {Promise<{ target: Object, name: string, baseName: string, description: string, ctx: Object, existing: Object|null }>}
|
|
177
|
+
*/
|
|
178
|
+
async function prepareChannelContext(channelTarget, options) {
|
|
179
|
+
const target = getChannelTarget(channelTarget);
|
|
180
|
+
if (target.experimental) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Channel target "${channelTarget}" is experimental. Confirm product requirement before use.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
if (!options.name || typeof options.name !== 'string' || !options.name.trim()) {
|
|
186
|
+
throw new Error('--name is required for app add-channel');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const baseName = normalizeBaseChannelName(options.name);
|
|
190
|
+
const ctx = await resolveChannelAuthContext(channelTarget, { silent: options.quiet });
|
|
191
|
+
const name = resolveChannelDisplayName(baseName, ctx.environment);
|
|
192
|
+
const description =
|
|
193
|
+
options.description && String(options.description).trim()
|
|
194
|
+
? String(options.description).trim()
|
|
195
|
+
: getDefaultChannelDescription();
|
|
196
|
+
|
|
197
|
+
const system = await fetchCommunicationSystem({
|
|
198
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
199
|
+
authConfig: ctx.authConfig,
|
|
200
|
+
channelTarget
|
|
201
|
+
});
|
|
202
|
+
const existing = getExistingChannelExtension(system);
|
|
203
|
+
return { target, name, baseName, description, ctx, existing };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @param {Object} params
|
|
208
|
+
* @returns {Promise<Object>}
|
|
209
|
+
*/
|
|
210
|
+
async function completeLiveInstall(params) {
|
|
211
|
+
const { ctx, channelTarget, channelBlock, status, artifact, target, name, baseName, options } = params;
|
|
212
|
+
|
|
213
|
+
await ensureChannelCredential({
|
|
214
|
+
ctx,
|
|
215
|
+
channelTarget,
|
|
216
|
+
target,
|
|
217
|
+
force: options.force === true
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
await patchConfigWithAudit(ctx, channelTarget, channelBlock, status, artifact.artifactHash);
|
|
221
|
+
|
|
222
|
+
const approvalUrl =
|
|
223
|
+
status === 'approvalRequired'
|
|
224
|
+
? resolveApprovalUrl(target, channelBlock, { artifactPath: artifact.outputPath })
|
|
225
|
+
: null;
|
|
226
|
+
if (approvalUrl) {
|
|
227
|
+
auditApprovalRequired(channelTarget, { approvalUrl });
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const validation = await maybeRunProbe(ctx, channelBlock, channelTarget, options.probe);
|
|
231
|
+
|
|
232
|
+
displayChannelInstallResult({
|
|
233
|
+
channelTarget,
|
|
234
|
+
name,
|
|
235
|
+
baseName,
|
|
236
|
+
statusLabel: status === 'approvalRequired' ? 'Approval required' : 'Installed',
|
|
237
|
+
credentialKey: target.credentialKey,
|
|
238
|
+
capabilities: target.capabilities,
|
|
239
|
+
artifactPath: artifact.outputPath,
|
|
240
|
+
installGuidePath: artifact.installPath,
|
|
241
|
+
validation: toValidationDisplay(validation),
|
|
242
|
+
approvalUrl
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
return { channelBlock, artifact, validation, approvalUrl };
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {Object} params
|
|
250
|
+
* @returns {{ dryRun: true, channelBlock: Object, artifact: Object }}
|
|
251
|
+
*/
|
|
252
|
+
function finishDryRunInstall(params) {
|
|
253
|
+
displayChannelInstallResult({
|
|
254
|
+
channelTarget: params.channelTarget,
|
|
255
|
+
name: params.name,
|
|
256
|
+
baseName: params.baseName,
|
|
257
|
+
statusLabel: 'Generated (dry-run)',
|
|
258
|
+
credentialKey: params.target.credentialKey,
|
|
259
|
+
capabilities: params.target.capabilities,
|
|
260
|
+
artifactPath: params.artifact.outputPath,
|
|
261
|
+
installGuidePath: params.artifact.installPath
|
|
262
|
+
});
|
|
263
|
+
return { dryRun: true, channelBlock: params.channelBlock, artifact: params.artifact };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @param {string} channelTarget
|
|
268
|
+
* @param {Object} options
|
|
269
|
+
* @returns {Promise<Object>}
|
|
270
|
+
*/
|
|
271
|
+
async function runAddChannel(channelTarget, options = {}) {
|
|
272
|
+
const { target, name, baseName, description, ctx, existing } = await prepareChannelContext(
|
|
273
|
+
channelTarget,
|
|
274
|
+
options
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const skipped = showExistingChannelStatus({
|
|
278
|
+
existing,
|
|
279
|
+
options,
|
|
280
|
+
target,
|
|
281
|
+
channelTarget,
|
|
282
|
+
name,
|
|
283
|
+
baseName
|
|
284
|
+
});
|
|
285
|
+
if (skipped) return skipped;
|
|
286
|
+
|
|
287
|
+
const runtimeValues = resolveChannelRuntimeValues({
|
|
288
|
+
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
289
|
+
channelTarget,
|
|
290
|
+
appName: name,
|
|
291
|
+
baseName,
|
|
292
|
+
environment: ctx.environment,
|
|
293
|
+
appDescription: description,
|
|
294
|
+
icon: options.icon
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
298
|
+
const artifact = generateArtifactWithAudit(channelTarget, {
|
|
299
|
+
projectRoot,
|
|
300
|
+
channelTarget,
|
|
301
|
+
runtimeValues,
|
|
302
|
+
dryRun: options.dryRun === true
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const status = resolveInstallStatus(target, existing, options.dryRun === true);
|
|
306
|
+
const channelBlock = buildChannelExtensionBlock(
|
|
307
|
+
{ name, baseName, description, artifactHash: artifact.artifactHash, status },
|
|
308
|
+
target
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (options.dryRun) {
|
|
312
|
+
return finishDryRunInstall({ channelTarget, name, baseName, target, artifact, channelBlock });
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return completeLiveInstall({
|
|
316
|
+
ctx,
|
|
317
|
+
channelTarget,
|
|
318
|
+
channelBlock,
|
|
319
|
+
status,
|
|
320
|
+
artifact,
|
|
321
|
+
target,
|
|
322
|
+
name,
|
|
323
|
+
baseName,
|
|
324
|
+
options
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @param {string} channelTarget
|
|
330
|
+
* @param {Object} options
|
|
331
|
+
*/
|
|
332
|
+
async function addChannelCommand(channelTarget, options = {}) {
|
|
333
|
+
try {
|
|
334
|
+
await runAddChannel(channelTarget, options);
|
|
335
|
+
} catch (err) {
|
|
336
|
+
displayChannelError(err.message || String(err));
|
|
337
|
+
throw err;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
module.exports = {
|
|
342
|
+
runAddChannel,
|
|
343
|
+
addChannelCommand,
|
|
344
|
+
resolveApprovalUrl,
|
|
345
|
+
resolveInstallStatus,
|
|
346
|
+
normalizeBaseChannelName,
|
|
347
|
+
resolveChannelDisplayName
|
|
348
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate channel artifacts from Handlebars templates (plan 152).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Channel artifact generation — dist/channels, sha256 hash, no secrets
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const crypto = require('crypto');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const Handlebars = require('handlebars');
|
|
15
|
+
const { getChannelTarget } = require('./channel-targets');
|
|
16
|
+
|
|
17
|
+
const SECRET_PATTERNS = [/xoxb-/i, /xoxp-/i, /client_secret/i, /signing_secret/i, /Bearer\s+/i];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} content
|
|
21
|
+
* @throws {Error}
|
|
22
|
+
*/
|
|
23
|
+
function assertNoSecretsInArtifact(content) {
|
|
24
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
25
|
+
if (pattern.test(content)) {
|
|
26
|
+
throw new Error('Generated artifact must not contain secret-like values');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (content.includes('your-domain.com')) {
|
|
30
|
+
throw new Error('Generated artifact still contains placeholder domain your-domain.com');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} projectRoot
|
|
36
|
+
* @param {string} channelTarget
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function getTemplatesDir(projectRoot, channelTarget) {
|
|
40
|
+
const target = getChannelTarget(channelTarget);
|
|
41
|
+
return path.join(projectRoot, 'templates', 'channels', target.templateDir);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} projectRoot
|
|
46
|
+
* @param {string} channelTarget
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
function getArtifactOutputPath(projectRoot, channelTarget) {
|
|
50
|
+
const target = getChannelTarget(channelTarget);
|
|
51
|
+
return path.join(
|
|
52
|
+
projectRoot,
|
|
53
|
+
'dist',
|
|
54
|
+
'channels',
|
|
55
|
+
channelTarget,
|
|
56
|
+
target.artifactFileName
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} templatePath
|
|
62
|
+
* @param {Object} context
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
function renderTemplateFile(templatePath, context) {
|
|
66
|
+
if (!fs.existsSync(templatePath)) {
|
|
67
|
+
throw new Error(`Channel template not found: ${templatePath}`);
|
|
68
|
+
}
|
|
69
|
+
const raw = fs.readFileSync(templatePath, 'utf8');
|
|
70
|
+
const template = Handlebars.compile(raw);
|
|
71
|
+
return template(context);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {string} templatesDir
|
|
76
|
+
* @param {Object} runtimeValues
|
|
77
|
+
* @param {string} outputDir
|
|
78
|
+
* @param {boolean} dryRun
|
|
79
|
+
* @returns {{ installPath: string, content: string }|null}
|
|
80
|
+
*/
|
|
81
|
+
function renderInstallGuideIfPresent(templatesDir, runtimeValues, outputDir, dryRun) {
|
|
82
|
+
const installTemplate = path.join(templatesDir, 'install.template.md.hbs');
|
|
83
|
+
if (!fs.existsSync(installTemplate)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const content = renderTemplateFile(installTemplate, runtimeValues);
|
|
87
|
+
assertNoSecretsInArtifact(content);
|
|
88
|
+
const installPath = path.join(outputDir, 'INSTALL.md');
|
|
89
|
+
if (!dryRun) {
|
|
90
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
91
|
+
fs.writeFileSync(installPath, content, 'utf8');
|
|
92
|
+
}
|
|
93
|
+
return { installPath, content };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Object} params
|
|
98
|
+
* @param {string} params.projectRoot
|
|
99
|
+
* @param {string} params.channelTarget
|
|
100
|
+
* @param {Object} params.runtimeValues
|
|
101
|
+
* @param {boolean} [params.dryRun]
|
|
102
|
+
* @returns {{ outputPath: string, artifactHash: string, content: string, installPath?: string }}
|
|
103
|
+
*/
|
|
104
|
+
function generateChannelArtifact(params) {
|
|
105
|
+
const templatesDir = getTemplatesDir(params.projectRoot, params.channelTarget);
|
|
106
|
+
const manifestTemplate = path.join(templatesDir, 'manifest.template.json.hbs');
|
|
107
|
+
const content = renderTemplateFile(manifestTemplate, params.runtimeValues);
|
|
108
|
+
assertNoSecretsInArtifact(content);
|
|
109
|
+
|
|
110
|
+
const outputPath = getArtifactOutputPath(params.projectRoot, params.channelTarget);
|
|
111
|
+
const artifactHash = crypto.createHash('sha256').update(content, 'utf8').digest('hex');
|
|
112
|
+
const outputDir = path.dirname(outputPath);
|
|
113
|
+
|
|
114
|
+
if (!params.dryRun) {
|
|
115
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
116
|
+
fs.writeFileSync(outputPath, content, 'utf8');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const install = renderInstallGuideIfPresent(
|
|
120
|
+
templatesDir,
|
|
121
|
+
params.runtimeValues,
|
|
122
|
+
outputDir,
|
|
123
|
+
params.dryRun === true
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
outputPath,
|
|
128
|
+
artifactHash,
|
|
129
|
+
content,
|
|
130
|
+
installPath: install?.installPath
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
assertNoSecretsInArtifact,
|
|
136
|
+
getTemplatesDir,
|
|
137
|
+
getArtifactOutputPath,
|
|
138
|
+
renderTemplateFile,
|
|
139
|
+
renderInstallGuideIfPresent,
|
|
140
|
+
generateChannelArtifact
|
|
141
|
+
};
|