@aifabrix/builder 2.51.1 → 2.52.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/lib/app/run-container-start.js +4 -0
- package/lib/app/run-deploy-job.js +135 -27
- package/lib/app/run-env-compose.js +32 -0
- package/lib/app/run-env-recovery.js +35 -0
- package/lib/app/run-helpers.js +5 -6
- package/lib/app/run.js +11 -3
- package/lib/channels/approval-guides/chatgpt.js +12 -9
- package/lib/channels/channel-targets.js +18 -1
- package/lib/channels/chatgpt-runtime-contract.js +1 -1
- package/lib/cli/infra-guided-footers.js +1 -1
- package/lib/cli/infra-guided-public-url-warn.js +55 -0
- package/lib/cli/infra-guided.js +65 -56
- package/lib/cli/setup-app.help.js +4 -0
- package/lib/cli/setup-app.test-commands.js +59 -28
- package/lib/cli/setup-external-system.js +50 -12
- package/lib/commands/channel-add-setup.js +8 -2
- package/lib/commands/channel.js +16 -5
- package/lib/commands/deploy-gate-orchestrator.js +3 -2
- package/lib/commands/governance-verify-external.js +2 -5
- package/lib/commands/lifecycle-external.js +14 -7
- package/lib/commands/role-assistant.js +66 -8
- package/lib/commands/test-governance-external.js +2 -5
- package/lib/commands/up-miso.js +61 -24
- package/lib/commands/upload-data-sync-finalize.js +20 -3
- package/lib/commands/verify-governance-external.js +2 -5
- package/lib/commands/verify-operations-external.js +2 -5
- package/lib/commands/verify-operations-step-plan.js +31 -0
- package/lib/commands/verify-trust-command-action.js +2 -5
- package/lib/datasource/datasource-identifier.js +4 -3
- package/lib/datasource/integration-context.js +3 -3
- package/lib/datasource/resolve-app.js +90 -8
- package/lib/datasource/test-e2e.js +2 -2
- package/lib/datasource/unified-validation-run-body.js +15 -1
- package/lib/datasource/unified-validation-run-resolve.js +2 -2
- package/lib/external-system/deploy-helpers.js +9 -5
- package/lib/external-system/deploy.js +2 -1
- package/lib/external-system/test-system-level.js +21 -3
- package/lib/external-system/test.js +4 -4
- package/lib/generator/builders.js +9 -15
- package/lib/role-assistant/knowledge-markdown-frontmatter.js +75 -0
- package/lib/role-assistant/knowledge-sync.js +25 -5
- package/lib/role-assistant/test-runner-workhub-answers.js +44 -26
- package/lib/role-assistant/test-runner-workhub.js +21 -7
- package/lib/schema/application-schema.json +10 -28
- package/lib/schema/infra.parameter.yaml +0 -20
- package/lib/utils/certify-external-workspace.js +40 -0
- package/lib/utils/docker-run-ephemeral.js +77 -17
- package/lib/utils/health-check-public-warn.js +31 -13
- package/lib/utils/health-check.js +11 -1
- package/lib/utils/paths.js +13 -15
- package/lib/utils/role-assistant-paths.js +76 -14
- package/lib/utils/upload-sync-options.js +7 -4
- package/lib/validation/reserved-system-key-prefixes.js +56 -0
- package/lib/validation/validate.js +54 -19
- package/package.json +1 -1
- package/templates/applications/builder-api/application.yaml +3 -3
- package/templates/applications/dataplane/application.yaml +3 -4
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/env.template +5 -2
- package/templates/applications/miso-controller/application.yaml +3 -3
- package/templates/applications/miso-controller/env.template +16 -3
- package/templates/channels/chatgpt/install.template.md.hbs +75 -37
- package/templates/channels/chatgpt/integration/README.md +3 -2
- package/templates/channels/chatgpt/manifest.template.json.hbs +3 -3
- package/templates/channels/slack/install.template.md.hbs +6 -1
- package/templates/python/docker-compose.hbs +10 -0
- package/templates/typescript/docker-compose.hbs +10 -0
|
@@ -23,12 +23,9 @@ const { syncLocalIfRequested } = require('./test-e2e-external');
|
|
|
23
23
|
*/
|
|
24
24
|
async function runTestGovernanceForExternalSystem(externalSystem, options = {}) {
|
|
25
25
|
const pathsUtil = require('../utils/paths');
|
|
26
|
+
const { assertCertifyExternalWorkspace } = require('../utils/certify-external-workspace');
|
|
26
27
|
const appType = await pathsUtil.detectAppType(externalSystem).catch(() => null);
|
|
27
|
-
|
|
28
|
-
throw new Error(
|
|
29
|
-
'verify-governance applies to external integration folders only (integration/<systemKey>/).'
|
|
30
|
-
);
|
|
31
|
-
}
|
|
28
|
+
assertCertifyExternalWorkspace(appType && appType.baseDir, 'verify-governance');
|
|
32
29
|
|
|
33
30
|
const systemKey = externalSystem;
|
|
34
31
|
const packPath = resolveGovernancePackPath(systemKey, {
|
package/lib/commands/up-miso.js
CHANGED
|
@@ -41,40 +41,73 @@ function parseImageOptions(imageOpts) {
|
|
|
41
41
|
return map;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
* Build run options and run keycloak, then miso-controller
|
|
46
|
-
* @async
|
|
47
|
-
* @param {Object} options - Commander options (image, registry, registryMode)
|
|
48
|
-
*/
|
|
49
|
-
async function runMisoApps(options) {
|
|
50
|
-
const imageMap = parseImageOptions(options.image);
|
|
44
|
+
function buildPlatformCommonRunOpts(options) {
|
|
51
45
|
const useBaseImage = options.base !== false;
|
|
52
|
-
|
|
46
|
+
return {
|
|
53
47
|
registry: options.registry,
|
|
54
48
|
registryMode: options.registryMode,
|
|
55
49
|
skipEnvOutputPath: true,
|
|
56
50
|
skipInfraCheck: true,
|
|
57
51
|
base: useBaseImage,
|
|
58
|
-
skipManifestMetadataLine: true
|
|
52
|
+
skipManifestMetadataLine: true,
|
|
53
|
+
...(options.platformInstall === true ? { silentPoll: true } : {})
|
|
59
54
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function applyDeferredPublicUrlWarning(runOpts, options) {
|
|
58
|
+
if (typeof options.onDeferredPublicUrlWarning !== 'function') {
|
|
59
|
+
return runOpts;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
...runOpts,
|
|
63
|
+
deferPublicUrlWarning: true,
|
|
64
|
+
onDeferredPublicUrlWarning: options.onDeferredPublicUrlWarning
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function buildKeycloakRunOpts(options, imageMap) {
|
|
69
|
+
const runOpts = applyDeferredPublicUrlWarning(buildPlatformCommonRunOpts(options), options);
|
|
65
70
|
if (imageMap.keycloak) {
|
|
66
|
-
|
|
71
|
+
runOpts.image = imageMap.keycloak;
|
|
67
72
|
}
|
|
68
|
-
|
|
73
|
+
return runOpts;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildMisoControllerRunOpts(options, imageMap) {
|
|
77
|
+
const runOpts = applyDeferredPublicUrlWarning(buildPlatformCommonRunOpts(options), options);
|
|
69
78
|
if (imageMap['miso-controller']) {
|
|
70
|
-
|
|
79
|
+
runOpts.image = imageMap['miso-controller'];
|
|
71
80
|
}
|
|
81
|
+
if (typeof options.onMisoPollText === 'function') {
|
|
82
|
+
runOpts.onPollText = options.onMisoPollText;
|
|
83
|
+
delete runOpts.silentPoll;
|
|
84
|
+
}
|
|
85
|
+
return runOpts;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Build run options and run keycloak, then miso-controller
|
|
90
|
+
* @async
|
|
91
|
+
* @param {Object} options - Commander options (image, registry, registryMode)
|
|
92
|
+
*/
|
|
93
|
+
async function runMisoApps(options) {
|
|
94
|
+
const imageMap = parseImageOptions(options.image);
|
|
95
|
+
const keycloakRunOpts = buildKeycloakRunOpts(options, imageMap);
|
|
96
|
+
const misoRunOpts = buildMisoControllerRunOpts(options, imageMap);
|
|
72
97
|
const { emitSystemBuilderAppManifestLineIfTTY } = require('../utils/manifest-source-emit');
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
const platformInstall = options.platformInstall === true;
|
|
99
|
+
if (!platformInstall) {
|
|
100
|
+
logger.log(chalk.blue('Starting keycloak...'));
|
|
101
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'keycloak');
|
|
102
|
+
}
|
|
75
103
|
await app.runApp('keycloak', keycloakRunOpts);
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
if (typeof options.onAfterKeycloak === 'function') {
|
|
105
|
+
options.onAfterKeycloak();
|
|
106
|
+
}
|
|
107
|
+
if (!platformInstall) {
|
|
108
|
+
logger.log(chalk.blue('Starting miso-controller...'));
|
|
109
|
+
emitSystemBuilderAppManifestLineIfTTY(logger, 'miso-controller');
|
|
110
|
+
}
|
|
78
111
|
await app.runApp('miso-controller', misoRunOpts);
|
|
79
112
|
}
|
|
80
113
|
|
|
@@ -91,7 +124,9 @@ async function runMisoApps(options) {
|
|
|
91
124
|
* @throws {Error} If infra not up or any step fails
|
|
92
125
|
*/
|
|
93
126
|
async function handleUpMiso(options = {}) {
|
|
94
|
-
|
|
127
|
+
if (options.platformInstall !== true) {
|
|
128
|
+
logger.log(chalk.blue('Starting up-miso (keycloak + miso-controller from images)...\n'));
|
|
129
|
+
}
|
|
95
130
|
await assertDevInfraUp();
|
|
96
131
|
await ensureAppFromTemplate('keycloak');
|
|
97
132
|
await ensureAppFromTemplate('miso-controller');
|
|
@@ -103,8 +138,10 @@ async function handleUpMiso(options = {}) {
|
|
|
103
138
|
patchEnvOutputPathForDeployOnly('miso-controller');
|
|
104
139
|
refreshUrlsLocalRegistryForCurrentProject();
|
|
105
140
|
await runMisoApps(options);
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
if (options.platformInstall !== true) {
|
|
142
|
+
logger.log(formatSuccessParagraph('up-miso complete. Keycloak and miso-controller are running.') +
|
|
143
|
+
chalk.gray('\n Run onboarding and register Keycloak from the miso-controller repo if needed. Use \'aifabrix up-dataplane\' for dataplane.'));
|
|
144
|
+
}
|
|
108
145
|
}
|
|
109
146
|
|
|
110
147
|
module.exports = { handleUpMiso, parseImageOptions };
|
|
@@ -8,9 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
const { runPostPublishDataSync } = require('./run-post-publish-data-sync');
|
|
10
10
|
const { runUploadSidecarFollowups } = require('./upload-sidecar-followups');
|
|
11
|
-
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
11
|
+
const { formatSuccessLine, formatWarningLine, metadata } = require('../utils/cli-test-layout-chalk');
|
|
12
12
|
const logger = require('../utils/logger');
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Internal verify/test --sync / deploy-preflight paths suppress upload banners.
|
|
16
|
+
* Default CLI `aifabrix upload` uses minimal=true but must still announce "unchanged".
|
|
17
|
+
* @param {Object} [options]
|
|
18
|
+
* @returns {boolean}
|
|
19
|
+
*/
|
|
20
|
+
function suppressUnchangedUploadBanner(options = {}) {
|
|
21
|
+
return options.syncMode === true || options.suppressSummary === true;
|
|
22
|
+
}
|
|
14
23
|
|
|
15
24
|
/**
|
|
16
25
|
* @async
|
|
@@ -37,8 +46,16 @@ async function finalizeUploadPublishResult(ctx, payload, options) {
|
|
|
37
46
|
*/
|
|
38
47
|
async function finishUnchangedUploadPublication(params) {
|
|
39
48
|
const { systemKey, options, payload, dataplaneUrl, authConfig, environment } = params;
|
|
40
|
-
if (!
|
|
49
|
+
if (!suppressUnchangedUploadBanner(options)) {
|
|
50
|
+
logger.log('');
|
|
41
51
|
logger.log(formatSuccessLine('Config unchanged on dataplane — upload skipped.'));
|
|
52
|
+
logger.log(metadata(`System: ${systemKey}`));
|
|
53
|
+
if (options.probe === true) {
|
|
54
|
+
logger.log(
|
|
55
|
+
formatWarningLine('Probe skipped (nothing published). Use --force to republish, then --probe.')
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
logger.log('');
|
|
42
59
|
}
|
|
43
60
|
const sidecar = await runUploadSidecarFollowups({
|
|
44
61
|
systemKey,
|
|
@@ -53,12 +53,9 @@ function buildDbPackResult(resolvedKey, datasourceRows) {
|
|
|
53
53
|
*/
|
|
54
54
|
async function runVerifyGovernanceForExternalSystem(systemKey, options = {}) {
|
|
55
55
|
const pathsUtil = require('../utils/paths');
|
|
56
|
+
const { assertCertifyExternalWorkspace } = require('../utils/certify-external-workspace');
|
|
56
57
|
const appType = await pathsUtil.detectAppType(systemKey).catch(() => null);
|
|
57
|
-
|
|
58
|
-
throw new Error(
|
|
59
|
-
'verify-governance applies to external integration folders only (integration/<systemKey>/).'
|
|
60
|
-
);
|
|
61
|
-
}
|
|
58
|
+
assertCertifyExternalWorkspace(appType && appType.baseDir, 'verify-governance');
|
|
62
59
|
|
|
63
60
|
if (options.pack) {
|
|
64
61
|
const runPayload = await runTestGovernanceForExternalSystem(systemKey, options);
|
|
@@ -162,12 +162,9 @@ async function buildOperationsResult({
|
|
|
162
162
|
*/
|
|
163
163
|
async function assertIntegrationExternalSystem(systemKey) {
|
|
164
164
|
const pathsUtil = require('../utils/paths');
|
|
165
|
+
const { assertCertifyExternalWorkspace } = require('../utils/certify-external-workspace');
|
|
165
166
|
const appType = await pathsUtil.detectAppType(systemKey).catch(() => null);
|
|
166
|
-
|
|
167
|
-
throw new Error(
|
|
168
|
-
'verify-operations applies to external integration folders only (integration/<systemKey>/).'
|
|
169
|
-
);
|
|
170
|
-
}
|
|
167
|
+
assertCertifyExternalWorkspace(appType && appType.baseDir, 'verify-operations');
|
|
171
168
|
}
|
|
172
169
|
|
|
173
170
|
/**
|
|
@@ -66,6 +66,17 @@ function buildE2eStep(systemKey, options) {
|
|
|
66
66
|
ok: () => true
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
+
if (shouldSkipE2eForRoleAssistant(systemKey, options)) {
|
|
70
|
+
return {
|
|
71
|
+
key: 'e2e',
|
|
72
|
+
run: async() => ({
|
|
73
|
+
success: true,
|
|
74
|
+
skipped: true,
|
|
75
|
+
reason: 'role-assistant-auth-none'
|
|
76
|
+
}),
|
|
77
|
+
ok: () => true
|
|
78
|
+
};
|
|
79
|
+
}
|
|
69
80
|
return {
|
|
70
81
|
key: 'e2e',
|
|
71
82
|
run: (progress) =>
|
|
@@ -88,6 +99,26 @@ function buildE2eStep(systemKey, options) {
|
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Role Assistant packages use authType none + nested builder-api CIP.
|
|
104
|
+
* Live capacity E2E expects a system baseUrl credential and is not the RA certify path.
|
|
105
|
+
* @param {string} systemKey
|
|
106
|
+
* @param {Object} options
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
*/
|
|
109
|
+
function shouldSkipE2eForRoleAssistant(systemKey, options) {
|
|
110
|
+
if (options.forceE2e === true) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const { resolveAppWorkspace } = require('../utils/app-path-resolve');
|
|
115
|
+
const { baseDir } = resolveAppWorkspace(systemKey, {});
|
|
116
|
+
return baseDir === 'role-assistant';
|
|
117
|
+
} catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
91
122
|
/**
|
|
92
123
|
* @param {string} systemKey
|
|
93
124
|
* @param {Object} options
|
|
@@ -17,12 +17,9 @@ const { buildJsonEnvelope } = require('../lifecycle/json-envelope');
|
|
|
17
17
|
async function runVerifyTrustCommandAction(appName, options, cmd) {
|
|
18
18
|
const opts = normalizeTestTrustCliOptions(options, cmd);
|
|
19
19
|
const pathsUtil = require('../utils/paths');
|
|
20
|
+
const { assertCertifyExternalWorkspace } = require('../utils/certify-external-workspace');
|
|
20
21
|
const appType = await pathsUtil.detectAppType(appName).catch(() => null);
|
|
21
|
-
|
|
22
|
-
throw new Error(
|
|
23
|
-
'verify-trust applies to external integration folders only (integration/<systemKey>/).'
|
|
24
|
-
);
|
|
25
|
-
}
|
|
22
|
+
assertCertifyExternalWorkspace(appType && appType.baseDir, 'verify-trust');
|
|
26
23
|
|
|
27
24
|
const result = await runVerifyTrustForExternalSystem(appName, {
|
|
28
25
|
env: opts.env,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
const path = require('path');
|
|
10
|
-
const {
|
|
10
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
11
11
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
12
12
|
const { loadConfigFile } = require('../utils/config-format');
|
|
13
13
|
|
|
@@ -65,12 +65,13 @@ function pickIntegrationAppForDatasourceIdentifier(identifier, appNames) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
* List manifest datasource files for an
|
|
68
|
+
* List manifest datasource files for an external authoring app
|
|
69
|
+
* (integration/, role-assistant/, or enterprise-knowledge/).
|
|
69
70
|
* @param {string} appKey
|
|
70
71
|
* @returns {{ appPath: string, schemaBasePath: string, datasourceFiles: string[] }|null}
|
|
71
72
|
*/
|
|
72
73
|
function listDatasourceFilesForApp(appKey) {
|
|
73
|
-
const appPath =
|
|
74
|
+
const appPath = resolveExternalSystemPath(appKey);
|
|
74
75
|
let config;
|
|
75
76
|
try {
|
|
76
77
|
const configPath = resolveApplicationConfigPath(appPath);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const fs = require('fs').promises;
|
|
9
|
-
const {
|
|
9
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
10
10
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
11
11
|
const { loadConfigFile } = require('../utils/config-format');
|
|
12
12
|
const {
|
|
@@ -15,11 +15,11 @@ const {
|
|
|
15
15
|
} = require('./datasource-identifier');
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @param {string} appKey - Integration app key
|
|
18
|
+
* @param {string} appKey - Integration / role-assistant / EK app key
|
|
19
19
|
* @returns {Promise<string>} systemKey
|
|
20
20
|
*/
|
|
21
21
|
async function getSystemKeyFromAppKey(appKey) {
|
|
22
|
-
const appPath =
|
|
22
|
+
const appPath = resolveExternalSystemPath(appKey);
|
|
23
23
|
const configPath = resolveApplicationConfigPath(appPath);
|
|
24
24
|
const config = loadConfigFile(configPath);
|
|
25
25
|
if (!config.externalIntegration || !config.externalIntegration.systems || config.externalIntegration.systems.length === 0) {
|
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
* Resolve app key for datasource commands from explicit --app, cwd, scan, or key parse.
|
|
3
3
|
* @fileoverview App resolution for datasource test-e2e, test-integration, log-e2e, log-integration
|
|
4
4
|
* @author AI Fabrix Team
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.1.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
8
10
|
const fs = require('fs');
|
|
9
11
|
const {
|
|
10
|
-
getIntegrationPath,
|
|
11
12
|
listIntegrationAppNames,
|
|
13
|
+
listEnterpriseKnowledgeAnchors,
|
|
14
|
+
getRoleAssistantRoot,
|
|
15
|
+
getCwdRoleAssistantRoot,
|
|
12
16
|
resolveIntegrationAppKeyFromCwd
|
|
13
17
|
} = require('../utils/paths');
|
|
18
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
14
19
|
const {
|
|
15
20
|
appHasDatasourceIdentifier,
|
|
16
21
|
pickIntegrationAppForDatasourceIdentifier
|
|
@@ -21,6 +26,80 @@ function appHasDatasourceKey(appKey, datasourceKey) {
|
|
|
21
26
|
return appHasDatasourceIdentifier(appKey, datasourceKey);
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} appKey
|
|
31
|
+
* @returns {boolean}
|
|
32
|
+
*/
|
|
33
|
+
function externalAppPathExists(appKey) {
|
|
34
|
+
try {
|
|
35
|
+
const appPath = resolveExternalSystemPath(appKey);
|
|
36
|
+
return Boolean(appPath && fs.existsSync(appPath));
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {string} root
|
|
44
|
+
* @param {Set<string>} diskNames
|
|
45
|
+
*/
|
|
46
|
+
function addRoleAssistantAppDirs(root, diskNames) {
|
|
47
|
+
if (!root || !fs.existsSync(root)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let entries;
|
|
51
|
+
try {
|
|
52
|
+
entries = fs.readdirSync(root);
|
|
53
|
+
} catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const pathJoin = require('path').join;
|
|
57
|
+
for (const name of entries) {
|
|
58
|
+
if (!name || name.startsWith('.')) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
if (fs.statSync(pathJoin(root, name)).isDirectory()) {
|
|
63
|
+
diskNames.add(name);
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// skip
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* List app folders under role-assistant/ (cwd + materialization).
|
|
73
|
+
* @returns {string[]}
|
|
74
|
+
*/
|
|
75
|
+
function listRoleAssistantAppNames() {
|
|
76
|
+
const diskNames = new Set();
|
|
77
|
+
const roots = new Set();
|
|
78
|
+
const cwdRoot = getCwdRoleAssistantRoot();
|
|
79
|
+
if (cwdRoot) {
|
|
80
|
+
roots.add(cwdRoot);
|
|
81
|
+
}
|
|
82
|
+
roots.add(getRoleAssistantRoot());
|
|
83
|
+
for (const root of roots) {
|
|
84
|
+
addRoleAssistantAppDirs(root, diskNames);
|
|
85
|
+
}
|
|
86
|
+
return [...diskNames].sort();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* External authoring apps: integration + role-assistant + enterprise-knowledge.
|
|
91
|
+
* @returns {string[]}
|
|
92
|
+
*/
|
|
93
|
+
function listExternalAuthoringAppNames() {
|
|
94
|
+
return [
|
|
95
|
+
...new Set([
|
|
96
|
+
...listIntegrationAppNames(),
|
|
97
|
+
...listRoleAssistantAppNames(),
|
|
98
|
+
...listEnterpriseKnowledgeAnchors()
|
|
99
|
+
])
|
|
100
|
+
].sort();
|
|
101
|
+
}
|
|
102
|
+
|
|
24
103
|
/**
|
|
25
104
|
* @param {string} key
|
|
26
105
|
* @param {string} [explicitApp]
|
|
@@ -31,7 +110,7 @@ function resolveFromExplicitApp(key, explicitApp) {
|
|
|
31
110
|
return null;
|
|
32
111
|
}
|
|
33
112
|
const appKey = explicitApp.trim();
|
|
34
|
-
if (
|
|
113
|
+
if (externalAppPathExists(appKey)) {
|
|
35
114
|
return { appKey };
|
|
36
115
|
}
|
|
37
116
|
return null;
|
|
@@ -71,15 +150,16 @@ function resolveFromPrefixOrSegments(key, appNames) {
|
|
|
71
150
|
return null;
|
|
72
151
|
}
|
|
73
152
|
const candidate = segments.slice(0, -1).join('-');
|
|
74
|
-
|
|
75
|
-
if (fs.existsSync(candidatePath) && appHasDatasourceIdentifier(candidate, key)) {
|
|
153
|
+
if (externalAppPathExists(candidate) && appHasDatasourceIdentifier(candidate, key)) {
|
|
76
154
|
return { appKey: candidate };
|
|
77
155
|
}
|
|
78
156
|
return null;
|
|
79
157
|
}
|
|
80
158
|
|
|
81
159
|
const RESOLVE_APP_HINT =
|
|
82
|
-
'Could not determine app context. Use --app <app>, a datasource key, a datasource JSON filename
|
|
160
|
+
'Could not determine app context. Use --app <app>, a datasource key, a datasource JSON filename ' +
|
|
161
|
+
'(e.g. myapp-datasource-contacts), or run from integration/<systemKey>/, ' +
|
|
162
|
+
'role-assistant/<systemKey>/, or enterprise-knowledge/<systemKey>/.';
|
|
83
163
|
|
|
84
164
|
/**
|
|
85
165
|
* Resolve app key for a datasource: explicit --app, cwd, scan by key, or parse key convention.
|
|
@@ -108,7 +188,7 @@ async function resolveAppKeyForDatasource(datasourceKey, explicitApp) {
|
|
|
108
188
|
return { appKey: fromCwd };
|
|
109
189
|
}
|
|
110
190
|
|
|
111
|
-
const appNames =
|
|
191
|
+
const appNames = listExternalAuthoringAppNames();
|
|
112
192
|
const scanned = resolveFromAppScan(key, appNames);
|
|
113
193
|
if (scanned) {
|
|
114
194
|
return scanned;
|
|
@@ -124,5 +204,7 @@ async function resolveAppKeyForDatasource(datasourceKey, explicitApp) {
|
|
|
124
204
|
|
|
125
205
|
module.exports = {
|
|
126
206
|
resolveAppKeyForDatasource,
|
|
127
|
-
appHasDatasourceKey
|
|
207
|
+
appHasDatasourceKey,
|
|
208
|
+
listExternalAuthoringAppNames,
|
|
209
|
+
listRoleAssistantAppNames
|
|
128
210
|
};
|
|
@@ -9,7 +9,6 @@ const path = require('path');
|
|
|
9
9
|
const fs = require('fs').promises;
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const logger = require('../utils/logger');
|
|
12
|
-
const { getIntegrationPath } = require('../utils/paths');
|
|
13
12
|
const { resolveAppKeyForDatasource } = require('./resolve-app');
|
|
14
13
|
const { formatProgress, formatSuccessLine, infoLine } = require('../utils/cli-test-layout-chalk');
|
|
15
14
|
const { runUnifiedDatasourceValidation } = require('./unified-validation-run');
|
|
@@ -94,7 +93,8 @@ async function resolvePrimaryKeyValue(value) {
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
function e2eIntegrationLogDir(appKey) {
|
|
97
|
-
|
|
96
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
97
|
+
return path.dirname(resolveExternalSystemPath(appKey));
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -12,6 +12,16 @@ const {
|
|
|
12
12
|
const testHelpers = require('../utils/external-system-test-helpers');
|
|
13
13
|
const { withStageOnValidationRunBody } = require('../utils/validation-run-stage');
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @param {Object} datasource
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
function isVoidCipInput(datasource) {
|
|
20
|
+
const execution = datasource && typeof datasource === 'object' ? datasource.execution : null;
|
|
21
|
+
const cip = execution && typeof execution === 'object' ? execution.cip : null;
|
|
22
|
+
return String((cip && cip.inputType) || '').trim().toLowerCase() === 'void';
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
/**
|
|
16
26
|
* @param {Object} params
|
|
17
27
|
* @param {string} params.systemKey
|
|
@@ -31,7 +41,11 @@ async function buildUnifiedValidationBody(params) {
|
|
|
31
41
|
const customPayload = await testHelpers.loadCustomPayload(payloadPath);
|
|
32
42
|
payloadTemplate = testHelpers.determinePayloadTemplate(datasource, datasourceKey, customPayload);
|
|
33
43
|
if (runType === 'integration' && !payloadTemplate) {
|
|
34
|
-
|
|
44
|
+
if (isVoidCipInput(datasource)) {
|
|
45
|
+
payloadTemplate = {};
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error(`No test payload found for datasource '${datasourceKey}'`);
|
|
48
|
+
}
|
|
35
49
|
}
|
|
36
50
|
}
|
|
37
51
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @version 2.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
8
8
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
9
9
|
const { loadConfigFile } = require('../utils/config-format');
|
|
10
10
|
const {
|
|
@@ -48,7 +48,7 @@ function findDatasourceFileByIdentifier(appPath, schemaBasePath, datasourceFiles
|
|
|
48
48
|
* @returns {{ datasource: Object, datasourcePath: string, datasourceKey: string }}
|
|
49
49
|
*/
|
|
50
50
|
function loadDatasourceForApp(appKey, datasourceKey, findDatasourceFileByKey) {
|
|
51
|
-
const appPath =
|
|
51
|
+
const appPath = resolveExternalSystemPath(appKey);
|
|
52
52
|
const config = loadConfigFile(resolveApplicationConfigPath(appPath));
|
|
53
53
|
const schemaBasePath = config.externalIntegration?.schemaBasePath || './';
|
|
54
54
|
const datasourceFiles = config.externalIntegration?.dataSources || [];
|
|
@@ -142,7 +142,7 @@ function extractSystemKey(systemFilePath) {
|
|
|
142
142
|
* @param {Object} manifest - Controller manifest
|
|
143
143
|
* @returns {Promise<Object|null>} Upload result, or null when not a digital worker
|
|
144
144
|
*/
|
|
145
|
-
async function uploadDigitalWorkerIfNeeded(appName, options,
|
|
145
|
+
async function uploadDigitalWorkerIfNeeded(appName, options, _compact, manifest) {
|
|
146
146
|
const systemKind =
|
|
147
147
|
manifest && manifest.system && typeof manifest.system.systemKind === 'string'
|
|
148
148
|
? manifest.system.systemKind.trim()
|
|
@@ -150,9 +150,9 @@ async function uploadDigitalWorkerIfNeeded(appName, options, compact, manifest)
|
|
|
150
150
|
if (systemKind !== 'digitalWorker') {
|
|
151
151
|
return null;
|
|
152
152
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
154
|
+
const logger = require('../utils/logger');
|
|
155
|
+
if (options.json !== true) {
|
|
156
156
|
logger.log(
|
|
157
157
|
formatSuccessParagraph(
|
|
158
158
|
'Role Assistant deployment uses upload pipeline (controller deploy is skipped).'
|
|
@@ -162,7 +162,11 @@ async function uploadDigitalWorkerIfNeeded(appName, options, compact, manifest)
|
|
|
162
162
|
const { uploadExternalSystem } = require('../commands/upload');
|
|
163
163
|
return uploadExternalSystem(appName, {
|
|
164
164
|
...options,
|
|
165
|
-
uploadStatus: 'published'
|
|
165
|
+
uploadStatus: 'published',
|
|
166
|
+
// Match standalone `af upload` progress for the final publish.
|
|
167
|
+
silentResolve: false,
|
|
168
|
+
suppressPipelineSpinner: false,
|
|
169
|
+
syncMode: false
|
|
166
170
|
});
|
|
167
171
|
}
|
|
168
172
|
|
|
@@ -432,7 +432,8 @@ async function runExternalSystemDeployFlow(appName, options) {
|
|
|
432
432
|
await validateExternalSystemForDeploy(appName, options, compact);
|
|
433
433
|
const gateOutcomes = await runDeployGateOrchestrator(appName, {
|
|
434
434
|
...options,
|
|
435
|
-
|
|
435
|
+
// Compact deploy still shows step progress; only JSON mode stays fully quiet.
|
|
436
|
+
quietDeployUi: options.json === true
|
|
436
437
|
});
|
|
437
438
|
await syncDeployJsonFromSources(appName);
|
|
438
439
|
const manifest = await generateControllerManifest(appName, options);
|
|
@@ -12,7 +12,7 @@ const path = require('path');
|
|
|
12
12
|
const chalk = require('chalk');
|
|
13
13
|
const logger = require('../utils/logger');
|
|
14
14
|
const { writeTestLog } = require('../utils/test-log-writer');
|
|
15
|
-
const {
|
|
15
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
16
16
|
const { runUnifiedDatasourceValidation } = require('../datasource/unified-validation-run');
|
|
17
17
|
|
|
18
18
|
async function runOneDatasourceKey(appName, datasourceKey, opts) {
|
|
@@ -61,16 +61,34 @@ async function runOneDatasourceKey(appName, datasourceKey, opts) {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
const env = uni.envelope;
|
|
64
|
-
const ok = env
|
|
64
|
+
const ok = isDatasourceRunSuccessful(env);
|
|
65
65
|
return { key: datasourceKey, success: ok, skipped: false, datasourceTestRun: env };
|
|
66
66
|
} catch (err) {
|
|
67
67
|
return { key: datasourceKey, success: false, skipped: false, error: err.message };
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Prefer explicit envelope status; soft-pass when validation+certificate succeeded
|
|
73
|
+
* (documentStorage packs may report overall fail only for missing live evidence).
|
|
74
|
+
* @param {Object|null|undefined} env
|
|
75
|
+
* @returns {boolean}
|
|
76
|
+
*/
|
|
77
|
+
function isDatasourceRunSuccessful(env) {
|
|
78
|
+
if (!env || typeof env.status !== 'string') {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (env.status !== 'fail') {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
const validationOk = env.validation && env.validation.status === 'ok';
|
|
85
|
+
const certPassed = env.certificate && env.certificate.status === 'passed';
|
|
86
|
+
return Boolean(validationOk && certPassed);
|
|
87
|
+
}
|
|
88
|
+
|
|
71
89
|
async function maybeWriteSystemRunLog(appName, systemKey, datasourceKeys, runType, debug, payload) {
|
|
72
90
|
if (!debug) return;
|
|
73
|
-
const appPath =
|
|
91
|
+
const appPath = resolveExternalSystemPath(appName);
|
|
74
92
|
const integrationDir = path.dirname(appPath);
|
|
75
93
|
const logPath = await writeTestLog(
|
|
76
94
|
appName,
|
|
@@ -533,8 +533,8 @@ async function testExternalSystemIntegration(appName, options = {}) {
|
|
|
533
533
|
if (options.debug) {
|
|
534
534
|
try {
|
|
535
535
|
const { writeTestLog } = require('../utils/test-log-writer');
|
|
536
|
-
const {
|
|
537
|
-
const appPath =
|
|
536
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
537
|
+
const appPath = resolveExternalSystemPath(appName);
|
|
538
538
|
await writeTestLog(appName, { request: { systemKey }, error: err.message }, 'test-integration', path.dirname(appPath));
|
|
539
539
|
} catch (_) { /* ignore */ }
|
|
540
540
|
}
|
|
@@ -561,8 +561,8 @@ async function testExternalSystemIntegration(appName, options = {}) {
|
|
|
561
561
|
if (options.debug && results.datasourceResults.length > 0) {
|
|
562
562
|
try {
|
|
563
563
|
const { writeTestLog } = require('../utils/test-log-writer');
|
|
564
|
-
const {
|
|
565
|
-
const appPath =
|
|
564
|
+
const { resolveExternalSystemPath } = require('../utils/app-path-resolve');
|
|
565
|
+
const appPath = resolveExternalSystemPath(appName);
|
|
566
566
|
await writeTestLog(appName, {
|
|
567
567
|
request: { systemKey, datasource: options.datasource, includeDebug: true },
|
|
568
568
|
response: results
|