@aifabrix/builder 2.51.1 → 2.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.isolated-projects.js +25 -2
- package/jest.projects.js +4 -1
- package/lib/api/datasources-extended.api.js +8 -8
- package/lib/api/keycloak.api.js +92 -0
- package/lib/api/token-providers.api.js +77 -0
- package/lib/api/types/keycloak.types.js +23 -0
- package/lib/api/types/token-providers.types.js +65 -0
- package/lib/app/down.js +16 -1
- 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/add-channel.js +126 -19
- package/lib/channels/approval-guides/chatgpt.js +12 -9
- package/lib/channels/approval-guides/microsoft-copilot.js +16 -12
- package/lib/channels/channel-add-ensure.js +128 -0
- package/lib/channels/channel-artifact-generator.js +11 -1
- package/lib/channels/channel-branding.js +94 -0
- package/lib/channels/channel-credential.js +8 -0
- package/lib/channels/channel-discovery.js +330 -0
- package/lib/channels/channel-external-system.js +1 -1
- package/lib/channels/channel-runtime-resolver.js +103 -14
- package/lib/channels/channel-status-display.js +7 -1
- package/lib/channels/channel-targets.js +18 -1
- package/lib/channels/chatgpt-runtime-contract.js +1 -1
- package/lib/channels/microsoft-copilot-channel-add.js +138 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +180 -0
- package/lib/channels/microsoft-copilot-entra-sso.js +264 -0
- package/lib/channels/microsoft-copilot-icons.js +74 -0
- package/lib/channels/microsoft-copilot-limits.js +84 -0
- package/lib/channels/microsoft-copilot-package.js +130 -49
- package/lib/channels/microsoft-copilot-validate.js +197 -0
- package/lib/cli/index.js +2 -0
- 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 +78 -62
- 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/cli/setup-infra.js +31 -4
- package/lib/commands/channel-add-setup.js +35 -10
- package/lib/commands/channel.js +27 -12
- package/lib/commands/deploy-gate-orchestrator.js +3 -2
- package/lib/commands/governance-verify-external.js +2 -5
- package/lib/commands/integration-definition.js +158 -0
- package/lib/commands/lifecycle-external.js +14 -7
- package/lib/commands/repair-auth-apply.js +19 -5
- package/lib/commands/repair-datasource-sync-operations.js +4 -1
- package/lib/commands/role-assistant-test-output.js +200 -0
- package/lib/commands/role-assistant.js +131 -114
- 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/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- 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/infrastructure/index.js +19 -4
- package/lib/integration-definition/apply.js +478 -0
- package/lib/integration-definition/canonical-json.js +51 -0
- package/lib/integration-definition/emit-suite-bid.js +94 -0
- package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
- package/lib/integration-definition/enrich-openapi-operations.js +434 -0
- package/lib/integration-definition/from-discovery.js +339 -0
- package/lib/integration-definition/hash.js +37 -0
- package/lib/integration-definition/index.js +37 -0
- package/lib/integration-definition/openapi-enrichment/hubspot-crm-companies.json +205 -0
- package/lib/integration-definition/resource-type-catalog.js +59 -0
- package/lib/integration-definition/system-kind-enum.js +40 -0
- package/lib/integration-definition/validate.js +148 -0
- package/lib/programmatic/builder-api-request.js +5 -1
- package/lib/programmatic/builder-help-governance.js +3 -2
- package/lib/programmatic/capability-registry.js +19 -0
- package/lib/programmatic/openapi-component-schemas.js +6 -1
- package/lib/programmatic/openapi-descriptions.js +40 -0
- package/lib/programmatic/openapi-envelope-examples.js +269 -0
- package/lib/programmatic/openapi-operation-bindings.js +45 -0
- package/lib/programmatic/openapi-request-schemas.js +14 -0
- package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
- package/lib/programmatic/openapi-result-schemas.js +46 -99
- package/lib/programmatic/openapi-schema-descriptions-core.js +7 -4
- package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-operations.js +24 -0
- package/lib/programmatic/openapi-schema-helpers.js +9 -9
- package/lib/programmatic/openapi-spec.js +11 -1
- package/lib/programmatic/orchestration-openapi-meta.js +10 -0
- package/lib/programmatic/route-handler-map.js +29 -1
- package/lib/programmatic/run-channel-package.js +236 -0
- package/lib/programmatic/run-integration-definition.js +69 -0
- package/lib/role-assistant/knowledge-markdown-frontmatter.js +75 -0
- package/lib/role-assistant/knowledge-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +104 -89
- package/lib/role-assistant/test-cases-bid.js +155 -0
- package/lib/role-assistant/test-cases-evaluate.js +9 -1
- package/lib/role-assistant/test-cases-honesty.js +24 -10
- package/lib/role-assistant/test-cases.js +28 -0
- package/lib/role-assistant/test-runner-bid-apply.js +122 -0
- package/lib/role-assistant/test-runner-bid-document.js +278 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +289 -46
- package/lib/role-assistant/test-runner-workhub.js +121 -25
- package/lib/role-assistant/test-suite.js +119 -0
- package/lib/schema/application-schema.json +64 -32
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/infra.parameter.yaml +0 -20
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/certify-external-workspace.js +40 -0
- package/lib/utils/docker-build.js +3 -3
- 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/help-builder.js +1 -0
- package/lib/utils/paths.js +13 -15
- package/lib/utils/promote-dev-docker-image.js +97 -18
- package/lib/utils/role-assistant-paths.js +76 -14
- package/lib/utils/transient-developer-id.js +28 -0
- 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/scripts/pnpm/af.mjs +24 -9
- package/scripts/pnpm/help.mjs +1 -1
- package/templates/applications/builder-api/application.yaml +3 -3
- package/templates/applications/dataplane/application.yaml +5 -5
- package/templates/applications/dataplane/env.template +8 -7
- 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 +25 -11
- package/templates/applications/miso-controller/env.template +24 -5
- package/templates/channels/README.md +11 -1
- package/templates/channels/brand/color-192.png +0 -0
- package/templates/channels/brand/dark/128.png +0 -0
- package/templates/channels/brand/dark/192.png +0 -0
- package/templates/channels/brand/dark/256.png +0 -0
- package/templates/channels/brand/dark/32.png +0 -0
- package/templates/channels/brand/dark/512.png +0 -0
- package/templates/channels/brand/dark/64.png +0 -0
- package/templates/channels/brand/light/128.png +0 -0
- package/templates/channels/brand/light/192.png +0 -0
- package/templates/channels/brand/light/256.png +0 -0
- package/templates/channels/brand/light/32.png +0 -0
- package/templates/channels/brand/light/512.png +0 -0
- package/templates/channels/brand/light/64.png +0 -0
- package/templates/channels/brand/mono-white/128.png +0 -0
- package/templates/channels/brand/mono-white/192.png +0 -0
- package/templates/channels/brand/mono-white/256.png +0 -0
- package/templates/channels/brand/mono-white/32.png +0 -0
- package/templates/channels/brand/mono-white/512.png +0 -0
- package/templates/channels/brand/mono-white/64.png +0 -0
- package/templates/channels/brand/outline-32.png +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +76 -36
- package/templates/channels/chatgpt/integration/README.md +4 -4
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- package/templates/channels/chatgpt/manifest.template.json.hbs +3 -3
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +10 -16
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +27 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +39 -20
- package/templates/channels/microsoft-copilot/integration/README.md +2 -3
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +7 -7
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +11 -0
- package/templates/channels/slack/install.template.md.hbs +6 -1
- package/templates/channels/slack/integration/README.md +2 -4
- package/templates/channels/teams-bot/install.template.md.hbs +4 -0
- package/templates/channels/teams-bot/integration/README.md +3 -5
- package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
- package/templates/python/docker-compose.hbs +10 -0
- package/templates/typescript/docker-compose.hbs +10 -0
- /package/.cursor/plans/{Done → Archive}/157.1-security-quality-violations-by-type.csv +0 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
const path = require('path');
|
|
11
12
|
const logger = require('../utils/logger');
|
|
12
13
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
13
14
|
const {
|
|
@@ -22,6 +23,11 @@ const {
|
|
|
22
23
|
loadRoleAssistantTestCase,
|
|
23
24
|
evaluateRoleAssistantTestCase
|
|
24
25
|
} = require('../role-assistant/test-cases');
|
|
26
|
+
const {
|
|
27
|
+
resolveCasesRoot,
|
|
28
|
+
discoverSuiteCaseFiles,
|
|
29
|
+
filterDiscoveredCases
|
|
30
|
+
} = require('../role-assistant/test-suite');
|
|
25
31
|
const {
|
|
26
32
|
isExecutableRoleAssistantCase,
|
|
27
33
|
runRoleAssistantCaseLifecycle,
|
|
@@ -32,12 +38,17 @@ const { collectString } = require('./governance');
|
|
|
32
38
|
const {
|
|
33
39
|
sectionTitle,
|
|
34
40
|
headerKeyValue,
|
|
35
|
-
formatSuccessLine,
|
|
36
|
-
formatSuccessParagraph,
|
|
37
|
-
formatWarningLine,
|
|
38
|
-
formatBlockingError,
|
|
39
41
|
metadata
|
|
40
42
|
} = require('../utils/cli-test-layout-chalk');
|
|
43
|
+
const {
|
|
44
|
+
formatStepsRunSummary,
|
|
45
|
+
buildRoleAssistantTestEnvelope,
|
|
46
|
+
displayRoleAssistantTestSummary
|
|
47
|
+
} = require('./role-assistant-test-output');
|
|
48
|
+
const {
|
|
49
|
+
bareRoleKey,
|
|
50
|
+
roleAssistantSystemKey
|
|
51
|
+
} = require('../utils/role-assistant-paths');
|
|
41
52
|
|
|
42
53
|
function roleAssistantHelpAfter() {
|
|
43
54
|
return `
|
|
@@ -46,8 +57,9 @@ Examples:
|
|
|
46
57
|
$ aifabrix role-assistant test customer-support-bot --case smoke
|
|
47
58
|
$ aifabrix role-assistant test customer-support-bot --case tests/customer-address-change.yaml
|
|
48
59
|
$ aifabrix role-assistant test customer-support-bot --subject-email ops@example.com
|
|
49
|
-
$ aifabrix role-assistant test customer-support-bot --
|
|
50
|
-
$ aifabrix role-assistant test customer-support-bot --
|
|
60
|
+
$ aifabrix role-assistant test customer-support-bot --suite 001
|
|
61
|
+
$ aifabrix role-assistant test customer-support-bot --list-cases
|
|
62
|
+
$ aifabrix role-assistant test customer-support-bot --suite 001 --fail-fast --json
|
|
51
63
|
|
|
52
64
|
Notes:
|
|
53
65
|
- Uses the public/running Role Assistant on the dataplane by default (does not publish local datasources).
|
|
@@ -55,6 +67,7 @@ Notes:
|
|
|
55
67
|
- Runs lifecycle checks, then prints a portal deep link for full step-by-step status.
|
|
56
68
|
- Case files with input.message/input.content execute Work Hub plan→accept (or work.start when executionPath: intent).
|
|
57
69
|
- answers[] and approvals[] are matched to runtime wait payloads (questionKey/requestKey/waitReason).
|
|
70
|
+
- --suite runs all YAML under tests/role-assistant/ra-<roleKey>/<suite>/ (or --cases-root).
|
|
58
71
|
- Use the portal URL for detailed human review while automation reads CLI/JSON output.
|
|
59
72
|
`;
|
|
60
73
|
}
|
|
@@ -91,97 +104,123 @@ function normalizeRoleAssistantTestOptions(options, cmd) {
|
|
|
91
104
|
certificationProfile: options.certificationProfile || 'bronze',
|
|
92
105
|
case: trimOptionalString(options.case),
|
|
93
106
|
testsDir: trimOptionalString(options.testsDir),
|
|
107
|
+
suite: trimOptionalString(options.suite),
|
|
108
|
+
casesRoot: trimOptionalString(options.casesRoot),
|
|
109
|
+
listCases: optionOrFlag(options, 'listCases', cmd, '--list-cases'),
|
|
110
|
+
failFast: optionOrFlag(options, 'failFast', cmd, '--fail-fast'),
|
|
94
111
|
run: true
|
|
95
112
|
};
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
portalUrl,
|
|
105
|
-
openApiPublished: result.openApiPublished === true,
|
|
106
|
-
certification: report.certification || null,
|
|
107
|
-
recommendations: Array.isArray(report.recommendations) ? report.recommendations : [],
|
|
108
|
-
warnings: Array.isArray(report.warnings) ? report.warnings : [],
|
|
109
|
-
stepsRun: result.stepsRun || [],
|
|
110
|
-
case: caseResult
|
|
111
|
-
? {
|
|
112
|
-
caseId: caseResult.caseId,
|
|
113
|
-
sourceFile: caseResult.sourceFile,
|
|
114
|
-
passed: caseResult.passed,
|
|
115
|
-
lifecycleState: caseResult.lifecycleState,
|
|
116
|
-
assertions: caseResult.assertions,
|
|
117
|
-
failedAssertions: caseResult.failedAssertions,
|
|
118
|
-
warnings: Array.isArray(caseResult.warnings) ? caseResult.warnings : [],
|
|
119
|
-
execution: caseResult.execution || null
|
|
120
|
-
}
|
|
121
|
-
: null
|
|
122
|
-
};
|
|
123
|
-
if (opts.verbose || opts.debug) {
|
|
124
|
-
envelope.report = report;
|
|
115
|
+
function computeRoleAssistantExitCode(verdict, caseResult) {
|
|
116
|
+
if (Array.isArray(caseResult)) {
|
|
117
|
+
if (caseResult.some((row) => row && row.passed === false)) {
|
|
118
|
+
return 2;
|
|
119
|
+
}
|
|
120
|
+
return 0;
|
|
125
121
|
}
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
observation: caseResult ? caseResult.observation : null,
|
|
129
|
-
lifecycleResult: result
|
|
130
|
-
};
|
|
122
|
+
if (caseResult) {
|
|
123
|
+
return caseResult.passed ? 0 : 2;
|
|
131
124
|
}
|
|
132
|
-
|
|
125
|
+
if (verdict === VERDICT.VERIFIED) {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
return exitCodeFromVerdict(verdict, { partial: verdict === VERDICT.NOT_VERIFIED });
|
|
133
129
|
}
|
|
134
130
|
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
function listRoleAssistantCases(roleKey, opts) {
|
|
132
|
+
const root = resolveCasesRoot(roleKey, { casesRoot: opts.casesRoot || undefined });
|
|
133
|
+
const rows = discoverSuiteCaseFiles(root, { suite: opts.suite || undefined });
|
|
134
|
+
const filtered = filterDiscoveredCases(rows, opts.case);
|
|
135
|
+
if (opts.json) {
|
|
136
|
+
logger.log(
|
|
137
|
+
JSON.stringify(
|
|
138
|
+
{
|
|
139
|
+
roleKey: bareRoleKey(roleKey),
|
|
140
|
+
command: 'role-assistant test',
|
|
141
|
+
mode: 'list-cases',
|
|
142
|
+
casesRoot: root,
|
|
143
|
+
cases: filtered.map((r) => ({
|
|
144
|
+
suite: r.suite,
|
|
145
|
+
file: r.file,
|
|
146
|
+
path: r.absPath,
|
|
147
|
+
caseIdHint: r.caseIdHint
|
|
148
|
+
}))
|
|
149
|
+
},
|
|
150
|
+
null,
|
|
151
|
+
2
|
|
152
|
+
)
|
|
153
|
+
);
|
|
154
|
+
} else {
|
|
155
|
+
logger.log(sectionTitle('ROLE ASSISTANT CASES'));
|
|
156
|
+
logger.log(headerKeyValue('Cases root:', root));
|
|
157
|
+
for (const row of filtered) {
|
|
158
|
+
logger.log(`${row.suite}\t${row.file}\t${row.absPath}`);
|
|
159
|
+
}
|
|
160
|
+
logger.log(metadata(`total ${filtered.length}`));
|
|
138
161
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function resolveSuiteCaseResults(systemKey, opts, result, verdict, portalUrl) {
|
|
166
|
+
const root = resolveCasesRoot(systemKey, { casesRoot: opts.casesRoot || undefined });
|
|
167
|
+
const discovered = discoverSuiteCaseFiles(root, { suite: opts.suite || undefined });
|
|
168
|
+
const selected = filterDiscoveredCases(discovered, opts.case);
|
|
169
|
+
if (selected.length === 0) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`No role-assistant cases found under ${root}` +
|
|
172
|
+
(opts.suite ? ` suite=${opts.suite}` : '')
|
|
173
|
+
);
|
|
145
174
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
const outcomes = [];
|
|
176
|
+
for (const row of selected) {
|
|
177
|
+
const caseOpts = { ...opts, case: row.absPath, testsDir: path.dirname(row.absPath) };
|
|
178
|
+
const one = await resolveRoleAssistantCaseResult(systemKey, caseOpts, result, verdict, portalUrl);
|
|
179
|
+
outcomes.push(one);
|
|
180
|
+
if (opts.failFast && one && one.passed === false) {
|
|
181
|
+
break;
|
|
151
182
|
}
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
logger.log(formatBlockingError('Case assertions failed.'));
|
|
155
|
-
for (const row of caseResult.failedAssertions) {
|
|
156
|
-
logger.log(formatWarningLine(row.message));
|
|
157
183
|
}
|
|
184
|
+
return outcomes;
|
|
158
185
|
}
|
|
159
186
|
|
|
160
|
-
function
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
|
|
187
|
+
async function runRoleAssistantTestAction(roleKey, options, cmd) {
|
|
188
|
+
const opts = normalizeRoleAssistantTestOptions(options, cmd);
|
|
189
|
+
const systemKey = roleAssistantSystemKey(roleKey);
|
|
190
|
+
const displayKey = bareRoleKey(roleKey);
|
|
191
|
+
|
|
192
|
+
if (opts.listCases) {
|
|
193
|
+
return listRoleAssistantCases(systemKey, opts);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const result = await runLifecycleForExternalSystem(systemKey, opts);
|
|
197
|
+
const verdict = lifecycleVerdictFromReport(result.report || {});
|
|
198
|
+
const portalUrl = buildExternalSystemUiUrl(result.dataplaneUiBaseUrl, systemKey);
|
|
199
|
+
|
|
200
|
+
let caseResult = null;
|
|
201
|
+
if (opts.suite) {
|
|
202
|
+
caseResult = await resolveSuiteCaseResults(systemKey, opts, result, verdict, portalUrl);
|
|
167
203
|
} else {
|
|
168
|
-
|
|
204
|
+
caseResult = await resolveRoleAssistantCaseResult(systemKey, opts, result, verdict, portalUrl);
|
|
169
205
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
206
|
+
|
|
207
|
+
if (opts.json) {
|
|
208
|
+
logger.log(
|
|
209
|
+
JSON.stringify(
|
|
210
|
+
buildRoleAssistantTestEnvelope(displayKey, verdict, portalUrl, result, opts, caseResult),
|
|
211
|
+
null,
|
|
212
|
+
2
|
|
213
|
+
)
|
|
214
|
+
);
|
|
176
215
|
} else {
|
|
177
|
-
|
|
216
|
+
displayRoleAssistantTestSummary(displayKey, verdict, portalUrl, result, caseResult);
|
|
178
217
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
218
|
+
|
|
219
|
+
const exitCode = computeRoleAssistantExitCode(verdict, caseResult);
|
|
220
|
+
if (exitCode !== 0) {
|
|
221
|
+
process.exit(exitCode);
|
|
183
222
|
}
|
|
184
|
-
|
|
223
|
+
return exitCode;
|
|
185
224
|
}
|
|
186
225
|
|
|
187
226
|
async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl) {
|
|
@@ -218,41 +257,6 @@ async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, po
|
|
|
218
257
|
return evaluation;
|
|
219
258
|
}
|
|
220
259
|
|
|
221
|
-
function computeRoleAssistantExitCode(verdict, caseResult) {
|
|
222
|
-
if (caseResult) {
|
|
223
|
-
return caseResult.passed ? 0 : 2;
|
|
224
|
-
}
|
|
225
|
-
if (verdict === VERDICT.VERIFIED) {
|
|
226
|
-
return 0;
|
|
227
|
-
}
|
|
228
|
-
return exitCodeFromVerdict(verdict, { partial: verdict === VERDICT.NOT_VERIFIED });
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async function runRoleAssistantTestAction(roleKey, options, cmd) {
|
|
232
|
-
const opts = normalizeRoleAssistantTestOptions(options, cmd);
|
|
233
|
-
const result = await runLifecycleForExternalSystem(roleKey, opts);
|
|
234
|
-
const verdict = lifecycleVerdictFromReport(result.report || {});
|
|
235
|
-
const portalUrl = buildExternalSystemUiUrl(result.dataplaneUiBaseUrl, roleKey);
|
|
236
|
-
const caseResult = await resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl);
|
|
237
|
-
|
|
238
|
-
if (opts.json) {
|
|
239
|
-
logger.log(
|
|
240
|
-
JSON.stringify(
|
|
241
|
-
buildRoleAssistantTestEnvelope(roleKey, verdict, portalUrl, result, opts, caseResult),
|
|
242
|
-
null,
|
|
243
|
-
2
|
|
244
|
-
)
|
|
245
|
-
);
|
|
246
|
-
} else {
|
|
247
|
-
displayRoleAssistantTestSummary(roleKey, verdict, portalUrl, result, caseResult);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const exitCode = computeRoleAssistantExitCode(verdict, caseResult);
|
|
251
|
-
if (exitCode !== 0) {
|
|
252
|
-
process.exit(exitCode);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
260
|
async function roleAssistantTestHandler(roleKey, options, cmd) {
|
|
257
261
|
try {
|
|
258
262
|
await runRoleAssistantTestAction(roleKey, options, cmd);
|
|
@@ -273,6 +277,16 @@ function setupRoleAssistantCommands(program) {
|
|
|
273
277
|
.option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
|
|
274
278
|
.option('--case <caseIdOrPath>', 'Run and evaluate one role-assistant test case')
|
|
275
279
|
.option('--tests-dir <dir>', 'Override role-assistant test case directory')
|
|
280
|
+
.option(
|
|
281
|
+
'--suite <suiteId>',
|
|
282
|
+
'Run all YAML cases under tests/role-assistant/ra-<roleKey>/<suiteId>/'
|
|
283
|
+
)
|
|
284
|
+
.option(
|
|
285
|
+
'--cases-root <dir>',
|
|
286
|
+
'Override cases root (default: tests/role-assistant/ra-<roleKey>/)'
|
|
287
|
+
)
|
|
288
|
+
.option('--list-cases', 'List discoverable case files and exit')
|
|
289
|
+
.option('--fail-fast', 'Stop suite run after the first failing case')
|
|
276
290
|
.option('-v, --verbose', 'Include full lifecycle report payload in --json output')
|
|
277
291
|
.option('-d, --debug', 'Write debug logs under role-assistant/<roleKey>/logs/')
|
|
278
292
|
.option(
|
|
@@ -309,5 +323,8 @@ module.exports = {
|
|
|
309
323
|
normalizeRoleAssistantTestOptions,
|
|
310
324
|
buildRoleAssistantTestEnvelope,
|
|
311
325
|
computeRoleAssistantExitCode,
|
|
312
|
-
resolveRoleAssistantCaseResult
|
|
326
|
+
resolveRoleAssistantCaseResult,
|
|
327
|
+
resolveSuiteCaseResults,
|
|
328
|
+
listRoleAssistantCases,
|
|
329
|
+
formatStepsRunSummary
|
|
313
330
|
};
|
|
@@ -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,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @version 2.0.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
const { capabilitiesIncludes } = require('./capability-manifest');
|
|
9
|
+
const { capabilitiesIncludes, capabilityKeyFromEntry } = require('./capability-manifest');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @param {object|undefined} operations
|
|
@@ -44,6 +44,16 @@ function resolveSingleOpsKey(operations, logicalKey, label) {
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @param {unknown} entry
|
|
49
|
+
* @param {string} userKey
|
|
50
|
+
* @returns {boolean}
|
|
51
|
+
*/
|
|
52
|
+
function capabilityEntryMatches(entry, userKey) {
|
|
53
|
+
const key = capabilityKeyFromEntry(entry);
|
|
54
|
+
return Boolean(key) && key.toLowerCase() === String(userKey).toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
47
57
|
/**
|
|
48
58
|
* For --from on copy: when capabilities[] is non-empty, the name must appear there (case-insensitive).
|
|
49
59
|
*
|
|
@@ -56,14 +66,14 @@ function resolveSourceCapabilityForCopy(doc, userKey) {
|
|
|
56
66
|
const u = String(userKey).trim();
|
|
57
67
|
const caps = doc.capabilities;
|
|
58
68
|
if (Array.isArray(caps) && caps.length > 0) {
|
|
59
|
-
const hit = caps.find((c) =>
|
|
69
|
+
const hit = caps.find((c) => capabilityEntryMatches(c, u));
|
|
60
70
|
if (hit === undefined) {
|
|
61
71
|
throw new Error(
|
|
62
72
|
`Source capability "${userKey}" not found in capabilities[]. ` +
|
|
63
73
|
'Use a name that appears in capabilities[] (case-insensitive match is allowed).'
|
|
64
74
|
);
|
|
65
75
|
}
|
|
66
|
-
return
|
|
76
|
+
return capabilityKeyFromEntry(hit) || u;
|
|
67
77
|
}
|
|
68
78
|
return u;
|
|
69
79
|
}
|
|
@@ -79,9 +89,9 @@ function resolveLogicalNameForRemove(doc, userKey) {
|
|
|
79
89
|
const u = String(userKey).trim();
|
|
80
90
|
const caps = doc.capabilities;
|
|
81
91
|
if (Array.isArray(caps) && caps.length > 0) {
|
|
82
|
-
const hit = caps.find((c) =>
|
|
92
|
+
const hit = caps.find((c) => capabilityEntryMatches(c, u));
|
|
83
93
|
if (hit !== undefined) {
|
|
84
|
-
return
|
|
94
|
+
return capabilityKeyFromEntry(hit) || u;
|
|
85
95
|
}
|
|
86
96
|
}
|
|
87
97
|
return u;
|