@aifabrix/builder 2.54.1 → 2.55.2
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/README.md +8 -0
- package/lib/agent-kit/apply-ops.js +82 -0
- package/lib/agent-kit/checksums.js +28 -0
- package/lib/agent-kit/classify.js +113 -0
- package/lib/agent-kit/claude-shim.js +61 -0
- package/lib/agent-kit/constants.js +55 -0
- package/lib/agent-kit/file-list.js +103 -0
- package/lib/agent-kit/host-approve.js +172 -0
- package/lib/agent-kit/hosting/github.js +63 -0
- package/lib/agent-kit/hosts.js +71 -0
- package/lib/agent-kit/init.js +319 -0
- package/lib/agent-kit/kit-root.js +17 -0
- package/lib/agent-kit/managed-section.js +79 -0
- package/lib/agent-kit/package-load.js +45 -0
- package/lib/agent-kit/plan-ops.js +69 -0
- package/lib/agent-kit/remote-prompts.js +272 -0
- package/lib/agent-kit/render-host-markdown.js +40 -0
- package/lib/agent-kit/repo-guard.js +47 -0
- package/lib/agent-kit/report.js +107 -0
- package/lib/agent-kit/run.js +82 -0
- package/lib/agent-kit/scm/git.js +122 -0
- package/lib/agent-kit/start.js +310 -0
- package/lib/agent-kit/state-file.js +83 -0
- package/lib/agent-kit/status.js +50 -0
- package/lib/agent-kit/v1-detect.js +81 -0
- package/lib/agent-kit/validate-kit.js +87 -0
- package/lib/agent-kit/workspace-name.js +40 -0
- package/lib/agent-kit/workspace-skeleton.js +103 -0
- package/lib/api/role-assistant-test-pack.api.js +86 -0
- package/lib/api/work-search.api.js +31 -4
- package/lib/api/work.api.js +19 -12
- package/lib/app/deploy.js +7 -4
- package/lib/app/list-external-systems.js +2 -1
- package/lib/app/offer-create-from-template.js +184 -0
- package/lib/app/show-display.js +33 -6
- package/lib/app/show.js +25 -2
- package/lib/channels/add-channel.js +1 -0
- package/lib/channels/approval-guides/claude.js +2 -2
- package/lib/channels/channel-add-failure.js +1 -0
- package/lib/channels/channel-add-remaining.js +15 -9
- package/lib/channels/channel-definition-status.js +115 -0
- package/lib/channels/channel-description.js +2 -1
- package/lib/channels/channel-install-envelope.js +4 -2
- package/lib/channels/channel-integration-generator.js +2 -0
- package/lib/channels/channel-runtime-resolver.js +14 -0
- package/lib/channels/channel-targets.js +31 -5
- package/lib/channels/claude-setup-values.js +4 -1
- package/lib/channels/slack-channel-add.js +59 -6
- package/lib/channels/slack-mcp-callback.js +51 -0
- package/lib/channels/slack-mcp-runtime.js +156 -0
- package/lib/channels/slack-provisioning/install-cli.js +14 -2
- package/lib/channels/slack-provisioning/with-curl-on-path.js +6 -1
- package/lib/cli/index.js +4 -0
- package/lib/cli/setup-app.js +8 -1
- package/lib/cli/setup-auth.js +11 -2
- package/lib/cli/setup-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +3 -1
- package/lib/commands/agent-kit-help.js +149 -0
- package/lib/commands/agent-kit.js +417 -0
- package/lib/commands/auth-status-user.js +99 -0
- package/lib/commands/auth-status.js +14 -4
- package/lib/commands/channel-add-help.js +5 -5
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- package/lib/commands/datasource-load-export-cli.js +7 -2
- package/lib/commands/datasource-test-trust-cli.js +5 -1
- package/lib/commands/governance-command-action.js +5 -4
- package/lib/commands/identity-membership-role-cache.js +6 -1
- package/lib/commands/lifecycle-command-action.js +16 -15
- package/lib/commands/login-credentials.js +8 -3
- package/lib/commands/login-device.js +14 -5
- package/lib/commands/login.js +14 -1
- package/lib/commands/logout.js +50 -15
- package/lib/commands/repair-auth-apply.js +1 -1
- package/lib/commands/repair-datasource-key-skip.js +39 -0
- package/lib/commands/repair-datasource-keys.js +24 -12
- package/lib/commands/repair-rbac.js +16 -10
- package/lib/commands/role-assistant-copy-output.js +61 -0
- package/lib/commands/role-assistant-copy.js +155 -0
- package/lib/commands/role-assistant-test-output.js +8 -9
- package/lib/commands/role-assistant-test-result-rows.js +42 -0
- package/lib/commands/role-assistant.js +140 -59
- package/lib/commands/search.js +143 -0
- package/lib/commands/test-trust-external.js +7 -5
- package/lib/commands/upload-sidecar-followups.js +4 -1
- package/lib/commands/verify-governance-command-action.js +9 -7
- package/lib/commands/verify-operations-command-action.js +9 -8
- package/lib/commands/verify-operations-skip-e2e.js +131 -0
- package/lib/commands/verify-operations-step-plan.js +6 -33
- package/lib/commands/verify-operations-steps.js +3 -1
- package/lib/commands/verify-trust-command-action.js +6 -5
- package/lib/datasource/capability/relate-operations.js +28 -10
- package/lib/datasource/capability/run-capability-relate.js +48 -25
- package/lib/datasource/datasource-identifier.js +13 -5
- package/lib/deployment/deployer-poll-run.js +117 -35
- package/lib/external-system/deploy-dataplane-published.js +70 -0
- package/lib/external-system/deploy.js +12 -2
- package/lib/external-system/download-role-assistant.js +41 -15
- package/lib/external-system/download.js +8 -3
- package/lib/generator/helpers.js +12 -1
- package/lib/generator/wizard-datasource-key.js +54 -0
- package/lib/generator/wizard.js +55 -54
- package/lib/integration-definition/apply-datasource-keys.js +75 -0
- package/lib/integration-definition/apply-relationships.js +195 -0
- package/lib/integration-definition/apply-static-enterprise.js +232 -0
- package/lib/integration-definition/apply-system-file.js +71 -0
- package/lib/integration-definition/apply-test-endpoint.js +89 -0
- package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
- package/lib/integration-definition/apply.js +78 -59
- package/lib/integration-definition/enrich-openapi-operations.js +36 -10
- package/lib/integration-definition/enrich-openapi-pick.js +87 -0
- package/lib/lifecycle/role-assistant-governance.js +56 -21
- package/lib/programmatic/capability-registry.js +1 -0
- package/lib/programmatic/index.js +2 -0
- package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +4 -1
- package/lib/programmatic/openapi-component-schemas.js +1 -0
- package/lib/programmatic/openapi-descriptions.js +9 -3
- package/lib/programmatic/openapi-envelope-examples.js +7 -0
- package/lib/programmatic/openapi-operation-bindings.js +5 -0
- package/lib/programmatic/openapi-request-schemas.js +5 -0
- package/lib/programmatic/openapi-schema-descriptions-channel.js +8 -5
- package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
- package/lib/programmatic/openapi-spec.js +1 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +7 -0
- package/lib/programmatic/run-channel-catalog.js +50 -8
- package/lib/programmatic/run-channel-install-options.js +5 -1
- package/lib/programmatic/run-download.js +41 -0
- package/lib/protection/auth-context.js +3 -1
- package/lib/protection/protection-display.js +3 -2
- package/lib/protection/report-exit.js +50 -0
- package/lib/protection/run-commands.js +2 -0
- package/lib/role-assistant/knowledge-sync-settings-push.js +172 -0
- package/lib/role-assistant/knowledge-sync.js +9 -126
- package/lib/role-assistant/package-validate.js +175 -0
- package/lib/role-assistant/test-case-assertion-row.js +36 -0
- package/lib/role-assistant/test-case-copy-bind.js +77 -0
- package/lib/role-assistant/test-case-copy-expected.js +127 -0
- package/lib/role-assistant/test-case-copy-from-work.js +90 -0
- package/lib/role-assistant/test-case-copy-interactions.js +67 -0
- package/lib/role-assistant/test-case-copy.js +119 -0
- package/lib/role-assistant/test-case-expected-catalog.js +135 -0
- package/lib/role-assistant/test-case-validate.js +88 -0
- package/lib/role-assistant/test-cases-bid.js +117 -4
- package/lib/role-assistant/test-cases-evaluate.js +149 -31
- package/lib/role-assistant/test-cases-evidence.js +44 -5
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +297 -0
- package/lib/role-assistant/test-cases-search-graph.js +122 -0
- package/lib/role-assistant/test-cases-search.js +20 -2
- package/lib/role-assistant/test-cases.js +34 -168
- package/lib/role-assistant/test-pack-map.js +180 -0
- package/lib/role-assistant/test-pack-sync.js +187 -0
- package/lib/role-assistant/test-runner-debug.js +54 -0
- package/lib/role-assistant/test-runner-respond-body.js +36 -0
- package/lib/role-assistant/test-runner-search.js +20 -5
- package/lib/role-assistant/test-runner-start-payload.js +63 -10
- package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
- package/lib/role-assistant/test-runner-workhub.js +45 -21
- package/lib/role-assistant/test-runner.js +53 -10
- package/lib/schema/external-datasource.schema.json +36 -5
- package/lib/schema/external-system.schema.json +20 -2
- package/lib/schema/infra-parameter.schema.json +51 -3
- package/lib/schema/infra.parameter.yaml +476 -40
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- package/lib/schema/type/document-storage.json +1 -1
- package/lib/search/dataplane-context.js +23 -0
- package/lib/search/search-args.js +211 -0
- package/lib/search/search-display.js +238 -0
- package/lib/search/search-errors.js +50 -0
- package/lib/search/search-prompts.js +119 -0
- package/lib/search/search-roles.js +85 -0
- package/lib/search/search-run.js +241 -0
- package/lib/search/search-skills.js +198 -0
- package/lib/utils/api-required-permissions.js +271 -0
- package/lib/utils/api.js +16 -13
- package/lib/utils/authentication-slot-show.js +153 -0
- package/lib/utils/cli-json-exit.js +41 -0
- package/lib/utils/cli-utils.js +23 -5
- package/lib/utils/controller-url.js +78 -4
- package/lib/utils/credential-display.js +43 -1
- package/lib/utils/deployment-errors.js +15 -0
- package/lib/utils/deployment-validation-helpers.js +4 -1
- package/lib/utils/device-code.js +31 -10
- package/lib/utils/error-formatters/error-parser.js +16 -1
- package/lib/utils/error-formatters/permission-errors.js +19 -5
- package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
- package/lib/utils/external-system-readiness-compact-display.js +30 -1
- package/lib/utils/external-system-validators.js +2 -1
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/keycloak-realm-ready.js +5 -2
- package/lib/utils/logger.js +1 -0
- package/lib/utils/paths.js +26 -5
- package/lib/utils/schema-loader.js +37 -0
- package/lib/utils/secrets-helpers.js +2 -2
- package/lib/utils/write-stream-and-wait.js +63 -0
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +3 -2
- package/package.json +20 -6
- package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
- package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
- package/templates/agent-kit/agent-kit.yaml +45 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +104 -0
- package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
- package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
- package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
- package/templates/agent-kit/parity-inventory.yaml +188 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +59 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +52 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +51 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +43 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +65 -0
- package/templates/agent-kit/skills/shared/login.md +16 -0
- package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
- package/templates/agent-kit/workspace/LICENSE.mit +21 -0
- package/templates/agent-kit/workspace/README.md +89 -0
- package/templates/applications/builder-api/Dockerfile +3 -1
- package/templates/applications/dataplane/application.yaml +2 -3
- package/templates/applications/dataplane/env.template +5 -5
- package/templates/applications/dataplane/rbac.yaml +28 -0
- package/templates/applications/keycloak/env.template +3 -3
- package/templates/applications/miso-controller/application.yaml +21 -2
- package/templates/applications/miso-controller/env.template +96 -25
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +3 -0
- package/templates/channels/claude/channel.json +1 -1
- package/templates/channels/claude/install.template.md.hbs +1 -0
- package/templates/channels/claude/integration/claude-system.json +1 -1
- package/templates/channels/slack/channel.json +11 -0
- package/templates/channels/slack/install.template.md.hbs +9 -0
- package/templates/channels/slack/integration/slack-system.json +11 -0
- package/templates/channels/slack/manifest.template.json.hbs +6 -3
- package/templates/channels/teams-bot/channel.json +1 -0
- package/templates/python/docker-compose.hbs +14 -0
- package/templates/typescript/docker-compose.hbs +14 -0
|
@@ -18,52 +18,133 @@ const {
|
|
|
18
18
|
const { resolvePollIntervalFromController } = require('./poll-interval');
|
|
19
19
|
const { createDeployPollHandlers } = require('./deploy-poll-ui');
|
|
20
20
|
|
|
21
|
+
/** Same progress for this many polls + dataplane published → treat deploy as complete. */
|
|
22
|
+
const STUCK_PROGRESS_POLLS = 10;
|
|
23
|
+
|
|
24
|
+
function recordStuckProgress(state, snapshot) {
|
|
25
|
+
const progress = Number(snapshot && snapshot.progress);
|
|
26
|
+
const value = Number.isFinite(progress) ? progress : null;
|
|
27
|
+
if (value === state.lastProgress) {
|
|
28
|
+
state.stuckCount += 1;
|
|
29
|
+
} else {
|
|
30
|
+
state.lastProgress = value;
|
|
31
|
+
state.stuckCount = 1;
|
|
32
|
+
}
|
|
33
|
+
return state;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function completeIfDataplanePublished(lastSeen, options) {
|
|
37
|
+
if (!lastSeen || typeof options.isDataplanePublished !== 'function') {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
if (await options.isDataplanePublished()) {
|
|
42
|
+
return {
|
|
43
|
+
...lastSeen,
|
|
44
|
+
status: 'completed',
|
|
45
|
+
progress: 100,
|
|
46
|
+
completedViaDataplane: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
21
55
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @
|
|
25
|
-
* @param {string} deploymentId
|
|
26
|
-
* @param {string} controllerUrl
|
|
27
|
-
* @param {string} envKey
|
|
28
|
-
* @param {Object} authConfig
|
|
29
|
-
* @param {Object} [options]
|
|
30
|
-
* @returns {Promise<Object>}
|
|
56
|
+
* Poll until the controller job is terminal, or dataplane is already published.
|
|
57
|
+
* @param {Object} ctx
|
|
58
|
+
* @returns {Promise<Object|null>}
|
|
31
59
|
*/
|
|
60
|
+
async function pollUntilTerminal(ctx) {
|
|
61
|
+
const {
|
|
62
|
+
controllerUrl,
|
|
63
|
+
validatedEnvKey,
|
|
64
|
+
deploymentId,
|
|
65
|
+
pipelineAuthConfig,
|
|
66
|
+
interval,
|
|
67
|
+
maxAttempts,
|
|
68
|
+
onPollWait,
|
|
69
|
+
wrappedProgress,
|
|
70
|
+
stuckState,
|
|
71
|
+
options,
|
|
72
|
+
getLastSeen
|
|
73
|
+
} = ctx;
|
|
74
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
75
|
+
if (onPollWait) {
|
|
76
|
+
onPollWait(attempt, maxAttempts);
|
|
77
|
+
}
|
|
78
|
+
const response = await getPipelineDeployment(
|
|
79
|
+
controllerUrl,
|
|
80
|
+
validatedEnvKey,
|
|
81
|
+
deploymentId,
|
|
82
|
+
pipelineAuthConfig
|
|
83
|
+
);
|
|
84
|
+
const deploymentData = await processDeploymentStatusResponse(
|
|
85
|
+
response,
|
|
86
|
+
attempt,
|
|
87
|
+
maxAttempts,
|
|
88
|
+
interval,
|
|
89
|
+
deploymentId,
|
|
90
|
+
wrappedProgress
|
|
91
|
+
);
|
|
92
|
+
if (deploymentData) {
|
|
93
|
+
return deploymentData;
|
|
94
|
+
}
|
|
95
|
+
if (stuckState.stuckCount >= STUCK_PROGRESS_POLLS) {
|
|
96
|
+
const viaDataplane = await completeIfDataplanePublished(getLastSeen(), options);
|
|
97
|
+
if (viaDataplane) {
|
|
98
|
+
return viaDataplane;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
32
105
|
async function pollDeploymentStatus(deploymentId, controllerUrl, envKey, authConfig, options = {}) {
|
|
33
106
|
const interval = options.interval || 5000;
|
|
34
107
|
const maxAttempts = options.maxAttempts || 300;
|
|
35
|
-
|
|
36
108
|
const validatedEnvKey = validateEnvironmentKey(envKey);
|
|
37
109
|
const pipelineAuthConfig = convertToPipelineAuthConfig(authConfig);
|
|
38
|
-
|
|
39
110
|
const onPollProgress = typeof options.onPollProgress === 'function' ? options.onPollProgress : null;
|
|
40
111
|
const onPollWait = typeof options.onPollWait === 'function' ? options.onPollWait : null;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
112
|
+
const stuckState = { lastProgress: undefined, stuckCount: 0 };
|
|
113
|
+
let lastSeen = null;
|
|
114
|
+
const wrappedProgress = (data, attempt, max) => {
|
|
115
|
+
lastSeen = data;
|
|
116
|
+
recordStuckProgress(stuckState, data);
|
|
117
|
+
if (onPollProgress) {
|
|
118
|
+
onPollProgress(data, attempt, max);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
try {
|
|
122
|
+
const terminal = await pollUntilTerminal({
|
|
123
|
+
controllerUrl,
|
|
124
|
+
validatedEnvKey,
|
|
125
|
+
deploymentId,
|
|
126
|
+
pipelineAuthConfig,
|
|
127
|
+
interval,
|
|
128
|
+
maxAttempts,
|
|
129
|
+
onPollWait,
|
|
130
|
+
wrappedProgress,
|
|
131
|
+
stuckState,
|
|
132
|
+
options,
|
|
133
|
+
getLastSeen: () => lastSeen
|
|
134
|
+
});
|
|
135
|
+
if (terminal) {
|
|
136
|
+
return terminal;
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error.message && error.message.includes('not found')) {
|
|
63
140
|
throw error;
|
|
64
141
|
}
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
const timedOutComplete = await completeIfDataplanePublished(lastSeen, options);
|
|
145
|
+
if (timedOutComplete) {
|
|
146
|
+
return timedOutComplete;
|
|
65
147
|
}
|
|
66
|
-
|
|
67
148
|
throw new Error('Deployment timeout: Maximum polling attempts reached');
|
|
68
149
|
}
|
|
69
150
|
|
|
@@ -94,7 +175,8 @@ async function pollDeployment(result, url, validatedEnvKey, authConfig, options)
|
|
|
94
175
|
interval: resolvedInterval,
|
|
95
176
|
maxAttempts,
|
|
96
177
|
onPollProgress: pollUi.onPollProgress,
|
|
97
|
-
onPollWait: pollUi.onPollWait
|
|
178
|
+
onPollWait: pollUi.onPollWait,
|
|
179
|
+
isDataplanePublished: options.isDataplanePublished
|
|
98
180
|
}
|
|
99
181
|
);
|
|
100
182
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Treat a stuck controller deploy poll as complete when dataplane is already published.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Dataplane published check for external deploy poll
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { getExternalSystem } = require('../api/external-systems.api');
|
|
10
|
+
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
11
|
+
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Object|null|undefined} system
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
function isDataplaneSystemPublished(system) {
|
|
18
|
+
const status = String((system && system.status) || '').toLowerCase();
|
|
19
|
+
return status === 'published' || status === 'deployed';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} controllerUrl
|
|
24
|
+
* @param {string} environment
|
|
25
|
+
* @param {Object} authConfig
|
|
26
|
+
* @param {string} systemKey
|
|
27
|
+
* @param {string} [dataplaneUrl]
|
|
28
|
+
* @returns {Promise<boolean>}
|
|
29
|
+
*/
|
|
30
|
+
async function checkDataplaneSystemPublished(
|
|
31
|
+
controllerUrl,
|
|
32
|
+
environment,
|
|
33
|
+
authConfig,
|
|
34
|
+
systemKey,
|
|
35
|
+
dataplaneUrl
|
|
36
|
+
) {
|
|
37
|
+
let url = dataplaneUrl;
|
|
38
|
+
if (!url) {
|
|
39
|
+
url = await resolveDataplaneUrl(controllerUrl, environment, authConfig, { silent: true });
|
|
40
|
+
}
|
|
41
|
+
const getRes = await getExternalSystem(url, systemKey, authConfig);
|
|
42
|
+
return isDataplaneSystemPublished(unwrapApiData(getRes));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {Object} params
|
|
47
|
+
* @returns {() => Promise<boolean>}
|
|
48
|
+
*/
|
|
49
|
+
function createDataplanePublishedCheck(params) {
|
|
50
|
+
const { controllerUrl, environment, authConfig, systemKey, dataplaneUrl } = params;
|
|
51
|
+
return async function isDataplanePublished() {
|
|
52
|
+
try {
|
|
53
|
+
return await checkDataplaneSystemPublished(
|
|
54
|
+
controllerUrl,
|
|
55
|
+
environment,
|
|
56
|
+
authConfig,
|
|
57
|
+
systemKey,
|
|
58
|
+
dataplaneUrl
|
|
59
|
+
);
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
isDataplaneSystemPublished,
|
|
68
|
+
checkDataplaneSystemPublished,
|
|
69
|
+
createDataplanePublishedCheck
|
|
70
|
+
};
|
|
@@ -31,6 +31,7 @@ const { syncDeployJsonFromSources } = require('./sync-deploy-manifest');
|
|
|
31
31
|
const { runDeployGateOrchestrator } = require('../commands/deploy-gate-orchestrator');
|
|
32
32
|
const { runPostPublishDataSync } = require('../commands/run-post-publish-data-sync');
|
|
33
33
|
const { uploadDigitalWorkerIfNeeded, deployRoleAssistantShellIfNeeded } = require('./deploy-helpers');
|
|
34
|
+
const { createDataplanePublishedCheck } = require('./deploy-dataplane-published');
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Validates manifest on dataplane (dry-run) before controller deploy.
|
|
@@ -194,9 +195,10 @@ const EXTERNAL_DEPLOY_POLL_INTERVAL_MS = 2000;
|
|
|
194
195
|
/** 300 × 2s ≈ 10 minutes — must cover controller publish-job max wait with gates. */
|
|
195
196
|
const EXTERNAL_DEPLOY_POLL_MAX_ATTEMPTS = 300;
|
|
196
197
|
|
|
197
|
-
function buildExternalDeployPollOpts(options) {
|
|
198
|
+
function buildExternalDeployPollOpts(options, extra = {}) {
|
|
198
199
|
return {
|
|
199
200
|
...options,
|
|
201
|
+
...extra,
|
|
200
202
|
poll: true,
|
|
201
203
|
pollInterval:
|
|
202
204
|
options.pollInterval !== undefined ? options.pollInterval : EXTERNAL_DEPLOY_POLL_INTERVAL_MS,
|
|
@@ -300,7 +302,15 @@ async function executeDeployAndDisplay(manifest, controllerUrl, environment, aut
|
|
|
300
302
|
controllerUrl,
|
|
301
303
|
environment,
|
|
302
304
|
authConfig,
|
|
303
|
-
buildExternalDeployPollOpts(options
|
|
305
|
+
buildExternalDeployPollOpts(options, {
|
|
306
|
+
isDataplanePublished: createDataplanePublishedCheck({
|
|
307
|
+
controllerUrl,
|
|
308
|
+
environment,
|
|
309
|
+
authConfig,
|
|
310
|
+
systemKey: manifest.key,
|
|
311
|
+
dataplaneUrl: options.knownDataplaneUrl
|
|
312
|
+
})
|
|
313
|
+
})
|
|
304
314
|
);
|
|
305
315
|
|
|
306
316
|
const deploymentOutcome = parseControllerDeploymentOutcome(result);
|
|
@@ -24,13 +24,23 @@ const {
|
|
|
24
24
|
isPlatformShellKind
|
|
25
25
|
} = require('../utils/platform-shell-package');
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
function connectedSystemDryRunFileNames(systemKey, dataSources, format) {
|
|
28
|
+
const { getExternalDatasourceFileName } = require('../generator/split-variables');
|
|
29
|
+
const ext = format === 'json' ? 'json' : 'yaml';
|
|
30
|
+
const names = [
|
|
31
|
+
`${systemKey}-deploy.json`,
|
|
32
|
+
`application.${ext}`,
|
|
33
|
+
`${systemKey}-system.${ext}`,
|
|
34
|
+
'env.template',
|
|
35
|
+
'README.md'
|
|
36
|
+
];
|
|
37
|
+
const list = Array.isArray(dataSources) ? dataSources : [];
|
|
38
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
39
|
+
const yamlName = getExternalDatasourceFileName(systemKey, list[i], i);
|
|
40
|
+
names.push(ext === 'json' ? yamlName.replace(/\.yaml$/i, '.json') : yamlName);
|
|
41
|
+
}
|
|
42
|
+
return names;
|
|
43
|
+
}
|
|
34
44
|
|
|
35
45
|
async function maybeExportRoleAssistantEvidenceArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options) {
|
|
36
46
|
try {
|
|
@@ -47,6 +57,23 @@ async function maybeExportRoleAssistantEvidenceArtifacts(systemKey, manifest, da
|
|
|
47
57
|
}
|
|
48
58
|
}
|
|
49
59
|
|
|
60
|
+
async function maybeExportRoleAssistantTestsArtifacts(systemKey, dataplaneUrl, authConfig, options) {
|
|
61
|
+
try {
|
|
62
|
+
const { exportRoleAssistantTests } = require('../role-assistant/test-pack-sync');
|
|
63
|
+
const testsResult = await exportRoleAssistantTests({
|
|
64
|
+
systemKey,
|
|
65
|
+
dataplaneUrl,
|
|
66
|
+
authConfig,
|
|
67
|
+
options
|
|
68
|
+
});
|
|
69
|
+
if (testsResult && testsResult.skipped) {
|
|
70
|
+
logger.log(formatWarningLine(`Role assistant tests export skipped: ${testsResult.reason}`));
|
|
71
|
+
}
|
|
72
|
+
} catch (testsErr) {
|
|
73
|
+
logger.log(formatWarningLine(`Role assistant tests export skipped: ${testsErr.message}`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
50
77
|
async function maybeExportRoleAssistantKnowledgeArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options) {
|
|
51
78
|
try {
|
|
52
79
|
const knowledgeResult = await exportRoleAssistantKnowledge({
|
|
@@ -67,19 +94,17 @@ async function runRoleAssistantDownloadSidecars(params) {
|
|
|
67
94
|
const { systemKey, manifest, dataplaneUrl, authConfig, options = {} } = params;
|
|
68
95
|
await maybeExportRoleAssistantEvidenceArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options);
|
|
69
96
|
await maybeExportRoleAssistantKnowledgeArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options);
|
|
97
|
+
await maybeExportRoleAssistantTestsArtifacts(systemKey, dataplaneUrl, authConfig, options);
|
|
70
98
|
}
|
|
71
99
|
|
|
72
|
-
function logConnectedSystemDryRunFiles(systemKey) {
|
|
100
|
+
function logConnectedSystemDryRunFiles(systemKey, dataSources, format) {
|
|
73
101
|
logger.log(metadata('Would create:'));
|
|
74
|
-
|
|
75
|
-
const fileName = name === 'deploy.json' || name === 'system.yaml'
|
|
76
|
-
? `${systemKey}-${name}`
|
|
77
|
-
: name;
|
|
102
|
+
connectedSystemDryRunFileNames(systemKey, dataSources, format).forEach((fileName) => {
|
|
78
103
|
logger.log(metadata(` - integration/${systemKey}/${fileName}`));
|
|
79
104
|
});
|
|
80
105
|
}
|
|
81
106
|
|
|
82
|
-
function handleDownloadDryRun(systemKey, dataplaneUrl, application) {
|
|
107
|
+
function handleDownloadDryRun(systemKey, dataplaneUrl, application, dataSources, format) {
|
|
83
108
|
logger.log(formatWarningLine('Dry run mode: no files written.'));
|
|
84
109
|
logger.log(metadata(`Would fetch: ${dataplaneUrl}/api/v1/external/systems/${systemKey}/config`));
|
|
85
110
|
if (isEnterpriseKnowledgeKind(application)) {
|
|
@@ -91,7 +116,7 @@ function handleDownloadDryRun(systemKey, dataplaneUrl, application) {
|
|
|
91
116
|
logger.log(metadata(` - role-assistant/${systemKey}/role-assistant.yaml`));
|
|
92
117
|
return;
|
|
93
118
|
}
|
|
94
|
-
logConnectedSystemDryRunFiles(systemKey);
|
|
119
|
+
logConnectedSystemDryRunFiles(systemKey, dataSources, format);
|
|
95
120
|
}
|
|
96
121
|
|
|
97
122
|
async function downloadDigitalWorkerPackage(params) {
|
|
@@ -130,5 +155,6 @@ async function downloadPlatformShellIfNeeded(params) {
|
|
|
130
155
|
module.exports = {
|
|
131
156
|
runRoleAssistantDownloadSidecars,
|
|
132
157
|
downloadPlatformShellIfNeeded,
|
|
133
|
-
handleDownloadDryRun
|
|
158
|
+
handleDownloadDryRun,
|
|
159
|
+
connectedSystemDryRunFileNames
|
|
134
160
|
};
|
|
@@ -74,9 +74,8 @@ async function setupAuthenticationAndDataplane(systemKey, _options, _config) {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
77
|
-
|
|
77
|
+
// discoverDataplaneUrl already logs progress and success
|
|
78
78
|
const dataplaneUrl = await resolveDataplaneUrl(controllerUrl, environment, authConfig);
|
|
79
|
-
logger.log(formatSuccessLine(`Dataplane URL: ${dataplaneUrl}`));
|
|
80
79
|
|
|
81
80
|
return { authConfig, dataplaneUrl };
|
|
82
81
|
}
|
|
@@ -421,7 +420,13 @@ async function downloadExternalSystem(systemKey, options = {}) {
|
|
|
421
420
|
);
|
|
422
421
|
const manifest = await downloadFullManifest(dataplaneUrl, systemKey, authConfig, options);
|
|
423
422
|
if (options.dryRun) {
|
|
424
|
-
handleDownloadDryRun(
|
|
423
|
+
handleDownloadDryRun(
|
|
424
|
+
systemKey,
|
|
425
|
+
dataplaneUrl,
|
|
426
|
+
manifest.application,
|
|
427
|
+
manifest.dataSources,
|
|
428
|
+
format
|
|
429
|
+
);
|
|
425
430
|
return;
|
|
426
431
|
}
|
|
427
432
|
const platformHandled = await downloadPlatformShellIfNeeded({
|
package/lib/generator/helpers.js
CHANGED
|
@@ -234,6 +234,18 @@ function determineVariableLocation(value, key) {
|
|
|
234
234
|
required = true;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
if (location === 'keyvault' && value.startsWith('kv://')) {
|
|
238
|
+
try {
|
|
239
|
+
const { getInfraParameterCatalog } = require('../parameters/infra-parameter-catalog');
|
|
240
|
+
const entry = getInfraParameterCatalog().findEntryForKey(value.slice('kv://'.length));
|
|
241
|
+
if (entry?.scope === 'infra' && entry.generator?.type === 'emptyAllowed') {
|
|
242
|
+
required = false;
|
|
243
|
+
}
|
|
244
|
+
} catch {
|
|
245
|
+
// Keep the conservative required=true default when the catalog is unavailable.
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
237
249
|
return { location, required };
|
|
238
250
|
}
|
|
239
251
|
|
|
@@ -344,4 +356,3 @@ module.exports = {
|
|
|
344
356
|
validatePortalInput,
|
|
345
357
|
parseEnvironmentVariables
|
|
346
358
|
};
|
|
347
|
-
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical kebab datasource keys for wizard generate-config.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Wizard datasource key segments
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} str
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function toKeySegment(str) {
|
|
14
|
+
if (!str || typeof str !== 'string') {
|
|
15
|
+
return 'default';
|
|
16
|
+
}
|
|
17
|
+
const withHyphens = str.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
18
|
+
const sanitized = withHyphens.replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
19
|
+
return sanitized || 'default';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} finalSystemKey
|
|
24
|
+
* @param {{ key?: string, entityName?: string, entityType?: string, entityKey?: string }} ds
|
|
25
|
+
* @param {string} originalPrefix
|
|
26
|
+
* @param {Set<string>} [usedKeys]
|
|
27
|
+
* @returns {string}
|
|
28
|
+
*/
|
|
29
|
+
function wizardCanonicalDatasourceKey(finalSystemKey, ds, originalPrefix, usedKeys) {
|
|
30
|
+
const dsKey = String(ds.key || '').trim();
|
|
31
|
+
let segment;
|
|
32
|
+
if (dsKey && originalPrefix && dsKey.startsWith(originalPrefix)) {
|
|
33
|
+
segment = toKeySegment(dsKey.substring(originalPrefix.length));
|
|
34
|
+
} else {
|
|
35
|
+
const raw = ds.entityName || dsKey || ds.entityType || ds.entityKey || 'default';
|
|
36
|
+
segment = toKeySegment(raw);
|
|
37
|
+
}
|
|
38
|
+
let candidate = segment.includes('-') && !segment.startsWith(`${finalSystemKey}-`)
|
|
39
|
+
? segment
|
|
40
|
+
: `${finalSystemKey}-${segment}`;
|
|
41
|
+
if (usedKeys && usedKeys.has(candidate)) {
|
|
42
|
+
let suffix = 2;
|
|
43
|
+
while (usedKeys.has(`${candidate}-${suffix}`)) {
|
|
44
|
+
suffix += 1;
|
|
45
|
+
}
|
|
46
|
+
candidate = `${candidate}-${suffix}`;
|
|
47
|
+
}
|
|
48
|
+
return candidate;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
toKeySegment,
|
|
53
|
+
wizardCanonicalDatasourceKey
|
|
54
|
+
};
|
package/lib/generator/wizard.js
CHANGED
|
@@ -17,19 +17,7 @@ const { loadConfigFile, writeConfigFile } = require('../utils/config-format');
|
|
|
17
17
|
const { systemKeyToKvPrefix, securityKeyToVar, isValidKvPath } = require('../utils/credential-secrets-env');
|
|
18
18
|
const { generateExternalEnvTemplateContent } = require('../utils/external-env-template');
|
|
19
19
|
const { generateReadme } = require('./wizard-readme');
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Converts a string to a schema-valid key segment (lowercase letters, numbers, hyphens only).
|
|
23
|
-
* e.g. "recordStorage" -> "record-storage", "documentStorage" -> "document-storage"
|
|
24
|
-
* @param {string} str - Raw entity type or key segment (may be camelCase)
|
|
25
|
-
* @returns {string} Segment matching ^[a-z0-9-]+$
|
|
26
|
-
*/
|
|
27
|
-
function toKeySegment(str) {
|
|
28
|
-
if (!str || typeof str !== 'string') return 'default';
|
|
29
|
-
const withHyphens = str.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
30
|
-
const sanitized = withHyphens.replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
31
|
-
return sanitized || 'default';
|
|
32
|
-
}
|
|
20
|
+
const { toKeySegment, wizardCanonicalDatasourceKey } = require('./wizard-datasource-key');
|
|
33
21
|
|
|
34
22
|
const { normalizeAuthenticationToSystemKey } = require('../utils/authentication-shape');
|
|
35
23
|
|
|
@@ -118,10 +106,46 @@ async function writeDatasourceYamlFiles(appPath, finalSystemKey, datasourceConfi
|
|
|
118
106
|
* @param {string} [params.aiGeneratedReadme] - Optional AI-generated README content
|
|
119
107
|
* @returns {Promise<Object>} Object with file paths
|
|
120
108
|
*/
|
|
121
|
-
async function
|
|
122
|
-
const
|
|
109
|
+
async function writeWizardEnvTemplate(appPath, systemConfig) {
|
|
110
|
+
const envTemplatePath = path.join(appPath, 'env.template');
|
|
111
|
+
const envTemplateContent = generateExternalEnvTemplateContent(systemConfig);
|
|
112
|
+
await fs.writeFile(envTemplatePath, envTemplateContent, 'utf8');
|
|
113
|
+
logger.log(formatSuccessLine('Generated env.template'));
|
|
114
|
+
try {
|
|
115
|
+
const secretsEnsure = require('../core/secrets-ensure');
|
|
116
|
+
await secretsEnsure.ensureSecretsFromEnvTemplate(envTemplatePath, {
|
|
117
|
+
emptyValuesForCredentials: true
|
|
118
|
+
});
|
|
119
|
+
} catch (err) {
|
|
120
|
+
if (err.code !== 'ENOENT') {
|
|
121
|
+
logger.warn(`Could not ensure integration placeholder secrets: ${err.message}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return envTemplatePath;
|
|
125
|
+
}
|
|
123
126
|
|
|
124
|
-
|
|
127
|
+
async function writeWizardDeployManifest(appPath, appName, finalSystemKey) {
|
|
128
|
+
const { generateControllerManifest, toDeployJsonShape } = require('./external-controller-manifest');
|
|
129
|
+
const manifest = await generateControllerManifest(appName, { appPath });
|
|
130
|
+
const deployJson = toDeployJsonShape(manifest);
|
|
131
|
+
const deployManifestPath = path.join(appPath, `${finalSystemKey}-deploy.json`);
|
|
132
|
+
await fs.writeFile(deployManifestPath, JSON.stringify(deployJson, null, 2), 'utf8');
|
|
133
|
+
logger.log(formatSuccessLine(`Generated deployment manifest: ${finalSystemKey}-deploy.json`));
|
|
134
|
+
return deployManifestPath;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function generateConfigFilesForWizard(params) {
|
|
138
|
+
const {
|
|
139
|
+
appPath,
|
|
140
|
+
appName,
|
|
141
|
+
finalSystemKey,
|
|
142
|
+
systemFileName,
|
|
143
|
+
datasourceFileNames,
|
|
144
|
+
systemConfig,
|
|
145
|
+
datasourceConfigs,
|
|
146
|
+
aiGeneratedReadme,
|
|
147
|
+
format
|
|
148
|
+
} = params;
|
|
125
149
|
const configPath = await generateOrUpdateVariablesYaml({
|
|
126
150
|
appPath,
|
|
127
151
|
appName,
|
|
@@ -131,21 +155,7 @@ async function generateConfigFilesForWizard(params) {
|
|
|
131
155
|
systemConfig,
|
|
132
156
|
format: format || 'yaml'
|
|
133
157
|
});
|
|
134
|
-
|
|
135
|
-
// Generate env.template with Authentication and Configuration sections (Handlebars)
|
|
136
|
-
const envTemplatePath = path.join(appPath, 'env.template');
|
|
137
|
-
const envTemplateContent = generateExternalEnvTemplateContent(systemConfig);
|
|
138
|
-
await fs.writeFile(envTemplatePath, envTemplateContent, 'utf8');
|
|
139
|
-
logger.log(formatSuccessLine('Generated env.template'));
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const secretsEnsure = require('../core/secrets-ensure');
|
|
143
|
-
await secretsEnsure.ensureSecretsFromEnvTemplate(envTemplatePath, { emptyValuesForCredentials: true });
|
|
144
|
-
} catch (err) {
|
|
145
|
-
if (err.code !== 'ENOENT') logger.warn(`Could not ensure integration placeholder secrets: ${err.message}`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Generate README.md (use AI-generated content if available)
|
|
158
|
+
const envTemplatePath = await writeWizardEnvTemplate(appPath, systemConfig);
|
|
149
159
|
await generateReadme({
|
|
150
160
|
appPath,
|
|
151
161
|
appName,
|
|
@@ -155,21 +165,16 @@ async function generateConfigFilesForWizard(params) {
|
|
|
155
165
|
aiGeneratedContent: aiGeneratedReadme,
|
|
156
166
|
format
|
|
157
167
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
const deployJson = toDeployJsonShape(manifest);
|
|
166
|
-
const deployManifestPath = path.join(appPath, `${finalSystemKey}-deploy.json`);
|
|
167
|
-
await fs.writeFile(deployManifestPath, JSON.stringify(deployJson, null, 2), 'utf8');
|
|
168
|
-
logger.log(formatSuccessLine(`Generated deployment manifest: ${finalSystemKey}-deploy.json`));
|
|
169
|
-
|
|
168
|
+
const deployScripts = await generateDeployScripts(
|
|
169
|
+
appPath,
|
|
170
|
+
finalSystemKey,
|
|
171
|
+
systemFileName,
|
|
172
|
+
datasourceFileNames
|
|
173
|
+
);
|
|
174
|
+
const deployManifestPath = await writeWizardDeployManifest(appPath, appName, finalSystemKey);
|
|
170
175
|
return {
|
|
171
176
|
variablesPath: configPath,
|
|
172
|
-
envTemplatePath
|
|
177
|
+
envTemplatePath,
|
|
173
178
|
readmePath: path.join(appPath, 'README.md'),
|
|
174
179
|
applicationSchemaPath: deployManifestPath,
|
|
175
180
|
...deployScripts
|
|
@@ -190,16 +195,10 @@ async function prepareWizardContext(appName, systemConfig, datasourceConfigs) {
|
|
|
190
195
|
appDisplayName
|
|
191
196
|
);
|
|
192
197
|
const originalPrefix = `${originalSystemKey}-`;
|
|
198
|
+
const usedKeys = new Set();
|
|
193
199
|
const updatedDatasourceConfigs = datasourceConfigs.map(ds => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (dsKey && dsKey.startsWith(originalPrefix)) {
|
|
197
|
-
newKey = `${finalSystemKey}-${dsKey.substring(originalPrefix.length)}`;
|
|
198
|
-
} else {
|
|
199
|
-
const entityType = ds.entityType || ds.entityKey || dsKey.split('-').pop() || 'default';
|
|
200
|
-
const keySegment = toKeySegment(entityType);
|
|
201
|
-
newKey = `${finalSystemKey}-${keySegment}`;
|
|
202
|
-
}
|
|
200
|
+
const newKey = wizardCanonicalDatasourceKey(finalSystemKey, ds, originalPrefix, usedKeys);
|
|
201
|
+
usedKeys.add(newKey);
|
|
203
202
|
const entityType = ds.entityType || ds.entityKey || newKey.split('-').pop() || 'default';
|
|
204
203
|
const entityDisplayName = String(entityType).charAt(0).toUpperCase() + String(entityType).slice(1).replace(/-/g, ' ');
|
|
205
204
|
return { ...ds, key: newKey, systemKey: finalSystemKey, displayName: ds.displayName || `${appDisplayName} ${entityDisplayName}` };
|
|
@@ -481,6 +480,8 @@ const { generateDeployScripts } = require('./deploy-script');
|
|
|
481
480
|
|
|
482
481
|
module.exports = {
|
|
483
482
|
generateWizardFiles,
|
|
484
|
-
generateDeployScripts
|
|
483
|
+
generateDeployScripts,
|
|
484
|
+
wizardCanonicalDatasourceKey,
|
|
485
|
+
toKeySegment
|
|
485
486
|
};
|
|
486
487
|
|