deploy-stack 0.3.3 → 0.4.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/README.md +11 -5
- package/package.json +1 -1
- package/src/commands/init.js +20 -5
- package/src/utils/detector.js +11 -1
- package/src/utils/generator.js +2 -0
- package/src/utils/warnings.js +3 -4
- package/templates/docker/static.Dockerfile +2 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-

|
|
7
|
+
<!--  -->
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -25,7 +25,8 @@ You retain complete ownership of your infrastructure code without relying on bla
|
|
|
25
25
|
## ✨ Features
|
|
26
26
|
|
|
27
27
|
* **Zero Vendor Lock-In:** Generates standard, clean `.tf` files. Modify, expand, or decouple them at any time.
|
|
28
|
-
* **Framework Agnostic:** Tailored container presets for Next.js
|
|
28
|
+
* **Framework Agnostic:** Tailored container presets for Next.js, Express.js, FastAPI, and **Zero-Config Static Sites** (React, Vue, SvelteKit, Astro, Vite).
|
|
29
|
+
* **Smart Git Integration:** Automatically detects your working branch (`main`, `master`, `develop`) and binds it directly to the generated GitHub Actions pipeline.
|
|
29
30
|
* **Production-Grade Defaults:** Automatically provisions an Amazon ECS Fargate cluster fronted by an Application Load Balancer across multiple availability zones.
|
|
30
31
|
* **Global Edge Acceleration:** Includes an integrated AWS CloudFront CDN distribution with SSL termination and optimized caching.
|
|
31
32
|
* **Keyless, Zero-Secret CI/CD:** Uses AWS IAM OpenID Connect (OIDC) for automated GitHub Actions deployments—no long-lived AWS keys stored in GitHub Secrets.
|
|
@@ -46,7 +47,7 @@ npx deploy-stack
|
|
|
46
47
|
The interactive CLI will guide you through the setup:
|
|
47
48
|
1. **Target Directory / Name:** (Type `.` to bootstrap your current directory)
|
|
48
49
|
2. **Setup Mode:** (Choose **Quickstart** for sensible defaults, or **Advanced** for custom scaling and branch names)
|
|
49
|
-
3. **Zero-Config Detection:** The CLI automatically scans your
|
|
50
|
+
3. **Zero-Config Detection:** The CLI automatically scans your project to detect your framework. For static sites, it intelligently discovers your build output directory (`dist`, `build`, `.output`, etc.) and dynamically configures the hardened Nginx container.
|
|
50
51
|
4. **AWS Region & Compute Tier:** (Select your target region and Fargate size with live cost estimates)
|
|
51
52
|
|
|
52
53
|
---
|
|
@@ -104,8 +105,13 @@ your-project/
|
|
|
104
105
|
|
|
105
106
|
## 📦 Reference Implementations
|
|
106
107
|
|
|
107
|
-
* **[Next.js Fullstack
|
|
108
|
-
|
|
108
|
+
* **[Next.js Fullstack App](https://github.com/anton-codes-iac/deploy-stack-nextjs-example):** A complete Next.js deployment showcasing the generated Terraform, CloudFront setup, and automated OIDC workflow.
|
|
109
|
+
* **[Express.js API](https://github.com/anton-codes-iac/deploy-stack-express-example):** A standard Node.js backend setup.
|
|
110
|
+
* **[Python FastAPI](https://github.com/anton-codes-iac/deploy-stack-fastapi-example):** A Python API demonstrating unprivileged port mapping.
|
|
111
|
+
* **[Vite / React SPA](https://github.com/anton-codes-iac/deploy-stack-vite-example):** Demonstrates SPA routing and `dist/` auto-detection.
|
|
112
|
+
* **[Create React App](https://github.com/anton-codes-iac/deploy-stack-cra-example):** Validates backward compatibility with legacy Webpack pipelines and `build/` auto-detection.
|
|
113
|
+
* **[Astro Static Site](https://github.com/anton-codes-iac/deploy-stack-astro-example):** Demonstrates modern static site generation (SSG).
|
|
114
|
+
* **[SvelteKit Application](https://github.com/anton-codes-iac/deploy-stack-svelte-example):** Demonstrates static adapter integration and custom output folder detection.
|
|
109
115
|
---
|
|
110
116
|
|
|
111
117
|
## 🛡️ Telemetry & Privacy
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { intro, outro, group, text, select, spinner, cancel, confirm, log } from '@clack/prompts';
|
|
5
5
|
import color from 'picocolors';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
6
7
|
|
|
7
8
|
import { checkDependency } from '../utils/system.js';
|
|
8
9
|
import { detectFramework } from '../utils/detector.js';
|
|
@@ -88,6 +89,14 @@ export async function mainStack() {
|
|
|
88
89
|
if (finalFramework === 'static') defaultPort = '8080';
|
|
89
90
|
if (finalFramework === 'python') defaultPort = '8000';
|
|
90
91
|
|
|
92
|
+
// 2.8 Check current Git branch
|
|
93
|
+
let currentGitBranch = 'main';
|
|
94
|
+
try {
|
|
95
|
+
currentGitBranch = execSync('git symbolic-ref --short HEAD', { cwd: targetDir, stdio: 'pipe' }).toString().trim();
|
|
96
|
+
} catch (e) {
|
|
97
|
+
// Not a git repo yet, fallback to 'main'
|
|
98
|
+
}
|
|
99
|
+
|
|
91
100
|
// 3. Prompt Configuration Group
|
|
92
101
|
const project = await group(
|
|
93
102
|
{
|
|
@@ -140,8 +149,8 @@ export async function mainStack() {
|
|
|
140
149
|
if (setupType === 'quick') return undefined;
|
|
141
150
|
return text({
|
|
142
151
|
message: 'Primary Git deployment branch for CI/CD:',
|
|
143
|
-
placeholder:
|
|
144
|
-
defaultValue:
|
|
152
|
+
placeholder: currentGitBranch,
|
|
153
|
+
defaultValue: currentGitBranch,
|
|
145
154
|
});
|
|
146
155
|
},
|
|
147
156
|
},
|
|
@@ -162,7 +171,9 @@ export async function mainStack() {
|
|
|
162
171
|
|
|
163
172
|
const healthCheckPath = project.healthCheckPath || '/';
|
|
164
173
|
const desiredCount = project.desiredCount || '1';
|
|
165
|
-
const deployBranch = project.branch ||
|
|
174
|
+
const deployBranch = project.branch || currentGitBranch;
|
|
175
|
+
|
|
176
|
+
const buildDir = detectedFramework?.buildDir || 'dist';
|
|
166
177
|
|
|
167
178
|
// 5. Check for existing files that might be overwritten
|
|
168
179
|
const dockerfilePath = path.join(targetDir, 'Dockerfile');
|
|
@@ -213,6 +224,7 @@ export async function mainStack() {
|
|
|
213
224
|
HEALTH_CHECK_PATH: healthCheckPath,
|
|
214
225
|
DESIRED_COUNT: desiredCount,
|
|
215
226
|
DEPLOY_BRANCH: deployBranch,
|
|
227
|
+
BUILD_DIR: buildDir,
|
|
216
228
|
finalFramework: finalFramework
|
|
217
229
|
});
|
|
218
230
|
|
|
@@ -230,7 +242,10 @@ export async function mainStack() {
|
|
|
230
242
|
s.stop('Infrastructure provisioned successfully!');
|
|
231
243
|
|
|
232
244
|
// 9. Provide the Outro, Framework Warnings and Next Steps
|
|
233
|
-
|
|
245
|
+
let frameworkWarnings = '';
|
|
246
|
+
if (!(finalFramework === 'static' && detectedFramework?.buildDir)) {
|
|
247
|
+
frameworkWarnings = getFrameworkWarning(finalFramework);
|
|
248
|
+
}
|
|
234
249
|
|
|
235
250
|
const isGitInitialized = fsSync.existsSync(path.join(targetDir, '.git'));
|
|
236
251
|
|
|
@@ -240,7 +255,7 @@ export async function mainStack() {
|
|
|
240
255
|
|
|
241
256
|
const gitInstructions = isGitInitialized
|
|
242
257
|
? `git add .\n git commit -m "chore: add AWS infrastructure and CI/CD"\n git push`
|
|
243
|
-
: `git init\n git add .\n git commit -m "chore: add AWS infrastructure and CI/CD"\n git branch -M
|
|
258
|
+
: `git init\n git add .\n git commit -m "chore: add AWS infrastructure and CI/CD"\n git branch -M ${deployBranch}\n git remote add origin https://github.com/your-username/your-repo.git\n git push -u origin ${deployBranch}`;
|
|
244
259
|
|
|
245
260
|
outro(`
|
|
246
261
|
${color.green('✅ Project provisioned successfully!')}
|
package/src/utils/detector.js
CHANGED
|
@@ -12,9 +12,19 @@ export function detectFramework(targetDir) {
|
|
|
12
12
|
// Merge dependencies and devDependencies to check both
|
|
13
13
|
const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
14
14
|
|
|
15
|
+
// Next.js & Express
|
|
15
16
|
if (deps['next']) return { id: 'nextjs', name: 'Next.js' };
|
|
16
|
-
if (deps['vite'] || deps['astro'] || deps['@sveltejs/kit'] || deps['gatsby'] || deps['react-scripts'] || deps['@vue/cli-service']) return { id: 'static', name: 'Static Site (Vite, Astro, React)' };
|
|
17
17
|
if (deps['express']) return { id: 'node', name: 'Node.js / Express' };
|
|
18
|
+
|
|
19
|
+
// Static Site Generators & SPAs (with precise build directories)
|
|
20
|
+
if (deps['@sveltejs/kit']) return { id: 'static', name: 'SvelteKit', buildDir: 'build' };
|
|
21
|
+
if (deps['react-scripts']) return { id: 'static', name: 'Create React App', buildDir: 'build' };
|
|
22
|
+
if (deps['gatsby']) return { id: 'static', name: 'Gatsby', buildDir: 'public' };
|
|
23
|
+
if (deps['nuxt']) return { id: 'static', name: 'Nuxt', buildDir: '.output/public' };
|
|
24
|
+
if (deps['astro']) return { id: 'static', name: 'Astro', buildDir: 'dist' };
|
|
25
|
+
if (deps['vite']) return { id: 'static', name: 'Vite', buildDir: 'dist' };
|
|
26
|
+
if (deps['@vue/cli-service']) return { id: 'static', name: 'Vue.js', buildDir: 'dist' };
|
|
27
|
+
if (deps['@angular/cli']) return { id: 'static', name: 'Angular', buildDir: 'dist' };
|
|
18
28
|
} catch (e) {
|
|
19
29
|
// Silently fail if package.json is malformed
|
|
20
30
|
}
|
package/src/utils/generator.js
CHANGED
package/src/utils/warnings.js
CHANGED
|
@@ -25,10 +25,9 @@ export function getFrameworkWarning(frameworkId) {
|
|
|
25
25
|
return (
|
|
26
26
|
color.bgYellow(color.black(' ⚠️ IMPORTANT: STATIC SITE SETUP REQUIRED ')) +
|
|
27
27
|
color.yellow('\n 1. Open your generated Dockerfile.') +
|
|
28
|
-
color.yellow('\n 2.
|
|
29
|
-
color.yellow('\n
|
|
30
|
-
color.yellow('\n
|
|
31
|
-
color.yellow('\n 3. Ensure your package.json has a "build" script (e.g., "vite build").\n\n')
|
|
28
|
+
color.yellow('\n 2. We defaulted your output folder to /app/dist.') +
|
|
29
|
+
color.yellow('\n 3. If your framework uses a different folder (like build/ or out/), change it in the COPY command.') +
|
|
30
|
+
color.yellow('\n 4. Ensure your package.json has a "build" script (e.g., "vite build").\n\n')
|
|
32
31
|
);
|
|
33
32
|
default:
|
|
34
33
|
return '';
|
|
@@ -13,9 +13,8 @@ RUN npm run build
|
|
|
13
13
|
# STAGE 2: Serve with Hardened Nginx
|
|
14
14
|
FROM nginx:alpine
|
|
15
15
|
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
COPY --from=builder /app/dist /usr/share/nginx/html
|
|
16
|
+
# Adjusts BUILD_DIR to match your framework's output folder
|
|
17
|
+
COPY --from=builder /app/{{BUILD_DIR}} /usr/share/nginx/html
|
|
19
18
|
|
|
20
19
|
# Inject custom Nginx configuration for unprivileged ports and SPA routing
|
|
21
20
|
RUN echo "server {" > /etc/nginx/conf.d/default.conf && \
|