create-aws-project 1.5.1 → 1.7.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/__tests__/aws/cdk-bootstrap.spec.d.ts +1 -0
- package/dist/__tests__/aws/cdk-bootstrap.spec.js +266 -0
- package/dist/__tests__/aws/root-credentials.spec.d.ts +1 -0
- package/dist/__tests__/aws/root-credentials.spec.js +230 -0
- package/dist/__tests__/config/non-interactive-aws.spec.d.ts +1 -0
- package/dist/__tests__/config/non-interactive-aws.spec.js +100 -0
- package/dist/__tests__/config/non-interactive.spec.d.ts +1 -0
- package/dist/__tests__/config/non-interactive.spec.js +152 -0
- package/dist/aws/cdk-bootstrap.d.ts +77 -0
- package/dist/aws/cdk-bootstrap.js +139 -0
- package/dist/aws/iam.js +17 -0
- package/dist/aws/organizations.d.ts +7 -1
- package/dist/aws/organizations.js +19 -1
- package/dist/aws/root-credentials.d.ts +68 -0
- package/dist/aws/root-credentials.js +157 -0
- package/dist/cli.js +58 -23
- package/dist/commands/initialize-github.js +162 -83
- package/dist/commands/setup-aws-envs.d.ts +2 -2
- package/dist/commands/setup-aws-envs.js +590 -52
- package/dist/config/non-interactive-aws.d.ts +27 -0
- package/dist/config/non-interactive-aws.js +80 -0
- package/dist/config/non-interactive.d.ts +48 -0
- package/dist/config/non-interactive.js +92 -0
- package/dist/git/setup.d.ts +3 -3
- package/dist/git/setup.js +28 -24
- package/dist/utils/project-context.d.ts +14 -0
- package/package.json +4 -3
- package/templates/apps/web/src/App.tsx +4 -2
- package/templates/apps/web/src/__tests__/App.spec.tsx +27 -9
- package/templates/apps/web/vite.config.ts +3 -0
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import { showDeprecationNotice } from './commands/setup-github.js';
|
|
|
8
8
|
import { runSetupAwsEnvs } from './commands/setup-aws-envs.js';
|
|
9
9
|
import { runInitializeGitHub } from './commands/initialize-github.js';
|
|
10
10
|
import { promptGitSetup, setupGitRepository } from './git/setup.js';
|
|
11
|
+
import { loadNonInteractiveConfig } from './config/non-interactive.js';
|
|
11
12
|
/**
|
|
12
13
|
* Write project configuration file for downstream commands
|
|
13
14
|
*/
|
|
@@ -48,22 +49,29 @@ Scaffold a new AWS Starter Kit project with React, Lambda, and CDK infrastructur
|
|
|
48
49
|
Commands:
|
|
49
50
|
(default) Create a new project (interactive wizard)
|
|
50
51
|
setup-aws-envs Set up AWS Organizations and environment accounts
|
|
51
|
-
initialize-github Configure GitHub Environment for deployment
|
|
52
|
+
initialize-github Configure GitHub Environment for deployment (supports batch mode)
|
|
52
53
|
setup-github ${pc.dim('[DEPRECATED]')} Use initialize-github instead
|
|
53
54
|
|
|
54
55
|
Options:
|
|
55
56
|
--help, -h Show this help message
|
|
56
57
|
--version, -v Show version number
|
|
58
|
+
--config <path> Create project from JSON config file (non-interactive)
|
|
57
59
|
|
|
58
60
|
Usage:
|
|
59
|
-
create-aws-project
|
|
60
|
-
create-aws-project
|
|
61
|
-
create-aws-project
|
|
61
|
+
create-aws-project Run interactive wizard
|
|
62
|
+
create-aws-project --config project.json Non-interactive mode
|
|
63
|
+
create-aws-project setup-aws-envs Create AWS accounts
|
|
64
|
+
create-aws-project initialize-github dev Configure dev environment
|
|
65
|
+
create-aws-project initialize-github --all Configure all environments
|
|
66
|
+
create-aws-project initialize-github dev stage Configure specific environments
|
|
62
67
|
|
|
63
68
|
Examples:
|
|
64
69
|
create-aws-project my-app
|
|
70
|
+
create-aws-project --config project.json
|
|
65
71
|
create-aws-project setup-aws-envs
|
|
66
72
|
create-aws-project initialize-github dev
|
|
73
|
+
create-aws-project initialize-github --all
|
|
74
|
+
create-aws-project initialize-github dev stage prod
|
|
67
75
|
create-aws-project --help
|
|
68
76
|
`.trim());
|
|
69
77
|
}
|
|
@@ -83,33 +91,47 @@ function printWelcome() {
|
|
|
83
91
|
/**
|
|
84
92
|
* Print post-generation instructions
|
|
85
93
|
*/
|
|
86
|
-
function printNextSteps(projectName
|
|
94
|
+
function printNextSteps(projectName) {
|
|
87
95
|
console.log('');
|
|
88
96
|
console.log(pc.bold('Next steps:'));
|
|
89
97
|
console.log('');
|
|
90
98
|
console.log(` ${pc.cyan('cd')} ${projectName}`);
|
|
91
|
-
console.log(` ${pc.cyan('npm install')}`);
|
|
92
99
|
console.log('');
|
|
93
|
-
|
|
94
|
-
console.log(` ${pc.gray('# Start web app')}`);
|
|
95
|
-
console.log(` ${pc.cyan('npm run web')}`);
|
|
96
|
-
console.log('');
|
|
97
|
-
}
|
|
98
|
-
if (platforms.includes('mobile')) {
|
|
99
|
-
console.log(` ${pc.gray('# Start mobile app')}`);
|
|
100
|
-
console.log(` ${pc.cyan('npm run mobile')}`);
|
|
101
|
-
console.log('');
|
|
102
|
-
}
|
|
103
|
-
if (platforms.includes('api')) {
|
|
104
|
-
console.log(` ${pc.gray('# Deploy API')}`);
|
|
105
|
-
console.log(` ${pc.cyan('npm run cdk:deploy')}`);
|
|
106
|
-
console.log('');
|
|
107
|
-
}
|
|
108
|
-
console.log(` ${pc.gray('# Configure AWS environments')}`);
|
|
100
|
+
console.log(` ${pc.gray('# Set up AWS accounts and credentials')}`);
|
|
109
101
|
console.log(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
110
102
|
console.log('');
|
|
103
|
+
console.log(` ${pc.gray('# Push credentials to GitHub secrets')}`);
|
|
104
|
+
console.log(` ${pc.cyan('npx create-aws-project initialize-github')}`);
|
|
105
|
+
console.log('');
|
|
111
106
|
console.log(pc.gray('Happy coding!'));
|
|
112
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Run project creation in non-interactive mode from a JSON config file.
|
|
110
|
+
* Skips all prompts and git setup (NI-02, NI-06).
|
|
111
|
+
*/
|
|
112
|
+
async function runNonInteractive(configPath) {
|
|
113
|
+
const config = loadNonInteractiveConfig(configPath);
|
|
114
|
+
const outputDir = resolve(process.cwd(), config.projectName);
|
|
115
|
+
// Check if directory already exists
|
|
116
|
+
if (existsSync(outputDir)) {
|
|
117
|
+
console.error(pc.red('Error:') + ` Directory ${pc.cyan(config.projectName)} already exists.`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
// Create project directory
|
|
121
|
+
mkdirSync(outputDir, { recursive: true });
|
|
122
|
+
// Generate project
|
|
123
|
+
console.log('');
|
|
124
|
+
await generateProject(config, outputDir);
|
|
125
|
+
// Write config file for downstream commands
|
|
126
|
+
writeConfigFile(outputDir, config);
|
|
127
|
+
// NI-06: Skip git setup entirely in non-interactive mode
|
|
128
|
+
// promptGitSetup() is NOT called
|
|
129
|
+
// Success message and next steps
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log(pc.green('✔') + ` Created ${pc.bold(config.projectName)} successfully!`);
|
|
132
|
+
printNextSteps(config.projectName);
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
113
135
|
/**
|
|
114
136
|
* Run the create project wizard flow
|
|
115
137
|
* This is the default command when no subcommand is specified
|
|
@@ -117,6 +139,19 @@ function printNextSteps(projectName, platforms) {
|
|
|
117
139
|
async function runCreate(args) {
|
|
118
140
|
printWelcome();
|
|
119
141
|
console.log(''); // blank line after banner
|
|
142
|
+
// Non-interactive path: --config flag provided
|
|
143
|
+
const configFlagIndex = args.findIndex(arg => arg === '--config');
|
|
144
|
+
if (configFlagIndex !== -1) {
|
|
145
|
+
const configPath = args[configFlagIndex + 1];
|
|
146
|
+
if (!configPath || configPath.startsWith('--')) {
|
|
147
|
+
console.error(pc.red('Error:') + ' --config requires a path argument');
|
|
148
|
+
console.error(' Example: npx create-aws-project --config project.json');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
await runNonInteractive(configPath);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Interactive path (unchanged — existing code below)
|
|
120
155
|
// Extract project name from CLI args (first non-flag argument)
|
|
121
156
|
const nameArg = args.find(arg => !arg.startsWith('-'));
|
|
122
157
|
const config = await runWizard(nameArg ? { defaultName: nameArg } : undefined);
|
|
@@ -148,7 +183,7 @@ async function runCreate(args) {
|
|
|
148
183
|
// Success message and next steps
|
|
149
184
|
console.log('');
|
|
150
185
|
console.log(pc.green('✔') + ` Created ${pc.bold(config.projectName)} successfully!`);
|
|
151
|
-
printNextSteps(config.projectName
|
|
186
|
+
printNextSteps(config.projectName);
|
|
152
187
|
process.exit(0);
|
|
153
188
|
}
|
|
154
189
|
/**
|
|
@@ -10,7 +10,6 @@ import prompts from 'prompts';
|
|
|
10
10
|
import pc from 'picocolors';
|
|
11
11
|
import { execSync } from 'node:child_process';
|
|
12
12
|
import { requireProjectContext } from '../utils/project-context.js';
|
|
13
|
-
import { createCrossAccountIAMClient, createDeploymentUserWithCredentials, createAccessKey, } from '../aws/iam.js';
|
|
14
13
|
import { createGitHubClient, setEnvironmentCredentials, parseGitHubUrl, } from '../github/secrets.js';
|
|
15
14
|
const VALID_ENVIRONMENTS = ['dev', 'stage', 'prod'];
|
|
16
15
|
/**
|
|
@@ -151,49 +150,55 @@ async function promptForRepoInfo() {
|
|
|
151
150
|
return parseGitHubUrl(response.repo);
|
|
152
151
|
}
|
|
153
152
|
/**
|
|
154
|
-
*
|
|
153
|
+
* Determines batch environments from CLI args
|
|
154
|
+
* @param args Command arguments
|
|
155
|
+
* @param config Project config with deployment credentials
|
|
156
|
+
* @returns Array of environments to configure
|
|
157
|
+
*/
|
|
158
|
+
function determineBatchEnvironments(args, config) {
|
|
159
|
+
if (args.includes('--all')) {
|
|
160
|
+
const envs = VALID_ENVIRONMENTS.filter(env => config.deploymentCredentials?.[env]);
|
|
161
|
+
if (envs.length === 0) {
|
|
162
|
+
console.error(pc.red('Error:') + ' No environments have credentials configured.');
|
|
163
|
+
console.error('Run setup-aws-envs first to create deployment credentials:');
|
|
164
|
+
console.error(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
return [...envs];
|
|
168
|
+
}
|
|
169
|
+
// Multiple positional arguments (filter out flags)
|
|
170
|
+
const envArgs = args.filter(arg => !arg.startsWith('--'));
|
|
171
|
+
for (const envArg of envArgs) {
|
|
172
|
+
if (envArg !== envArg.toLowerCase()) {
|
|
173
|
+
console.error(pc.red('Error:') + ` Environment must be lowercase: ${pc.bold(envArg)}`);
|
|
174
|
+
console.error(`Did you mean: ${pc.cyan(envArg.toLowerCase())}?`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
if (!isValidEnvironment(envArg)) {
|
|
178
|
+
console.error(pc.red('Error:') + ` Invalid environment: ${pc.bold(envArg)}`);
|
|
179
|
+
console.error('Valid environments: ' + VALID_ENVIRONMENTS.join(', '));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
if (!config.deploymentCredentials?.[envArg]) {
|
|
183
|
+
console.error(pc.red('Error:') + ` No credentials for ${pc.bold(envArg)}.`);
|
|
184
|
+
console.error('Run setup-aws-envs first to create deployment credentials:');
|
|
185
|
+
console.error(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return envArgs;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Handles GitHub errors with actionable messages
|
|
155
193
|
* @param error The error to handle
|
|
156
|
-
* @param env The environment being configured
|
|
157
194
|
* @returns never - always exits
|
|
158
195
|
*/
|
|
159
|
-
function handleError(error
|
|
196
|
+
function handleError(error) {
|
|
160
197
|
console.error('');
|
|
161
198
|
if (!(error instanceof Error)) {
|
|
162
199
|
console.error(pc.red('Error:') + ' Unknown error occurred');
|
|
163
200
|
process.exit(1);
|
|
164
201
|
}
|
|
165
|
-
// AWS AssumeRole errors
|
|
166
|
-
if (error.name === 'AccessDenied' || error.message.includes('AssumeRole')) {
|
|
167
|
-
console.error(pc.red('Error: Cannot assume role in target account'));
|
|
168
|
-
console.error('');
|
|
169
|
-
console.error('This command requires cross-account access via:');
|
|
170
|
-
console.error(` arn:aws:iam::<${env}-account-id>:role/OrganizationAccountAccessRole`);
|
|
171
|
-
console.error('');
|
|
172
|
-
console.error('Ensure:');
|
|
173
|
-
console.error(` 1. The ${env} account was created via setup-aws-envs`);
|
|
174
|
-
console.error(' 2. Your credentials are from the management account');
|
|
175
|
-
console.error(' 3. OrganizationAccountAccessRole exists in target account');
|
|
176
|
-
process.exit(1);
|
|
177
|
-
}
|
|
178
|
-
// IAM user already exists
|
|
179
|
-
if (error.message.includes('already exists')) {
|
|
180
|
-
console.error(pc.red('Error:') + ` ${error.message}`);
|
|
181
|
-
console.error('');
|
|
182
|
-
console.error('To retry, delete the IAM user first:');
|
|
183
|
-
console.error(' 1. Go to AWS Console > IAM > Users');
|
|
184
|
-
console.error(` 2. Find and delete the existing deployment user`);
|
|
185
|
-
console.error(' 3. Run this command again');
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
// Access key limit exceeded
|
|
189
|
-
if (error.name === 'LimitExceeded' || error.message.includes('LimitExceeded')) {
|
|
190
|
-
console.error(pc.red('Error: Access key limit exceeded'));
|
|
191
|
-
console.error('');
|
|
192
|
-
console.error('IAM users can only have 2 active access keys.');
|
|
193
|
-
console.error('Delete an existing key before creating a new one:');
|
|
194
|
-
console.error(' AWS Console > IAM > Users > Security credentials > Access keys');
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
202
|
// GitHub authentication errors
|
|
198
203
|
if (error.message.includes('authentication failed') || error.name === 'HttpError') {
|
|
199
204
|
console.error(pc.red('Error: GitHub authentication failed'));
|
|
@@ -222,7 +227,84 @@ export async function runInitializeGitHub(args) {
|
|
|
222
227
|
// 1. Validate we're in a project directory
|
|
223
228
|
const context = await requireProjectContext();
|
|
224
229
|
const { config } = context;
|
|
225
|
-
|
|
230
|
+
// 2. Detect batch mode
|
|
231
|
+
const nonFlagArgs = args.filter(a => !a.startsWith('--'));
|
|
232
|
+
const isBatchMode = args.includes('--all') || nonFlagArgs.length > 1;
|
|
233
|
+
if (isBatchMode) {
|
|
234
|
+
// BATCH MODE: Configure multiple environments
|
|
235
|
+
const environments = determineBatchEnvironments(args, config);
|
|
236
|
+
// Get repository info once (try git remote, fallback to prompt)
|
|
237
|
+
let repoInfo = getGitRemoteOrigin();
|
|
238
|
+
if (!repoInfo) {
|
|
239
|
+
console.log('');
|
|
240
|
+
console.log(pc.yellow('Note:') + ' Could not detect GitHub repository from git remote.');
|
|
241
|
+
repoInfo = await promptForRepoInfo();
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
console.log('');
|
|
245
|
+
console.log(`Detected repository: ${pc.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);
|
|
246
|
+
}
|
|
247
|
+
// Prompt for GitHub PAT once
|
|
248
|
+
const pat = await promptForGitHubPAT();
|
|
249
|
+
// Create GitHub client once
|
|
250
|
+
const githubClient = createGitHubClient(pat);
|
|
251
|
+
// Track results for each environment
|
|
252
|
+
const results = [];
|
|
253
|
+
// Process each environment
|
|
254
|
+
for (const env of environments) {
|
|
255
|
+
const spinner = ora(`Configuring ${env} environment...`).start();
|
|
256
|
+
try {
|
|
257
|
+
const credentials = config.deploymentCredentials?.[env];
|
|
258
|
+
if (!credentials) {
|
|
259
|
+
throw new Error(`No deployment credentials found for ${env}`);
|
|
260
|
+
}
|
|
261
|
+
const githubEnvName = GITHUB_ENV_NAMES[env];
|
|
262
|
+
spinner.text = `Configuring GitHub Environment "${githubEnvName}"...`;
|
|
263
|
+
await setEnvironmentCredentials(githubClient, repoInfo.owner, repoInfo.repo, githubEnvName, credentials.accessKeyId, credentials.secretAccessKey);
|
|
264
|
+
spinner.succeed(`Configured ${githubEnvName} environment`);
|
|
265
|
+
results.push({ env, success: true });
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
269
|
+
spinner.fail(`Failed ${env}`);
|
|
270
|
+
results.push({ env, success: false, error: errorMessage });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Show batch summary
|
|
274
|
+
console.log('');
|
|
275
|
+
console.log(pc.bold('Batch Configuration Summary'));
|
|
276
|
+
console.log('');
|
|
277
|
+
for (const result of results) {
|
|
278
|
+
if (result.success) {
|
|
279
|
+
console.log(` ${pc.green('✓')} Configured ${GITHUB_ENV_NAMES[result.env]} environment`);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log(` ${pc.red('✗')} Failed ${result.env}: ${result.error}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const successCount = results.filter(r => r.success).length;
|
|
286
|
+
console.log('');
|
|
287
|
+
console.log(`Successfully configured ${successCount} of ${results.length} environments`);
|
|
288
|
+
if (successCount < results.length) {
|
|
289
|
+
console.log('');
|
|
290
|
+
console.log('You can retry failed environments individually:');
|
|
291
|
+
for (const result of results) {
|
|
292
|
+
if (!result.success) {
|
|
293
|
+
console.log(` ${pc.cyan(`npx create-aws-project initialize-github ${result.env}`)}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
console.log('');
|
|
298
|
+
console.log('View secrets at:');
|
|
299
|
+
console.log(` ${pc.cyan(`https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/environments`)}`);
|
|
300
|
+
console.log('');
|
|
301
|
+
// Exit with error code if any failed
|
|
302
|
+
if (successCount < results.length) {
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// SINGLE MODE (existing behavior, unchanged)
|
|
226
308
|
// 2. Determine environment
|
|
227
309
|
let env;
|
|
228
310
|
if (args[0]) {
|
|
@@ -245,26 +327,17 @@ export async function runInitializeGitHub(args) {
|
|
|
245
327
|
}
|
|
246
328
|
else {
|
|
247
329
|
// Interactive environment selection
|
|
248
|
-
const configuredEnvs = VALID_ENVIRONMENTS.filter((e) => config.
|
|
330
|
+
const configuredEnvs = VALID_ENVIRONMENTS.filter((e) => config.deploymentCredentials?.[e]);
|
|
249
331
|
if (configuredEnvs.length === 0) {
|
|
250
332
|
console.error(pc.red('Error:') + ' No environments configured.');
|
|
251
333
|
console.error('');
|
|
252
|
-
console.error('Run setup-aws-envs first to create
|
|
334
|
+
console.error('Run setup-aws-envs first to create deployment credentials:');
|
|
253
335
|
console.error(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
254
336
|
process.exit(1);
|
|
255
337
|
}
|
|
256
338
|
env = await promptForEnvironment(configuredEnvs);
|
|
257
339
|
}
|
|
258
|
-
// 3.
|
|
259
|
-
const accountId = config.accounts?.[env];
|
|
260
|
-
if (!accountId) {
|
|
261
|
-
console.error(pc.red('Error:') + ` No account ID for ${env}.`);
|
|
262
|
-
console.error('');
|
|
263
|
-
console.error('Run setup-aws-envs first to create environment accounts:');
|
|
264
|
-
console.error(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
265
|
-
process.exit(1);
|
|
266
|
-
}
|
|
267
|
-
// 4. Get repository info (try git remote, fallback to prompt)
|
|
340
|
+
// 3. Get repository info (try git remote, fallback to prompt)
|
|
268
341
|
let repoInfo = getGitRemoteOrigin();
|
|
269
342
|
if (!repoInfo) {
|
|
270
343
|
console.log('');
|
|
@@ -275,33 +348,27 @@ export async function runInitializeGitHub(args) {
|
|
|
275
348
|
console.log('');
|
|
276
349
|
console.log(`Detected repository: ${pc.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);
|
|
277
350
|
}
|
|
278
|
-
//
|
|
351
|
+
// 4. Prompt for GitHub PAT (always interactive per CONTEXT.md)
|
|
279
352
|
const pat = await promptForGitHubPAT();
|
|
280
|
-
//
|
|
353
|
+
// 5. Execute GitHub setup
|
|
281
354
|
const spinner = ora(`Initializing ${env} environment...`).start();
|
|
282
355
|
try {
|
|
283
|
-
// Step 1:
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
spinner.text = `Creating IAM deployment user...`;
|
|
300
|
-
const fullCredentials = await createDeploymentUserWithCredentials(iamClient, projectName, env, accountId);
|
|
301
|
-
userName = fullCredentials.userName;
|
|
302
|
-
credentials = fullCredentials;
|
|
356
|
+
// Step 1: Validate deployment credentials exist in config
|
|
357
|
+
const credentials = config.deploymentCredentials?.[env];
|
|
358
|
+
if (!credentials) {
|
|
359
|
+
spinner.fail(`No deployment credentials found for ${env}`);
|
|
360
|
+
console.error('');
|
|
361
|
+
// Check if user exists but credentials don't (migration case)
|
|
362
|
+
if (config.deploymentUsers?.[env]) {
|
|
363
|
+
console.error(pc.yellow('Note:') + ' Deployment user exists but credentials were not found.');
|
|
364
|
+
console.error('Your project may have been set up with an older version.');
|
|
365
|
+
console.error('');
|
|
366
|
+
}
|
|
367
|
+
console.error('Run setup-aws-envs first to create deployment credentials:');
|
|
368
|
+
console.error(` ${pc.cyan('npx create-aws-project setup-aws-envs')}`);
|
|
369
|
+
process.exit(1);
|
|
303
370
|
}
|
|
304
|
-
// Step
|
|
371
|
+
// Step 2: Configure GitHub environment
|
|
305
372
|
const githubEnvName = GITHUB_ENV_NAMES[env];
|
|
306
373
|
spinner.text = `Configuring GitHub Environment "${githubEnvName}"...`;
|
|
307
374
|
const githubClient = createGitHubClient(pat);
|
|
@@ -311,20 +378,16 @@ export async function runInitializeGitHub(args) {
|
|
|
311
378
|
console.log('');
|
|
312
379
|
console.log(pc.green(`${env} environment setup complete!`));
|
|
313
380
|
console.log('');
|
|
314
|
-
console.log('
|
|
315
|
-
console.log(` Deployment User: ${pc.cyan(userName)}`);
|
|
381
|
+
console.log('Credentials pushed to GitHub:');
|
|
382
|
+
console.log(` Deployment User: ${pc.cyan(credentials.userName)}`);
|
|
383
|
+
console.log(` Access Key ID: ${pc.cyan(credentials.accessKeyId)}`);
|
|
316
384
|
console.log(` GitHub Environment: ${pc.cyan(githubEnvName)}`);
|
|
317
|
-
// Add note if using existing user from setup-aws-envs
|
|
318
|
-
if (existingUserName) {
|
|
319
|
-
console.log('');
|
|
320
|
-
console.log(pc.dim('Note: Deployment user was created by setup-aws-envs. Access key created for GitHub.'));
|
|
321
|
-
}
|
|
322
385
|
console.log('');
|
|
323
386
|
console.log('View secrets at:');
|
|
324
387
|
console.log(` ${pc.cyan(`https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/environments`)}`);
|
|
325
388
|
console.log('');
|
|
326
389
|
// Show next steps (other environments if any remain)
|
|
327
|
-
const remainingEnvs = VALID_ENVIRONMENTS.filter((e) => e !== env && config.
|
|
390
|
+
const remainingEnvs = VALID_ENVIRONMENTS.filter((e) => e !== env && config.deploymentCredentials?.[e]);
|
|
328
391
|
if (remainingEnvs.length > 0) {
|
|
329
392
|
console.log(pc.bold('Next steps:'));
|
|
330
393
|
console.log('');
|
|
@@ -337,13 +400,29 @@ export async function runInitializeGitHub(args) {
|
|
|
337
400
|
else {
|
|
338
401
|
console.log(pc.bold('All environments configured!'));
|
|
339
402
|
console.log('');
|
|
340
|
-
console.log('
|
|
341
|
-
console.log(` ${pc.cyan('git push origin main')}`);
|
|
403
|
+
console.log(pc.bold('Get started:'));
|
|
342
404
|
console.log('');
|
|
405
|
+
console.log(` ${pc.cyan('npm install')}`);
|
|
406
|
+
console.log('');
|
|
407
|
+
if (config.platforms?.includes('web')) {
|
|
408
|
+
console.log(` ${pc.gray('# Start web app')}`);
|
|
409
|
+
console.log(` ${pc.cyan('npm run web')}`);
|
|
410
|
+
console.log('');
|
|
411
|
+
}
|
|
412
|
+
if (config.platforms?.includes('mobile')) {
|
|
413
|
+
console.log(` ${pc.gray('# Start mobile app')}`);
|
|
414
|
+
console.log(` ${pc.cyan('npm run mobile')}`);
|
|
415
|
+
console.log('');
|
|
416
|
+
}
|
|
417
|
+
if (config.platforms?.includes('api')) {
|
|
418
|
+
console.log(` ${pc.gray('# Deploy API')}`);
|
|
419
|
+
console.log(` ${pc.cyan('npm run cdk:deploy')}`);
|
|
420
|
+
console.log('');
|
|
421
|
+
}
|
|
343
422
|
}
|
|
344
423
|
}
|
|
345
424
|
catch (error) {
|
|
346
425
|
spinner.fail(`Failed to configure ${env} environment`);
|
|
347
|
-
handleError(error
|
|
426
|
+
handleError(error);
|
|
348
427
|
}
|
|
349
428
|
}
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Creates AWS Organizations and environment accounts (dev, stage, prod)
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
12
|
+
* @param args Command arguments
|
|
13
13
|
*/
|
|
14
|
-
export declare function runSetupAwsEnvs(
|
|
14
|
+
export declare function runSetupAwsEnvs(args: string[]): Promise<void>;
|