@sembix/cli 1.10.1 → 1.11.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/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +286 -88
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/update.js +143 -65
- package/dist/commands/update.js.map +1 -1
- package/dist/config-fields.d.ts.map +1 -1
- package/dist/config-fields.js +208 -29
- package/dist/config-fields.js.map +1 -1
- package/dist/config-schema.d.ts +76 -16
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config-schema.js +50 -15
- package/dist/config-schema.js.map +1 -1
- package/dist/prompts/azure-environment-setup.d.ts +8 -0
- package/dist/prompts/azure-environment-setup.d.ts.map +1 -0
- package/dist/prompts/azure-environment-setup.js +487 -0
- package/dist/prompts/azure-environment-setup.js.map +1 -0
- package/dist/prompts/environment-setup.d.ts.map +1 -1
- package/dist/prompts/environment-setup.js +17 -34
- package/dist/prompts/environment-setup.js.map +1 -1
- package/dist/sembix-cli-1.11.0.tgz +0 -0
- package/dist/types.d.ts +63 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +0 -8
- package/dist/utils/config-loader.js.map +1 -1
- package/package.json +1 -1
- package/dist/sembix-cli-1.10.1.tgz +0 -0
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import { input, select, confirm } from '@inquirer/prompts';
|
|
2
|
+
import { azureLocations, azureGuidSchema, azureStorageAccountSchema } from '../types.js';
|
|
3
|
+
import { promptIfMissing } from './prompt-helpers.js';
|
|
4
|
+
import * as ui from '../utils/ui.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
// ============================================================
|
|
7
|
+
// AZURE LOCATION SHORT CODE MAPPING
|
|
8
|
+
// ============================================================
|
|
9
|
+
const AZURE_LOCATION_SHORT_MAP = {
|
|
10
|
+
eastus: 'eus',
|
|
11
|
+
eastus2: 'eus2',
|
|
12
|
+
westus: 'wus',
|
|
13
|
+
westus2: 'wus2',
|
|
14
|
+
westus3: 'wus3',
|
|
15
|
+
centralus: 'cus',
|
|
16
|
+
northcentralus: 'ncus',
|
|
17
|
+
southcentralus: 'scus',
|
|
18
|
+
northeurope: 'neu',
|
|
19
|
+
westeurope: 'weu',
|
|
20
|
+
uksouth: 'uks',
|
|
21
|
+
ukwest: 'ukw',
|
|
22
|
+
australiaeast: 'aue',
|
|
23
|
+
southeastasia: 'sea',
|
|
24
|
+
japaneast: 'jpe',
|
|
25
|
+
canadacentral: 'cac',
|
|
26
|
+
};
|
|
27
|
+
export function azureLocationToShort(location) {
|
|
28
|
+
return AZURE_LOCATION_SHORT_MAP[location];
|
|
29
|
+
}
|
|
30
|
+
// ============================================================
|
|
31
|
+
// HELPERS
|
|
32
|
+
// ============================================================
|
|
33
|
+
function explainField(title, description, example) {
|
|
34
|
+
console.log();
|
|
35
|
+
console.log(chalk.cyan('❓ ' + chalk.bold(title)));
|
|
36
|
+
console.log(chalk.dim(' ' + description));
|
|
37
|
+
if (example) {
|
|
38
|
+
console.log(chalk.yellow(' Example: ') + chalk.white(example));
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
}
|
|
42
|
+
function getStepCount(mode) {
|
|
43
|
+
return mode === 'express' ? 6 : 9;
|
|
44
|
+
}
|
|
45
|
+
function hasAdvancedFields(partialConfig) {
|
|
46
|
+
if (!partialConfig)
|
|
47
|
+
return false;
|
|
48
|
+
const { security, networking } = partialConfig;
|
|
49
|
+
return !!(security?.useCustomSecurityGroups ||
|
|
50
|
+
security?.useCustomIamPolicies ||
|
|
51
|
+
security?.customSecurityGroups ||
|
|
52
|
+
security?.customIdentities ||
|
|
53
|
+
networking?.useCustomNetworking);
|
|
54
|
+
}
|
|
55
|
+
// ============================================================
|
|
56
|
+
// MODE SELECTION
|
|
57
|
+
// ============================================================
|
|
58
|
+
async function promptAzureModeSelection(partialConfig) {
|
|
59
|
+
if (hasAdvancedFields(partialConfig)) {
|
|
60
|
+
ui.info('Advanced mode auto-selected (config contains networking/security fields)');
|
|
61
|
+
return 'advanced';
|
|
62
|
+
}
|
|
63
|
+
console.log();
|
|
64
|
+
console.log(chalk.bold(' Choose setup mode:'));
|
|
65
|
+
console.log(chalk.dim(' Express mode uses sensible defaults for networking, security, and features.'));
|
|
66
|
+
console.log(chalk.dim(' Advanced mode gives full control over all configuration options.'));
|
|
67
|
+
console.log();
|
|
68
|
+
return select({
|
|
69
|
+
message: 'Setup mode:',
|
|
70
|
+
choices: [
|
|
71
|
+
{ name: 'Express (recommended)', value: 'express' },
|
|
72
|
+
{ name: 'Advanced', value: 'advanced' },
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// ============================================================
|
|
77
|
+
// STEP: AZURE BASIC CONFIGURATION
|
|
78
|
+
// ============================================================
|
|
79
|
+
async function promptAzureBasicConfig(ctx, stepNumber, owner, repo, providedEnvironmentName) {
|
|
80
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Azure Basic Configuration');
|
|
81
|
+
console.log(chalk.dim(' Configure your Azure deployment target.'));
|
|
82
|
+
console.log(chalk.dim(` Repository: ${chalk.white(`${owner}/${repo}`)}`));
|
|
83
|
+
console.log();
|
|
84
|
+
const environmentName = await promptIfMissing(providedEnvironmentName ?? ctx.partialConfig?.environmentName, async () => input({
|
|
85
|
+
message: 'Environment name (e.g., dev, staging, production):',
|
|
86
|
+
validate: (value) => {
|
|
87
|
+
if (!/^[a-z0-9-]+$/.test(value))
|
|
88
|
+
return 'Must be lowercase letters, numbers, and hyphens only';
|
|
89
|
+
if (value.length < 3)
|
|
90
|
+
return 'Must be at least 3 characters';
|
|
91
|
+
return true;
|
|
92
|
+
},
|
|
93
|
+
}), 'Environment Name');
|
|
94
|
+
const validateGuid = (value) => {
|
|
95
|
+
const result = azureGuidSchema.safeParse(value);
|
|
96
|
+
return result.success || result.error.issues[0].message;
|
|
97
|
+
};
|
|
98
|
+
explainField('Azure Subscription ID', 'Identifies the Azure subscription where infrastructure will be deployed.\nYou can find this in the Azure Portal under Subscriptions.', '12345678-1234-1234-1234-123456789abc');
|
|
99
|
+
const subscriptionId = await promptIfMissing(ctx.partialConfig?.azureSubscriptionId, async () => input({
|
|
100
|
+
message: 'Azure Subscription ID (GUID):',
|
|
101
|
+
validate: validateGuid,
|
|
102
|
+
}), 'Azure Subscription ID');
|
|
103
|
+
explainField('Azure Tenant ID', 'Identifies the Azure AD directory that manages users and applications.\nFound in Azure Portal under Azure Active Directory > Overview.', '87654321-4321-4321-4321-987654321fed');
|
|
104
|
+
const tenantId = await promptIfMissing(ctx.partialConfig?.azureTenantId, async () => input({
|
|
105
|
+
message: 'Azure Tenant ID (GUID):',
|
|
106
|
+
validate: validateGuid,
|
|
107
|
+
}), 'Azure Tenant ID');
|
|
108
|
+
explainField('GitHub Actions Client ID', 'The client ID of the service principal that GitHub Actions uses to deploy\ninto your subscription. This enables passwordless OIDC authentication\nfrom GitHub Actions to Azure.', '12345678-1234-1234-1234-123456789abc');
|
|
109
|
+
const clientId = await promptIfMissing(ctx.partialConfig?.azureClientId, async () => input({
|
|
110
|
+
message: 'GitHub Actions Client ID (GUID):',
|
|
111
|
+
validate: validateGuid,
|
|
112
|
+
}), 'Azure Client ID');
|
|
113
|
+
const location = await promptIfMissing(ctx.partialConfig?.azureLocation, async () => select({
|
|
114
|
+
message: 'Azure Location:',
|
|
115
|
+
choices: azureLocations.map(loc => ({ name: loc, value: loc })),
|
|
116
|
+
}), 'Azure Location');
|
|
117
|
+
const locationShort = ctx.partialConfig?.azureLocationShort ?? azureLocationToShort(location);
|
|
118
|
+
return { environmentName, clientId, tenantId, subscriptionId, location, locationShort };
|
|
119
|
+
}
|
|
120
|
+
// ============================================================
|
|
121
|
+
// STEP: TERRAFORM STATE
|
|
122
|
+
// ============================================================
|
|
123
|
+
async function promptAzureTerraformState(ctx, stepNumber) {
|
|
124
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Azure Terraform State Backend');
|
|
125
|
+
console.log(chalk.dim(' Configure the Azure Storage account for Terraform state.'));
|
|
126
|
+
console.log();
|
|
127
|
+
const storageAccountName = await promptIfMissing(ctx.partialConfig?.terraformState?.storageAccountName, async () => input({
|
|
128
|
+
message: 'Storage Account Name (3-24 lowercase alphanumeric):',
|
|
129
|
+
validate: (value) => {
|
|
130
|
+
const result = azureStorageAccountSchema.safeParse(value);
|
|
131
|
+
return result.success || result.error.issues[0].message;
|
|
132
|
+
},
|
|
133
|
+
}), 'TF Storage Account');
|
|
134
|
+
const containerName = await promptIfMissing(ctx.partialConfig?.terraformState?.containerName, async () => input({
|
|
135
|
+
message: 'Blob Container Name:',
|
|
136
|
+
default: 'tfstate',
|
|
137
|
+
}), 'TF Container Name');
|
|
138
|
+
const resourceGroupName = await promptIfMissing(ctx.partialConfig?.terraformState?.resourceGroupName, async () => input({
|
|
139
|
+
message: 'Resource Group Name:',
|
|
140
|
+
validate: (value) => value.length > 0 || 'Resource group name is required',
|
|
141
|
+
}), 'TF Resource Group');
|
|
142
|
+
return { storageAccountName, containerName, resourceGroupName };
|
|
143
|
+
}
|
|
144
|
+
// ============================================================
|
|
145
|
+
// STEP: DATABASE
|
|
146
|
+
// ============================================================
|
|
147
|
+
async function promptAzureDatabase(ctx, stepNumber) {
|
|
148
|
+
if (ctx.mode === 'express') {
|
|
149
|
+
ui.info('Using default Database: sembixstudio / sembixadmin');
|
|
150
|
+
console.log();
|
|
151
|
+
return {
|
|
152
|
+
name: ctx.partialConfig?.database?.name ?? 'sembixstudio',
|
|
153
|
+
user: ctx.partialConfig?.database?.user ?? 'sembixadmin',
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Database Configuration');
|
|
157
|
+
console.log(chalk.dim(' Configure the Azure PostgreSQL Flexible Server database.'));
|
|
158
|
+
console.log();
|
|
159
|
+
const dbValidate = (value) => {
|
|
160
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(value)) {
|
|
161
|
+
return 'Must start with a letter and contain only letters, numbers, and underscores';
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
};
|
|
165
|
+
const name = await promptIfMissing(ctx.partialConfig?.database?.name, async () => input({
|
|
166
|
+
message: 'Database name:',
|
|
167
|
+
default: 'sembixstudio',
|
|
168
|
+
validate: dbValidate,
|
|
169
|
+
}), 'Database Name');
|
|
170
|
+
const user = await promptIfMissing(ctx.partialConfig?.database?.user, async () => input({
|
|
171
|
+
message: 'Database admin username:',
|
|
172
|
+
default: 'sembixadmin',
|
|
173
|
+
validate: dbValidate,
|
|
174
|
+
}), 'Database User');
|
|
175
|
+
return { name, user };
|
|
176
|
+
}
|
|
177
|
+
// ============================================================
|
|
178
|
+
// STEP: NETWORKING (Advanced only)
|
|
179
|
+
// ============================================================
|
|
180
|
+
async function promptAzureNetworking(ctx, stepNumber) {
|
|
181
|
+
if (ctx.mode === 'express') {
|
|
182
|
+
ui.info('Using default Networking: new VNet (created by Terraform)');
|
|
183
|
+
console.log();
|
|
184
|
+
return { useCustomNetworking: false };
|
|
185
|
+
}
|
|
186
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Networking');
|
|
187
|
+
console.log(chalk.dim(' Configure custom VNet or let Terraform create one.'));
|
|
188
|
+
console.log();
|
|
189
|
+
const useCustomNetworking = ctx.partialConfig?.networking?.useCustomNetworking ??
|
|
190
|
+
await confirm({
|
|
191
|
+
message: 'Use an existing VNet?',
|
|
192
|
+
default: false,
|
|
193
|
+
});
|
|
194
|
+
if (!useCustomNetworking) {
|
|
195
|
+
return { useCustomNetworking: false };
|
|
196
|
+
}
|
|
197
|
+
const validateAzureResourceId = (prefix) => (value) => {
|
|
198
|
+
if (!value.startsWith('/subscriptions/')) {
|
|
199
|
+
return `Must be a full Azure resource ID (starts with /subscriptions/)`;
|
|
200
|
+
}
|
|
201
|
+
if (!value.includes(prefix)) {
|
|
202
|
+
return `Must be a ${prefix} resource ID`;
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
};
|
|
206
|
+
const validateSubnetIds = (value) => {
|
|
207
|
+
const ids = value.split(',').map(s => s.trim());
|
|
208
|
+
for (const id of ids) {
|
|
209
|
+
if (!id.startsWith('/subscriptions/') || !id.includes('/subnets/')) {
|
|
210
|
+
return 'Each subnet must be a full Azure resource ID (e.g., /subscriptions/.../subnets/my-subnet)';
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
};
|
|
215
|
+
explainField('VNet Resource ID', 'The full Azure resource ID of the existing Virtual Network.', '/subscriptions/12345678-.../resourceGroups/rg-network/providers/Microsoft.Network/virtualNetworks/my-vnet');
|
|
216
|
+
const customVpcId = await promptIfMissing(ctx.partialConfig?.networking?.customVpcId, async () => input({
|
|
217
|
+
message: 'VNet Resource ID:',
|
|
218
|
+
validate: validateAzureResourceId('/virtualNetworks/'),
|
|
219
|
+
}), 'Custom VNet ID');
|
|
220
|
+
const customPublicSubnetIds = await promptIfMissing(ctx.partialConfig?.networking?.customPublicSubnetIds, async () => input({
|
|
221
|
+
message: 'Public Subnet IDs (comma-separated resource IDs):',
|
|
222
|
+
validate: validateSubnetIds,
|
|
223
|
+
}), 'Custom Public Subnet IDs');
|
|
224
|
+
const customPrivateSubnetIds = await promptIfMissing(ctx.partialConfig?.networking?.customPrivateSubnetIds, async () => input({
|
|
225
|
+
message: 'Private Subnet IDs (comma-separated resource IDs):',
|
|
226
|
+
validate: validateSubnetIds,
|
|
227
|
+
}), 'Custom Private Subnet IDs');
|
|
228
|
+
return { useCustomNetworking, customVpcId, customPublicSubnetIds, customPrivateSubnetIds };
|
|
229
|
+
}
|
|
230
|
+
// ============================================================
|
|
231
|
+
// STEP: SECURITY GROUPS / NSGs (Advanced only)
|
|
232
|
+
// ============================================================
|
|
233
|
+
async function promptAzureSecurityGroups(ctx, stepNumber) {
|
|
234
|
+
if (ctx.mode === 'express') {
|
|
235
|
+
ui.info('Using default Security: NSGs created by Terraform');
|
|
236
|
+
console.log();
|
|
237
|
+
return { useCustomSecurityGroups: false };
|
|
238
|
+
}
|
|
239
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Network Security Groups');
|
|
240
|
+
console.log(chalk.dim(' Use custom NSGs or let Terraform create them.'));
|
|
241
|
+
console.log();
|
|
242
|
+
const useCustomSecurityGroups = ctx.partialConfig?.security?.useCustomSecurityGroups ??
|
|
243
|
+
await confirm({
|
|
244
|
+
message: 'Use custom Network Security Groups?',
|
|
245
|
+
default: false,
|
|
246
|
+
});
|
|
247
|
+
if (!useCustomSecurityGroups) {
|
|
248
|
+
return { useCustomSecurityGroups: false };
|
|
249
|
+
}
|
|
250
|
+
console.log();
|
|
251
|
+
console.log(chalk.yellow(' Custom NSG IDs'));
|
|
252
|
+
console.log(chalk.dim(' Provide the full Azure resource ID for each Network Security Group.'));
|
|
253
|
+
console.log(chalk.dim(' Example: /subscriptions/.../resourceGroups/rg-network/providers/Microsoft.Network/networkSecurityGroups/nsg-bff'));
|
|
254
|
+
console.log();
|
|
255
|
+
const validateNsgId = (value) => {
|
|
256
|
+
if (!value.startsWith('/subscriptions/') || !value.includes('/networkSecurityGroups/')) {
|
|
257
|
+
return 'Must be a full NSG resource ID (starts with /subscriptions/, contains /networkSecurityGroups/)';
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
};
|
|
261
|
+
const customSecurityGroups = {
|
|
262
|
+
workflowEngine: await input({
|
|
263
|
+
message: 'Workflow Engine NSG ID:',
|
|
264
|
+
validate: validateNsgId,
|
|
265
|
+
}),
|
|
266
|
+
aurora: await input({
|
|
267
|
+
message: 'Database NSG ID:',
|
|
268
|
+
validate: validateNsgId,
|
|
269
|
+
}),
|
|
270
|
+
bffEcs: await input({
|
|
271
|
+
message: 'BFF NSG ID:',
|
|
272
|
+
validate: validateNsgId,
|
|
273
|
+
}),
|
|
274
|
+
semanticEventEngine: await input({
|
|
275
|
+
message: 'Semantic Event Engine NSG ID:',
|
|
276
|
+
validate: validateNsgId,
|
|
277
|
+
}),
|
|
278
|
+
};
|
|
279
|
+
return { useCustomSecurityGroups, customSecurityGroups };
|
|
280
|
+
}
|
|
281
|
+
// ============================================================
|
|
282
|
+
// STEP: CUSTOM IDENTITIES (Advanced only)
|
|
283
|
+
// ============================================================
|
|
284
|
+
async function promptAzureIdentities(ctx, stepNumber) {
|
|
285
|
+
if (ctx.mode === 'express') {
|
|
286
|
+
ui.info('Using default Identities: managed identities from bootstrap');
|
|
287
|
+
console.log();
|
|
288
|
+
return { useCustomIamPolicies: false };
|
|
289
|
+
}
|
|
290
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Managed Identities');
|
|
291
|
+
console.log(chalk.dim(' Use custom managed identities or reference bootstrap-created ones.'));
|
|
292
|
+
console.log();
|
|
293
|
+
const useCustomIamPolicies = ctx.partialConfig?.security?.useCustomIamPolicies ??
|
|
294
|
+
await confirm({
|
|
295
|
+
message: 'Use custom managed identities (instead of bootstrap)?',
|
|
296
|
+
default: false,
|
|
297
|
+
});
|
|
298
|
+
if (!useCustomIamPolicies) {
|
|
299
|
+
return { useCustomIamPolicies: false };
|
|
300
|
+
}
|
|
301
|
+
console.log();
|
|
302
|
+
console.log(chalk.yellow(' Custom Managed Identity Details'));
|
|
303
|
+
console.log(chalk.dim(' For each service, provide three values:'));
|
|
304
|
+
console.log(chalk.dim(' Identity Resource ID — full Azure resource path'));
|
|
305
|
+
console.log(chalk.dim(' Principal ID — GUID (object ID of the identity)'));
|
|
306
|
+
console.log(chalk.dim(' Client ID — GUID (application/client ID of the identity)'));
|
|
307
|
+
console.log();
|
|
308
|
+
console.log(chalk.yellow(' Example Identity Resource ID:'));
|
|
309
|
+
console.log(chalk.dim(' /subscriptions/12345678-.../resourceGroups/rg-bootstrap/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-bff-dev'));
|
|
310
|
+
console.log();
|
|
311
|
+
const services = [
|
|
312
|
+
{ key: 'workflowEngine', label: 'Workflow Engine' },
|
|
313
|
+
{ key: 'bff', label: 'BFF' },
|
|
314
|
+
{ key: 'semanticEventEngine', label: 'Semantic Event Engine' },
|
|
315
|
+
{ key: 'workspaceRuntime', label: 'Workspace Runtime' },
|
|
316
|
+
{ key: 'migrations', label: 'Migrations' },
|
|
317
|
+
];
|
|
318
|
+
const customIdentities = {};
|
|
319
|
+
for (const { key, label } of services) {
|
|
320
|
+
console.log(chalk.cyan(` ${label}:`));
|
|
321
|
+
const existing = ctx.partialConfig?.security?.customIdentities?.[key];
|
|
322
|
+
const identityId = await promptIfMissing(existing?.identityId, async () => input({
|
|
323
|
+
message: ` ${label} Identity Resource ID:`,
|
|
324
|
+
validate: (v) => v.startsWith('/subscriptions/') || 'Must be a full Azure resource ID (starts with /subscriptions/)',
|
|
325
|
+
}), `${label} Identity ID`);
|
|
326
|
+
const principalId = await promptIfMissing(existing?.principalId, async () => input({
|
|
327
|
+
message: ` ${label} Principal ID (GUID):`,
|
|
328
|
+
validate: (v) => {
|
|
329
|
+
const result = azureGuidSchema.safeParse(v);
|
|
330
|
+
return result.success || result.error.issues[0].message;
|
|
331
|
+
},
|
|
332
|
+
}), `${label} Principal ID`);
|
|
333
|
+
const clientId = await promptIfMissing(existing?.clientId, async () => input({
|
|
334
|
+
message: ` ${label} Client ID (GUID):`,
|
|
335
|
+
validate: (v) => {
|
|
336
|
+
const result = azureGuidSchema.safeParse(v);
|
|
337
|
+
return result.success || result.error.issues[0].message;
|
|
338
|
+
},
|
|
339
|
+
}), `${label} Client ID`);
|
|
340
|
+
customIdentities[key] = { identityId, principalId, clientId };
|
|
341
|
+
console.log();
|
|
342
|
+
}
|
|
343
|
+
return { useCustomIamPolicies, customIdentities };
|
|
344
|
+
}
|
|
345
|
+
// ============================================================
|
|
346
|
+
// STEP: CDN (FRONT DOOR)
|
|
347
|
+
// ============================================================
|
|
348
|
+
async function promptAzureCdn(ctx, stepNumber) {
|
|
349
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Azure Front Door / CDN');
|
|
350
|
+
console.log(chalk.dim(' Configure Azure Front Door for the React frontend.'));
|
|
351
|
+
console.log(chalk.dim(' A custom domain is optional — Front Door provides a default endpoint.'));
|
|
352
|
+
console.log();
|
|
353
|
+
const frontDoorCustomDomain = await promptIfMissing(ctx.partialConfig?.cdn?.frontDoorCustomDomain, async () => input({
|
|
354
|
+
message: 'Front Door Custom Domain (press Enter to skip):',
|
|
355
|
+
default: '',
|
|
356
|
+
}), 'Front Door Domain');
|
|
357
|
+
let frontDoorCustomDomainDnsZoneId = '';
|
|
358
|
+
if (frontDoorCustomDomain) {
|
|
359
|
+
frontDoorCustomDomainDnsZoneId = await promptIfMissing(ctx.partialConfig?.cdn?.frontDoorCustomDomainDnsZoneId, async () => input({
|
|
360
|
+
message: 'DNS Zone ID for custom domain:',
|
|
361
|
+
validate: (value) => value.length > 0 || 'DNS Zone ID is required for custom domains',
|
|
362
|
+
}), 'Front Door DNS Zone ID');
|
|
363
|
+
}
|
|
364
|
+
return { frontDoorCustomDomain, frontDoorCustomDomainDnsZoneId };
|
|
365
|
+
}
|
|
366
|
+
// ============================================================
|
|
367
|
+
// STEP: AZURE FEATURES
|
|
368
|
+
// ============================================================
|
|
369
|
+
async function promptAzureFeatures(ctx, stepNumber) {
|
|
370
|
+
if (ctx.mode === 'express') {
|
|
371
|
+
ui.info('Using default Features: Application Insights enabled, private endpoints disabled');
|
|
372
|
+
console.log();
|
|
373
|
+
return { enableApplicationInsights: true, enablePrivateEndpoints: false };
|
|
374
|
+
}
|
|
375
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Azure Feature Configuration');
|
|
376
|
+
console.log(chalk.dim(' Enable or disable Azure-specific features.'));
|
|
377
|
+
console.log();
|
|
378
|
+
const enableApplicationInsights = ctx.partialConfig?.features?.enableApplicationInsights ??
|
|
379
|
+
await confirm({
|
|
380
|
+
message: 'Enable Application Insights for monitoring?',
|
|
381
|
+
default: true,
|
|
382
|
+
});
|
|
383
|
+
const enablePrivateEndpoints = ctx.partialConfig?.features?.enablePrivateEndpoints ??
|
|
384
|
+
await confirm({
|
|
385
|
+
message: 'Enable private endpoints for PaaS services?',
|
|
386
|
+
default: false,
|
|
387
|
+
});
|
|
388
|
+
return { enableApplicationInsights, enablePrivateEndpoints };
|
|
389
|
+
}
|
|
390
|
+
// ============================================================
|
|
391
|
+
// STEP: FRONTEND (shared with AWS)
|
|
392
|
+
// ============================================================
|
|
393
|
+
async function promptAzureFrontend(ctx, stepNumber) {
|
|
394
|
+
ui.stepHeader(stepNumber, getStepCount(ctx.mode), 'Frontend Configuration');
|
|
395
|
+
console.log(chalk.dim(' Configure GitHub App and Jira OAuth credentials.'));
|
|
396
|
+
console.log();
|
|
397
|
+
const githubAppClientId = await promptIfMissing(ctx.partialConfig?.frontend?.githubAppClientId, async () => input({
|
|
398
|
+
message: 'GitHub App OAuth Client ID:',
|
|
399
|
+
validate: (value) => value.length > 0 || 'Required',
|
|
400
|
+
}), 'GitHub App Client ID');
|
|
401
|
+
const githubAppName = await promptIfMissing(ctx.partialConfig?.frontend?.githubAppName, async () => input({
|
|
402
|
+
message: 'GitHub App Name:',
|
|
403
|
+
validate: (value) => value.length > 0 || 'Required',
|
|
404
|
+
}), 'GitHub App Name');
|
|
405
|
+
const jiraClientId = await promptIfMissing(ctx.partialConfig?.frontend?.jiraClientId, async () => input({
|
|
406
|
+
message: 'Jira OAuth Client ID:',
|
|
407
|
+
validate: (value) => value.length > 0 || 'Required',
|
|
408
|
+
}), 'Jira Client ID');
|
|
409
|
+
return { githubAppClientId, githubAppName, jiraClientId };
|
|
410
|
+
}
|
|
411
|
+
// ============================================================
|
|
412
|
+
// ORCHESTRATOR
|
|
413
|
+
// ============================================================
|
|
414
|
+
export async function promptAzureEnvironmentSetup(githubClient, repository, providedEnvironmentName, partialConfig, isUpdate = false) {
|
|
415
|
+
const mode = await promptAzureModeSelection(partialConfig);
|
|
416
|
+
const ctx = { mode, githubClient, partialConfig, isUpdate };
|
|
417
|
+
// Step 1: Basic Azure config
|
|
418
|
+
const basic = await promptAzureBasicConfig(ctx, 1, repository.owner, repository.repo, providedEnvironmentName);
|
|
419
|
+
// Checkpoint: Azure basics
|
|
420
|
+
ui.checkpoint('Azure Basics', {
|
|
421
|
+
'Environment': basic.environmentName,
|
|
422
|
+
'Subscription': basic.subscriptionId,
|
|
423
|
+
'Location': basic.location,
|
|
424
|
+
});
|
|
425
|
+
// Step 2: Terraform State
|
|
426
|
+
const terraformState = await promptAzureTerraformState(ctx, 2);
|
|
427
|
+
// Step 3: Database
|
|
428
|
+
const database = await promptAzureDatabase(ctx, 3);
|
|
429
|
+
// Steps 4-6 (advanced) or auto-defaults (express)
|
|
430
|
+
let networking;
|
|
431
|
+
let securityGroups;
|
|
432
|
+
let identities;
|
|
433
|
+
if (mode === 'advanced') {
|
|
434
|
+
networking = await promptAzureNetworking(ctx, 4);
|
|
435
|
+
securityGroups = await promptAzureSecurityGroups(ctx, 5);
|
|
436
|
+
identities = await promptAzureIdentities(ctx, 6);
|
|
437
|
+
// Checkpoint: Infrastructure
|
|
438
|
+
ui.checkpoint('Infrastructure', {
|
|
439
|
+
'Networking': networking.useCustomNetworking ? 'Custom VNet' : 'New VNet (default)',
|
|
440
|
+
'NSGs': securityGroups.useCustomSecurityGroups ? 'Custom' : 'Default',
|
|
441
|
+
'Identities': identities.useCustomIamPolicies ? 'Custom' : 'Bootstrap',
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
networking = { useCustomNetworking: false };
|
|
446
|
+
securityGroups = { useCustomSecurityGroups: false };
|
|
447
|
+
identities = { useCustomIamPolicies: false };
|
|
448
|
+
}
|
|
449
|
+
// CDN step
|
|
450
|
+
const cdnStep = mode === 'advanced' ? 7 : 4;
|
|
451
|
+
const cdn = await promptAzureCdn(ctx, cdnStep);
|
|
452
|
+
// Features step
|
|
453
|
+
const featuresStep = mode === 'advanced' ? 8 : 5;
|
|
454
|
+
const features = await promptAzureFeatures(ctx, featuresStep);
|
|
455
|
+
// Frontend step
|
|
456
|
+
const frontendStep = mode === 'advanced' ? 9 : 6;
|
|
457
|
+
const frontend = await promptAzureFrontend(ctx, frontendStep);
|
|
458
|
+
return {
|
|
459
|
+
cloudProvider: 'azure',
|
|
460
|
+
repository,
|
|
461
|
+
environmentName: basic.environmentName,
|
|
462
|
+
database,
|
|
463
|
+
frontend,
|
|
464
|
+
azureClientId: basic.clientId,
|
|
465
|
+
azureTenantId: basic.tenantId,
|
|
466
|
+
azureSubscriptionId: basic.subscriptionId,
|
|
467
|
+
azureLocation: basic.location,
|
|
468
|
+
azureLocationShort: basic.locationShort,
|
|
469
|
+
terraformState,
|
|
470
|
+
cdn,
|
|
471
|
+
features,
|
|
472
|
+
networking: {
|
|
473
|
+
enableVpcEndpoints: false,
|
|
474
|
+
useCustomNetworking: networking.useCustomNetworking,
|
|
475
|
+
customVpcId: networking.customVpcId,
|
|
476
|
+
customPublicSubnetIds: networking.customPublicSubnetIds,
|
|
477
|
+
customPrivateSubnetIds: networking.customPrivateSubnetIds,
|
|
478
|
+
},
|
|
479
|
+
security: {
|
|
480
|
+
useCustomSecurityGroups: securityGroups.useCustomSecurityGroups,
|
|
481
|
+
customSecurityGroups: securityGroups.customSecurityGroups,
|
|
482
|
+
useCustomIamPolicies: identities.useCustomIamPolicies,
|
|
483
|
+
customIdentities: identities.customIdentities,
|
|
484
|
+
},
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
//# sourceMappingURL=azure-environment-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-environment-setup.js","sourceRoot":"","sources":["../../src/prompts/azure-environment-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment-setup.d.ts","sourceRoot":"","sources":["../../src/prompts/environment-setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"environment-setup.d.ts","sourceRoot":"","sources":["../../src/prompts/environment-setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAwC,MAAM,aAAa,CAAC;AAGhG,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA0qClD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,YAAY,EAC1B,uBAAuB,CAAC,EAAE,MAAM,EAChC,YAAY,CAAC,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,EAC/C,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,sBAAsB,CAAC,CA4HjC"}
|
|
@@ -3,6 +3,7 @@ import { awsRegions, awsAccountIdSchema, iamRoleArnSchema, acmCertArnSchema, rou
|
|
|
3
3
|
import * as ui from '../utils/ui.js';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { promptIfMissing } from './prompt-helpers.js';
|
|
6
|
+
import { promptAzureEnvironmentSetup } from './azure-environment-setup.js';
|
|
6
7
|
// ============================================================
|
|
7
8
|
// HELPERS
|
|
8
9
|
// ============================================================
|
|
@@ -26,7 +27,6 @@ function hasAdvancedFields(partialConfig) {
|
|
|
26
27
|
security?.workflowRunsKeyAlias ||
|
|
27
28
|
tls?.certificateArn ||
|
|
28
29
|
tls?.bffAlbInternal ||
|
|
29
|
-
tls?.bffInternalAlbCertificateArn ||
|
|
30
30
|
tls?.privateCaCertSecretArn ||
|
|
31
31
|
networking?.useCustomNetworking);
|
|
32
32
|
}
|
|
@@ -513,10 +513,6 @@ async function promptSecurity(ctx, stepNumber) {
|
|
|
513
513
|
message: 'Semantic Event Engine Security Group ID:',
|
|
514
514
|
validate: (v) => !v || /^sg-[a-f0-9]+$/.test(v) || 'Must be valid SG ID (sg-xxxxx)'
|
|
515
515
|
}),
|
|
516
|
-
workspaceRuntime: await input({
|
|
517
|
-
message: 'Workspace Runtime Security Group ID:',
|
|
518
|
-
validate: (v) => !v || /^sg-[a-f0-9]+$/.test(v) || 'Must be valid SG ID (sg-xxxxx)'
|
|
519
|
-
}),
|
|
520
516
|
workspaceRuntimeEfs: await input({
|
|
521
517
|
message: 'Workspace Runtime EFS Security Group ID:',
|
|
522
518
|
validate: (v) => !v || /^sg-[a-f0-9]+$/.test(v) || 'Must be valid SG ID (sg-xxxxx)'
|
|
@@ -575,14 +571,6 @@ async function promptSecurity(ctx, stepNumber) {
|
|
|
575
571
|
message: 'Sembix Studio Notification Role ARN:',
|
|
576
572
|
validate: validateRoleArn
|
|
577
573
|
}),
|
|
578
|
-
workspaceRuntimeExecutionRole: await input({
|
|
579
|
-
message: 'Workspace Runtime Execution Role ARN:',
|
|
580
|
-
validate: validateRoleArn
|
|
581
|
-
}),
|
|
582
|
-
workspaceRuntimeTaskRole: await input({
|
|
583
|
-
message: 'Workspace Runtime Task Role ARN:',
|
|
584
|
-
validate: validateRoleArn
|
|
585
|
-
}),
|
|
586
574
|
};
|
|
587
575
|
}
|
|
588
576
|
return {
|
|
@@ -766,27 +754,9 @@ async function promptTls(ctx, stepNumber, awsRegion) {
|
|
|
766
754
|
}
|
|
767
755
|
}
|
|
768
756
|
}
|
|
769
|
-
// ─── Private
|
|
770
|
-
let bffInternalAlbCertificateArn;
|
|
757
|
+
// ─── Private CA Certificate ─── (Advanced only)
|
|
771
758
|
let privateCaCertSecretArn;
|
|
772
759
|
if (mode === 'advanced') {
|
|
773
|
-
ui.subsectionHeader('Private Services ALB');
|
|
774
|
-
bffInternalAlbCertificateArn = await promptIfMissing(partialConfig?.tls?.bffInternalAlbCertificateArn, async () => {
|
|
775
|
-
explainField('Private Services ALB Certificate (Optional)', 'The ACM certificate ARN for the private services load balancer.\nThis ALB handles internal service-to-service traffic (e.g. workspace runtime, websockets).\nOverrides the primary certificate for this ALB.\n\n' +
|
|
776
|
-
chalk.green(' Tip: ') + 'Leave blank to use the primary certificate.', 'arn:aws:acm:' + awsRegion + ':123456789012:certificate/ghi789... (or leave blank)');
|
|
777
|
-
return input({
|
|
778
|
-
message: 'Private Services ALB Certificate ARN (press Enter to skip):',
|
|
779
|
-
default: '',
|
|
780
|
-
validate: (value) => {
|
|
781
|
-
if (!value)
|
|
782
|
-
return true;
|
|
783
|
-
const result = acmCertArnSchema.safeParse(value);
|
|
784
|
-
if (!result.success)
|
|
785
|
-
return 'Must be a valid ACM certificate ARN';
|
|
786
|
-
return true;
|
|
787
|
-
},
|
|
788
|
-
});
|
|
789
|
-
}, 'Private Services ALB Certificate ARN') || undefined;
|
|
790
760
|
privateCaCertSecretArn = await promptIfMissing(partialConfig?.tls?.privateCaCertSecretArn, async () => {
|
|
791
761
|
explainField('Private CA Certificate Secret (Optional)', 'If either load balancer uses an ACM Private CA certificate, services need the CA\nroot certificate to trust it. Provide the Secrets Manager ARN that holds the PEM file.', 'arn:aws:secretsmanager:' + awsRegion + ':123456789012:secret:my-private-ca-pem-AbCdEf');
|
|
792
762
|
return input({
|
|
@@ -805,7 +775,6 @@ async function promptTls(ctx, stepNumber, awsRegion) {
|
|
|
805
775
|
}
|
|
806
776
|
else {
|
|
807
777
|
// Express: use config values if present
|
|
808
|
-
bffInternalAlbCertificateArn = partialConfig?.tls?.bffInternalAlbCertificateArn;
|
|
809
778
|
privateCaCertSecretArn = partialConfig?.tls?.privateCaCertSecretArn;
|
|
810
779
|
}
|
|
811
780
|
// ─── DNS ───
|
|
@@ -833,7 +802,6 @@ async function promptTls(ctx, stepNumber, awsRegion) {
|
|
|
833
802
|
bffAlbCertificateArn: bffAlbCertificateArn || undefined,
|
|
834
803
|
bffAlbInternal: bffAlbInternal || undefined,
|
|
835
804
|
bffAlbIngressCidrBlocks: bffAlbIngressCidrBlocks?.length ? bffAlbIngressCidrBlocks : undefined,
|
|
836
|
-
bffInternalAlbCertificateArn: bffInternalAlbCertificateArn || undefined,
|
|
837
805
|
privateCaCertSecretArn: privateCaCertSecretArn || undefined,
|
|
838
806
|
hostedZoneId: hostedZoneId || undefined,
|
|
839
807
|
};
|
|
@@ -920,6 +888,20 @@ export async function promptEnvironmentSetup(githubClient, providedEnvironmentNa
|
|
|
920
888
|
};
|
|
921
889
|
// Step 1: Repository Selection (always step 1)
|
|
922
890
|
const repository = await promptRepository(preliminaryCtx, 1, providedRepo);
|
|
891
|
+
// Cloud Provider Selection
|
|
892
|
+
const cloudProvider = partialConfig?.cloudProvider ??
|
|
893
|
+
await select({
|
|
894
|
+
message: 'Select cloud provider:',
|
|
895
|
+
choices: [
|
|
896
|
+
{ name: 'AWS', value: 'aws' },
|
|
897
|
+
{ name: 'Azure', value: 'azure' },
|
|
898
|
+
],
|
|
899
|
+
});
|
|
900
|
+
// Azure path — delegate to Azure wizard
|
|
901
|
+
if (cloudProvider === 'azure') {
|
|
902
|
+
return promptAzureEnvironmentSetup(githubClient, { owner: repository.owner, repo: repository.repo }, providedEnvironmentName, partialConfig, isUpdate);
|
|
903
|
+
}
|
|
904
|
+
// AWS path continues below
|
|
923
905
|
// Mode Selection (between repo and basic config)
|
|
924
906
|
const mode = await promptModeSelection(partialConfig);
|
|
925
907
|
const ctx = { mode, githubClient, partialConfig, isUpdate };
|
|
@@ -980,6 +962,7 @@ export async function promptEnvironmentSetup(githubClient, providedEnvironmentNa
|
|
|
980
962
|
const frontendStepNumber = mode === 'advanced' ? 8 : 4;
|
|
981
963
|
const frontend = await promptFrontend(ctx, frontendStepNumber);
|
|
982
964
|
return {
|
|
965
|
+
cloudProvider: 'aws',
|
|
983
966
|
repository: { owner: repository.owner, repo: repository.repo },
|
|
984
967
|
environmentName: basicConfig.environmentName,
|
|
985
968
|
awsAccountId: basicConfig.awsAccountId,
|