@smi-digital/create-smi-app 2.6.0 → 2.7.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/dist/index.js CHANGED
@@ -667,6 +667,33 @@ async function initializeGitRepository(projectRoot) {
667
667
  );
668
668
  }
669
669
  }
670
+ async function activateVaultFilter(projectRoot) {
671
+ try {
672
+ await access2(join6(projectRoot, ".vault-password"));
673
+ } catch {
674
+ return;
675
+ }
676
+ const setFilter = async (key, value) => runCommandQuiet2(
677
+ "git",
678
+ ["config", `filter.ansible-vault.${key}`, value],
679
+ projectRoot
680
+ );
681
+ try {
682
+ await setFilter(
683
+ "clean",
684
+ "ansible-vault encrypt --vault-password-file .vault-password --output=- -"
685
+ );
686
+ await setFilter(
687
+ "smudge",
688
+ "ansible-vault decrypt --vault-password-file .vault-password --output=- -"
689
+ );
690
+ await setFilter("required", "true");
691
+ } catch {
692
+ console.warn(
693
+ "Could not configure the Ansible-Vault git filter automatically. Run `npm run setup:vault` before committing."
694
+ );
695
+ }
696
+ }
670
697
  async function createScaffold(options, targetDir, templatesDir) {
671
698
  const projectName = options.projectName.trim();
672
699
  if (!projectName) {
@@ -694,6 +721,12 @@ async function createScaffold(options, targetDir, templatesDir) {
694
721
  }
695
722
  await createApps(projectRoot, getAppTargets(options));
696
723
  await createIntegrations(options, projectRoot, templatesDir);
724
+ if (options.configureCd) {
725
+ await runStep(
726
+ "Activating Ansible-Vault git filter",
727
+ async () => activateVaultFilter(projectRoot)
728
+ );
729
+ }
697
730
  if (options.tools.includes("basic")) {
698
731
  await runStep(
699
732
  "Installing root dependencies",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smi-digital/create-smi-app",
3
- "version": "2.6.0",
3
+ "version": "2.7.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1,2 +1,15 @@
1
1
  #!/usr/bin/env sh
2
- npx lint-staged
2
+ npx lint-staged
3
+
4
+ # Safety net: never let an unencrypted production env file reach a commit.
5
+ # The Ansible-Vault git filter normally encrypts these as they are staged; this
6
+ # guard inspects the *staged* blob and aborts if the filter was inactive (e.g.
7
+ # on a fresh clone where `npm run setup:vault` was not re-run) and a plaintext
8
+ # secret slipped through. No-op for projects without production.*.env files.
9
+ staged_envs=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^production\..*\.env$' || true)
10
+ for f in $staged_envs; do
11
+ if ! git show ":$f" | head -n 1 | grep -q 'ANSIBLE_VAULT'; then
12
+ echo "✖ $f is staged UNENCRYPTED. Run 'npm run setup:vault', re-stage the file, then commit." >&2
13
+ exit 1
14
+ fi
15
+ done
@@ -13,7 +13,6 @@ jobs:
13
13
  project_domain: __PROJECT_DOMAIN__
14
14
  backend_domain: __BACKEND_DOMAIN__
15
15
  app_name: __APP_NAME__
16
- image_tag: latest
17
16
  secrets:
18
17
  # These secrets must be configured at the Organization or Repository level:
19
18
  SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }}
@@ -4,7 +4,7 @@
4
4
  # ========================================================
5
5
 
6
6
  # Stage 1: Builder
7
- FROM node:24-alpine as builder
7
+ FROM node:24-alpine AS builder
8
8
  # Installing libvips-dev for sharp Compatibility
9
9
  RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev curl > /dev/null 2>&1
10
10
 
@@ -20,7 +20,7 @@ RUN npm run build
20
20
 
21
21
  # Stage 2: Production
22
22
  FROM node:24-alpine
23
- RUN apk update && apk add --no-cache vips-dev curl > /dev/null 2>&1
23
+ RUN apk update && apk add --no-cache vips-dev > /dev/null 2>&1
24
24
  ARG NODE_ENV=production
25
25
  ENV NODE_ENV=${NODE_ENV}
26
26
 
@@ -1,31 +1,31 @@
1
1
  # ========================================================
2
- # EXAMPLE: Dockerfile for Astro SSR (Server-Side Rendering)
2
+ # Dockerfile for Astro SSR (Server-Side Rendering)
3
3
  # Place this in your /frontend folder and name it 'Dockerfile'
4
+ #
5
+ # Uses npm + the committed package-lock.json so installs are reproducible,
6
+ # and the @astrojs/node adapter for the runtime (matches `astro add node`).
4
7
  # ========================================================
5
8
 
6
- # Stage 1: Build with Bun
7
- FROM oven/bun:1 as builder
9
+ # Stage 1: Build
10
+ FROM node:24-alpine AS builder
8
11
  WORKDIR /app
9
12
  COPY package.json package-lock.json ./
10
- RUN bun install
13
+ RUN npm ci
11
14
  COPY . .
12
- RUN bun run build
15
+ RUN npm run build
13
16
 
14
- # Stage 2: Serve dynamic application using Bun
15
- FROM oven/bun:1-alpine
17
+ # Stage 2: Serve the SSR server bundle
18
+ FROM node:24-alpine
16
19
  WORKDIR /app
17
20
 
18
- # Copy the built SSR server bundle and node_modules
21
+ # Copy the built SSR server bundle and its dependencies
19
22
  COPY --from=builder /app/node_modules ./node_modules
20
23
  COPY --from=builder /app/dist ./dist
21
24
  COPY --from=builder /app/package.json ./
22
25
 
23
- # Expose port 4321 (Matches the 'frontend_port' logic in Ansible for SSR)
24
26
  EXPOSE 4321
25
-
26
- # Default environment variables
27
27
  ENV HOST=0.0.0.0
28
28
  ENV PORT=4321
29
29
 
30
- # Start the server (Adjust entrypoint depending on your Astro Node/Bun adapter)
31
- CMD ["bun", "./dist/server/entry.mjs"]
30
+ # @astrojs/node standalone server entrypoint
31
+ CMD ["node", "./dist/server/entry.mjs"]
@@ -2,7 +2,7 @@ services:
2
2
  __APP_NAME__-strapi:
3
3
  container_name: __APP_NAME__-strapi
4
4
  # The image is built in CI and pushed to Zot
5
- image: registry.smi-digital.com/__APP_NAME__-strapi:${IMAGE_TAG:-latest}
5
+ image: registry.smi-digital.com/__APP_NAME__-strapi:latest
6
6
  restart: unless-stopped
7
7
  env_file:
8
8
  - ./backend.env
@@ -12,7 +12,8 @@ services:
12
12
  networks:
13
13
  - agency_shared_network
14
14
  healthcheck:
15
- test: ["CMD", "curl", "-f", "http://localhost:1337/admin"]
15
+ # node-based (no curl dependency): node is always present in the image
16
+ test: ["CMD", "node", "-e", "fetch('http://localhost:1337/admin').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"]
16
17
  interval: 10s
17
18
  timeout: 5s
18
19
  retries: 15
@@ -30,7 +31,7 @@ services:
30
31
 
31
32
  __APP_NAME__-astro:
32
33
  container_name: __APP_NAME__-astro
33
- image: registry.smi-digital.com/__APP_NAME__-astro:${IMAGE_TAG:-latest}
34
+ image: registry.smi-digital.com/__APP_NAME__-astro:latest
34
35
  restart: unless-stopped
35
36
  env_file:
36
37
  - ./frontend.env
@@ -40,7 +41,8 @@ services:
40
41
  __APP_NAME__-strapi:
41
42
  condition: service_healthy
42
43
  healthcheck:
43
- test: ["CMD", "wget", "-q", "--spider", "http://localhost:4321"]
44
+ # node-based liveness (image is node:alpine); any HTTP response = server up
45
+ test: ["CMD", "node", "-e", "fetch('http://localhost:4321/').then(() => process.exit(0)).catch(() => process.exit(1))"]
44
46
  interval: 5s
45
47
  timeout: 2s
46
48
  retries: 5
@@ -59,7 +61,7 @@ services:
59
61
  depends_on:
60
62
  - __APP_NAME__-astro
61
63
  healthcheck:
62
- test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
64
+ test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost/"]
63
65
  interval: 5s
64
66
  timeout: 2s
65
67
  retries: 5
@@ -1,9 +1,13 @@
1
1
  # ==============================================================================
2
2
  # PRODUCTION BACKEND SECRETS (Strapi)
3
- #
4
- # 🚨 SECURITY WARNING 🚨
5
- # This file MUST be encrypted before committing to Git!
6
- # Run: ansible-vault encrypt production.backend.env --vault-password-file .vault-password
3
+ #
4
+ # 🔒 Encrypted automatically by the Ansible-Vault git filter.
5
+ # Edit in plaintext locally — it is encrypted on commit (GitHub only ever stores
6
+ # ciphertext) and decrypted again on checkout. The deploy decrypts it on the
7
+ # server. Do NOT run `ansible-vault encrypt` by hand; the filter handles it.
8
+ #
9
+ # If `git status` shows this file as plaintext after staging, the filter is not
10
+ # active on this machine — run `npm run setup:vault` before committing.
7
11
  # ==============================================================================
8
12
 
9
13
  # Strapi System Keys (Automatically generated by create-smi-app)
@@ -1,9 +1,13 @@
1
1
  # ==============================================================================
2
2
  # PRODUCTION FRONTEND SECRETS (Astro SSR)
3
- #
4
- # 🚨 SECURITY WARNING 🚨
5
- # This file MUST be encrypted before committing to Git!
6
- # Run: ansible-vault encrypt production.frontend.env --vault-password-file .vault-password
3
+ #
4
+ # 🔒 Encrypted automatically by the Ansible-Vault git filter.
5
+ # Edit in plaintext locally — it is encrypted on commit (GitHub only ever stores
6
+ # ciphertext) and decrypted again on checkout. The deploy decrypts it on the
7
+ # server. Do NOT run `ansible-vault encrypt` by hand; the filter handles it.
8
+ #
9
+ # If `git status` shows this file as plaintext after staging, the filter is not
10
+ # active on this machine — run `npm run setup:vault` before committing.
7
11
  # ==============================================================================
8
12
 
9
13
  # Internal Docker Network routing (Do not change)