@smi-digital/create-smi-app 2.5.0 → 2.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/index.js +33 -0
- package/package.json +1 -1
- package/templates/.husky/pre-commit +14 -1
- package/templates/integrations/strapi-astro/.github/workflows/deploy.yml.template +0 -1
- package/templates/integrations/strapi-astro/Dockerfile.backend.template +2 -2
- package/templates/integrations/strapi-astro/Dockerfile.frontend.ssr.template +13 -13
- package/templates/integrations/strapi-astro/docker-compose.yml.template +20 -3
- package/templates/integrations/strapi-astro/production.backend.env.template +8 -4
- package/templates/integrations/strapi-astro/production.frontend.env.template +8 -4
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,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
|
|
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
|
|
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
|
-
#
|
|
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
|
|
7
|
-
FROM
|
|
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
|
|
13
|
+
RUN npm ci
|
|
11
14
|
COPY . .
|
|
12
|
-
RUN
|
|
15
|
+
RUN npm run build
|
|
13
16
|
|
|
14
|
-
# Stage 2: Serve
|
|
15
|
-
FROM
|
|
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
|
|
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
|
-
#
|
|
31
|
-
CMD ["
|
|
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
|
|
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
|
-
|
|
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
|
|
34
|
+
image: registry.smi-digital.com/__APP_NAME__-astro:latest
|
|
34
35
|
restart: unless-stopped
|
|
35
36
|
env_file:
|
|
36
37
|
- ./frontend.env
|
|
@@ -39,6 +40,14 @@ services:
|
|
|
39
40
|
depends_on:
|
|
40
41
|
__APP_NAME__-strapi:
|
|
41
42
|
condition: service_healthy
|
|
43
|
+
healthcheck:
|
|
44
|
+
test: ["CMD", "wget", "-q", "--spider", "http://localhost:4321"]
|
|
45
|
+
interval: 5s
|
|
46
|
+
timeout: 2s
|
|
47
|
+
retries: 5
|
|
48
|
+
deploy:
|
|
49
|
+
update_config:
|
|
50
|
+
order: start-first
|
|
42
51
|
|
|
43
52
|
__APP_NAME__-cache:
|
|
44
53
|
container_name: __APP_NAME__-cache
|
|
@@ -50,6 +59,14 @@ services:
|
|
|
50
59
|
- agency_shared_network
|
|
51
60
|
depends_on:
|
|
52
61
|
- __APP_NAME__-astro
|
|
62
|
+
healthcheck:
|
|
63
|
+
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
|
|
64
|
+
interval: 5s
|
|
65
|
+
timeout: 2s
|
|
66
|
+
retries: 5
|
|
67
|
+
deploy:
|
|
68
|
+
update_config:
|
|
69
|
+
order: start-first
|
|
53
70
|
labels:
|
|
54
71
|
- "traefik.enable=true"
|
|
55
72
|
# Listen on both www and non-www
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# ==============================================================================
|
|
2
2
|
# PRODUCTION BACKEND SECRETS (Strapi)
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
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
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
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)
|