deploy-stack 0.2.10 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deploy-stack",
3
- "version": "0.2.10",
3
+ "version": "0.3.1",
4
4
  "description": "Provision production-ready AWS infrastructure and CI/CD pipelines in seconds.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -232,10 +232,16 @@ export async function mainStack() {
232
232
  // 9. Provide the Outro, Framework Warnings and Next Steps
233
233
  const frameworkWarnings = getFrameworkWarning(finalFramework);
234
234
 
235
+ const isGitInitialized = fsSync.existsSync(path.join(targetDir, '.git'));
236
+
235
237
  const cdStep = projectName === '.' ? '' : `1. cd ${projectName}\n `;
236
238
  const deployStepNum = projectName === '.' ? '1' : '2';
237
239
  const gitStepNum = projectName === '.' ? '2' : '3';
238
240
 
241
+ const gitInstructions = isGitInitialized
242
+ ? `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 main\n git remote add origin https://github.com/your-username/your-repo.git\n git push -u origin main`;
244
+
239
245
  outro(`
240
246
  ${color.green('✅ Project provisioned successfully!')}
241
247
 
@@ -244,8 +250,10 @@ export async function mainStack() {
244
250
  Next steps:
245
251
  ${cdStep}${deployStepNum}. Deploy infrastructure:
246
252
  cd terraform && terraform init && terraform apply
247
- ${gitStepNum}. Push to GitHub:
248
- git init && git add . && git commit -m "Initial commit"
253
+
254
+ ${gitStepNum}. Push to GitHub to trigger CI/CD:
255
+ cd ..
256
+ ${gitInstructions}
249
257
 
250
258
  ${color.cyan('Once deployed, Terraform will output your new https://*.cloudfront.net URL.')}
251
259
 
@@ -13,7 +13,7 @@ export function detectFramework(targetDir) {
13
13
  const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
14
14
 
15
15
  if (deps['next']) return { id: 'nextjs', name: 'Next.js' };
16
- if (deps['gatsby'] || deps['react-scripts'] || deps['vue']) return { id: 'static', name: 'Static Site' };
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
18
  } catch (e) {
19
19
  // Silently fail if package.json is malformed
@@ -15,10 +15,21 @@ export function getFrameworkWarning(frameworkId) {
15
15
  color.yellow('\n 2. Your app must listen on 0.0.0.0 (not localhost) to receive traffic in Docker.\n\n')
16
16
  );
17
17
  case 'python':
18
- return color.yellow(' ⚠️ IMPORTANT: PYTHON SETUP REQUIRED ') +
18
+ return (
19
+ color.bgYellow(color.black(' ⚠️ IMPORTANT: PYTHON SETUP REQUIRED ')) +
19
20
  color.yellow('\n 1. Ensure your requirements.txt includes your web framework (e.g., fastapi, uvicorn).') +
20
21
  color.yellow('\n 2. Your app must listen on 0.0.0.0 (not localhost) to receive traffic in Docker.') +
21
- color.yellow('\n 3. Ensure your app has a health check route returning 200 OK.\n\n');
22
+ color.yellow('\n 3. Ensure your app has a health check route returning 200 OK.\n\n')
23
+ );
24
+ case 'static':
25
+ return (
26
+ color.bgYellow(color.black(' ⚠️ IMPORTANT: STATIC SITE SETUP REQUIRED ')) +
27
+ color.yellow('\n 1. Open your generated Dockerfile.') +
28
+ color.yellow('\n 2. Ensure the build output folder on line 15 matches your framework:') +
29
+ color.yellow('\n Vite / Astro: COPY --from=builder /app/dist /usr/share/nginx/html') +
30
+ color.yellow('\n Create React App: COPY --from=builder /app/build /usr/share/nginx/html') +
31
+ color.yellow('\n 3. Ensure your package.json has a "build" script (e.g., "vite build").\n\n')
32
+ );
22
33
  default:
23
34
  return '';
24
35
  }
@@ -92,4 +92,10 @@ When running inside a Docker container, your server must bind to all network int
92
92
 
93
93
  Make sure your app is configured correctly:
94
94
  * **Express.js:** `app.listen(port, '0.0.0.0', () => ...)`
95
- * **FastAPI:** `uvicorn.run(app, host="0.0.0.0", port=8000)`
95
+ * **FastAPI:** `uvicorn.run(app, host="0.0.0.0", port=8000)`
96
+
97
+ ### 4. Static Sites (Vite, Astro, React, Vue)
98
+
99
+ If you are deploying a static site, your application is served via a highly optimized, unprivileged Nginx container.
100
+ 1. **Build Folder:** Different frameworks output compiled assets to different folders. Open your `Dockerfile` and ensure the `COPY --from=builder` command points to the correct folder (`dist`, `build`, or `out`).
101
+ 2. **Health Checks:** You do not need to configure a custom `/health` route. Nginx will automatically return a `200 OK` when AWS pings the root `/` index page.
@@ -1,13 +1,37 @@
1
+ # STAGE 1: Build the static assets
2
+ FROM node:20-alpine AS builder
3
+ WORKDIR /app
4
+
5
+ COPY package*.json ./
6
+ # Use clean install for reliable, reproducible builds
7
+ RUN npm ci
8
+
9
+ COPY . .
10
+ # Runs the standard build script defined in package.json
11
+ RUN npm run build
12
+
13
+ # STAGE 2: Serve with Hardened Nginx
1
14
  FROM nginx:alpine
2
15
 
3
- # Remove default Nginx static assets
4
- RUN rm -rf /usr/share/nginx/html/*
16
+ # ⚠️ CRITICAL: Adjust 'dist' to match your framework's output folder!
17
+ # Vite/Astro = dist | Create React App/Gatsby = build | Next.js Static = out
18
+ COPY --from=builder /app/dist /usr/share/nginx/html
19
+
20
+ # Dynamically update the Nginx port
21
+ RUN sed -i "s/listen 80;/listen {{PORT}};/g" /etc/nginx/conf.d/default.conf
22
+
23
+ # Silence unprivileged user directive warning in main config
24
+ RUN sed -i 's/^user\s\+nginx;/# user nginx;/' /etc/nginx/nginx.conf
5
25
 
6
- # Copy your static build output (e.g., from Gatsby, React, or pure HTML)
7
- COPY . /usr/share/nginx/html
26
+ # DevSecOps Hardening: Drop root privileges for the Nginx process
27
+ RUN chown -R nginx:nginx /usr/share/nginx/html && \
28
+ chown -R nginx:nginx /var/cache/nginx && \
29
+ chown -R nginx:nginx /var/log/nginx && \
30
+ chown -R nginx:nginx /etc/nginx/conf.d && \
31
+ touch /var/run/nginx.pid && \
32
+ chown -R nginx:nginx /var/run/nginx.pid
8
33
 
9
- # Dynamically update the Nginx config to use the user's chosen port
10
- RUN sed -i 's/listen *80;/listen {{PORT}};/g' /etc/nginx/conf.d/default.conf
34
+ USER nginx
11
35
 
12
36
  EXPOSE {{PORT}}
13
37
  CMD ["nginx", "-g", "daemon off;"]