@aifabrix/builder 2.39.2 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/project-rules.mdc +6 -6
- package/README.md +2 -2
- package/babel.config.js +6 -0
- package/integration/hubspot/README.md +53 -141
- package/integration/hubspot/application.yaml +37 -0
- package/integration/hubspot/env.template +2 -11
- package/integration/hubspot/hubspot-deploy.json +1 -0
- package/integration/hubspot/test.js +5 -5
- package/lib/api/credentials.api.js +5 -5
- package/lib/api/deployments.api.js +2 -2
- package/lib/api/pipeline.api.js +17 -17
- package/lib/api/wizard.api.js +2 -2
- package/lib/app/config.js +11 -6
- package/lib/app/deploy-config.js +13 -16
- package/lib/app/deploy.js +29 -22
- package/lib/app/display.js +1 -1
- package/lib/app/dockerfile.js +11 -12
- package/lib/app/helpers.js +51 -13
- package/lib/app/index.js +14 -2
- package/lib/app/prompts.js +37 -45
- package/lib/app/push.js +8 -11
- package/lib/app/readme.js +16 -12
- package/lib/app/register.js +3 -3
- package/lib/app/run-helpers.js +31 -22
- package/lib/app/run.js +44 -5
- package/lib/app/show-display.js +104 -44
- package/lib/app/show.js +123 -43
- package/lib/build/index.js +11 -18
- package/lib/cli/setup-app.js +38 -28
- package/lib/cli/setup-auth.js +18 -15
- package/lib/cli/setup-credential-deployment.js +3 -1
- package/lib/cli/setup-external-system.js +35 -16
- package/lib/cli/setup-infra.js +45 -23
- package/lib/cli/setup-utility.js +79 -31
- package/lib/commands/app-logs.js +165 -10
- package/lib/commands/app.js +30 -26
- package/lib/commands/convert.js +202 -0
- package/lib/commands/credential-list.js +78 -17
- package/lib/commands/datasource.js +24 -24
- package/lib/commands/deployment-list.js +13 -6
- package/lib/commands/up-common.js +80 -42
- package/lib/commands/up-dataplane.js +15 -14
- package/lib/commands/up-miso.js +15 -14
- package/lib/commands/upload.js +163 -0
- package/lib/commands/wizard-core.js +5 -4
- package/lib/core/diff.js +84 -9
- package/lib/core/key-generator.js +9 -12
- package/lib/core/secrets-docker-env.js +2 -2
- package/lib/core/secrets.js +3 -2
- package/lib/core/templates.js +2 -2
- package/lib/datasource/deploy.js +2 -1
- package/lib/deployment/deployer.js +76 -48
- package/lib/external-system/delete.js +0 -1
- package/lib/external-system/deploy-helpers.js +5 -6
- package/lib/external-system/deploy.js +7 -2
- package/lib/external-system/download-helpers.js +4 -4
- package/lib/external-system/download.js +11 -10
- package/lib/external-system/generator.js +19 -17
- package/lib/external-system/test.js +10 -15
- package/lib/generator/builders.js +1 -1
- package/lib/generator/external-controller-manifest.js +26 -29
- package/lib/generator/external-schema-utils.js +6 -18
- package/lib/generator/external.js +32 -27
- package/lib/generator/github.js +1 -1
- package/lib/generator/helpers.js +12 -19
- package/lib/generator/index.js +15 -15
- package/lib/generator/parse-image.js +35 -0
- package/lib/generator/split-readme.js +105 -0
- package/lib/generator/split-variables.js +149 -0
- package/lib/generator/split.js +86 -246
- package/lib/generator/wizard.js +46 -69
- package/lib/schema/application-schema.json +4 -4
- package/lib/schema/deployment-rules.yaml +0 -4
- package/lib/schema/external-datasource.schema.json +5 -0
- package/lib/schema/external-system.schema.json +10 -0
- package/lib/utils/app-config-resolver.js +52 -0
- package/lib/utils/app-register-api.js +1 -1
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +16 -23
- package/lib/utils/app-register-display.js +22 -3
- package/lib/utils/app-register-validator.js +2 -2
- package/lib/utils/cli-utils.js +47 -3
- package/lib/utils/config-format.js +154 -0
- package/lib/utils/config-paths.js +19 -52
- package/lib/utils/config-tokens.js +1 -0
- package/lib/utils/docker-build.js +71 -94
- package/lib/utils/dockerfile-utils.js +1 -1
- package/lib/utils/env-copy.js +4 -4
- package/lib/utils/env-ports.js +2 -2
- package/lib/utils/error-formatter.js +1 -1
- package/lib/utils/error-formatters/validation-errors.js +1 -1
- package/lib/utils/external-readme.js +12 -5
- package/lib/utils/external-system-test-helpers.js +2 -0
- package/lib/utils/health-check.js +55 -66
- package/lib/utils/image-version.js +12 -21
- package/lib/utils/paths.js +39 -66
- package/lib/utils/port-resolver.js +8 -8
- package/lib/utils/schema-loader.js +22 -0
- package/lib/utils/schema-resolver.js +23 -33
- package/lib/utils/secrets-helpers.js +7 -7
- package/lib/utils/secrets-utils.js +10 -12
- package/lib/utils/template-helpers.js +13 -13
- package/lib/utils/token-manager.js +20 -2
- package/lib/utils/variable-transformer.js +2 -2
- package/lib/validation/validate-display.js +3 -4
- package/lib/validation/validate.js +33 -27
- package/lib/validation/validator.js +50 -30
- package/package.json +2 -1
- package/templates/README.md +1 -1
- package/templates/applications/README.md.hbs +3 -3
- package/templates/applications/miso-controller/env.template +3 -1
- package/templates/external-system/README.md.hbs +4 -4
- package/integration/hubspot/variables.yaml +0 -17
- /package/templates/applications/dataplane/{variables.yaml → application.yaml} +0 -0
- /package/templates/applications/keycloak/{variables.yaml → application.yaml} +0 -0
- /package/templates/applications/miso-controller/{variables.yaml → application.yaml} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Credential list command – list credentials from
|
|
2
|
+
* Credential list command – list credentials from Dataplane
|
|
3
3
|
* GET /api/v1/credential. Used by `aifabrix credential list`.
|
|
4
|
+
* The Controller does not expose this endpoint; credentials are listed from the Dataplane.
|
|
4
5
|
*
|
|
5
6
|
* @fileoverview Credential list command implementation
|
|
6
7
|
* @author AI Fabrix Team
|
|
@@ -11,7 +12,8 @@ const chalk = require('chalk');
|
|
|
11
12
|
const logger = require('../utils/logger');
|
|
12
13
|
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
13
14
|
const { getOrRefreshDeviceToken } = require('../utils/token-manager');
|
|
14
|
-
const { normalizeControllerUrl } = require('../core/config');
|
|
15
|
+
const { normalizeControllerUrl, resolveEnvironment } = require('../core/config');
|
|
16
|
+
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
15
17
|
const { listCredentials } = require('../api/credentials.api');
|
|
16
18
|
|
|
17
19
|
const DEFAULT_PAGE_SIZE = 50;
|
|
@@ -48,10 +50,10 @@ function extractCredentials(response) {
|
|
|
48
50
|
/**
|
|
49
51
|
* Display credential list to user
|
|
50
52
|
* @param {Array} list - Credentials array
|
|
51
|
-
* @param {string}
|
|
53
|
+
* @param {string} baseUrl - Dataplane (or base) URL for header
|
|
52
54
|
*/
|
|
53
|
-
function displayCredentialList(list,
|
|
54
|
-
logger.log(chalk.bold(`\n🔐 Credentials (${
|
|
55
|
+
function displayCredentialList(list, baseUrl) {
|
|
56
|
+
logger.log(chalk.bold(`\n🔐 Credentials (${baseUrl}):\n`));
|
|
55
57
|
if (list.length === 0) {
|
|
56
58
|
logger.log(chalk.gray(' No credentials found.\n'));
|
|
57
59
|
return;
|
|
@@ -65,36 +67,95 @@ function displayCredentialList(list, controllerUrl) {
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
/**
|
|
68
|
-
*
|
|
70
|
+
* Ensure controller URL and auth; exit on failure. Returns { controllerUrl, authConfig } when valid.
|
|
69
71
|
* @async
|
|
70
|
-
* @param {Object} options - CLI options
|
|
71
|
-
* @
|
|
72
|
-
* @param {boolean} [options.activeOnly] - List only active credentials
|
|
73
|
-
* @param {number} [options.pageSize] - Items per page
|
|
74
|
-
* @returns {Promise<void>}
|
|
72
|
+
* @param {Object} options - CLI options with optional controller
|
|
73
|
+
* @returns {Promise<{controllerUrl: string, authConfig: Object}>}
|
|
75
74
|
*/
|
|
76
|
-
async function
|
|
75
|
+
async function ensureControllerAndAuth(options) {
|
|
77
76
|
const controllerUrl = options.controller || (await resolveControllerUrl());
|
|
78
77
|
if (!controllerUrl) {
|
|
79
78
|
logger.error(chalk.red('❌ Controller URL is required. Run "aifabrix login" first.'));
|
|
80
79
|
process.exit(1);
|
|
81
|
-
return;
|
|
82
80
|
}
|
|
83
81
|
const authResult = await getCredentialListAuth(controllerUrl);
|
|
84
82
|
if (!authResult || !authResult.token) {
|
|
85
83
|
logger.error(chalk.red(`❌ No authentication token for controller: ${controllerUrl}`));
|
|
86
84
|
logger.error(chalk.gray('Run: aifabrix login'));
|
|
87
85
|
process.exit(1);
|
|
88
|
-
return;
|
|
89
86
|
}
|
|
90
|
-
|
|
87
|
+
return {
|
|
88
|
+
controllerUrl,
|
|
89
|
+
authConfig: { type: 'bearer', token: authResult.token }
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Resolve Dataplane URL for credential list (override or discover from controller + environment)
|
|
95
|
+
* @async
|
|
96
|
+
* @param {string} controllerUrl - Controller base URL
|
|
97
|
+
* @param {Object} authConfig - Auth config with token
|
|
98
|
+
* @param {Object} options - CLI options
|
|
99
|
+
* @param {string} [options.dataplane] - Optional Dataplane URL override
|
|
100
|
+
* @returns {Promise<string>} Dataplane base URL
|
|
101
|
+
* @throws {Error} When resolution fails (caller should exit)
|
|
102
|
+
*/
|
|
103
|
+
async function resolveCredentialListDataplaneUrl(controllerUrl, authConfig, options) {
|
|
104
|
+
if (options.dataplane) {
|
|
105
|
+
return options.dataplane.replace(/\/$/, '');
|
|
106
|
+
}
|
|
107
|
+
const environment = await resolveEnvironment();
|
|
108
|
+
return await resolveDataplaneUrl(controllerUrl, environment, authConfig);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Call Dataplane credential API and display results; exits on failure
|
|
113
|
+
* @param {string} dataplaneUrl - Dataplane base URL
|
|
114
|
+
* @param {Object} authConfig - Auth config
|
|
115
|
+
* @param {Object} listOptions - pageSize, activeOnly
|
|
116
|
+
*/
|
|
117
|
+
async function fetchAndDisplayCredentials(dataplaneUrl, authConfig, listOptions) {
|
|
118
|
+
const response = await listCredentials(dataplaneUrl, authConfig, listOptions);
|
|
119
|
+
displayCredentialList(extractCredentials(response), dataplaneUrl);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Resolve Dataplane URL or log error and exit
|
|
124
|
+
* @async
|
|
125
|
+
* @param {string} controllerUrl - Controller URL
|
|
126
|
+
* @param {Object} authConfig - Auth config
|
|
127
|
+
* @param {Object} options - CLI options
|
|
128
|
+
* @returns {Promise<string>} Dataplane URL (never returns on failure; process.exit(1))
|
|
129
|
+
*/
|
|
130
|
+
async function resolveDataplaneUrlOrExit(controllerUrl, authConfig, options) {
|
|
131
|
+
try {
|
|
132
|
+
return await resolveCredentialListDataplaneUrl(controllerUrl, authConfig, options);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
logger.error(chalk.red(`❌ Could not resolve Dataplane URL: ${err.message}`));
|
|
135
|
+
logger.error(chalk.gray('Use --dataplane <url> to specify the Dataplane URL directly.'));
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Run credential list command: call GET /api/v1/credential on Dataplane and display results
|
|
142
|
+
* @async
|
|
143
|
+
* @param {Object} options - CLI options
|
|
144
|
+
* @param {string} [options.controller] - Controller URL override
|
|
145
|
+
* @param {string} [options.dataplane] - Dataplane URL override (default: resolved from controller + environment)
|
|
146
|
+
* @param {boolean} [options.activeOnly] - List only active credentials
|
|
147
|
+
* @param {number} [options.pageSize] - Items per page
|
|
148
|
+
* @returns {Promise<void>}
|
|
149
|
+
*/
|
|
150
|
+
async function runCredentialList(options = {}) {
|
|
151
|
+
const { controllerUrl, authConfig } = await ensureControllerAndAuth(options);
|
|
152
|
+
const dataplaneUrl = await resolveDataplaneUrlOrExit(controllerUrl, authConfig, options);
|
|
91
153
|
const listOptions = {
|
|
92
154
|
pageSize: options.pageSize || DEFAULT_PAGE_SIZE,
|
|
93
155
|
activeOnly: options.activeOnly
|
|
94
156
|
};
|
|
95
157
|
try {
|
|
96
|
-
|
|
97
|
-
displayCredentialList(extractCredentials(response), authResult.controllerUrl);
|
|
158
|
+
await fetchAndDisplayCredentials(dataplaneUrl, authConfig, listOptions);
|
|
98
159
|
} catch (error) {
|
|
99
160
|
logger.error(chalk.red(`❌ Failed to list credentials: ${error.message}`));
|
|
100
161
|
process.exit(1);
|
|
@@ -16,18 +16,8 @@ const { listDatasources } = require('../datasource/list');
|
|
|
16
16
|
const { compareDatasources } = require('../datasource/diff');
|
|
17
17
|
const { deployDatasource } = require('../datasource/deploy');
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* @param {Command} program - Commander program instance
|
|
22
|
-
*/
|
|
23
|
-
function setupDatasourceCommands(program) {
|
|
24
|
-
const datasource = program
|
|
25
|
-
.command('datasource')
|
|
26
|
-
.description('Manage external data sources');
|
|
27
|
-
|
|
28
|
-
// Validate command
|
|
29
|
-
datasource
|
|
30
|
-
.command('validate <file>')
|
|
19
|
+
function setupDatasourceValidateCommand(datasource) {
|
|
20
|
+
datasource.command('validate <file>')
|
|
31
21
|
.description('Validate external datasource JSON file')
|
|
32
22
|
.action(async(file) => {
|
|
33
23
|
try {
|
|
@@ -36,9 +26,7 @@ function setupDatasourceCommands(program) {
|
|
|
36
26
|
logger.log(chalk.green(`\n✓ Datasource file is valid: ${file}`));
|
|
37
27
|
} else {
|
|
38
28
|
logger.log(chalk.red(`\n✗ Datasource file has errors: ${file}`));
|
|
39
|
-
result.errors.forEach(error => {
|
|
40
|
-
logger.log(chalk.red(` • ${error}`));
|
|
41
|
-
});
|
|
29
|
+
result.errors.forEach(error => logger.log(chalk.red(` • ${error}`)));
|
|
42
30
|
process.exit(1);
|
|
43
31
|
}
|
|
44
32
|
} catch (error) {
|
|
@@ -46,10 +34,10 @@ function setupDatasourceCommands(program) {
|
|
|
46
34
|
process.exit(1);
|
|
47
35
|
}
|
|
48
36
|
});
|
|
37
|
+
}
|
|
49
38
|
|
|
50
|
-
|
|
51
|
-
datasource
|
|
52
|
-
.command('list')
|
|
39
|
+
function setupDatasourceListCommand(datasource) {
|
|
40
|
+
datasource.command('list')
|
|
53
41
|
.description('List datasources from environment (uses environment from config.yaml)')
|
|
54
42
|
.action(async() => {
|
|
55
43
|
try {
|
|
@@ -59,10 +47,10 @@ function setupDatasourceCommands(program) {
|
|
|
59
47
|
process.exit(1);
|
|
60
48
|
}
|
|
61
49
|
});
|
|
50
|
+
}
|
|
62
51
|
|
|
63
|
-
|
|
64
|
-
datasource
|
|
65
|
-
.command('diff <file1> <file2>')
|
|
52
|
+
function setupDatasourceDiffCommand(datasource) {
|
|
53
|
+
datasource.command('diff <file1> <file2>')
|
|
66
54
|
.description('Compare two datasource configuration files (for dataplane)')
|
|
67
55
|
.action(async(file1, file2) => {
|
|
68
56
|
try {
|
|
@@ -72,10 +60,10 @@ function setupDatasourceCommands(program) {
|
|
|
72
60
|
process.exit(1);
|
|
73
61
|
}
|
|
74
62
|
});
|
|
63
|
+
}
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
datasource
|
|
78
|
-
.command('deploy <myapp> <file>')
|
|
65
|
+
function setupDatasourceDeployCommand(datasource) {
|
|
66
|
+
datasource.command('deploy <myapp> <file>')
|
|
79
67
|
.description('Deploy datasource to dataplane')
|
|
80
68
|
.action(async(myapp, file, options) => {
|
|
81
69
|
try {
|
|
@@ -87,5 +75,17 @@ function setupDatasourceCommands(program) {
|
|
|
87
75
|
});
|
|
88
76
|
}
|
|
89
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Setup datasource management commands
|
|
80
|
+
* @param {Command} program - Commander program instance
|
|
81
|
+
*/
|
|
82
|
+
function setupDatasourceCommands(program) {
|
|
83
|
+
const datasource = program.command('datasource').description('Manage external data sources');
|
|
84
|
+
setupDatasourceValidateCommand(datasource);
|
|
85
|
+
setupDatasourceListCommand(datasource);
|
|
86
|
+
setupDatasourceDiffCommand(datasource);
|
|
87
|
+
setupDatasourceDeployCommand(datasource);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
90
|
module.exports = { setupDatasourceCommands };
|
|
91
91
|
|
|
@@ -36,13 +36,19 @@ async function getDeploymentListAuth(controllerUrl) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Extract deployments array from API response
|
|
40
|
-
*
|
|
39
|
+
* Extract deployments array from API response.
|
|
40
|
+
* Supports OpenAPI/SDK paginated format: { meta, data: Deployment[], links }
|
|
41
|
+
* and legacy shapes: { data: { items } }, { data: { deployments } }, or { data: [] }.
|
|
42
|
+
* @param {Object} response - API response (from ApiClient: { success, data: body, status })
|
|
41
43
|
* @returns {Array}
|
|
42
44
|
*/
|
|
43
45
|
function extractDeployments(response) {
|
|
44
|
-
const
|
|
45
|
-
const items =
|
|
46
|
+
const body = response?.data ?? response;
|
|
47
|
+
const items =
|
|
48
|
+
(Array.isArray(body?.data) ? body.data : undefined) ??
|
|
49
|
+
body?.items ??
|
|
50
|
+
body?.deployments ??
|
|
51
|
+
(Array.isArray(body) ? body : []);
|
|
46
52
|
return Array.isArray(items) ? items : [];
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -60,10 +66,11 @@ function displayDeploymentList(deployments, environment, controllerUrl) {
|
|
|
60
66
|
}
|
|
61
67
|
deployments.forEach((d) => {
|
|
62
68
|
const id = d.id ?? d.deploymentId ?? '-';
|
|
63
|
-
const
|
|
69
|
+
const target =
|
|
70
|
+
d.applicationKey ?? d.appKey ?? d.targetId ?? d.application?.key ?? '-';
|
|
64
71
|
const status = d.status ?? '-';
|
|
65
72
|
const createdAt = d.createdAt ?? d.created ?? '';
|
|
66
|
-
logger.log(` ${chalk.cyan(id)} ${
|
|
73
|
+
logger.log(` ${chalk.cyan(id)} ${target} ${status} ${chalk.gray(createdAt)}`);
|
|
67
74
|
});
|
|
68
75
|
logger.log('');
|
|
69
76
|
}
|
|
@@ -10,24 +10,27 @@
|
|
|
10
10
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const fs = require('fs');
|
|
13
|
-
const yaml = require('js-yaml');
|
|
14
13
|
const chalk = require('chalk');
|
|
15
14
|
const logger = require('../utils/logger');
|
|
16
15
|
const pathsUtil = require('../utils/paths');
|
|
16
|
+
const { loadConfigFile, writeConfigFile } = require('../utils/config-format');
|
|
17
|
+
const { isYamlPath } = require('../utils/config-format');
|
|
17
18
|
const { copyTemplateFiles } = require('../validation/template');
|
|
18
19
|
const { ensureReadmeForAppPath, ensureReadmeForApp } = require('../app/readme');
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* Copy template to a target path if
|
|
22
|
+
* Copy template to a target path if application config is missing there.
|
|
22
23
|
* After copy, generates README.md from templates/applications/README.md.hbs.
|
|
23
24
|
* @param {string} appName - Application name
|
|
24
25
|
* @param {string} targetAppPath - Target directory (e.g. builder/keycloak)
|
|
25
26
|
* @returns {Promise<boolean>} True if template was copied, false if already present
|
|
26
27
|
*/
|
|
27
28
|
async function ensureTemplateAtPath(appName, targetAppPath) {
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
try {
|
|
30
|
+
pathsUtil.resolveApplicationConfigPath(targetAppPath);
|
|
30
31
|
return false;
|
|
32
|
+
} catch {
|
|
33
|
+
// No application config; copy template
|
|
31
34
|
}
|
|
32
35
|
await copyTemplateFiles(appName, targetAppPath);
|
|
33
36
|
await ensureReadmeForAppPath(targetAppPath, appName);
|
|
@@ -37,18 +40,55 @@ async function ensureTemplateAtPath(appName, targetAppPath) {
|
|
|
37
40
|
/**
|
|
38
41
|
* Resolve the directory (folder) that would contain the .env file for envOutputPath.
|
|
39
42
|
* @param {string} envOutputPath - Value from build.envOutputPath (e.g. ../../.env)
|
|
40
|
-
* @param {string}
|
|
43
|
+
* @param {string} configPath - Path to application config file
|
|
41
44
|
* @returns {string} Absolute path to the folder that would contain the output .env file
|
|
42
45
|
*/
|
|
43
|
-
function getEnvOutputPathFolder(envOutputPath,
|
|
44
|
-
const
|
|
45
|
-
const resolvedFile = path.resolve(
|
|
46
|
+
function getEnvOutputPathFolder(envOutputPath, configPath) {
|
|
47
|
+
const configDir = path.dirname(configPath);
|
|
48
|
+
const resolvedFile = path.resolve(configDir, envOutputPath);
|
|
46
49
|
return path.dirname(resolvedFile);
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
/**
|
|
50
|
-
*
|
|
53
|
+
* Patches envOutputPath to null in raw YAML content so comments and formatting are preserved.
|
|
54
|
+
* Only touches the line that sets envOutputPath under build.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} content - Raw file content (YAML)
|
|
57
|
+
* @returns {string|null} Patched content, or null if no change
|
|
58
|
+
*/
|
|
59
|
+
function patchEnvOutputPathInYamlContent(content) {
|
|
60
|
+
const re = /^(\s*)envOutputPath\s*:\s*.+$/m;
|
|
61
|
+
const match = content.match(re);
|
|
62
|
+
if (!match) return null;
|
|
63
|
+
const indent = match[1];
|
|
64
|
+
return content.replace(re, `${indent}envOutputPath: null`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Patches config file to set build.envOutputPath to null, preserving comments (YAML only).
|
|
69
|
+
* For JSON or when in-place patch fails, falls back to full write.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} configPath - Path to application config file
|
|
72
|
+
* @returns {boolean} True if file was modified
|
|
73
|
+
*/
|
|
74
|
+
function patchEnvOutputPathInFile(configPath) {
|
|
75
|
+
if (!isYamlPath(configPath)) {
|
|
76
|
+
const variables = loadConfigFile(configPath);
|
|
77
|
+
const updated = { ...variables, build: { ...(variables.build || {}), envOutputPath: null } };
|
|
78
|
+
writeConfigFile(configPath, updated);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
82
|
+
const patched = patchEnvOutputPathInYamlContent(content);
|
|
83
|
+
if (patched === null) return false;
|
|
84
|
+
fs.writeFileSync(configPath, patched, 'utf8');
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validates envOutputPath: if the target folder does not exist, patches application config to set envOutputPath to null.
|
|
51
90
|
* Used by up-platform, up-miso, up-dataplane so we do not keep a path that points outside an existing tree.
|
|
91
|
+
* Patches in place for YAML to preserve comments.
|
|
52
92
|
*
|
|
53
93
|
* @param {string} appName - Application name (e.g. keycloak, miso-controller, dataplane)
|
|
54
94
|
*/
|
|
@@ -59,48 +99,44 @@ function validateEnvOutputPathFolderOrNull(appName) {
|
|
|
59
99
|
if (path.resolve(cwdBuilderPath) !== path.resolve(pathsToPatch[0])) {
|
|
60
100
|
pathsToPatch.push(cwdBuilderPath);
|
|
61
101
|
}
|
|
62
|
-
const envOutputPathLine = /^(\s*envOutputPath:)\s*.*$/m;
|
|
63
|
-
const replacement = '$1 null # deploy only, no copy';
|
|
64
102
|
for (const appPath of pathsToPatch) {
|
|
65
|
-
|
|
66
|
-
|
|
103
|
+
let configPath;
|
|
104
|
+
try {
|
|
105
|
+
configPath = pathsUtil.resolveApplicationConfigPath(appPath);
|
|
106
|
+
} catch {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
67
109
|
try {
|
|
68
|
-
const
|
|
69
|
-
const variables = yaml.load(content);
|
|
110
|
+
const variables = loadConfigFile(configPath);
|
|
70
111
|
const value = variables?.build?.envOutputPath;
|
|
71
112
|
if (value === null || value === undefined || value === '') continue;
|
|
72
|
-
const folder = getEnvOutputPathFolder(String(value).trim(),
|
|
113
|
+
const folder = getEnvOutputPathFolder(String(value).trim(), configPath);
|
|
73
114
|
if (fs.existsSync(folder)) continue;
|
|
74
|
-
|
|
75
|
-
fs.writeFileSync(variablesPath, newContent, 'utf8');
|
|
115
|
+
patchEnvOutputPathInFile(configPath);
|
|
76
116
|
} catch (err) {
|
|
77
|
-
logger.warn(chalk.yellow(`Could not validate envOutputPath in ${
|
|
117
|
+
logger.warn(chalk.yellow(`Could not validate envOutputPath in ${configPath}: ${err.message}`));
|
|
78
118
|
}
|
|
79
119
|
}
|
|
80
120
|
}
|
|
81
121
|
|
|
82
122
|
/**
|
|
83
|
-
* Patches a single
|
|
123
|
+
* Patches a single application config file to set build.envOutputPath to null for deploy-only.
|
|
124
|
+
* Only writes when a change is needed (value is set and target folder does not exist).
|
|
125
|
+
* Uses in-place YAML patch when possible to preserve comments.
|
|
84
126
|
*
|
|
85
|
-
* @param {string}
|
|
86
|
-
* @param {RegExp} envOutputPathLine - Regex for envOutputPath line
|
|
87
|
-
* @param {string} replacement - Replacement string
|
|
127
|
+
* @param {string} configPath - Path to application config file
|
|
88
128
|
*/
|
|
89
|
-
function patchOneVariablesFileForDeployOnly(
|
|
90
|
-
const
|
|
91
|
-
if (!envOutputPathLine.test(content)) return;
|
|
92
|
-
const variables = yaml.load(content);
|
|
129
|
+
function patchOneVariablesFileForDeployOnly(configPath) {
|
|
130
|
+
const variables = loadConfigFile(configPath);
|
|
93
131
|
const value = variables?.build?.envOutputPath;
|
|
94
|
-
if (value
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const newContent = content.replace(envOutputPathLine, replacement);
|
|
99
|
-
fs.writeFileSync(variablesPath, newContent, 'utf8');
|
|
132
|
+
if (value === null || value === undefined || value === '') return;
|
|
133
|
+
const folder = getEnvOutputPathFolder(String(value).trim(), configPath);
|
|
134
|
+
if (fs.existsSync(folder)) return;
|
|
135
|
+
patchEnvOutputPathInFile(configPath);
|
|
100
136
|
}
|
|
101
137
|
|
|
102
138
|
/**
|
|
103
|
-
* Patches
|
|
139
|
+
* Patches application config to set build.envOutputPath to null for deploy-only (no local code).
|
|
104
140
|
* Only patches when the target folder does NOT exist; when folder exists, keeps the value.
|
|
105
141
|
* Use when running up-miso/up-platform so we do not copy .env to repo paths or show that message.
|
|
106
142
|
* Patches both primary builder path and cwd/builder if different.
|
|
@@ -114,22 +150,24 @@ function patchEnvOutputPathForDeployOnly(appName) {
|
|
|
114
150
|
if (path.resolve(cwdBuilderPath) !== path.resolve(pathsToPatch[0])) {
|
|
115
151
|
pathsToPatch.push(cwdBuilderPath);
|
|
116
152
|
}
|
|
117
|
-
const envOutputPathLine = /^(\s*envOutputPath:)\s*.*$/m;
|
|
118
|
-
const replacement = '$1 null # deploy only, no copy';
|
|
119
153
|
for (const appPath of pathsToPatch) {
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
let configPath;
|
|
155
|
+
try {
|
|
156
|
+
configPath = pathsUtil.resolveApplicationConfigPath(appPath);
|
|
157
|
+
} catch {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
122
160
|
try {
|
|
123
|
-
patchOneVariablesFileForDeployOnly(
|
|
161
|
+
patchOneVariablesFileForDeployOnly(configPath);
|
|
124
162
|
} catch (err) {
|
|
125
|
-
logger.warn(chalk.yellow(`Could not patch envOutputPath in ${
|
|
163
|
+
logger.warn(chalk.yellow(`Could not patch envOutputPath in ${configPath}: ${err.message}`));
|
|
126
164
|
}
|
|
127
165
|
}
|
|
128
166
|
}
|
|
129
167
|
|
|
130
168
|
/**
|
|
131
|
-
* Ensures builder app directory exists from template if
|
|
132
|
-
* If builder/<appName>/
|
|
169
|
+
* Ensures builder app directory exists from template if application config is missing.
|
|
170
|
+
* If builder/<appName>/application config does not exist, copies from templates/applications/<appName>.
|
|
133
171
|
* Uses AIFABRIX_BUILDER_DIR when set (e.g. by up-miso/up-dataplane from config aifabrix-env-config).
|
|
134
172
|
* When using a custom builder dir, also populates cwd/builder/<appName> so the repo's builder/ is not empty.
|
|
135
173
|
*
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Always local deployment: registers or rotates dataplane app in dev, sends
|
|
5
5
|
* deployment manifest to Miso Controller, then runs the dataplane app locally
|
|
6
|
-
* (same as aifabrix deploy dataplane --
|
|
6
|
+
* (same as aifabrix deploy dataplane --local). If app is already
|
|
7
7
|
* registered, uses rotate-secret; otherwise registers.
|
|
8
8
|
*
|
|
9
9
|
* @fileoverview up-dataplane command implementation
|
|
@@ -11,10 +11,9 @@
|
|
|
11
11
|
* @version 2.0.0
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
const path = require('path');
|
|
15
|
-
const fs = require('fs');
|
|
16
|
-
const yaml = require('js-yaml');
|
|
17
14
|
const chalk = require('chalk');
|
|
15
|
+
const pathsUtil = require('../utils/paths');
|
|
16
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
18
17
|
const logger = require('../utils/logger');
|
|
19
18
|
const config = require('../core/config');
|
|
20
19
|
const { checkAuthentication } = require('../utils/app-register-auth');
|
|
@@ -47,20 +46,22 @@ async function registerOrRotateDataplane(options, controllerUrl, environmentKey,
|
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
/**
|
|
50
|
-
* Build full image ref from registry and dataplane
|
|
49
|
+
* Build full image ref from registry and dataplane config (registry/name:tag)
|
|
51
50
|
* @param {string} registry - Registry URL
|
|
52
51
|
* @returns {string|undefined} Full image reference or undefined
|
|
53
52
|
*/
|
|
54
53
|
function buildDataplaneImageRef(registry) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
try {
|
|
55
|
+
const builderPath = pathsUtil.getBuilderPath('dataplane');
|
|
56
|
+
const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
|
|
57
|
+
const variables = loadConfigFile(configPath);
|
|
58
|
+
const name = variables?.image?.name || variables?.app?.key || 'dataplane';
|
|
59
|
+
const tag = variables?.image?.tag || 'latest';
|
|
60
|
+
const base = (registry || '').replace(/\/+$/, '');
|
|
61
|
+
return base ? `${base}/${name}:${tag}` : undefined;
|
|
62
|
+
} catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/**
|
package/lib/commands/up-miso.js
CHANGED
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
* @version 2.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const fs = require('fs');
|
|
14
|
-
const yaml = require('js-yaml');
|
|
15
12
|
const chalk = require('chalk');
|
|
13
|
+
const pathsUtil = require('../utils/paths');
|
|
14
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
16
15
|
const logger = require('../utils/logger');
|
|
17
16
|
const config = require('../core/config');
|
|
18
17
|
const secrets = require('../core/secrets');
|
|
@@ -21,7 +20,7 @@ const app = require('../app');
|
|
|
21
20
|
const { saveLocalSecret } = require('../utils/local-secrets');
|
|
22
21
|
const { ensureAppFromTemplate, patchEnvOutputPathForDeployOnly, validateEnvOutputPathFolderOrNull } = require('./up-common');
|
|
23
22
|
|
|
24
|
-
/** Keycloak base port (from templates/applications/keycloak
|
|
23
|
+
/** Keycloak base port (from templates/applications/keycloak application config) */
|
|
25
24
|
const KEYCLOAK_BASE_PORT = 8082;
|
|
26
25
|
/** Miso controller base port (dev-config app base) */
|
|
27
26
|
const MISO_BASE_PORT = 3000;
|
|
@@ -46,21 +45,23 @@ function parseImageOptions(imageOpts) {
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
/**
|
|
49
|
-
* Build full image ref from registry and app
|
|
48
|
+
* Build full image ref from registry and app config (registry/name:tag)
|
|
50
49
|
* @param {string} appName - keycloak or miso-controller
|
|
51
50
|
* @param {string} registry - Registry URL
|
|
52
51
|
* @returns {string} Full image reference
|
|
53
52
|
*/
|
|
54
53
|
function buildImageRefFromRegistry(appName, registry) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
try {
|
|
55
|
+
const builderPath = pathsUtil.getBuilderPath(appName);
|
|
56
|
+
const configPath = pathsUtil.resolveApplicationConfigPath(builderPath);
|
|
57
|
+
const variables = loadConfigFile(configPath);
|
|
58
|
+
const name = variables?.image?.name || variables?.app?.key || appName;
|
|
59
|
+
const tag = variables?.image?.tag || 'latest';
|
|
60
|
+
const base = (registry || '').replace(/\/+$/, '');
|
|
61
|
+
return base ? `${base}/${name}:${tag}` : undefined;
|
|
62
|
+
} catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/**
|